Skip to content

✨ Feat: Match 도메인 조회 API 추가 (참가자 목록 / 구장 기반 매칭)#72

Merged
angoroa merged 3 commits intodevelopfrom
feat/match-api
Mar 11, 2026
Merged

✨ Feat: Match 도메인 조회 API 추가 (참가자 목록 / 구장 기반 매칭)#72
angoroa merged 3 commits intodevelopfrom
feat/match-api

Conversation

@angoroa
Copy link
Member

@angoroa angoroa commented Mar 9, 2026

#️⃣ Issue Number

📝 요약(Summary)

  • 매칭 참가자 목록 조회 API 추가
  • 특정 구장에서 열리는 매칭 목록 조회 API 추가

🛠️ PR 유형

어떤 변경 사항이 있나요?

  • 새로운 기능 추가
  • 버그 수정
  • CSS 등 사용자 UI 디자인 변경
  • 코드에 영향을 주지 않는 변경사항(오타 수정, 탭 사이즈 변경, 변수명 변경)
  • 코드 리팩토링
  • 주석 추가 및 수정
  • 문서 수정
  • 테스트 추가, 테스트 리팩토링
  • 빌드 부분 혹은 패키지 매니저 수정
  • 파일 혹은 폴더명 수정
  • 파일 혹은 폴더 삭제

📸스크린샷 (선택)

💬 공유사항 to 리뷰어

✅ PR Checklist

PR이 다음 요구 사항을 충족하는지 확인하세요.

  • 커밋 메시지 컨벤션에 맞게 작성했습니다.
  • 변경 사항에 대한 테스트를 했습니다.(버그 수정/기능에 대한 테스트).

Summary by CodeRabbit

릴리스 노트

  • New Features
    • 매치 참가자 조회 API 추가: 특정 매치의 참가자 목록을 조회할 수 있습니다.
    • 시설별 매치 조회 API 추가: 특정 시설에서 진행 예정인 매치 목록을 조회할 수 있습니다.

안훈기 added 3 commits March 9, 2026 17:37
GET /api/matches/{matchId}/participants
JOINED 상태 참가자만 반환 (N+1 방지 fetch join)
GET /api/matches?facilityId={facilityId}
OPEN/FULL 상태이며 시작 전인 매칭만 반환
@angoroa angoroa linked an issue Mar 9, 2026 that may be closed by this pull request
4 tasks
@coderabbitai
Copy link

coderabbitai bot commented Mar 9, 2026

Walkthrough

매칭 도메인에 두 가지 새로운 API 엔드포인트를 추가했습니다: 특정 매치의 참가자 목록을 조회하는 엔드포인트와 시설별 진행 예정인 매칭 목록을 조회하는 엔드포인트입니다. 이를 위해 컨트롤러, 서비스, 리포지토리 계층에 대응하는 메서드들을 추가했습니다.

Changes

Cohort / File(s) Summary
Build Configuration
.gitignore
Makefile을 gitignore 목록에 추가했습니다.
Controller Layer
src/main/java/com/be/sportizebe/domain/match/controller/MatchController.java
GET /api/matches/{matchId}/participants와 GET /api/matches?facilityId=... 두 개의 새로운 엔드포인트를 추가했습니다.
Service Layer
src/main/java/com/be/sportizebe/domain/match/service/MatchService.java, src/main/java/com/be/sportizebe/domain/match/service/MatchServiceImpl.java
두 엔드포인트에 대응하는 getMatchParticipants()getMatchesByFacility() 메서드를 추가했습니다. 후자는 OPEN 또는 FULL 상태의 미래 매칭만 필터링합니다.
Repository Layer
src/main/java/com/be/sportizebe/domain/match/repository/MatchParticipantRepository.java, src/main/java/com/be/sportizebe/domain/match/repository/MatchRoomRepository.java
매치 ID와 상태로 참가자를 조회하는 findAllByMatchRoomIdAndStatusFetch() 메서드와 시설 ID, 상태, 스케줄 시간으로 매칭을 조회하는 findByFacilityIdAndStatusInAndScheduledAtAfterOrderByScheduledAtAsc() 메서드를 추가했습니다.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • Feat/match #58: 동일한 매칭 도메인(MatchController, MatchParticipantRepository, MatchRoomRepository)을 수정하고 같은 엔티티에 대한 리포지토리/컨트롤러 메서드를 추가하므로 관련이 있습니다.
  • ♻️Refactor: MatchDetailResponse 응답 구조 개선 #68: MatchServiceImpl을 수정하여 매칭 관련 응답이 어떻게 구성되고 조회되는지 변경하므로 관련이 있습니다.

Poem

