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.
| @Table(uniqueConstraints = { | ||
| @UniqueConstraint(name = "uk_team_like_member_team", columnNames = {"member_id", "team_id"}) | ||
| }) |
There was a problem hiding this comment.
@Table에 (member_id, team_id) 유니크 제약을 추가했지만, 이 프로젝트는 spring.jpa.hibernate.ddl-auto: none + schema.sql로 스키마를 관리하고 있어서 실제 DB에 유니크 키가 없으면 중복 row가 생성될 수 있습니다. 중복이 생기면 findByMemberIdAndTeam(...)가 다건 매칭으로 예외를 던지거나(IncorrectResultSize) 좋아요 토글 로직이 깨질 수 있으니, schema.sql(또는 사용하는 마이그레이션 방식)에 uk_team_like_member_team (member_id, team_id) 유니크 키를 반드시 반영해주세요.
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이 누락된 것 같습니다! 확인 부탁드려요~!
|
|
||
| === ⚠️ 실패 케이스 | ||
|
|
There was a problem hiding this comment.
ApiDocsTest를 보면 pathParameters나 requestFields 등 잘 적어주셨는데 adoc에도 해두면 좋을 것 같아요!
| |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가 없는게 낫지 않을까요?
| private void saveTeamLike(Long memberId, Team team, Boolean isLiked) { | ||
| try { | ||
| teamLikeRepository.save(TeamLike.builder() | ||
| .memberId(memberId) | ||
| .team(team) | ||
| .isLiked(isLiked) | ||
| .build()); | ||
| teamLikeRepository.flush(); | ||
| } catch (DataIntegrityViolationException e) { | ||
| throw new TeamLikeException(DUPLICATE_LIKE_REQUEST); | ||
| } | ||
| } |
There was a problem hiding this comment.
투표와 비슷한 흐름으로 설계하신 것 같아요!
근데 제 생각에는 투표와 달리 반복해서 좋아요-좋아요 취소가 가능하고 (투표는 취소는 가능하나, 재투표는 불가) 한 transaction 내에서 flush가 발생하는 것도 예상하지 못한 side effect 발생 가능성 있다고 생각해서 DB hit를 강제할 필요는 없다고 생각하는데, 어떻게 생각하시나요??
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가 없는게 낫지 않을까요?
🔥 연관된 이슈
close: #64
📜 작업 내용
💬 리뷰 요구사항
✨ 기타