오늘은 파이널 프로젝트에 대해서 코드 정리하는 시간을 갖도록 하였다.
해당 부분에 대해서는 프론트/ 백 모두 진행 하였다.
6. 파이널 프로젝트 회고
8월, 파이널프로젝트 시작 그리고 SQLD도 같이 시작 스프링을 어느 정도 배우자 10월이 되자 마자 파이널프로젝트가 찾아왔다. 확실히 servelt으로 할 때보다는 훨배 재미있었고 편했다. 이번에는
jnaa.tistory.com
파이널 프로젝트는 Spring을 이용해서 개발을 진행했다.
이전 세미때는 다들 하고 싶은게 많아서 사다리타기로 진행하다보니,
게시판 CRUD를 제대로 못한 것 같아서, CRUD를 중점적으로 사용하고 싶었고 또한 API를 이용해보고 싶었다.
또한 이전 세미때 초기 기획이 매우 중요한 것을 깨닫고 기획부분도 맡아서 진행했다!
💡 주제선정 - 개발자를 위한 커뮤니티 사이트
세미와 다르게 내가 만들고 싶은 사이트를 만들고 싶었다.
그래서 '공동구매'라는 아이템을 가지고 사이트를 만들려고 했으나 벤치마킹하는데 공동구매하는 사이트가 많이 없고
할 수 있는 게시판종류가 부족하다는 생각이 들어 우리에게 어울리는 사이트를 만들자고 의견을 내 IT직군들을 위한 사이트를 만들자고 의견을 모았다 !
💻 이름 - Hello World
IT 직군을 위한 사이트를 만들자고 의견을 모였고, 주는 개발자로 의견이 모여졌다.
우리 사이트 이름을 뭐로 할까 하다 개발자들이 가장 설레는 순간인 Hello World가 찍혔을때라는 의견을 내
우리 사이트 이름은 Hello World 로 지었다.
💻 로고
로고는 처음 세팅을 할때 cmd 창을 키는 경우가 많다.
cmd를 쳐보면 : > 보고 아래와 같이 로고를 만들었다 ! 또한 그라데이션을 해서 좀 더 예쁘게 제작 했다
💻 ERD
일단 나를 가장 괴롭힌 ERD부터 설명을 하자면 다른조와 다르게 실무에서는 외래키를 사용하지 않는다고 하여
우리는 외래키 사용을 배제 해서 진행했다 !
( 외래키 잘 사용하지 않는 이유는 데이터의 정합성을 유지하기 위해서인데, 실무에서는 데이터를 수정하고 생성하는 경우가 빈번하다고 한다. 근데 데이터 생성 순서가 맞지 않으면 에러가 발생하기도 하고 이럴때 어쩔 수 없이 데이터를 생성하거나 자식테이블을 삭제하는데 CASCADE 옵션이 걸려있다면 부모 데이터가 삭제되는 참사가 발생..생각만해도 끔찍... 이런 이유로 인해 외래키 사용을 배제한다고 한다. )
그래서 ERD를 만들때 필요한 정보를 모두 적어놓고 하나하나 나눠서 진행했다..
내가 맡은 스터디 같은 경우는 게시글에 속해있지만, 작성시에는 다른 게시글과 다른 정보를 받기 위한 테이블도 필요했고, 같이 스터디하고 싶은 분야와 인원 위치를 받아야하는데 이부분은 다른 게시글에 태그와 같이 작성했다.
즉 스터디에만 필요한 테이블은 총 5개 였다...
💻 와이어프레임
서비스기획 방법은 처음에는 와이어프레임을 다 작성한 다음에 의사소통을 하려고 했는데,
그렇게 하면 도저히 시간도 부족할 것 같아 먼저 화면을 그리고 어떻게 수정할 것 인지 의사소통을 통해 진행했다.
예를들어 로그인화면은 모달창으로 보이게 해주고 ! 로그인창이 뜨면 뒤에 화면은 멈춰 있게 해줘!
이런식으로 많은 일정을 쓰지 않고 빠르고 효율적으로 진행 할 수 있게 했다 !
📂 기능 설명 스터디 게시판 📂
💻 스터디 메인 게시판
- 스터디메인 화면은 작성 / 인기글 / 목록 화면으로 구성했다.
- 인기글은 조회수가 많은 수부터 띄우도록 구현했으며 모집완료된 게시글은 목록에 보이지 않도록 설정했다.
💻 스터디 메인 게시판 (검색기능)
<select id="selectSearch" resultMap="StudyResultMap">
SELECT ROWNUM,S.STUDY_STATUS
, B.BOARD_NO
, M.MEMBER_NICK
, S.HEAD_COUNT
, B.MEMBER_ID
, B.BOARD_TITLE
, B.BOARD_CONTENT
, B.CREATE_DT
, B.MODIFY_DT
, B.DELETED_FL
, B.READ_COUNT
, S.LOCATION
, S.STUDY_NO
, T.TAG_NM
, TR.TAG_NO
, B.MODIFY_DT
, TO_CHAR(B.CREATE_DT, 'YYYY"년" MM"월" DD"일" HH24"시" MI"분"') AS CREATE_DT
, (SELECT COUNT(*) FROM "LIKE" L WHERE L.BOARD_NO = S.BOARD_NO) LIKE_COUNT
FROM BOARD B
JOIN "MEMBER" M ON (B.MEMBER_ID = M.MEMBER_ID)
JOIN BOARD_STUDY S ON (B.BOARD_NO = S.BOARD_NO)
JOIN TAG_RELATION TR ON (B.BOARD_NO = TR.ITEM_NO)
JOIN TAG T ON (TR.TAG_NO = T.TAG_NO)
WHERE TR.ITEM_TYPE = 1
<if test="location != null && !location.equals('서울전체')">
AND S.LOCATION LIKE '%${location}%'
</if>
<if test="tagNm != null">
AND T.TAG_NM LIKE '%${tagNm}%'
</if>
<if test="headCount != null">
AND S.HEAD_COUNT LIKE '%${headCount}%'
</if>
AND S.STUDY_STATUS = 'N'
AND B.DELETED_FL = 'N'
ORDER BY ROWNUM DESC
</select>
- 검색 기능은 누구나 쉽게 검색할 수 있도록 selectbox형태로 구현했지만 너무 안예뻐서 ul태그로 직접 만들었다.
- 검색은 동적 SQL을 이용해서 조건을 하나하나 모두 걸어 선택 가능하도록 구현했다.
💻 스터디 모집글 작성페이지
- 게시글 내용은Summernote 을 이용해서 만들어서 XSS 방지 따로 처리 하지 않았다.
- 위치의 경우는 QGIS을 이용해서 구별로 좌표를 따서 카카오맵 API와 연동 처리를 해주었다.
<insert id="studyInsert" parameterType="Study">
<selectKey order="BEFORE" resultType="Study" keyProperty="studyNo,boardNo">
SELECT SEQ_STUDY_NO.NEXTVAL AS "studyNo", SEQ_BOARD_NO.NEXTVAL AS "boardNo" FROM DUAL
</selectKey>
INSERT ALL
INTO STUDY VALUES(${studyNo}, #{boardTitle}, #{memberId}, DEFAULT)
INTO BOARD VALUES(${boardNo}, #{memberId}, #{boardTitle}, #{boardContent}, DEFAULT, NULL, DEFAULT, DEFAULT)
INTO BOARD_STUDY VALUES(${boardNo}, ${studyNo}, #{location}, ${headCount}, 'N')
INTO TAG_RELATION VALUES((SELECT TAG_NO FROM TAG WHERE TAG_NM = #{tagNm} AND ROWNUM = 1), 0, ${boardNo})
INTO TAG_RELATION VALUES((SELECT TAG_NO FROM TAG WHERE TAG_NM = #{tagNm} AND ROWNUM = 1), 1, ${boardNo})
SELECT * FROM DUAL
</insert>
😥 정말 가장 어려웠던 게시글 삽입 ! selectKey 를 이용해서 총 5개의 테이블에 값을 넣었다.
구글에 작성해보니 대부분 2개정도만 작성되어 있이 2개 이상부터는 정말 글이 없었다...
점심먹고부터 저녁 8시까지 삽입하나 하느라 하루종일 잡고 있었던 기억이 있다.
하지만 진짜 mybatis에 있는 INSERT ALL과 selectKey로 인해 1번으로 삽입을 처리 할 수 있었다!
💻 스터디 상세페이지
- 작성 시 카테고리로 설정한 위치 / 분야 / 인원 / 제목 / 내용이 보이도록 구현 하였다.
- 좋아요 / 조회수 / 댓글 / 목록으로 구현 하였다.
- 작성자가 일 경우, 아닐 경우에 따라 상세페이지 다르게 구현 하였다.
📍 스터디 상세페이지 (작성자 본인 )
- 작성자 정보를 확인을 위해 sticky 을 이용해서 작성한 글이 길어도 바로 확인할 수 있게 하였다.
- 수정 / 삭제 / 모집중 은 본인이 작성한 부분이 보이도록 구현하였다.
💻 스터디 상세페이지 ( 작성자 본인 ) - 수정
- 수정 카테고리의 경우, 이전에 작성했던 내용이 기억이 안 날 거라는 생각에 기존 값이 있도록 jsp에서 처리 해주었다.
💻 스터디 상세페이지 ( 작성자 본인 ) - 삭제
- DELETED_FL 컬럼을 Y로 UPDATE 하여 구현하였다.
💻 스터디 상세페이지 ( 작성자 본인 ) - 모집완료
- ajax로 모집완료로 구현하였으며 모집완료시 모집중에서 모집완료로 문구 변경 및 색 변경을 하였다.
const completeBtn = document.getElementById("completeBtn");
if(completeBtn!=null){
completeBtn.addEventListener("click", () => {
if (confirm("모집완료되신건가요 ?")) {
alert("🎉 축하합니다! 모집완료되었습니다.")
}
const data = {
"boardNo" :boardNo
}
fetch("/study/detail/completed",{
method:"POST",
headers:{"Content-Type":"application/json"},
body:JSON.stringify(data)
})
.then(resp=> resp.text())
.then(result =>{
console.log(result)
if(result>0){
location.reload(true);
}
})
.catch(e=>{console.log(e)})
})
}
📍 스터디 상세페이지 ( 작성자 본인 X )
- 본인이 작성하지 않은 것은 팔로우 기능과 문의하기 기능을 넣어주었다.
💻 스터디 상세페이지 (팔로우 / 좋아요 )
- 팔로우 기능 / 좋아요 기능은 AJAX로 구현해주었으며 0 / 1로 구분을 하여 했는지 안했는지 구별했다.
두개의 코드는 같은 형식으로 구현하였다.
// 좋아요 클릭 시
const like = document.getElementById("like");
const countSpan = document.getElementById("count");
const loginMemberId = document.getElementById("loginMemberId").value;
like.addEventListener("click", e=>{
// 로그인 여부
if(loginMemberId == ""){
alert("로그인 후 이용해주세요");
return;
}
let check;
if( e.target.classList.contains("fa-regular")){
check=0; // 좋아요 안 눌른 상태
} else {
check=1;
}
const data = {
"memberId": loginMemberId,
"boardNo" : boardNo,
"likeCheck" : check
};
fetch("/study/detail/like",{
method: "POST",
headers:{"Content-Type" : "application/json" },
body : JSON.stringify(data)
})
.then( res => res.text())
.then( count => {
if(count == -1) { // DML 실패
alert("좋아요 실패 ㅜㅜ");
return;
}
e.target.classList.toggle("fa-regular");
e.target.classList.toggle("fa-solid");
countSpan.innerText = count;
})
.catch( err => {
console.log("예외발생")
})
})
💻 스터디 상세페이지 (문의하기 / 목록 )
사이트를 이용할때마다 누가 나한테 댓글을 달았는데 나의 현생을 살다가 못보고 놓치는 경우가 많아서,
문의하기를 눌렀을때 작성자에게 문자가 가 누가 나에게 문의를 했는지 알 수 있게 진행했다.
네이버 API를 이용해서 문자발송 서비스를 이용하였으며 AJAX를 이용해서 문의하기를 구현하였다.
if(confirm("친구와 같이 스터디 하기 원하면 확인 버튼을 눌러주세요!\n친구에게 문자로 알림이 갑니다!📧")){
fetch("/study/detail/"+boardNo+"/message",{
method:"POST",
headers:{"Content-Type":"application/json"}
})
.then(res=>res.text())
.then(result =>{
console.log(result)
if(result>0){
location.reload(true);
}
})
.catch(e=>console.log("에러발생"))
alert("친구에서 문자가 갔습니다. 자세한 내용은 체팅을 이용해주세요!")
}
💻 스터디 상세페이지 (댓글 / 대댓글 / 수정/ 삭제 )
- 댓글의 경우 계층형 쿼리를 이용해서 작업하였으며, 기존에 배웠던 내용을 응용하였으며
우리의 홈페이지에 맞게 화면과 CSS를 다시 구현하였다.
👀 짧은나의 소감
이렇게보니 역시 아쉽다.
더 많은 기능을 하지 못한것에 대해서 좀 아쉽지만 그래도 뿌듯했다!
그래도 세미때는 CRUD를 제대로 해보지 못했는데 이번에는 전체 게시글을 해본 것 같아서 좋았고,
또한 API 사용 못해서 아쉬웠는데 파이널 때 API를 활용해서 기술 구현을 해서 재미있었다.
또한 의사소통하는 방법에 대해서 다시한번 생각 할 수 있었던 파이널 프로젝트였다.
'프로젝트' 카테고리의 다른 글
[ 세미프로젝트 ] K-HOTEL (1) | 2023.11.14 |
---|---|
6. 파이널 프로젝트 회고 (1) | 2023.10.27 |
5. 세미프로젝트 회고 (1) | 2023.10.24 |
[ 파이널 프로젝트 ] 스터디 상세페이지 진입 실패😥 [오류도 없고 콘솔에도 아무것도 안 찍히고 페이지 진입이 안 될때 디버깅을 쓰자] (0) | 2023.09.21 |
[ 파이널 프로젝트 ] This branch has conflicts that must be resolvedUse the web editor or the to resolve conflicts.Conflicting files GIT 깃 병합 오류 해결하기 (0) | 2023.09.20 |