🐰 두 개의 새 길을 뚫었네,
참가자 목록과 구장별 매칭,
리포지토리는 깊이 파고,
서비스는 데이터 담고,
컨트롤러는 응답 날려보내네! ⚽✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning .gitignore 수정(Makefile 항목 추가)은 부수적 변경이며, 핵심 API 구현과 무관한 범위 외 변경입니다. .gitignore 변경을 별도의 PR로 분리하거나, PR 설명에서 정당성을 명시하세요.
Docstring Coverage ⚠️ Warning Docstring coverage is 43.75% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목은 두 개의 새로운 API 추가를 명확하게 설명하며, 변경 사항의 핵심 내용을 정확하게 반영합니다.
Linked Issues check ✅ Passed PR은 링크된 이슈 #71의 두 가지 요구사항을 충족합니다: 매칭 참가자 목록 조회 API와 구장 기반 매칭 목록 조회 API 구현.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/match-api

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@src/main/java/com/be/sportizebe/domain/match/repository/MatchParticipantRepository.java`:
- Around line 35-37: The query in
MatchParticipantRepository.findAllByMatchRoomIdAndStatusFetch lacks an ORDER BY
so result order can vary; update the JPQL to include a deterministic ordering
(e.g., append "ORDER BY mp.createdAt ASC" or "ORDER BY mp.id ASC" depending on
which field represents join order) so participants are consistently returned in
the intended sequence when selecting MatchParticipant JOIN FETCH mp.user WHERE
mp.matchRoom.id = :matchId AND mp.status = :status.

In `@src/main/java/com/be/sportizebe/domain/match/service/MatchServiceImpl.java`:
- Around line 186-189: The current query in MatchServiceImpl uses
findByFacilityIdAndStatusInAndScheduledAtAfterOrderByScheduledAtAsc with
List.of(MatchStatus.OPEN, MatchStatus.FULL) which returns both OPEN and FULL
matches; update it to only include MatchStatus.OPEN so the API returns only OPEN
matches as per issue `#71` (i.e., change the status list passed to the repository
call to contain only MatchStatus.OPEN).
- Around line 184-193: The current getMatchesByFacility method hides a
non-existent facility by returning an empty list; before querying
matchRoomRepository, verify the facility exists via sportsFacilityRepository
(e.g., existsById or findById) and if not present throw the existing not-found
error using FacilityErrorCode.FACILITY_NOT_FOUND (or the project's
NotFoundException wrapper), then proceed to call
matchRoomRepository.findByFacilityIdAndStatusInAndScheduledAtAfterOrderByScheduledAtAsc
and map to MatchResponse::from; update getMatchesByFacility to perform this
existence check using sportsFacilityRepository and throw the proper error when
missing.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 1551c842-f050-41f9-b800-5b129a557b10

📥 Commits

Reviewing files that changed from the base of the PR and between 1f527ad and 8097b9f.

📒 Files selected for processing (6)
  • .gitignore
  • src/main/java/com/be/sportizebe/domain/match/controller/MatchController.java
  • src/main/java/com/be/sportizebe/domain/match/repository/MatchParticipantRepository.java
  • src/main/java/com/be/sportizebe/domain/match/repository/MatchRoomRepository.java
  • src/main/java/com/be/sportizebe/domain/match/service/MatchService.java
  • src/main/java/com/be/sportizebe/domain/match/service/MatchServiceImpl.java

Comment on lines +35 to +37
// 매칭 참가자 목록 (N+1 방지 fetch join)
@Query("SELECT mp FROM MatchParticipant mp JOIN FETCH mp.user WHERE mp.matchRoom.id = :matchId AND mp.status = :status")
List<MatchParticipant> findAllByMatchRoomIdAndStatusFetch(@Param("matchId") Long matchId, @Param("status") MatchParticipantStatus status);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

참가자 목록 정렬 기준을 쿼리에 고정해 주세요.

현재 쿼리는 ORDER BY가 없어 응답 순서가 DB 실행 계획에 따라 바뀔 수 있습니다. 사용자 목록을 그대로 노출하는 API라면 가입 순서 등 의도한 기준을 명시하는 편이 안전합니다.

