후기/프로젝트, 해커톤

[SOLUX/솔룩션🫂/웹백엔드] 🧭🤝'MIDPOINT : 우리 어디서 만날까?' 프로젝트 후기💙

최연재 2024. 8. 7. 09:36

🔗 깃허브 링크

https://github.com/Solucitation/midpoint-backend

 

GitHub - Solucitation/midpoint-backend

Contribute to Solucitation/midpoint-backend development by creating an account on GitHub.

github.com

 

시작에 앞서

 
올해 프로그래밍 중앙동아리 솔룩스에 합격하며 1년간 활동하게 되었습니다. 솔룩스는 학기별로 팀이 바뀌며 기획 + 디자인 + 프론트엔드 + 백엔드로 팀을 나눠서 웹/앱/게임 프로젝트를 진행합니다. 저는 웹백엔드로 1학기에 솔룩션 팀에 속해서 프로젝트를 진행했습니다.
 
여담인데 팀명과 프로젝트 주제 모두 제가 제시한 아이디어가 베이스가 되었습니다. 솔룩션의 경우에는 처음에는 솔루션(솔룩스에서 솔루션을 찾자는 의미)을 내놓았는데, 다른 팀원 분이 '루' 대신 '룩'이 어떻냐고 제안하셔서 최종적으로 솔룩션이 되었습니다. 주제는 저는 '목적을 제시하고, 여러 명이 본인의 주소를 입력하면 이를 바탕으로 중간 지점이면서 목적에 부합하는 장소를 추천해주는' 사이트를 제시했었습니다. 이후 중간 지점은 위도와 경도의 중간값을 이용해서 찾고, 목적은 구글 장소 api를 활용하였습니다.
 

개발 전 준비

이후 주제에 맞춰서 각 팀 내부 역할별로 회의 등을 진행하고 매주 정기회의를 하면서 구현물을 구체화합니다. 사실 제가 낸 아이디어였음에도 불구하고, 본격적인 프로젝트는 솔룩션이 처음이었던 터라 기간 내 기술적인 구현이 가능한지 잘 몰라서 확답을 잘 못해주는 부분이 있었습니다. 다행히 저희 팀 백엔드 팀원 중 한 분이 프로젝트를 해보셨던 터라 잘 방향성을 잡아주셨습니다. 기존에 존재하는 유사 사이트와의 차이점을 잡기 위해서 열심히 논의했던 것이 기억에 남습니다.
 
학기 중에는 주로 스터디를 하는 방식으로 진행되었는데, 스터디 기간 동안 저는 SQL과 JPA를 공부했습니다. 스프링 부트를 이용한 개발을 하게 되었습니다.
 

역할 분배

학기 중에는 아무래도 팀원 모두 여러 일정들이 있다 보니, 본격적인 개발은 주로 종강 이후인 방학부터 진행하게 되었습니다. 저는 ER model과 ERD 다이어그램을 제작하는 일, 커뮤니티 게시판을 제작하는 일을 맡았습니다.

 

 💙 ER model과 ERD 다이어그램 제작하기

제가 1학기에 <소프트웨어분석및설계>(== 소프트웨어공학) 수업을 들으면서 해당 내용들을 최근에 공부했었기에 제가 맡았습니다. 6월 22일 ~ 23일 동안 열심히 만들어서 24일에 백엔드 회의에서 이를 확정 지었습니다!
 
수업에서 다이어그램을 제작하는 과제를 몇 번 해봤었는데도 어려웠습니다. 1차적으로는 아래와 같이 짰습니다.

하면서 이게 맞나? 걱정을 많이 했는데 전반적으로 이해도를 높일 수 있었던 거 같습니다.

 최종적으로 바뀐 ERD는 아래와 같습니다. 개발 과정에서 회의하면서 수정했어요.

전반적으로 ERD 짜는 건 약간 감이 잡혔는데, 아직도 연관관계 선에서 파란색 선이랑 분홍색 선의 차이를 잘 모르겠습니다.. 저는 위의 ERD의 파랑색 + 분홍색 테이블 파트를 전부 담당했습니다. 
 

