Skip to content

Feature/#64 좋아요 토글 api 구현#69

Open
pykido wants to merge 7 commits intodevelopfrom
Feature/#64-좋아요_토글_API_구현

Hidden character warning

The head ref may contain hidden characters: "Feature/#64-\uc88b\uc544\uc694_\ud1a0\uae00_API_\uad6c\ud604"
Open

Feature/#64 좋아요 토글 api 구현#69
pykido wants to merge 7 commits intodevelopfrom
Feature/#64-좋아요_토글_API_구현

Conversation

@pykido
Copy link
Contributor

@pykido pykido commented Jan 31, 2026

🔥 연관된 이슈

close: #64

📜 작업 내용

  • 팀 좋아요 토글 API를 구현하였습니다.
  • 투표 토글 API 리뷰에서 받은피드백을 미리 반영하여 개발하였습니다.
  • 투표 토글 API와의 차이점은 좋아요 토글 API의 경우 투표 기간이 아닐 때만 가능하고, 개수 제한이 없다는 것입니다.

💬 리뷰 요구사항

  • 항상 좋은 리뷰 감사드립니다.

✨ 기타

  • 이제 정말 얼마 남지 않았군요! 화이팅입니다~!

@pykido pykido self-assigned this Jan 31, 2026
@pykido pykido added the ⭐️ 기능 구현 새로운 기능을 구현 label Jan 31, 2026
Copilot AI review requested due to automatic review settings January 31, 2026 15:13
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines +23 to +25
@Table(uniqueConstraints = {
@UniqueConstraint(name = "uk_team_like_member_team", columnNames = {"member_id", "team_id"})
})
Copy link

Copilot AI Jan 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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) 유니크 키를 반드시 반영해주세요.

Copilot uses AI. Check for mistakes.
Copy link
Collaborator

@JJimini JJimini left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생하셨습니다! 전체적으로 좋아요와 투표를 잘 분리하신 것 같아요~!
간단하게 제가 궁금한 부분 남겨두었습니다!

1. 좋아요 API의 위치

  • 현재 좋아요 API는 TeamController 내에 있지만, 서비스 코드는 TeamLikeCommandService에 있습니다
  • TeamController에 작성하신 이유는 좋아요 API는 독자적인 Entity를 가지지만 CURD 기능이 있지 않기 때문에 convention 상 TeamController에 작성하신 것으로 이해됩니다.
  • 하지만 TeamLikeCommandService단독 Service class를 가지고 있는 부분이 애매한 것 같습니다..
  • TeamVote 등 비슷한 API의 사례를 확인하고 동일한 규칙을 적용하면 추후 유지보수가 쉬울 것 같습니다!
  • 언제나 정해진 정답은 없으니 태윤님이 생각하신 알맞은 방법 소개하고 함께 공유하고 이야기해서 정해나가면 좋을 것 같습니다😊

2. schema.sqlunique 제약 추가 누락

  • 현재 entity 상에서는 unique 제약을 작성한 것으로 확인되는데, schema.sql에는 추가되지 않은 것 같습니다.
  • 운영 서버에는 schema.sql를 기준으로 테이블이 관리되기 때문에 작성하지 않으면 실제로 적용되지 않는 문제가 있어서 추가 부탁드립니다!

3. final 누락

  • 전체적으로 final이 누락된 것 같습니다! 확인 부탁드려요~!

Comment on lines +98 to +100

=== ⚠️ 실패 케이스

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ApiDocsTest를 보면 pathParametersrequestFields 등 잘 적어주셨는데 adoc에도 해두면 좋을 것 같아요!

Comment on lines +72 to +75
|true
|true
|이미 좋아요한 팀입니다.
|400 Bad Request
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

API의 이름이 좋아요 토글인데 이미 좋아요 한 팀에게 해당 API를 다시 요청할 경우 Bad Request가 뜨는 것이 조금 어색하게 느껴집니다.

만약 좋아요 한 팀에 재요청이 들어갔다면, 좋아요 취소 처리가 되는 것은 어떤가요??
같은 흐름으로 이미 좋아요를 취소한 팀경우도 같은 것 같습니다!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 이 부분을 생각해봤는데 현재 구현에서는isLiked=True 상태인 팀에 다시 isLiked=True를 하면 예외를 던지는게 맞는게 아닐까 생각합니다.

토글만 하려면 Body가 없는게 낫지 않을까요?

Comment on lines +64 to +75
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);
}
}
Copy link
Collaborator

@JJimini JJimini Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

투표와 비슷한 흐름으로 설계하신 것 같아요!

근데 제 생각에는 투표와 달리 반복해서 좋아요-좋아요 취소가 가능하고 (투표는 취소는 가능하나, 재투표는 불가) 한 transaction 내에서 flush가 발생하는 것도 예상하지 못한 side effect 발생 가능성 있다고 생각해서 DB hit를 강제할 필요는 없다고 생각하는데, 어떻게 생각하시나요??

Copy link
Contributor

@sjmoon00 sjmoon00 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

수고하셨습니다~
투표와 비슷하게 잘 구현하신것 같습니다

Comment on lines +72 to +75
|true
|true
|이미 좋아요한 팀입니다.
|400 Bad Request
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 이 부분을 생각해봤는데 현재 구현에서는isLiked=True 상태인 팀에 다시 isLiked=True를 하면 예외를 던지는게 맞는게 아닐까 생각합니다.

토글만 하려면 Body가 없는게 낫지 않을까요?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

⭐️ 기능 구현 새로운 기능을 구현

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] 좋아요 토글 API 구현

3 participants