기능 개발 시작
& 역할 분배 및 협업
2~3주차부터 본격적인 기능 개발 시작 및 팀원별로 역할을 나누고, Git 협업 방식을 정리하여 프로젝트를 체계적으로 진행
1. 기능별 역할 분배
- 채팅 담당 : WebSocket, STOMP, Redis Pub/Sub 을 활용한 실시간 채팅 기능
- 인증 / 인가 와 지도 검색 API 담당 : Spring Security와 JWT를 활용한 보안 기능 + 카카오 지도 연동
- 배포 및 S3 이미지 업로드 담당 : AWS EC2, Docker를 활용한 배포환경 구축 및 S3 연동
- GPT AI 연동 및 취향 카테고리 담당 : OpenAI API를 연결하고 Spring AI를 활용해 프롬프트 설계 및 취향 기반 추천
이렇게 4개의 역할로 분배하고 개발을 진행했으며, 나는 실시간 채팅 기능을 맡아 WebSocket과 STOMP를 활용한 메시지 송수신 시스템을 구축했다. 또한, Redis Pub/Sub을 적용해 다중 서버 환경에서도 안정적으로 채팅이 동작할 수 있도록 구현하는 데 집중했다
2. Git 협업 방식 & 문제 해결
GitFlow 전략을 기반으로 기능을 개발하기 시작했지만, 협업 과정에서 여러 시행착오가 있었음
초반에 겪은 문제점
- PR을 API 단위로 올리기로 했지만, 이를 지키지 않아 코드 리뷰가 어려웠음
- 여러 개의 기능을 동시에 맡은 경우, 브랜치를 혼동하여 잘못 사용하는 실수 발생
- 코드 컨벤션을 정했음에도 불구하고 일관성이 부족하여, 수정에 많은 시간이 소요
개선된 Git & 코드 리뷰 방식
: 이러한 문제를 해결하기 위해 Git 협업 방식을 다시 정리하고, 코드 리뷰 강화
- PR 단위를 기능별로 세분화 -> API 단위로 나누되, 너무 길어지면 더 작게 쪼개서 올리기
- PR 작성 시 기능 설명 & 주요 변경 사항 기록 -> 팀원들이 쉽게 파악하고 리뷰할 수 있도록 정리
- 팀원 간 코드 리뷰 필수 -> 최소 2명의 Approve 후 Merge 가능
- 코드 컨벤션 준수 -> 컨벤션 위반 시 수정 후 다시 리뷰 진행
결론 : 이렇게 협업 방식을 개선하면서 코드 리뷰가 원활해지고, 코드의 일관성과 가독성 향상
3. 코드 리뷰 & 협업 방식
PR을 단순한 코드 공유 수단으로 활용하는 것이 아니라, 코드 리뷰를 진행하며 팀원 간 피드백을 주고받는 협업을 하였다.
초기에는 "이 부분을 이렇게 수정하는게 어떨까요?" 라는 피드백이 남겨지면, 주로 지적된 부분을 바로 수정하는 방식이었지만, 점차 코드 리뷰가 단순한 수정 요청을 넘어서 서로의 개발 의도를 공유하고 논의하는 협업 과정으로 발전해 나갔다.
"이 부분은 이렇게 구현한 이유가 있는데, 이 의도는 어떻게 생각하시나요?" 같은 논의 중심의 코멘트들이 늘어나면서 코드 리뷰가 단순 검토가 아닌 팀원 간 기술적 의사결정이 이루어지는 과정이 되었다.
결론 : 협업을 통해 코드 리뷰는 단순한 수정 요청을 넘어, 팀원 간 개발 의도를 공유하고 설계를 논의하는 과정이 되었으며, 단순한 기능 구현을 넘어 코드의 유지보수성과 확장성을 함께 고민하며 발전시키는 협업 방식으로 자리 잡았다.
개발 중 발생한 주요 문제
& 해결 과정
개발을 진행하면서 팀원별로 다양한 기술적 문제에 직면했으며, 이를 해결하는 과정에서 프로젝트의 안정성과 코드 품질을 개선
1. 진행 중 발생한 문제와 해결 방법은 트러블 슈팅을 작성해 정리
https://jy3574.tistory.com/137
[트러블 슈팅 / 중간발표 전] 최종 프로젝트 : 9kcal. 오늘 뭐 먹지?
1. WebSocket 인증 및 Spring Security와 충돌 문제1)개요WebSocket 연결 시 Authorization 헤더에 Access Token이 포함되지 않아 Spring Security의 인증이 실패하여 연결이 차단 됨(인증된 사용자만 접근할 수 있도록
jy3574.tistory.com
2. 팀에서 발생한 문제와 해결 방법
* Jackson 역직렬화 오류(PasswordVerifyRequestDto)
- 문제
- PasswordVerifyRequestDto 클래스에서 Jackson 역직렬화 오류 발생
- 기본 생성자가 없고, final 필드가 있는 경우 Jackson이 객체를 생성할 수 없어 역직렬화 실패
- 원인
- 필드가 하나만 있는 경우 Jackson이 어떤 생성자를 사용할지 명확히 판단하지 못함
- 기본 생성자가 없고, final 필드가 있는 경우 객체를 생성할 방법이 없어 오류 발생
- 해결
- @JsonCreator와 @JsonProperty를 활용하여 Jackson이 사용할 생성자를 명시적으로 지정하여 문제 해결
- 클래스의 불변성을 유지하면서 안전한 객체 생성이 가능하도록 함
* Spring Security 403 오류(인증 실패 & 권한 부족 구분 문제)
- 문제
- 인증 실패(401 Unauthorized)와 권한 부족(403 Forbidden)이 구분되지 않아 디버깅이 어려움
- 모든 오류가 403 Forbidden으로 반환되어 문제 원인을 정확히 파악하기 어려움
- 원인
- JwtAuthFilter에서 발생한 인증 실패 예외(CustomException)가 명확하게 처리되지 않음
- Spring Security 기본 설정에서 예외가 발생하면 403 Forbidden을 반환
- 해결
- JwtAuthFilter 내부에서 인증 실패 예외를 명시적으로 처리하여 401 Unauthorized 반환
- SecurityConfig에서 예외 처리를 추가하여 인증 실패(401)와 권한 부족(403)을 명확히 구분
* JPA 영속성 컨텍스트로 인한 이미지 삭제 오류
- 문제
- 사용자의 프로필 사진 삭제가 정상적으로 수행되지 않음
- JPA에서 부모-자식 객체 간 연관관계가 설정된 경우, 부모 삭제 시 자식 삭제가 제한됨
- 원인
- 1:1 양방향 매핑으로 인해 삭제 제한 발생
- CascadeType.REMOVE 설정이 없어 부모를 삭제해도 자식이 자동으로 삭제되지 않음
- 중첩 트랜잭션 문제로 인해 내부 메서드(deleteImage())의 트랜잭션이 무시됨
- 해결
- 삭제 전에 연관관계를 끊고, flush()를 사용해 영속성 컨텍스트 동기화
- 이후 1:N 양방향 매핑으로 변경하여 삭제 제한 완화
* JSON 응답 역직렬화 오류 해결(Spring AI 연결 시)
- 문제
- Spring AI를 통해 OpenAI API를 호출할 때 DTO 클래스의 역직렬화 오류 발생
- Jackson이 API 응답을 올바르게 역직렬화하지 못함
- 원인
- DTO 클래스에서 직렬화/역직렬화 설정 부족
- 기본적으로 Jackson은 Getter/Setter를 활용하여 직렬화 & 역직렬화를 수행하는데, DTO에 적절한 설정이 없을 경우 JSON 변환 오류 발생
- Record 타입을 사용하지 않고 일반 클래스를 사용하여 직렬화 문제 발생
- record 타입은 불변성을 보장하면서도 직렬화/역직렬화에 최적화된 구조이지만, 기존 DTO는 class로 선언되어 있어 직렬화 오류 발생
- 해결
- DTO를 record 클래스로 선언하여 JSON 응답을 올바르게 처리
- Java 14 이상에서 지원하는 record를 사용하여 불변성과 직렬화 안정성 확보
- DTO를 record 클래스로 선언하여 JSON 응답을 올바르게 처리
- DTO 클래스에서 직렬화/역직렬화 설정 부족
* OpenAI를 Spring AI로 연결(Spring AI 적용 & 버전 문제)
- 문제
- OpenAI를 Spring 환경에서 연결하는 방법을 고민
- 직접 API 호출 vs Spring AI 사용 고민
- Spring 3.4.1에서는 Spring AI가 지원되지 않음
- 원인
- 직접 API 호출 방식(WebClient 사용)
- OpenAI API를 직접 WebClient로 호출하는 방식
- 직접 요청을 구성해야 하고, 응답 처리 로직도 직접 작성해야 함
- Spring AI 사용
- Spring AI는 OpenAI API를 쉽게 연결할 수 있도록 지원
- ChatClient를 활용하여 자동화된 방식으로 통합 가능
- 직접 API 호출 방식(WebClient 사용)
- 해결
- WebClient를 활용한 OpenAI API 호출 방식 적용
- build.gradle에 Spring AI 의존성 추가
- application.properties에서 OpenAI API 키를 환경 변수로 설정
- Spring 3.4.1에서는 Spring AI가 지원되지 않아 Spring 버전을 3.2.X로 다운그레이드하여 해결
중간 발표
& 피드백
1. 중간 발표 준비
기존 발표는 기능 구현 중심이었지만, 이번 발표에서는 MVP, 기술적 의사결정, 트러블슈팅 과정을 강조하는 방향으로 변경하여 진행
단순히 "이런 기능을 구현했다"가 아닌 "왜 이 기술을 선택했고, 어떤 문제를 해결했고, 앞으로 어떻게 발전시킬 것인지"를 중심으로 발표를 구성
<발표 준비 자료 및 발표 대본 정리>
https://clumsy-octave-632.notion.site/1971d0afa972810eb9dece2391f82ef2?pvs=4
중간 발표 전체 취합 | Notion
*기술적 의사결정 발표 내용정리 완료
clumsy-octave-632.notion.site
<발표 자료>
오늘 뭐 먹지?
백은영 님이 디자인한 프레젠테이션 살펴보기
www.canva.com
2. 발표 후 피드백 & 개선 방향
*ERD 수정
- ERD에 포함된 테이블이 너무 적어 데이터 구조가 불명확함
- AI 관련 데이터가 Redis에 저장되기 때문에 ERD에서 누락됨
- 변수명을 snake_case로 통일
- ERD는 보통 RDB 기준으로 설계되지만, 캐싱 용도로 사용하는 Redis도 설계 문서에 포함하는 것이 명확성 측면에서 필요함
- 다른 튜터님 의견 : ERD는 Entity의 연관관계를 나타내는 것이니 필요없음. 차라리 API 명세서에 표현하는게 나음
결론
- 변수명 컨벤션 일관성 유지
- Redis 데이터는 ERD에 추가하지 않고, API 명세서 및 아키텍쳐에 설명하는 방식으로 정리하기로 결정
*API 명세서 보완
- API 명세서에 실제 백엔드에서 제공하는 모든 URL을 가지고 있는 기능을 작성
- 프론트엔드에서 처리하는 기능이 API 문서에 포함되어 있으면 혼동을 줄 수 있음
- API가 어떤 화면에서 호출되는지 명확하지 않음
- Request와 Response의 명확성 부족
- 기존 명세서는 API의 기능만 간단히 나열했지만, 요청 헤더와 요청 본문에 대한 구체적인 설명 부족
- 응답도 어떤 데이터가 반환되는지 명확히 정리되어 있지 않음
- API 문서화 방식의 통일성 부족
- 일부 필수 파라미터나 데이터 타입이 누락
- 프론트엔드 개발자가 API를 활용할 때 어떤 값을 넣어야 하는지 명확하게 이해하기 어려운 구조
- 비개발자도 이해할 수 있도록 정리 필요
- 프로젝트에 참여하는 비개발자도 쉽게 API를 활용할 수 있도록 정리
결론
- API 호출 시 필요한 정보(요청 헤더, 바디, 예제 응답)를 명확하게 정리하여, 개발자들이 참고하기 쉽게 문서화
- 프로젝트의 완성도를 높이기 위해 명확한 API 문서 작성 필요
*Wireframe 수정
- 프론트엔드와 백엔드가 와이어프레임을 참고하여 작업해야 하는데, 현재 와이어프레임만 보고는 명확한 기능 흐름을 이해하기 어려움
- 에러 메시지가 발생하는 조건을 설명하지 않아서, 특정 상황에서 어떤 메시지가 표시되는지 불분명
- AI 요청이 실패했을 때 타임아웃을 어디까지 설정할지 결정
- 현재 와이어프레임이 애매하게 설계되어 있기 때문에, 백엔드 개발자가 각자 상상해서 기능을 구현해야 하는 상황이 발생할 수 있음
결론
- 화살표를 UI 흐름에 맞게 수정 후 버튼 클릭 시 이동 경로를 명확하게 표시
- 에러 메시지가 표시되는 조건을 설명하고 예제 추가
- 와이어프레임이 명확하게 작성되어 있어야 프론트엔드가 이를 참고하여 정확한 화면 구현 가능
*Cloud Architecture 수정
- 단일 EC2 서버에서 모든 것을 처리 -> 확장성 부족, 서버 부하 위험
- DB, 캐시, API 통신 흐름이 명확하지 않음 -> 서비스 규모가 커질수록 유지보수 어려워짐
- 프론트엔드와 백엔드의 독립성 부족 -> 전체 서비스 흐름을 파악하기 어려움
- 외부 API 연동이 어떻게 이루어지는지 명확하지 않음 -> 문서화가 부족하여 기능 추가 시 영향도를 예측하기 어려움
* 기능 확장 및 성능 최적화
- 채팅 기능 고도화
- 단일 채팅방 지원 -> 다중 채팅방 기능 추가 및 메시지 응답 속도 개선(Redis 활용)
- STOMP 핸들러 보안 강화(인증 방식 개선)
- 다중 채팅방을 지원하도록 데이터 구조 수정
- AI 추천 기능 개선
- GPT 호출 빈도를 줄이고, 캐싱을 활용한 성능 최적화
- 사용자 취향 데이터를 더욱 반영할 수 있도록 데이터 처리 방식 개선
- 취향 데이터 구조 개선
- 기존 하나의 취향테이블을 5개의 개별 테이블로 분리 후 각각의 연관 테이블을 생성하여 취향 데이터 저장
- 사용자 정보와 연결하여 사용자의 개별 취향을 체계적으로 저장하고 관리할 수 있도록 개선
- 정교한 필터링 가능, 개인화된 추천 품질 향상
- API 명세서 업데이트 필요
3. 최종 발표까지 피드백을 반영한 기능 개선 목표
- 설계 보완
- 기존 설계(백엔드 개발자 위주)에서 프론트엔드 및 UX/UI를 고려하여 수정
- API 명세서, ERD, 와이어프레임 업데이트
- 데이터 흐름 및 관계 명확히 정리
- 리팩토링 및 성능 최적화
- 기존 코드 최적화 및 Redis 캐싱 적용
- 단위테스트 추가 -> 코드 안정성 강화
- 채팅 기능 고도화
- 단일 채팅방 -> 다중 채팅방으로 확장
- STOMP 핸들러 보안 강화
- 메시지 응답 속도 개선
- AI 추천 기능 개선
- GPT 호출 빈도 최적화
- 프론트엔드 구현 & 기능확장
- React 기반 UX/UI 개선
- 지도 API를 Redis와 연동하여 검색 성능 개선
2~3주차 요약
- Git 협업을 할 때 PR 단위를 잘게 나누고 코드 리뷰를 꾸준히 하는 게 협업에 큰 도움이 됐다.
- 기능 개발 중 문제가 생겼을 때, 팀원들끼리 빠르게 소통하는 게 해결 속도를 높이는 좋은 방법이었다.
- 성능이나 보안을 생각하면서 코드를 짜는 게 중요했고, 리팩토링이나 캐싱 같은 최적화 작업도 필요하다는 걸 알게 됐다.
- 프론트엔드랑 데이터 구조나 API 설계를 미리 조율하면 개발이 훨씬 매끄러워진다는 걸 느꼈다.
- 그냥 기능만 만드는 게 아니라, 왜 이렇게 개발했는지, 어떤 문제를 해결했는지 정리해서 공유하는 게 더 중요한 과정이었다.
결론
2~3주차 동안 단순히 기능을 구현하는 것보다 팀원들과의 효율적인 협업과 유지보수하기 쉬운 코드를 작성하는 것이 더 중요하다는 것을 배웠다. Git 협업 방식과 코드 리뷰 문화를 정착시키는 과정에서 팀원 간 소통의 필요성을 다시 한번 실감했고, 개발자의 의도를 공유하고 의견을 조율하는 과정이 결국 코드 품질 향상으로 이어진다는 걸 경험했다. 또한, 예상치 못한 오류와 기술적 문제를 해결하면서 트러블슈팅 능력이 개발 과정에서 필수적인 역량이라는 점을 깨달았다. 특히, 성능 최적화와 보안 강화는 한 번 설정하고 끝나는 것이 아니라, 지속적으로 점검하고 개선해야 하는 요소라는 점을 직접 겪으며 배울 수 있었다.
기존과는 다른 방향으로 중간 발표를 준비하면서 프로젝트를 더 큰 그림에서 바라볼 수 있었고, 현재 구조에서 부족한 점과 앞으로 보완해야 할 부분을 구체적으로 정리할 수 있었다. 이 과정에서 단순한 기능 추가보다 설계를 더욱 탄탄하게 다듬는 것이 중요하다는 점을 실감했고, 기능을 확장하면서도 안정성을 유지하는 방향으로 개선해야 한다는 목표를 세우게 되었다.
남은 기간 동안 성능 최적화, AI 호출 비용 절감, 채팅 기능 확장, 그리고 기존 설계를 보완하는 작업을 집중적으로 진행할 예정이다. 또한, 이번 과정을 통해 협업과 트러블슈팅이 기능 구현만큼이나 중요하다는 것을 깨달았으며, 이를 적극적으로 적용해 더 나은 코드와 구조를 만들어가는 데 집중해야겠다는 목표를 가지게 되었다.
'TIL(Today I Learned) > 프로젝트' 카테고리의 다른 글
[TIL] 최종 프로젝트 : 9kcal. 오늘 뭐 먹지? (4~5 주차. 중간발표 이후 리팩토링 및 추가 개발 + 프론트) (1) | 2025.04.18 |
---|---|
[TIL] 최종 프로젝트 : 9kcal. 오늘 뭐 먹지? (1~2 주차. 프로젝트 시작 및 설계 과정) (0) | 2025.02.25 |
[TIL] Trello(칸반보드) 프로젝트 (0) | 2025.02.20 |
[TIL] 배달 앱 아웃소싱 프로젝트 (0) | 2024.12.19 |
[TIL] 고객과 통화 연관관계로 환전요청 만들기 (0) | 2024.12.02 |