🩵 기능 구현 : 커뮤니티 게시판 만들기 + 검색 기록 저장 및 조회

커뮤니티 게시판 CRUD 기능이 엮여 있는 곳이 많았던 터라 저는 6월 24일 ~ 7월 22일 동안 해당 작업만을 담당하였습니다. 검색 기록의 경우 원래 후순위 기능이었는데,  게시판 개발이 생각보다 일찍 끝나서 당시 백엔드에서 개발이 거의 끝난 제가 맡았습니다. 게시판에서 수정할 부분이 몇 부분 생겨서 수정만 마무리하고 26일 회의에서 세부사항을 논의하고 개발을 시작했습니다. 개발 자체는 금방 마무리했습니다. 
 
1️⃣ 게시판 글 리스트

  • 글은 최신순부터 보인다.
  • 로그인되어 있지 않거나, 로그인한 사용자이지만 글에 좋아요를 누르지 않았을 경우에는 빈 하트가 나오게 한다.
  • 로그인한 사용자이며 글에 좋아요를 눌렀을 때는 채워진 하트가 나오게 한다.

2️⃣ 게시판 글 작성하기

  • 로그인된 사용자만 할 수 있다.

3️⃣  게시판 글 상세 보기

  • 로그인되어 있지 않아도 볼 수 있다.

4️⃣ 게시판 글 수정/삭제

  • 글 작성자만 가능하다.
  • 제목, 본문, 해시태그 수정이 가능하다
  • 이미지 변경이 가능하다.

5️⃣  게시판 글 검색

  • 해시태그를 이용한 검색이 가능하다.
  • 키워드를 이용한 검색이 가능하다.

6️⃣  게시글 좋아요 등록 or 취소

  • 로그인된 사용자만 가능하다.
  • 좋아요를 누른 상태의 글일 경우에는 좋아요가 취소된다.
  • 좋아요를 누르지 않은 상태의 글일 경우에는 좋아요가 등록된다.

7️⃣ 검색 기록 저장 + 조회

  • 로그인된 사용자만 가능하다.
  • 체크박스를 이용해서 조회된 장소를 선택하고 저장 버튼을 누르면 저장된다.
  • 마이페이지에서 저장한 검색 기록을 확인할 수 있다.

 

💚 에러 해결 : 탈퇴 회원 게시글 처리

회원 탈퇴 후 게시글을 어떻게 처리할지 회의를 했었습니다. 에브리타임처럼 게시글은 유지하되, 유저 정보를 "알수없음"으로 처리하기로 했는데, 이 부분은 제가 구현했습니다. ERD를 보면 아시겠지만, 게시글은 멤버 아이디를 NOT NULL 필드로 설정해 두었기 때문에 단순히 member 엔티티를 바로 삭제하려고 하면 연속된 외래 키 에러를 만나게 됩니다.
 
다른 분이 짜신 코드에 추가적인 로직을 추가해서 성공적으로 구현했습니다. 처음부터 제가 구현한 것이 아니고, 사실상 외래 키 에러를 해결한 것이기 때문에 항목을 분리했습니다.
 

개발 과정

🧡 로컬에서 개발

🎮 게시글 전체 리스트 + 상세 보기
: 가장 처음 개발하기 시작한 부분인데 200 OK를 보기까지 정말 많은 시간이 걸렸습니다...  회원가입 + 글 작성이 완전해질 동안 더미 데이터를 직접 SQL문으로 넣어두고 작업했습니다.  이때 정말 다양한 에러를 만나봤고, 해결하면서 백엔드 개발의 감을 조금씩 잡아가기 시작했습니다. 상세 보기 구현 시 fetch join 관련 오류를 만났었습니다. One to Many인 엔티티를 여러 개 조인해서 가져오려다가 생긴 오류였는데 쿼리를 쪼개서 해결했습니다.
 
🎮 게시글 좋아요 등록 + 취소
: 로직 자체는 간단했습니다. 회원 아이디와 게시글 아이디를 이용해서 좋아요 DB에서 데이터를 찾을 수 있다면 좋아요가 눌린 상태이니 이 데이터를 삭제합니다. 반대로 데이터를 찾을 수 없다면 추가하면 됩니다.
 
