1. 프로젝트 개요
이 프로젝트는 '모두의 플리'라는 제목을 가지고 좀 더 자세히 설명하자면 '대규모 트래픽이 예상되는 글로벌 컨텐츠 평점 및 큐레이션 플랫폼'이다. 이 서비스는 영화, 드라마, 스포츠 등 다양한 콘텐츠를 큐레이팅하고 공유하며, 실시간 같이 보기 기능까지 제공하는 소셜 서비스로, 사용자들은 자신만의 플레이리스트를 만들고 다른 사용자와 소통하며 콘텐츠 경험을 확장할 수 있다.
주요 기능 :
- 콘텐츠 데이터 관리 (외부 API를 수집, 배치로 자동 업데이트)
- 콘텐츠 평가 및 큐레이팅 (리뷰, 플레이리스트 생성, 플레이리스트 구독)
- 실시간 같이 보기 (웹소켓 기반 실시간 채팅 및 시청 정보 공유)
- 알림 (SSE기반 실시간으로 사용자에게알림 전송)
- 사용자 관리 (회원가입, 로그인, 소셜 계정 연동, 어드민 기능)
- 프로필 관리 (사용자의 프로필 정보 확인, 팔로우, 웹소켓과 SSE 기반 DM 전송)
2. 담당한 작업
플레이리스트 기능 구현
- 플레이리스트 생성
- 플레이리스트 목록 조회(생성된 플레이리스트들 조회, 커서 페이지네이션)
- 플레이리스트 단건 조회(플레이리스트 내에 존재하는 컨텐츠)
- 플레이리스트 수정(플레이리스트 제목과 설명 수정)
- 플레이리스트에 콘텐츠 추가/삭제
- 플레이리스트 구독/구독 취소(본인의 플레이리스트가 아닌 타인의 플레이리스트 구독/구독 취소)
- 플레이리스트 삭제
리뷰 기능 구현
- 리뷰 생성(별점과 평가를 입력하여 생성)
- 리뷰 목록 조회(작성된 별점과 평가를 커서 페이지네이션으로 조회)
- 리뷰 수정(별점, 평가를 수정)
- 리뷰 삭제
알림 기능 구현
- 알림 목록 조회(구현된 SSE를 사용하여 아래의 경우에 알림이 생성 및 조회 되도록 구현)
- 권한 변경
- 내 플레이리스트를 구독
- 구독 중인 플레이리스트에 콘텐츠가 추가됨
- 팔로우한 사용자의 주요 활동
- 다른 사용자가 나를 팔로우
- DM 수신
- 알림 읽음 처리(읽은 알림은 삭제되도록 구현)
3. 기술적 성과
- Bean Validation을 도입하여 입력 데이터 유효성 검사를 표준화하고, 컨트롤러 단의 수동 검증 로직을 제거하여 코드 가독성과 유지보수성을 향상시켰다.
- Spring Batch를 활용해 플레이리스트 삭제 데이터를 주기적으로 완전 삭제하는 배치 프로세스를 구축하여 소프트 삭제 데이터 누적으로 인한 DB 관리 부담을 감소하고 데이터 정합성을 개선시켰다.
- CodeRabbit을 도입하여 코드 리뷰 시 누락되기 쉬운 스타일·잠재적 이슈를 자동 검출하고, 리뷰 소요 시간을 단축하여 코드 리뷰 품질과 개발 생산성을 향상시켰다.
- MDC를 활용해 요청 단위로 ID·IP를 로깅하고 이를 응답 헤더에 반영해 장애 발생 시 로그 추적성과 원인 분석 효율을 향상시켰다.
4. 문제점 및 해결 과정
알림 발생 시 시간 변환 문제
문제 상황
- 알림을 저장한 뒤 조회할 때, 알림 내용과 함께 조회된 알림 생성 시간이 실제 저장된 시간과 항상 9시간 차이가 생겨 9시간 전으로 표시가 되었다.
이유
- Entity의 시간 타입을 LocalDateTime으로 설정해놓았는데 LocalDateTime은 타임존이 없는 서버의 로컬 시간이기 때문에 DB에 저장될 때 시간은 UTC 기준 로컬 시간으로 저장되었고 프론트에서 저장된 시간을 그대로 KST로 인식하여 문제가 생겼다.
해결 방법
spring:
jackson:
time-zone: Asia/Seoul
- application.yml에 위와 같은 설정을 넣어 응답 시에 타임존을 KST로 자동 변환하도록 설정하였다.
- Entity의 LocalDateTime을 Instant로 변경하여 DB에 저장될 때 타임존이 UTC로 저장되도록 하였으며 LocalDatTime을 사용하는 다른 클래스들에서도 Instant를 사용하도록 변경하였다.
- 자세한 내용은 여기에서 → https://beginner-development.tistory.com/44
느낀점
LocalDateTime은 편리하지만 시간 기준이 명확하지 않아 오해를 낳기 쉽고 환경에 따라 달라질 수 있으며 시간 문제는 로직의 문제가 아니라 기준과 표현을 어떻게 분리했는지에 대한 설계 문제라는 걸 배웠습니다. 또한 이번 문제를 해결하면서 “어디까지가 내부 시간이고, 어디서부터가 사용자에게 보여지는 시간인가”를 레이어별로 명확히 나누는 게 가장 중요하다는 걸 배웠습니다. 앞으로는 시간 관련 이슈가 생기면 '이 시간은 어떤 기준의 시간인지'를 먼저 생각하고 개발하게 될 것 같습니다.
5. 협업 및 피드백
- 느낀점
- 고급 프로젝트를 진행하면서 팀원들과의 소통이 이전 초/중급 프로젝트 때보다 훨씬 더 자연스러워졌다는 것을 가장 크게 느꼈습니다. 노션과 디스코드를 적극적으로 활용하여 서로 필요한 문서를 공유하고 진행 상황과 일정, 논의사항들을 공유하다보니 서로의 작업에 대해 명확하게 파악할 수 있었고, 이러한 방식이 프로젝트가 안정적으로 진행되는 것에 도움이 되었다고 생각합니다. 이로 인해 협업에는 작은 일이더라도 개발에 관련된 일이라면 서로 공유해야 개발이 편해진다는 것을 느꼈습니다.
- 배운점
- 이번 프로젝트에서 개발을 진행하다가 다른 팀원이 개발 중인 도메인의 mapper나 repository에 코드를 추가해야하는 일이 있었습니다. 해당 사실을 팀원 전체에게 알리지 않고 도메인 담당 팀원에게만 알려서 담당 팀원이 PR을 올릴 때 같이 올리도록 했었는데, 이로인해 PR이 꼬일 뻔한 적이 있었습니다. 이를 통해서 제가 담당하는 도메인이 아니더라도 필요한 코드가 있으면 담당자에게 알려서 해당 담당자가 추가하는게 아니라, 제가 직접 추가해서 PR을 날린 후 팀원 전체에게 해당 사실을 공유하고 PR에서 conflict를 해결하면 된다는 사실을 배웠습니다.
- 피드백
- 개발이 진행되면서 ERD나 클래스 파일들이 수정되거나 다른 도메인의 기능이 필요한 일들이 생각보다 자주 발생했고, 이런 사항들을 바로 공유하지 않으면 팀 전체가 혼란을 겪을 수 있다는 것을 알게 되었습니다. 이후에 또 다른 프로젝트를 진행할 때도 개발 도중 이러한 변경사항이나 필요사항이 생길 수 있기 때문에 다른 사람에게 맡기는게 아니라 본인이 직접 코드를 짜면서, 그에 따라 발생한 사소한 내용이라도 문서화하고 공유하면서 협업에 대한 효율을 높이고자 합니다.
6. 코드 품질 및 최적화
이번 프로젝트에선 유지보수성과 운영 안정성을 고려한 코드 품질 개선에 중점을 두었다. 이를 위해 각 계층이 명확한 책임을 가지도록 구조를 분리하여, 비즈니스 로직과 인프라 로직이 혼재되지 않도록 설계하였다.
이와 함께 코드 전반에 일관된 구조와 작성 규칙을 적용하여 가독성을 높였으며, 도메인 기반 커스텀 예외를 도입해 예외 상황을 보다 명확하게 구분할 수 있도록 개선하였다.
또한 운영 환경에서의 디버깅과 장애 대응을 고려하여 MDC 기반 로깅을 적용하였다. 요청 ID와 사용자 정보를 함께 기록함으로써, 요청 단위의 흐름을 추적하고 문제 원인을 보다 효율적으로 파악할 수 있도록 하였다.
마지막으로 데이터 관리 측면에서는 소프트 딜리트 전략과 배치 작업을 도입하여, 불필요한 데이터를 주기적으로 정리함으로써 서비스 안정성과 관리 효율성을 함께 향상시켰다.
7. 향후 개선 사항 및 제안
향후에는 기능 구현에 앞서 테스트 코드를 먼저 작성하고, 해당 테스트를 만족하도록 도메인 코드를 구현하는 TDD(Test-Driven Development) 방식의 개발을 도입하고자 한다. 이를 통해 요구사항을 보다 명확하게 정의하고, 핵심 비즈니스 로직을 테스트 가능한 구조로 설계할 수 있을 것으로 기대한다. 또한 테스트를 기반으로 한 개발 방식은 코드 변경 시 발생할 수 있는 사이드 이펙트를 조기에 검증할 수 있어, 리팩토링에 대한 부담을 줄이고 전반적인 코드 안정성과 품질을 더욱 향상시키는 데 기여할 것으로 판단된다.
'코드잇 BE스프린트' 카테고리의 다른 글
| 위클리 페이퍼 - 3주차 (1) | 2026.03.17 |
|---|---|
| 위클리 페이퍼 - 2주차 (0) | 2026.03.17 |
| 위클리 페이퍼 - 1주차 (1) | 2026.03.16 |
| 알림 조회 시 겪은 타임존 변환 문제와 해결과정 (0) | 2025.12.15 |
| 코드잇 스프린트 초급 프로젝트(FINDEX) 개발 회고록 (2) | 2025.08.06 |