Feature/#64 좋아요 토글 api 구현#69
Conversation
There was a problem hiding this comment.
Pull request overview
팀 좋아요(찜) 토글 API를 추가하고, 투표 기간에는 좋아요가 불가능하도록 제약을 적용한 PR입니다. 관련 RestDocs/통합 테스트도 함께 추가되었습니다.
Changes:
- TeamLike 도메인/예외/레포지토리 및 좋아요 토글 서비스 로직 추가
PUT /teams/{teamId}/likes엔드포인트 및 요청/응답 DTO 추가- RestDocs 문서/테스트 및 “투표 기간 중 불가” 예외 타입 정리(공용 convenience로 이동)
Reviewed changes
Copilot reviewed 20 out of 20 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/main/java/com/opus/opus/modules/team/application/TeamLikeCommandService.java | 좋아요 토글 핵심 비즈니스 로직(투표기간 검증 포함) 추가 |
| src/main/java/com/opus/opus/modules/team/api/TeamController.java | 팀 좋아요 토글 API 엔드포인트 추가 |
| src/main/java/com/opus/opus/modules/team/domain/TeamLike.java | TeamLike 엔티티 및 유니크 제약(회원+팀) 추가 |
| src/main/java/com/opus/opus/modules/team/domain/dao/TeamLikeRepository.java | TeamLike 조회용 JPA 레포지토리 추가 |
| src/main/java/com/opus/opus/modules/team/exception/TeamLikeExceptionType.java | 좋아요 도메인 예외 타입 정의 추가 |
| src/main/java/com/opus/opus/modules/team/exception/TeamLikeException.java | 좋아요 도메인 예외 클래스 추가 |
| src/main/java/com/opus/opus/modules/team/application/dto/request/TeamLikeToggleRequest.java | 좋아요 토글 요청 DTO 추가 |
| src/main/java/com/opus/opus/modules/team/application/dto/response/TeamLikeToggleResponse.java | 좋아요 토글 응답 DTO 추가 |
| src/main/java/com/opus/opus/modules/contest/application/convenience/ContestConvenience.java | “투표 기간 중 작업 불가” 공용 검증 로직 추가 |
| src/main/java/com/opus/opus/modules/contest/application/ContestCommandService.java | 투표기간 검증을 convenience로 위임하도록 리팩터링 |
| src/main/java/com/opus/opus/modules/contest/exception/ContestExceptionType.java | 투표기간 작업 불가 예외 타입 명/메시지 정리 |
| src/test/java/com/opus/opus/team/application/TeamLikeCommandServiceTest.java | 좋아요 토글 서비스 통합 테스트 추가 |
| src/test/java/com/opus/opus/team/TeamLikeFixture.java | TeamLike 테스트 픽스처 추가 |
| src/test/java/com/opus/opus/team/TeamFixture.java | contestId 주입 가능한 팀 픽스처로 확장 |
| src/test/java/com/opus/opus/restdocs/docs/TeamLikeApiDocsTest.java | 팀 좋아요 토글 API RestDocs 테스트 추가 |
| src/test/java/com/opus/opus/restdocs/docs/ContestApiDocsTest.java | 투표기간 작업 불가 예외 타입 변경 반영 |
| src/test/java/com/opus/opus/restdocs/RestDocsTest.java | RestDocs 테스트 컨텍스트에 TeamLikeCommandService mock 추가 |
| src/test/java/com/opus/opus/contest/application/ContestCommandServiceTest.java | 투표기간 작업 불가 예외 타입 변경 반영 |
| src/main/java/com/opus/opus/docs/asciidoc/team-like.adoc | 팀 좋아요 API 문서 신규 추가 |
| src/main/java/com/opus/opus/docs/asciidoc/opus.adoc | API 목록에 팀 좋아요 문서 링크 추가 |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
JJimini
left a comment
There was a problem hiding this comment.
고생하셨습니다! 전체적으로 좋아요와 투표를 잘 분리하신 것 같아요~!
간단하게 제가 궁금한 부분 남겨두었습니다!
1. 좋아요 API의 위치
- 현재 좋아요 API는
TeamController내에 있지만, 서비스 코드는TeamLikeCommandService에 있습니다 TeamController에 작성하신 이유는 좋아요 API는 독자적인 Entity를 가지지만 CURD 기능이 있지 않기 때문에 convention 상TeamController에 작성하신 것으로 이해됩니다.- 하지만
TeamLikeCommandService는 단독 Service class를 가지고 있는 부분이 애매한 것 같습니다.. TeamVote등 비슷한 API의 사례를 확인하고 동일한 규칙을 적용하면 추후 유지보수가 쉬울 것 같습니다!- 언제나 정해진 정답은 없으니 태윤님이 생각하신 알맞은 방법 소개하고 함께 공유하고 이야기해서 정해나가면 좋을 것 같습니다😊
2. schema.sql의 unique 제약 추가 누락
- 현재 entity 상에서는 unique 제약을 작성한 것으로 확인되는데,
schema.sql에는 추가되지 않은 것 같습니다. - 운영 서버에는
schema.sql를 기준으로 테이블이 관리되기 때문에 작성하지 않으면 실제로 적용되지 않는 문제가 있어서 추가 부탁드립니다!
3. final 누락
- 전체적으로 final이 누락된 것 같습니다! 확인 부탁드려요~!
| |true | ||
| |true | ||
| |이미 좋아요한 팀입니다. | ||
| |400 Bad Request |
There was a problem hiding this comment.
API의 이름이 좋아요 토글인데 이미 좋아요 한 팀에게 해당 API를 다시 요청할 경우 Bad Request가 뜨는 것이 조금 어색하게 느껴집니다.
만약 좋아요 한 팀에 재요청이 들어갔다면, 좋아요 취소 처리가 되는 것은 어떤가요??
같은 흐름으로 이미 좋아요를 취소한 팀경우도 같은 것 같습니다!
There was a problem hiding this comment.
저도 이 부분을 생각해봤는데 현재 구현에서는isLiked=True 상태인 팀에 다시 isLiked=True를 하면 예외를 던지는게 맞는게 아닐까 생각합니다.
토글만 하려면 Body가 없는게 낫지 않을까요?
There was a problem hiding this comment.
@JJimini @sjmoon00
두 분 모두 좋은 의견 감사드립니다!
지금 다시 생각해보니, 투표 API와 좋아요 API 모두 '토글'이라는 네이밍이 잘못되었다는 생각이 드네요. 제가 의도한 것은 프론트엔드가 isLiked, isVoted 값을 통해 원하는 최종 상태를 명시적으로 지정하고, 백엔드는 그 상태로 변경 가능한지 검증하는 구조였습니다. 이를 통해 '이미 좋아요한 팀입니다'와 같은 명확한 에러 핸들링이 가능하고, 프론트와 백엔드 간 상태 불일치도 조기에 감지할 수 있어 안정성을 확보하고자 했어요. 하지만 이는 '토글'이 아니라 '상태 변경'에 가까운 방식인 거 같아요!
그래서 단기적으로는 API 명을 '팀 좋아요 상태 변경', '팀 투표 상태 변경'으로 수정하면 어떨까 싶습니다. 이렇게 하면 현재 로직을 유지하면서도 API의 실제 동작과 네이밍이 일치하게 될 것 같아요. 다만, 실제 주요 기업들(GitHub, Twitter, Instagram 등)의 구현 사례를 찾아보니 POST/DELETE로 분리하고 멱등성을 보장하는 형태가 업계 표준이더라고요. 추후 이 방식으로 리팩토링하는 것도 고려해보면 좋을 것 같습니다!
우선 이번 PR에서는 네이밍만 수정하고, 추후에 리팩토링하는 건 어떨까요?
There was a problem hiding this comment.
좋습니다! 사실 저도 POST/DELETE로 분리하는 게 더 깔끔하다고 생각했어요. 근데 이미 토글로 구현해두셔서 전면 수정해야 하는 작업이라 comment를 남기지는 않았지만요ㅎㅎ
그런데 수정하실 예정이라면 프론트에서도 작업이 바뀔텐데, 지금 이 pr을 머지시키고 리팩토링하면 이중 작업이 되지 않을까 생각도 듭니다.. 원래 코드를 지우고 해야하니까요.. 태윤님이 PR Merge 일정까지 고려해서 저희 전체 회의 전까지 완성할 수 있으시면 지금 머지 후 리팩토링 방식, 아니면 PR Close 하고 새로 설계하는 방식으로 하시면 시간 절약이 될 것 같아요!
추가로 comment를 읽으면서 멱등성에 대해 궁금한 부분이 생겼는데, POST는 멱등성을 보장하지 않는다고 알고 있는데 멱등성을 보장하는 형태가 어떤 식으로 구현이 되었는지 궁금하네요..! 혹시 관련 reference 나중에 ICE BREAKING 때 소개해주셔도 좋을 것 같아요!ㅎㅎ
There was a problem hiding this comment.
@JJimini
좋은 의견 감사합니다!
말씀해주신 것처럼 지금 머지 후 이슈를 파서 리팩토링하는게 좋을 거 같아요! 리팩토링은 프론트분과 협의 후에 이슈를 파서 진행하겠습니다.
또한 POST 자체로는 비멱등적이지만, 로직으로 멱등성을 보통 구현한다더군요! 이와 관련해서는 아이스 브레이킹 때 다뤄보겠습니다!
src/main/java/com/opus/opus/modules/team/application/TeamLikeCommandService.java
Outdated
Show resolved
Hide resolved
sjmoon00
left a comment
There was a problem hiding this comment.
수고하셨습니다~
투표와 비슷하게 잘 구현하신것 같습니다
| |true | ||
| |true | ||
| |이미 좋아요한 팀입니다. | ||
| |400 Bad Request |
There was a problem hiding this comment.
저도 이 부분을 생각해봤는데 현재 구현에서는isLiked=True 상태인 팀에 다시 isLiked=True를 하면 예외를 던지는게 맞는게 아닐까 생각합니다.
토글만 하려면 Body가 없는게 낫지 않을까요?
|
@JJimini 이에 대해 제가 현재 구조로 결정한 이유를 공유해드립니다!
따라서 이번 좋아요, 투표 기능처럼 CRUD를 포함하지 않는 작은 기능은 큰 도메인의 Controller에 속하되, 서비스 로직은 분리하는 것으로 통일하는 것이 어떨까요~? |
태윤님의 의견 잘 읽었습니다! 그런데 추후 다른 사람들이 이 코드를 유지보수하기 위해 확인했을 때, Controller와 Service가 매치되지 않거나 Service 내에서도 Query와 Command가 맞지 않으면 헷갈릴 수도 있을 것 같아요 또한 코드의 길이에 차이가 있을 뿐 따라서 제 의견은 아래와 같습니다!
|
🔥 연관된 이슈
close: #64
📜 작업 내용
💬 리뷰 요구사항
✨ 기타