이후 좋아요 여부를 Boolean 타입으로 반환해 주었습니다.
 
🎮 게시글 글 작성하기
: 이미지 저장을 위해 AWS S3를 사용했습니다. 다른 팀원 분이 멤버 관련 작업을 했는데(회원가입~탈퇴 전 과정) 프로필 이미지를 AWS S3에 저장할 건데 같이 쓰자고 하셔서 버킷을 같이 썼어요. 관련 코드를 다 만들어주시고 저는 호출해서 쓰기만 하면 돼서 별 문제는 없었습니다.
 
이 부분이 가장 예외처리를 많이 해야 하는 부분인 것 같습니다. 이틀 동안 테스트케이스를 만들고 대입해 보면서 좀 더 꼼꼼히 코드를 작성했습니다.
 
게시글에 이미지를 1~3개 필수로 넣도록 했는데, api테스트하면서 궁금한 부분이 생겼습니다. 

체크박스가 눌리지 않은 채 보내지면 백엔드 측에서 postImages가 null인 경우로 처리하면 되는 건 이해했는데, 체크박스를 누르고 파일을 선택하지 않고 보냈을 때 어떻게 되는 건지 모르겠습니다. 체크박스를 누르고,  파일을 넣지 않고 보내면 postImages가 NULL이 아니고, size도 1로 나옵니다. 그래서 반복문을 돌려서 원소들의 데이터를 출력해 봤는데 isEmpty가 true로 나오는 걸 알았습니다. 그래서 일단은 경우를 나눠서 다 처리해 주고 위의 경우는 이미지 정보가 유효하지 않다고 예외를 반환하게 했습니다. 
 
혹시 이 경우에는 프론트에서 데이터가 어떻게 보내지는 건지 아시는 분은 댓글 달아주시면 감사하겠습니다...
 
🎮 게시글 검색 (해시태그 검색, 키워드 검색)
: 해시태그 검색은 ERD 짤 때부터 고려하고 중간 테이블을 만들어두었기 때문에 이를 이용해서 금방 끝냈습니다. 키워드 검색은 문장 형태로 검색되면 이를 공백 기준으로 파싱하고 단어 리스트를 만들고 이를 이용해서 검색하도록 구현했습니다. 검색 부분이 최적화를 할 부분이 좀 됐는데, 일단은 기능 구현이 주를 이뤄야 하니 최적화는 후순위였습니다.
 
🎮 게시글 글 수정하기
: 여기에서 PATCH를 처음 써봤는데, 솔직히 이론적인 이해를 하느라 개발은 조금 늦었습니다. 
 
"변경된 부분만 보내주면 그 부분만 수정을 진행한다"는 로직은 이해했는데, 이걸 코드로 어떻게 해야 할지 고민을 했습니다. 처음엔 게시글 작성하기에서 사용한 DTO를 그대로 사용하려고 했는데, 변경사항이 없으면 데이터를 보내지 않기 때문에 새롭게 updateDto를 생성해서 처리했습니다.
 
 이제 두 번째 난관에 부딪힙니다. 제목이나 본문은 그냥 받아오면 되는데, 해시태그나 이미지처럼 여러 개의 항목이 있는 데이터는 어떻게 변경감지를 해야 할지 감을 잡지 못했습니다. 그래서 일단은 변경이 발생했을 경우에 프론트 측에서 최종적으로 선택된 결과 전체를 보내달라고 부탁했습니다. 
 
해시태그는 큰 문제가 없었는데, 이미지가 발목을 잡았습니다.. 어찌어찌 오랜 시간을 들여서 전부 테스트까지 하고 개발을 끝냈습니다. 이후 저 문제는 프론트엔드 + 백엔드 연결에서 돌아옵니다...
 
🎮 게시글 글 삭제하기
: DB에서 연관 데이터를 전부 삭제하기만 하면 돼서 큰 어려움은 없었습니다. 다만, S3에 올라간 이미지를 지우는 로직을 추가했다가, 이미지 DB에서 외래 키 에러가 나서 그 부분을 수정했습니다.
 
