Conversation
|
Caution Review failedThe pull request is closed. ℹ️ Recent review infoConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro 📒 Files selected for processing (1)
📝 WalkthroughWalkthrough관리자가 접근 가능한 승인된 회원 가입 신청들의 개별 질문+답변 목록을 페이징으로 조회하는 새 API와 이에 필요한 DTO, 서비스 헬퍼, 및 레파지토리 쿼리들이 추가·리팩터링되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant Controller as ClubApplicationController
participant Service as ClubApplicationService
participant QueryRepo as ClubApplyQueryRepository
participant AnswerRepo as ClubApplyAnswerRepository
participant QuestionRepo as ClubApplyQuestionRepository
participant DB as Database
Client->>Controller: GET /{clubId}/member-applications/answers?page&limit&sort...
Controller->>Service: getApprovedMemberApplicationAnswersList(clubId, requesterId, condition)
Service->>Service: 관리자 권한 검증
Service->>QueryRepo: findApprovedMemberApplicationsByClubId(clubId, condition)
QueryRepo->>DB: 쿼리: 승인된 ClubApply 목록(유저 fetch join)
DB-->>QueryRepo: List<ClubApply>
QueryRepo-->>Service: 승인된 신청 목록
Service->>AnswerRepo: findAllByApplyIdsWithQuestion(applyIds)
AnswerRepo->>DB: 쿼리: ClubApplyAnswer + question fetch
DB-->>AnswerRepo: List<ClubApplyAnswer>
AnswerRepo-->>Service: 답변들
Service->>QuestionRepo: findAllCandidatesVisibleBetweenApplyTimes(clubId, minAppliedAt, maxAppliedAt)
QuestionRepo->>DB: 쿼리: 시간범위 가시 질문
DB-->>QuestionRepo: List<ClubApplyQuestion>
QuestionRepo-->>Service: 질문들
Service->>Service: 질문/답변 그룹화 및 응답 DTO 조립
Service-->>Controller: ClubMemberApplicationAnswersResponse
Controller-->>Client: 200 OK (응답 바디)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Pull request overview
동아리 관리자 권한으로 승인된 동아리 멤버들의 “최신 지원서 답변”을 통합(리스트) 조회할 수 있는 API를 추가해, 기존 회원별 단건 조회 흐름을 리스트 응답으로 확장합니다.
Changes:
- 승인된 동아리 멤버들의 지원서 답변을 리스트로 조회하는 API/서비스 로직 추가
- 승인된 멤버들의 “유저별 최신 승인 지원서”를 전부 조회하는 QueryDSL 리포지토리 메서드 추가
- 여러 applyId에 대한 답변을 한 번에 가져오는 JPA Repository 메서드 추가 및 리스트 응답 DTO 신설
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/main/java/gg/agit/konect/domain/club/service/ClubApplicationService.java | 승인 멤버 지원서 답변 리스트 조회 서비스 추가 및 응답 조립 로직 공통화 |
| src/main/java/gg/agit/konect/domain/club/repository/ClubApplyQueryRepository.java | 승인 멤버의 최신 승인 지원서 전체 조회 쿼리 메서드 추가 |
| src/main/java/gg/agit/konect/domain/club/repository/ClubApplyAnswerRepository.java | 여러 applyId에 대한 답변+문항 fetch 조회 메서드 추가 |
| src/main/java/gg/agit/konect/domain/club/dto/ClubMemberApplicationAnswersResponse.java | 승인 멤버 지원서 답변 리스트 응답 DTO 추가 |
| src/main/java/gg/agit/konect/domain/club/controller/ClubApplicationController.java | 신규 리스트 조회 엔드포인트 컨트롤러 구현 추가 |
| src/main/java/gg/agit/konect/domain/club/controller/ClubApplicationApi.java | 신규 리스트 조회 엔드포인트 스웨거/인터페이스 정의 추가 |
src/main/java/gg/agit/konect/domain/club/repository/ClubApplyQueryRepository.java
Outdated
Show resolved
Hide resolved
src/main/java/gg/agit/konect/domain/club/service/ClubApplicationService.java
Outdated
Show resolved
Hide resolved
src/main/java/gg/agit/konect/domain/club/service/ClubApplicationService.java
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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/gg/agit/konect/domain/club/controller/ClubApplicationApi.java`:
- Around line 119-131: The current API method
getApprovedMemberApplicationAnswersList returns all approved member application
answers without pagination; change its signature to accept pagination parameters
(e.g., page, limit, sort) and return a paged contract (replace or wrap
ClubMemberApplicationAnswersResponse with a paged response type) so callers can
request slices of results; update the `@GetMapping` method parameters (add
`@RequestParam` Integer page, `@RequestParam` Integer limit,
`@RequestParam`(required=false) String sort or use a Pageable) and adjust the
controller/service flow handling (getApprovedMemberApplicationAnswersList ->
service method) to apply offset/limit and sorting while guarding against
N+1/performance issues and validating bounds.
In
`@src/main/java/gg/agit/konect/domain/club/service/ClubApplicationService.java`:
- Around line 147-153: The N+1 comes from calling findAllVisibleAtApplyTime for
each application while assembling responses in ClubApplicationService (during
the approvedApplications -> toClubApplicationAnswersResponse mapping); fix by
pre-aggregating question snapshots keyed by the apply-time (or other
deterministic key used by findAllVisibleAtApplyTime) before mapping: collect
distinct apply-times from approvedApplications, call findAllVisibleAtApplyTime
once per distinct key to build a Map<applyTime, List<QuestionSnapshot>> (or a
single snapshot if identical), then change toClubApplicationAnswersResponse to
accept the pre-fetched snapshot from that map (use the same keys when building
responses from approvedApplications and answersByApplyId); apply the same
prefetch/mapping approach for the other occurrence referenced (lines ~171-173).
ℹ️ Review info
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (6)
src/main/java/gg/agit/konect/domain/club/controller/ClubApplicationApi.javasrc/main/java/gg/agit/konect/domain/club/controller/ClubApplicationController.javasrc/main/java/gg/agit/konect/domain/club/dto/ClubMemberApplicationAnswersResponse.javasrc/main/java/gg/agit/konect/domain/club/repository/ClubApplyAnswerRepository.javasrc/main/java/gg/agit/konect/domain/club/repository/ClubApplyQueryRepository.javasrc/main/java/gg/agit/konect/domain/club/service/ClubApplicationService.java
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Agent
🧰 Additional context used
📓 Path-based instructions (2)
src/main/java/**/*.java
⚙️ CodeRabbit configuration file
src/main/java/**/*.java: 아래 원칙으로 리뷰 코멘트를 작성한다.
- 코멘트는 반드시 한국어로 작성한다.
- 반드시 수정이 필요한 항목만 코멘트로 남기고, 단순 취향 차이는 지적하지 않는다.
- 각 코멘트 첫 줄에 심각도를
[LEVEL: high|medium|low]형식으로 반드시 표기한다.- 심각도 기준: high=운영 장애 가능, medium=품질 저하, low=개선 권고.
- 각 코멘트는 "문제 -> 영향 -> 제안" 순서로 3문장 이내로 간결하게 작성한다.
- 가능하면 재현 조건 및 실패 시나리오도 포함한다.
- 제안은 현재 코드베이스(Spring Boot + JPA + Flyway) 패턴과 일치해야 한다.
- 보안, 트랜잭션 경계, 예외 처리, N+1, 성능 회귀 가능성을 우선 점검한다.
- 가독성: 변수/메서드 이름이 의도를 바로 드러내는지, 중첩과 메서드 길이가 과도하지 않은지 점검한다.
- 단순화: 불필요한 추상화, 중복 로직, 과한 방어 코드가 있으면 더 단순한 대안을 제시한다.
- 확장성: 새 요구사항 추가 시 변경 범위가 최소화되는 구조인지(하드코딩 분기/값 여부 포함) 점검한다.
Files:
src/main/java/gg/agit/konect/domain/club/repository/ClubApplyQueryRepository.javasrc/main/java/gg/agit/konect/domain/club/service/ClubApplicationService.javasrc/main/java/gg/agit/konect/domain/club/controller/ClubApplicationController.javasrc/main/java/gg/agit/konect/domain/club/dto/ClubMemberApplicationAnswersResponse.javasrc/main/java/gg/agit/konect/domain/club/repository/ClubApplyAnswerRepository.javasrc/main/java/gg/agit/konect/domain/club/controller/ClubApplicationApi.java
**/*
⚙️ CodeRabbit configuration file
**/*: 공통 리뷰 톤 가이드:
- 모든 코멘트는 첫 줄에
[LEVEL: ...]태그를 포함한다.- 과장된 표현 없이 사실 기반으로 작성한다.
- 한 코멘트에는 하나의 이슈만 다룬다.
- 코드 예시가 필요하면 최소 수정 예시를 제시한다.
- 가독성/단순화/확장성 이슈를 발견하면 우선순위를 높여 코멘트한다.
Files:
src/main/java/gg/agit/konect/domain/club/repository/ClubApplyQueryRepository.javasrc/main/java/gg/agit/konect/domain/club/service/ClubApplicationService.javasrc/main/java/gg/agit/konect/domain/club/controller/ClubApplicationController.javasrc/main/java/gg/agit/konect/domain/club/dto/ClubMemberApplicationAnswersResponse.javasrc/main/java/gg/agit/konect/domain/club/repository/ClubApplyAnswerRepository.javasrc/main/java/gg/agit/konect/domain/club/controller/ClubApplicationApi.java
src/main/java/gg/agit/konect/domain/club/controller/ClubApplicationApi.java
Show resolved
Hide resolved
src/main/java/gg/agit/konect/domain/club/service/ClubApplicationService.java
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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/gg/agit/konect/domain/club/repository/ClubApplyQueryRepository.java`:
- Around line 177-181: The method findAllApprovedMemberApplicationsByClubId in
ClubApplyQueryRepository is unused dead code—either remove this method entirely
or, if you intend to keep it for future use, add a clear comment above it
explaining the intended future usage and why it's not currently referenced;
ensure you reference the existing paging method
findApprovedMemberApplicationsByClubId in the comment so reviewers know the
active alternative.
In
`@src/main/java/gg/agit/konect/domain/club/service/ClubApplicationService.java`:
- Around line 219-223: The method isVisibleAtApplyTime currently uses
!question.getCreatedAt().isAfter(appliedAt) which is equivalent to createdAt <=
appliedAt but can be confusing; update the check to a clearer expression such as
!appliedAt.isBefore(question.getCreatedAt()) or add a concise comment clarifying
it matches the JPQL createdAt <= appliedAt semantics, referencing
isVisibleAtApplyTime(ClubApplyQuestion, LocalDateTime) so reviewers immediately
see the intent and consistency with findAllVisibleAtApplyTime.
ℹ️ Review info
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (6)
src/main/java/gg/agit/konect/domain/club/controller/ClubApplicationApi.javasrc/main/java/gg/agit/konect/domain/club/controller/ClubApplicationController.javasrc/main/java/gg/agit/konect/domain/club/dto/ClubMemberApplicationAnswersResponse.javasrc/main/java/gg/agit/konect/domain/club/repository/ClubApplyQueryRepository.javasrc/main/java/gg/agit/konect/domain/club/repository/ClubApplyQuestionRepository.javasrc/main/java/gg/agit/konect/domain/club/service/ClubApplicationService.java
📜 Review details
🧰 Additional context used
📓 Path-based instructions (2)
src/main/java/**/*.java
⚙️ CodeRabbit configuration file
src/main/java/**/*.java: 아래 원칙으로 리뷰 코멘트를 작성한다.
- 코멘트는 반드시 한국어로 작성한다.
- 반드시 수정이 필요한 항목만 코멘트로 남기고, 단순 취향 차이는 지적하지 않는다.
- 각 코멘트 첫 줄에 심각도를
[LEVEL: high|medium|low]형식으로 반드시 표기한다.- 심각도 기준: high=운영 장애 가능, medium=품질 저하, low=개선 권고.
- 각 코멘트는 "문제 -> 영향 -> 제안" 순서로 3문장 이내로 간결하게 작성한다.
- 가능하면 재현 조건 및 실패 시나리오도 포함한다.
- 제안은 현재 코드베이스(Spring Boot + JPA + Flyway) 패턴과 일치해야 한다.
- 보안, 트랜잭션 경계, 예외 처리, N+1, 성능 회귀 가능성을 우선 점검한다.
- 가독성: 변수/메서드 이름이 의도를 바로 드러내는지, 중첩과 메서드 길이가 과도하지 않은지 점검한다.
- 단순화: 불필요한 추상화, 중복 로직, 과한 방어 코드가 있으면 더 단순한 대안을 제시한다.
- 확장성: 새 요구사항 추가 시 변경 범위가 최소화되는 구조인지(하드코딩 분기/값 여부 포함) 점검한다.
Files:
src/main/java/gg/agit/konect/domain/club/controller/ClubApplicationController.javasrc/main/java/gg/agit/konect/domain/club/controller/ClubApplicationApi.javasrc/main/java/gg/agit/konect/domain/club/service/ClubApplicationService.javasrc/main/java/gg/agit/konect/domain/club/repository/ClubApplyQueryRepository.javasrc/main/java/gg/agit/konect/domain/club/dto/ClubMemberApplicationAnswersResponse.javasrc/main/java/gg/agit/konect/domain/club/repository/ClubApplyQuestionRepository.java
**/*
⚙️ CodeRabbit configuration file
**/*: 공통 리뷰 톤 가이드:
- 모든 코멘트는 첫 줄에
[LEVEL: ...]태그를 포함한다.- 과장된 표현 없이 사실 기반으로 작성한다.
- 한 코멘트에는 하나의 이슈만 다룬다.
- 코드 예시가 필요하면 최소 수정 예시를 제시한다.
- 가독성/단순화/확장성 이슈를 발견하면 우선순위를 높여 코멘트한다.
Files:
src/main/java/gg/agit/konect/domain/club/controller/ClubApplicationController.javasrc/main/java/gg/agit/konect/domain/club/controller/ClubApplicationApi.javasrc/main/java/gg/agit/konect/domain/club/service/ClubApplicationService.javasrc/main/java/gg/agit/konect/domain/club/repository/ClubApplyQueryRepository.javasrc/main/java/gg/agit/konect/domain/club/dto/ClubMemberApplicationAnswersResponse.javasrc/main/java/gg/agit/konect/domain/club/repository/ClubApplyQuestionRepository.java
🔇 Additional comments (7)
src/main/java/gg/agit/konect/domain/club/repository/ClubApplyQuestionRepository.java (1)
36-48: LGTM!새로 추가된
findAllCandidatesVisibleBetweenApplyTimes쿼리는 지원 시점 범위 내에서 보일 수 있는 모든 문항 후보를 효율적으로 조회합니다. 서비스 레이어에서 개별appliedAt에 맞춰 필터링하는 방식과 잘 연계됩니다.src/main/java/gg/agit/konect/domain/club/repository/ClubApplyQueryRepository.java (1)
162-166: LGTM!공통 조건을
approvedMemberApplicationBaseQuery와approvedMemberApplicationPredicates로 추출하여 코드 중복을 줄이고 유지보수성을 개선했습니다.Also applies to: 183-198
src/main/java/gg/agit/konect/domain/club/dto/ClubMemberApplicationAnswersResponse.java (1)
12-39: LGTM!새로운 DTO는 기존 페이지네이션 응답 패턴을 잘 따르고 있으며, Swagger 문서화도 적절합니다.
src/main/java/gg/agit/konect/domain/club/controller/ClubApplicationApi.java (1)
119-140: LGTM!이전 리뷰에서 지적된 페이지네이션 미적용 문제가 해결되었습니다.
page,limit,sortBy,sortDirection파라미터가 기존 엔드포인트 패턴과 일관되게 적용되어 있습니다.src/main/java/gg/agit/konect/domain/club/controller/ClubApplicationController.java (1)
91-104: LGTM!기존 컨트롤러 패턴을 따라 구현되었으며, 서비스 레이어에 적절히 위임합니다.
src/main/java/gg/agit/konect/domain/club/service/ClubApplicationService.java (2)
125-180: LGTM!이전 리뷰에서 지적된 N+1 문제가 해결되었습니다. 답변과 문항을 배치로 사전 조회(
findAllByApplyIdsWithQuestion,findAllCandidatesVisibleBetweenApplyTimes)한 후 메모리에서 필터링하는 방식으로 개선되어 성능이 크게 향상되었습니다.
195-217: LGTM!헬퍼 메서드 오버로딩을 통해 단건 조회와 리스트 조회 모두 지원하는 구조로 잘 설계되었습니다. 단건 조회 시에는 기존 방식대로 문항을 조회하고, 리스트 조회 시에는 사전 조회된 문항 맵을 활용합니다.
src/main/java/gg/agit/konect/domain/club/repository/ClubApplyQueryRepository.java
Outdated
Show resolved
Hide resolved
src/main/java/gg/agit/konect/domain/club/service/ClubApplicationService.java
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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/gg/agit/konect/domain/club/repository/ClubApplyQueryRepository.java`:
- Around line 168-172: The count query using
jpaQueryFactory.select(clubApply.count()).from(clubApply) is missing the join to
clubApply.user, but approvedMemberApplicationPredicates(clubId) references
user.deletedAt, causing mismatched join contexts with
approvedMemberApplicationBaseQuery(clubId) which does join(clubApply.user,
user). Modify the count query to include the same join by adding
.join(clubApply.user, user) after .from(clubApply) (no fetchJoin needed) so the
predicates resolve against the same join structure.
ℹ️ Review info
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (2)
src/main/java/gg/agit/konect/domain/club/repository/ClubApplyQueryRepository.javasrc/main/java/gg/agit/konect/domain/club/service/ClubApplicationService.java
📜 Review details
🧰 Additional context used
📓 Path-based instructions (2)
src/main/java/**/*.java
⚙️ CodeRabbit configuration file
src/main/java/**/*.java: 아래 원칙으로 리뷰 코멘트를 작성한다.
- 코멘트는 반드시 한국어로 작성한다.
- 반드시 수정이 필요한 항목만 코멘트로 남기고, 단순 취향 차이는 지적하지 않는다.
- 각 코멘트 첫 줄에 심각도를
[LEVEL: high|medium|low]형식으로 반드시 표기한다.- 심각도 기준: high=운영 장애 가능, medium=품질 저하, low=개선 권고.
- 각 코멘트는 "문제 -> 영향 -> 제안" 순서로 3문장 이내로 간결하게 작성한다.
- 가능하면 재현 조건 및 실패 시나리오도 포함한다.
- 제안은 현재 코드베이스(Spring Boot + JPA + Flyway) 패턴과 일치해야 한다.
- 보안, 트랜잭션 경계, 예외 처리, N+1, 성능 회귀 가능성을 우선 점검한다.
- 가독성: 변수/메서드 이름이 의도를 바로 드러내는지, 중첩과 메서드 길이가 과도하지 않은지 점검한다.
- 단순화: 불필요한 추상화, 중복 로직, 과한 방어 코드가 있으면 더 단순한 대안을 제시한다.
- 확장성: 새 요구사항 추가 시 변경 범위가 최소화되는 구조인지(하드코딩 분기/값 여부 포함) 점검한다.
Files:
src/main/java/gg/agit/konect/domain/club/repository/ClubApplyQueryRepository.javasrc/main/java/gg/agit/konect/domain/club/service/ClubApplicationService.java
**/*
⚙️ CodeRabbit configuration file
**/*: 공통 리뷰 톤 가이드:
- 모든 코멘트는 첫 줄에
[LEVEL: ...]태그를 포함한다.- 과장된 표현 없이 사실 기반으로 작성한다.
- 한 코멘트에는 하나의 이슈만 다룬다.
- 코드 예시가 필요하면 최소 수정 예시를 제시한다.
- 가독성/단순화/확장성 이슈를 발견하면 우선순위를 높여 코멘트한다.
Files:
src/main/java/gg/agit/konect/domain/club/repository/ClubApplyQueryRepository.javasrc/main/java/gg/agit/konect/domain/club/service/ClubApplicationService.java
🔍 개요
🚀 주요 변경 내용
💬 참고 사항
✅ Checklist (완료 조건)