정렬 기준을 명시하는 예시
-    `@Query`("SELECT mp FROM MatchParticipant mp JOIN FETCH mp.user WHERE mp.matchRoom.id = :matchId AND mp.status = :status")
+    `@Query`("SELECT mp FROM MatchParticipant mp JOIN FETCH mp.user WHERE mp.matchRoom.id = :matchId AND mp.status = :status ORDER BY mp.joinedAt ASC")
     List<MatchParticipant> findAllByMatchRoomIdAndStatusFetch(`@Param`("matchId") Long matchId, `@Param`("status") MatchParticipantStatus status);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/java/com/be/sportizebe/domain/match/repository/MatchParticipantRepository.java`
around lines 35 - 37, The query in
MatchParticipantRepository.findAllByMatchRoomIdAndStatusFetch lacks an ORDER BY
so result order can vary; update the JPQL to include a deterministic ordering
(e.g., append "ORDER BY mp.createdAt ASC" or "ORDER BY mp.id ASC" depending on
which field represents join order) so participants are consistently returned in
the intended sequence when selecting MatchParticipant JOIN FETCH mp.user WHERE
mp.matchRoom.id = :matchId AND mp.status = :status.

Comment on lines +184 to +193
public List<MatchResponse> getMatchesByFacility(Long facilityId) {
return matchRoomRepository
.findByFacilityIdAndStatusInAndScheduledAtAfterOrderByScheduledAtAsc(
facilityId,
List.of(MatchStatus.OPEN, MatchStatus.FULL),
LocalDateTime.now()
)
.stream()
.map(MatchResponse::from)
.toList();
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

존재하지 않는 facilityId를 빈 목록으로 숨기지 마세요.

지금 구현은 잘못된 facilityId와 "해당 구장에 예정된 매치가 없음"을 동일하게 빈 리스트로 반환합니다. 이미 sportsFacilityRepositoryFacilityErrorCode.FACILITY_NOT_FOUND가 있으니, 조회 전에 구장 존재 여부를 검증해서 404로 구분하는 편이 API 계약상 안전합니다.

구장 존재 여부를 먼저 검증하는 예시
     `@Override`
     `@Transactional`(readOnly = true)
     public List<MatchResponse> getMatchesByFacility(Long facilityId) {
+        if (!sportsFacilityRepository.existsById(facilityId)) {
+            throw new CustomException(FacilityErrorCode.FACILITY_NOT_FOUND);
+        }
+
         return matchRoomRepository
                 .findByFacilityIdAndStatusInAndScheduledAtAfterOrderByScheduledAtAsc(
                         facilityId,
                         List.of(MatchStatus.OPEN, MatchStatus.FULL),
                         LocalDateTime.now()
                 )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/com/be/sportizebe/domain/match/service/MatchServiceImpl.java`
around lines 184 - 193, The current getMatchesByFacility method hides a
non-existent facility by returning an empty list; before querying
matchRoomRepository, verify the facility exists via sportsFacilityRepository
(e.g., existsById or findById) and if not present throw the existing not-found
error using FacilityErrorCode.FACILITY_NOT_FOUND (or the project's
NotFoundException wrapper), then proceed to call
matchRoomRepository.findByFacilityIdAndStatusInAndScheduledAtAfterOrderByScheduledAtAsc
and map to MatchResponse::from; update getMatchesByFacility to perform this
existence check using sportsFacilityRepository and throw the proper error when
missing.

Comment on lines +186 to +189
.findByFacilityIdAndStatusInAndScheduledAtAfterOrderByScheduledAtAsc(
facilityId,
List.of(MatchStatus.OPEN, MatchStatus.FULL),
LocalDateTime.now()
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

구장 조회 API가 요구사항보다 넓은 상태를 반환합니다.

linked issue #71은 특정 구장의 OPEN 매치 목록 조회를 목표로 하고 있는데, Line 186-189는 FULL도 함께 포함합니다. 요구사항 변경이 아니라면 여기서는 OPEN만 조회해야 합니다.

요구사항에 맞추는 예시
         return matchRoomRepository
                 .findByFacilityIdAndStatusInAndScheduledAtAfterOrderByScheduledAtAsc(
                         facilityId,
-                        List.of(MatchStatus.OPEN, MatchStatus.FULL),
+                        List.of(MatchStatus.OPEN),
                         LocalDateTime.now()
                 )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
.findByFacilityIdAndStatusInAndScheduledAtAfterOrderByScheduledAtAsc(
facilityId,
List.of(MatchStatus.OPEN, MatchStatus.FULL),
LocalDateTime.now()
.findByFacilityIdAndStatusInAndScheduledAtAfterOrderByScheduledAtAsc(
facilityId,
List.of(MatchStatus.OPEN),
LocalDateTime.now()
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/com/be/sportizebe/domain/match/service/MatchServiceImpl.java`
around lines 186 - 189, The current query in MatchServiceImpl uses
findByFacilityIdAndStatusInAndScheduledAtAfterOrderByScheduledAtAsc with
List.of(MatchStatus.OPEN, MatchStatus.FULL) which returns both OPEN and FULL
matches; update it to only include MatchStatus.OPEN so the API returns only OPEN
matches as per issue `#71` (i.e., change the status list passed to the repository
call to contain only MatchStatus.OPEN).

@angoroa angoroa merged commit 7269d94 into develop Mar 11, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

✨Feat: Match API 추가 (참가자 목록 조회 / 구장 기반 매칭 목록)

1 participant