🎮 검색 기록 저장
: 원래 개발 후순위 기능이었고,  개발 마감이 약 일주일 남은 시점부터 시작해서인지 마음이 많이 급했던 것 같습니다.  프론트로부터 받아와야 하는 것이 위치 정보, 장소 정보 리스트 두 가지였는데, 이때 판단을 잘못 해서 DTO 디자인을 잘못했고 이것도 프론트 + 백 연결에서 파도로 돌아옵니다.
 
🎮 겸색 기록 조회
: 기능 자체는 어렵지 않아서 정말 빠르게 끝냈습니다.
 
🎮 탈퇴 회원 처리
: 단순히 멤버 엔티티를 삭제하면 위에서 언급한 것처럼 외래 키 에러가 발생합니다. 그래서 좋아요, 검색 기록 등과 같은 엔티티는 모두 찾아서 삭제하고, 게시글과 게시글 이미지 데이터만 이관해 주도록 코드를 짰습니다!
 

🩷 백엔드 배포 후 프론트 + 백엔드 연결

🎮 게시글 전체 리스트 + 상세 조회
: 상세 조회에서 사용자의 좋아요 정보를 T/F로 반환하는 부분을 놓쳤었습니다.. 프론트엔드랑 같이 연결하다가 발견해서 바로 DTO을 수정해서 메인에 push 했습니다. 그 뒤로는 문제없었습니다.
 
🎮 게시글 글 작성하기
: 문제없이 연결되었습니다.
 
🎮 게시글 좋아요 등록 + 취소 
: 자잘한 에러가 많아서... 가장 마지막에 연결되었습니다..
 
🎮 게시글 검색 (해시태그 검색, 키워드 검색)
: 문제 없이 연결되었습니다.
 
🎮 게시글 글 수정하기
: 앞서 언급했던 이미지가 AWS CORS 에러로 돌아왔습니다. AWS 버킷에서 권한도 변경하고, 구글링 해서 할 수 있는 시도는 다 해봤는데, 전부 안 됐습니다. 한 시간 정도 고민했는데, 방안이 떠올라서 API를 갈아엎었습니다. 사실 기존 방안이 마음에 들진 않았던 터라(비효율적) 새로운 방안이 더욱 효율적인 것 같아서 미련이 없었습니다.
 
2안은 삭제할 이미지는 URL 정보로 받아오고, 추가할 이미지만 파일로 받아오는 것입니다. 
기존 이미지 개수 - 삭제할 이미지 개수 + 추가할 이미지 개수를 계산해서 게시글 이미지 조건을 충족하는지 검사해 주고, 삭제할 이미지는 게시글 아이디와 이미지 URL을 이용해서 DB에서 삭제하고, S3에서도 삭제했습니다. 엔티티 연관관계 설정 시 고아객체 처리도 해주었기 때문에 기존의 이미지 리스트에서 삭제할 이미지를 제거하면 자동으로 기존의 이미지 리스트에는 변경되지 않은 이미지만 남게 됩니다. 여기에 추가할 이미지를 반복문을 통해 넣어주고 나서 게시글을 builder로 다시 만들어주었습니다.
 
이때 게시글 이미지를 단순히 DB에 올라간 순서대로 가져오면 중간 사진을 변경한 경우가 처리되지 않습니다. 그래서 이미지 엔티티에서 순서를 저장하는 int 필드를 만들어주고 이를 이용해서 순서가 바르게 출력되게 했습니다.
 
🎮 게시글 글 삭제하기
: 문제없이 연결되었습니다.
 
🎮 검색 기록 저장
: DTO 파싱에서 계속 에러가 나서 그냥 API를 갈아엎었습니다. 장소 정보를 저장할 DTO를 아예 코드에서 분리해 주고 좀 더 명시적으로 코드를 변경했습니다. 변경된 API는 바로 잘 되었습니다. 다만, 이미지 URL 필드에 별 다른 설정을 하지 않았는데, 길이가 255가 넘는 경우가 있어서 1024로 길이를 늘렸습니다.
 
🎮 겸색 기록 조회
: 문제없이 잘 연결되었습니다.
 
🎮 탈퇴 회원 - 게시글 처리
: 사실상 백엔드에서만 처리한 후 프론트로 전달만 하면 되기에 연결 과정에서는 문제가 없었습니다. 다만, 프로필 이미지가 일부 화면에서 깨지는 사소한 에러가 있었는데, 기본 이미지가 삭제돼서 생긴 오류였습니다. 이 부분은 저와 회원 기능을 구현하신 팀원 분이 같이 이야기하면서 문제를 찾아봤는데 s3에서 이미지를 삭제하는 함수 위치 문제였습니다. 회원 기능을 구현하신 팀원 분이 찾아서 수정하셨습니다.

 

 

최종발표회 (8월 5일)

솔룩스는 프로젝트를 최종발표회에서 소개하면서 한 학기의 끝을 맞이하는 시스템입니다. 이를 위해 시연 영상(불가피한 상황 시 사용)과 PPT를 만들어야 했는데, 제 컴퓨터로 시연 영상을 찍어서 당일 발표에서도 기획 분과 함께 발표를 했습니다. 사실 말은 하지 않았지만, 노트북으로 저희의 결과물을 시연하는데, 손이 많이 떨렸습니다..
 


 다행히 잘 끝났습니다!

회고 -  개발 ver.

초반부 개발 과정에서 소위 말하는 '삽질'을 정말 심하게 했습니다... 실제로 URL 링크를 잘못 봐서 3일 동안 문제없는 코드를 수정하기도 했었습니다... 백엔드 회의에서 처음에 역할을 분담할 때 백엔드 개발의 기본인 게시판 CRUD 기능을 하겠다고 했었는데, 개발하면서 많이 배웠습니다. 역시 실제로 해봐야 내 것이 되는 것 같습니다. 그리고 다른 백엔드 팀원의 코드를 봐야 이 코드를 이용해서 개발이 가능했기 때문에 타인의 코드를 읽는 방법을 제대로 경험했습니다. 깃 커밋 컨벤션은 혼자서 할 때도 지켜와서 익숙했으나 이슈 작성법, PR 작성법 같은 깃허브 기본 이용도 팀 작업을 하면서 처음 해봤습니다. 
 
게시판 기능을 위해서는 전반적으로 다른 기능들도 되어 있어야 하고, 특히 로그인이 된 상태에서의 테스트가 필요하다 보니 1~3번을 동시에 개발했습니다. 처음에 하나의 브랜치에서 쭉 업데이트하다 보니 브랜치 별로 역할을 명확히 구분하고 싶었는데, 이 점을 제대로 지키지 못한 것 같아서 아쉽습니다. 그래서 게시판 글 리스트 기능까지를 기존에 작업하던 feature/community-board 브랜치에서 PR 한 후 이후 작업부터는 의식적으로 브랜치를 쪼개가며 개발하였습니다. 

추가적으로 프론트엔드에게 보내달라고 요청할 데이터를 잘 구상해야 함을 깨달았습니다. 처음에는 기능 구현에 급급해서 포스트맨에서 성공만 하면 바로 확정을 지었었는데, 효율을 위해 필요한 데이터만 잘 받아오도록 계획을 짜는 것의 중요성을 느꼈습니다. SQL문 최적화, 코드 리팩토링 등 하고 싶은 일이 많았는데 시간 관계 상 못해서 아쉽습니다.
 

마무리

기획 1분, 디자이너 1분, 프론트엔드 3분과 같이 협업하다 보니 매주 하는 회의에서 많은 이야기를 했었습니다. 다 같이 대면 회의도 하고 개발 마지막 날에는 새벽까지 디스코드에서 PPT나 리드미를 수정했습니다. 팀원 분들이 모두 좋으셔서 성공적으로 프로젝트를 끝낼 수 있었던 것 같아요. 우리 솔룩션 팀 최고!🥰
 
 

시연 영상입니다!

 
ERD를 짜고, 포스트맨으로 API 테스트하면서 예외를 잡아나가는 과정이 재밌어서 아마 2학기 프로젝트도 백엔드 지망으로 갈 거 같습니다!