Skip to content

Conversation

@yerinchun
Copy link
Contributor

@yerinchun yerinchun commented Dec 7, 2025

#️⃣ 연관된 이슈

관련된 이슈 번호를 적어주세요.
Close #128

✨ 작업 내용 (Summary)

이번 PR에서 작업한 내용을 간략히 설명해주세요. (이미지 첨부 가능)
사용자가 참여한 모든 챌린지의 인증 기록을 통합 조회할 수 있는 API를 구현했습니다.

  • 최신순 정렬 (verifiedAt DESC)
  • 완료된 인증만 조회 (COMPLETED 상태)
  • 각 인증에 챌린지 정보 포함 (challengeId, challengeTitle)

✅ 변경 사항 체크리스트

다음 항목들을 확인하고 체크해주세요.

  • 코드에 영향이 있는 모든 부분에 대한 테스트를 작성하고 실행했나요?
  • 문서를 작성하거나 수정했나요? (필요한 경우)
  • 중요한 변경 사항이 팀에 공유되었나요?

🧪 테스트 결과

코드 변경에 대해 테스트를 수행한 결과를 요약해주세요.

  • 테스트 환경: 로컬
  • 테스트 방법: 스웨거
  • 결과 요약: 테스트 통과

📸 스크린샷

관련된 스크린샷 또는 GIF가 있다면 여기에 첨부해주세요.

image

💬 리뷰 요구사항

리뷰어가 특별히 봐주었으면 하는 부분이 있다면 작성해주세요.


📎 참고 자료

관련 문서, 레퍼런스 링크 등이 있다면 여기에 첨부해주세요.

Summary by CodeRabbit

  • 새로운 기능

    • 로그인한 사용자의 인증 이력을 페이지 단위로 조회하는 새 API 제공 — 각 이력에 인증 ID, 챌린지 정보, 타입, 제목/내용, 사진/글 URL, 인증 시각 포함
  • 개선

    • 페이지네이션을 1부터 시작하도록 표준화하고 page/size 입력 검증(@Min/@max) 추가하여 안정성 향상

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Dec 7, 2025

📝 Walkthrough

Walkthrough

인증 이력 조회 API가 추가되었습니다. UserController에 새 엔드포인트와 VerificationService 의존성이 추가되고, VerificationRepository/Service/Converter/DTO에 히스토리 전용 쿼리·변환·페이징 로직(Slice 기반, COMPLETED 필터)이 도입되었습니다.

Changes

Cohort / File(s) 변경 요약
컨트롤러 — 엔드포인트 추가 및 페이징 검증
src/main/java/com/hrr/backend/domain/user/controller/UserController.java
VerificationService 주입 필드 추가 및 GET /api/v1/user/me/verifications/history 엔드포인트 추가. 페이지 파라미터를 1-based로 수신하고 내부에서 page-1 변환, @Min/@Max 유효성 적용, @AuthenticationPrincipal에서 userId 추출 후 서비스 호출.
DTO — 히스토리 응답 모델
src/main/java/com/hrr/backend/domain/verification/dto/VerificationResponseDto.java
HistoryDto 내부 클래스 추가(verificationId, challengeId, challengeTitle, type, title, content, photoUrl, textUrl, verifiedAt 등; Lombok/Swagger/Jackson 어노테이션 포함).
컨버터 — 엔티티→히스토리 DTO 변환
src/main/java/com/hrr/backend/domain/verification/converter/VerificationConverter.java
toHistoryDto(Verification) 메서드 추가: 엔티티 필드 매핑 및 photoUrl 전체 URL 변환 로직 포함(필드 매핑 규칙 명시).
레포지토리 — 히스토리 조회 쿼리 (Slice 반환)
src/main/java/com/hrr/backend/domain/verification/repository/VerificationRepository.java
Slice<Verification> findVerificationHistoryByUser(User user, VerificationStatus status, Pageable pageable) 메서드 추가(조인 페치 포함, status=COMPLETED 필터, createdAt DESC).
서비스 — 비즈니스 로직: 히스토리 조회
src/main/java/com/hrr/backend/domain/verification/service/VerificationService.java
src/main/java/com/hrr/backend/domain/verification/service/VerificationServiceImpl.java
getVerificationHistory(Long userId, int page, int size) 메서드 추가: 사용자 존재 검증 → Repository 호출(Slice) → Converter로 HistoryDto 변환 → SliceResponseDto<HistoryDto> 반환. 일부 import/포맷 정리 포함.

Sequence Diagram(s)

sequenceDiagram
    %%{init: {"themeVariables":{"actorBackground":"#F7FBFF","actorBorder":"#CFE8FF","noteBackground":"#FFF8E6"}}}%%
    participant Client as 클라이언트
    participant Controller as UserController
    participant Auth as AuthenticationPrincipal
    participant Service as VerificationService
    participant Repo as VerificationRepository
    participant Conv as VerificationConverter
    participant DB as Database

    Client->>Controller: GET /api/v1/user/me/verifications/history?page=1&size=10
    Controller->>Auth: 인증 정보(`@AuthenticationPrincipal`) 요청
    Auth-->>Controller: CustomUserDetails (userId)
    Controller->>Service: getVerificationHistory(userId, page-1, size)
    Service->>Repo: findVerificationHistoryByUser(User, COMPLETED, pageable)
    Repo->>DB: SQL (JOIN fetch, WHERE status=COMPLETED, ORDER BY created_at DESC)
    DB-->>Repo: Slice<Verification>
    Service->>Conv: toHistoryDto(...) 반복 호출
    Conv-->>Service: List<HistoryDto>
    Service-->>Controller: SliceResponseDto<HistoryDto>
    Controller-->>Client: ApiResponse(200, body: SliceResponseDto<HistoryDto>)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

페이지는 하나부터 시작하네,
기록은 최신순으로 흐르고,
컨트롤러가 묻고 서비스가 꺼내 와,
레포는 찾고 컨버터는 빚어,
응답은 깔끔히 돌아오네 ✨

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning PR은 #128의 주요 요구사항(사용자 인증 기록 조회, 완료된 인증만, 최신순 정렬, 챌린지 정보 포함)을 구현했으나, 요구된 엔드포인트와 페이징 방식에 불일치가 있습니다. 엔드포인트를 /api/v1/user/challenges/history에서 현재 구현된 /api/v1/user/me/verifications/history로 변경하거나, Page 기반 페이징(totalCount, totalPages)으로 수정하세요.
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목 '[FEAT] 내 인증현황 조회 API 구현'은 PR의 주요 변경사항을 명확하게 요약합니다.
Out of Scope Changes check ✅ Passed 모든 변경사항이 인증 기록 조회 기능과 관련되어 있으며, 범위를 벗어난 변경은 없습니다.
✨ Finishing touches
  • 📝 Generate docstrings

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bd41469 and 835dd97.

📒 Files selected for processing (2)
  • src/main/java/com/hrr/backend/domain/verification/service/VerificationService.java
  • src/main/java/com/hrr/backend/domain/verification/service/VerificationServiceImpl.java
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/main/java/com/hrr/backend/domain/verification/service/VerificationServiceImpl.java
  • src/main/java/com/hrr/backend/domain/verification/service/VerificationService.java

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.

@yerinchun yerinchun changed the title Feat/128 my verification history [FEAT] 내 인증현황 조회 API 구현 Dec 7, 2025
@yerinchun yerinchun self-assigned this Dec 7, 2025
@yerinchun yerinchun added 🌟 feat 새로운 기능 개발 예린 labels Dec 7, 2025
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: 2

🧹 Nitpick comments (3)
src/main/java/com/hrr/backend/domain/user/dto/UserVerificationResponseDto.java (1)

42-44: @JsonFormat의 'Z' 리터럴 사용 관련 참고사항

LocalDateTime은 타임존 정보가 없지만, 패턴에서 'Z'는 리터럴 문자로 출력됩니다. 클라이언트가 이를 UTC로 해석할 수 있으므로, 실제로 UTC 기준 시간을 저장/반환하는지 확인이 필요합니다.

기존 코드베이스 패턴을 따르고 있으므로 현재 구현은 유지하되, 향후 타임존 명확화가 필요하다면 ZonedDateTime 또는 OffsetDateTime 사용을 고려해보세요.

src/main/java/com/hrr/backend/domain/user/controller/UserController.java (1)

155-159: 검색 API 페이징 size 상한을 다른 엔드포인트와 통일하면 좋겠습니다

  • 이번에 @Min(1)과 기본값을 추가해 주신 덕분에 0 이하 페이지/사이즈 방어가 잘 되어서 👍 입니다.
  • 다만 다른 엔드포인트들(/me/challenge/ongoing, /challenges/history)은 size 파라미터에 @Max(100)까지 걸려 있는데, 여기 /search만 상한이 없어 대용량 요청 시 성능 이슈가 날 수 있습니다.

개선 제안:

  • 아래처럼 size에도 @Max(100)을 추가해서 검증 규칙을 통일하는 쪽을 추천드립니다.
-    @Min(1)
-    @RequestParam(name = "page", defaultValue = "1") int page, // 페이지 번호 (1부터 시작)
-    @Min(1)
-	@RequestParam(name = "size", defaultValue = "10") int size, // 페이지 크기
+    @Min(1)
+    @RequestParam(name = "page", defaultValue = "1") int page, // 페이지 번호 (1부터 시작)
+    @Min(1) @Max(100)
+    @RequestParam(name = "size", defaultValue = "10") int size, // 페이지 크기

참고로 자카르타 Bean Validation(jakarta.validation.constraints.Min/Max) 스펙을 보면, 이런 단순 범위 체크는 애노테이션만으로도 충분히 표현 가능하니 지금 방향이 맞습니다.

src/main/java/com/hrr/backend/domain/user/repository/UserVerificationRepository.java (1)

1-57: JPQL 쿼리 표현식과 인덱싱 관점에서 소소한 개선 포인트 제안

전체적으로 메서드 네이밍과 JPQL이 역할별로 잘 나뉘어 있어서 읽기 좋습니다. 살짝만 다듬으면 더 안전하고 성능 친화적으로 가져갈 수 있을 것 같습니다.

  1. existsTodayVerificationSELECT COUNT(v) > 0 표현식

    • Hibernate 기준으로는 SELECT COUNT(v) > 0이 잘 동작하지만, 순수 JPA 스펙 관점에서는 약간 그레이존에 가까운 표현이라 벤더 의존성이 생길 수 있습니다.
    • 보다 포터블하게 가져가려면 아래와 같이 CASE WHEN으로 boolean을 만들어 주는 패턴을 고려할 수 있습니다.
    @Query("""
        SELECT CASE WHEN COUNT(v) > 0 THEN true ELSE false END
        FROM Verification v
        WHERE v.roundRecord.userChallenge.id = :userChallengeId
          AND v.status = :status
          AND v.createdAt >= :startOfDay
          AND v.createdAt <= :endOfDay
    """)

    JPA 쿼리 문법을 엄격하게 따르는 편이, 향후 Hibernate 버전 업이나 다른 JPA 구현체로의 전환 시 리스크를 줄여 줍니다.

  2. 날짜 범위(BETWEEN / >= & <=) 경계 조건 재확인

    • findWeeklyVerificationsv.createdAt BETWEEN :start AND :endexistsTodayVerification>= :startOfDay AND <= :endOfDay 모두 양 끝단이 포함(inclusive) 입니다.
    • 주간/일간 통계를 만들 때, 호출부에서 end를 “마지막 날의 23:59:59.999…” 식으로 맞추는지, 혹은 [start, end) 형태로 쓰고 싶은지에 따라 off-by-one/밀리초 단위 누락이 발생할 수 있어, 서비스 레이어에서 파라미터 생성 규칙을 한 번 정리해 두는 걸 권장드립니다.
  3. 쿼리 대상 컬럼에 대한 인덱싱 고려

    • 세 쿼리 모두 공통적으로 다음 컬럼들을 where/order by에서 많이 사용합니다.
      • roundRecord.userChallenge.id
      • status
      • createdAt
      • (weekly 쿼리) uc.user.id, uc.challenge.id
    • 인증 데이터가 쌓이면 해당 조건 조합으로 자주 조회될 가능성이 높아서, 실제 DB 스키마에서 위 컬럼들에 대해 적절한 인덱스(특히 userId + challengeId + createdAt 조합 등)가 잡혀 있는지 한 번 확인해 보시면 좋겠습니다.

이 부분들은 모두 기능 버그라기보다는 JPA/Hibernate 베스트 프랙티스와 성능 튜닝에 가까운 내용이라, 여유 있을 때 반영해도 충분할 것 같습니다.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d029a2c and f35b7ee.

📒 Files selected for processing (7)
  • src/main/java/com/hrr/backend/domain/user/controller/UserController.java (4 hunks)
  • src/main/java/com/hrr/backend/domain/user/dto/UserVerificationResponseDto.java (1 hunks)
  • src/main/java/com/hrr/backend/domain/user/repository/UserVerificationRepository.java (1 hunks)
  • src/main/java/com/hrr/backend/domain/user/repository/UserVerificationRepositoryCustom.java (1 hunks)
  • src/main/java/com/hrr/backend/domain/user/repository/UserVerificationRepositoryCustomImpl.java (1 hunks)
  • src/main/java/com/hrr/backend/domain/user/service/UserVerificationService.java (1 hunks)
  • src/main/java/com/hrr/backend/domain/user/service/UserVerificationServiceImpl.java (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-06T08:06:38.145Z
Learnt from: yerinchun
Repo: Hrr-HabbitRoutineResult/hrr-server PR: 26
File: src/main/java/com/hrr/backend/domain/user/entity/User.java:42-44
Timestamp: 2025-11-06T08:06:38.145Z
Learning: In the hrr-server project User entity (src/main/java/com/hrr/backend/domain/user/entity/User.java), the password field is nullable because the application uses social login (OAuth), and social login users do not have passwords stored in the database.

Applied to files:

  • src/main/java/com/hrr/backend/domain/user/controller/UserController.java
🧬 Code graph analysis (6)
src/main/java/com/hrr/backend/domain/user/repository/UserVerificationRepositoryCustomImpl.java (1)
src/main/java/com/hrr/backend/domain/user/dto/UserVerificationResponseDto.java (1)
  • UserVerificationResponseDto (12-46)
src/main/java/com/hrr/backend/domain/user/repository/UserVerificationRepositoryCustom.java (4)
src/main/java/com/hrr/backend/domain/user/dto/UserVerificationResponseDto.java (1)
  • UserVerificationResponseDto (12-46)
src/main/java/com/hrr/backend/domain/user/repository/UserChallengeRepositoryCustom.java (1)
  • UserChallengeRepositoryCustom (8-17)
src/main/java/com/hrr/backend/domain/user/service/UserServiceImpl.java (1)
  • Override (70-126)
src/main/java/com/hrr/backend/domain/user/repository/UserChallengeRepositoryCustomImpl.java (1)
  • Override (26-66)
src/main/java/com/hrr/backend/domain/user/service/UserVerificationServiceImpl.java (1)
src/main/java/com/hrr/backend/domain/user/dto/UserVerificationResponseDto.java (1)
  • UserVerificationResponseDto (12-46)
src/main/java/com/hrr/backend/domain/user/dto/UserVerificationResponseDto.java (4)
src/main/java/com/hrr/backend/domain/verification/dto/VerificationDetailResponseDto.java (3)
  • Data (55-64)
  • Data (14-76)
  • Data (66-75)
src/main/java/com/hrr/backend/domain/verification/dto/VerificationResponseDto.java (4)
  • Getter (102-139)
  • Getter (80-100)
  • VerificationResponseDto (16-140)
  • Getter (18-61)
src/main/java/com/hrr/backend/domain/user/dto/UserMissionResponseDto.java (1)
  • UserMissionResponseDto (10-33)
src/main/java/com/hrr/backend/domain/user/dto/UserResponseDto.java (1)
  • Getter (58-88)
src/main/java/com/hrr/backend/domain/user/controller/UserController.java (1)
src/main/java/com/hrr/backend/domain/user/dto/UserVerificationResponseDto.java (1)
  • UserVerificationResponseDto (12-46)
src/main/java/com/hrr/backend/domain/user/service/UserVerificationService.java (1)
src/main/java/com/hrr/backend/domain/user/dto/UserVerificationResponseDto.java (1)
  • UserVerificationResponseDto (12-46)
🔇 Additional comments (5)
src/main/java/com/hrr/backend/domain/user/repository/UserVerificationRepositoryCustom.java (1)

8-17: 깔끔한 인터페이스 정의입니다! 👍

기존 UserChallengeRepositoryCustom 패턴을 잘 따르고 있으며, Slice를 사용한 페이지네이션 방식도 적절합니다. Javadoc 주석까지 잘 작성되어 있네요.

src/main/java/com/hrr/backend/domain/user/service/UserVerificationService.java (1)

6-14: 간결하고 명확한 서비스 인터페이스입니다!

메서드 시그니처가 명확하고, 단일 책임 원칙을 잘 따르고 있습니다. SliceResponseDto를 반환 타입으로 사용하여 페이지네이션 메타데이터까지 포함하는 것도 좋습니다.

src/main/java/com/hrr/backend/domain/user/dto/UserVerificationResponseDto.java (1)

14-19: S3 URL 변환 시 @Setter 필요 여부 확인

서비스 레이어에서 imageUrl에 대한 S3 URL 변환이 필요하다면, OngoingChallengeDto처럼 해당 필드에 @Setter를 추가해야 합니다.

 @Getter
 @Builder
 @NoArgsConstructor
 @AllArgsConstructor
 @Schema(description = "개별 인증 기록 DTO")
 public static class VerificationItemDto {
+    @Setter
+    private String imageUrl;
     // ... 기존 필드들

또는 클래스 레벨에 @Setter를 추가하거나, 빌더 패턴으로 새 객체를 생성하는 방법도 있습니다.

src/main/java/com/hrr/backend/domain/user/repository/UserVerificationRepositoryCustomImpl.java (2)

58-64: Slice 생성 로직 LGTM! 🎯

hasNext 판단과 리스트 조정 로직이 정확합니다. 기존 패턴과 동일하게 구현되어 있어 유지보수성도 좋습니다.


33-56: QueryDSL 쿼리 구현이 잘 되어 있습니다!

기존 UserChallengeRepositoryCustomImpl 패턴을 일관성 있게 따르고 있으며, hasNext 판단을 위한 +1 패턴도 적절합니다. Verification 엔티티는 createdAt 필드만 가지고 있으므로, 이를 DTO에서 verifiedAt으로 매핑하는 것이 올바른 구현입니다.

Likely an incorrect or invalid review comment.

Comment on lines 41 to 42
private final UserVerificationService userVerificationService;

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

🧩 Analysis chain

🏁 Script executed:

find . -name "UserController.java" -type f

Repository: Hrr-HabbitRoutineResult/hrr-server

Length of output: 152


🏁 Script executed:

cat -n ./src/main/java/com/hrr/backend/domain/user/controller/UserController.java

Repository: Hrr-HabbitRoutineResult/hrr-server

Length of output: 11900


🏁 Script executed:

find . -name "UserVerificationService.java" -type f

Repository: Hrr-HabbitRoutineResult/hrr-server

Length of output: 158


🏁 Script executed:

cat -n ./src/main/java/com/hrr/backend/domain/user/service/UserVerificationService.java

Repository: Hrr-HabbitRoutineResult/hrr-server

Length of output: 583


🏁 Script executed:

find . -name "*UserVerificationService*Impl*.java" -type f

Repository: Hrr-HabbitRoutineResult/hrr-server

Length of output: 162


🏁 Script executed:

cat -n ./src/main/java/com/hrr/backend/domain/user/service/UserVerificationServiceImpl.java

Repository: Hrr-HabbitRoutineResult/hrr-server

Length of output: 2135


🏁 Script executed:

find . -name "UserVerificationRepository.java" -type f

Repository: Hrr-HabbitRoutineResult/hrr-server

Length of output: 164


🏁 Script executed:

cat -n ./src/main/java/com/hrr/backend/domain/user/repository/UserVerificationRepository.java

Repository: Hrr-HabbitRoutineResult/hrr-server

Length of output: 2708


🏁 Script executed:

find . -name "UserVerificationRepositoryCustom*" -type f

Repository: Hrr-HabbitRoutineResult/hrr-server

Length of output: 267


🏁 Script executed:

cat -n ./src/main/java/com/hrr/backend/domain/user/repository/UserVerificationRepositoryCustom.java

Repository: Hrr-HabbitRoutineResult/hrr-server

Length of output: 764


🏁 Script executed:

cat -n ./src/main/java/com/hrr/backend/domain/user/repository/UserVerificationRepositoryCustomImpl.java

Repository: Hrr-HabbitRoutineResult/hrr-server

Length of output: 3524


🏁 Script executed:

find . -name "SliceResponseDto.java" -type f

Repository: Hrr-HabbitRoutineResult/hrr-server

Length of output: 147


🏁 Script executed:

cat -n ./src/main/java/com/hrr/backend/global/response/SliceResponseDto.java

Repository: Hrr-HabbitRoutineResult/hrr-server

Length of output: 1184


인증 기록 조회 API의 페이지네이션 설계와 응답 필드 일관성을 정리하면 좋겠습니다

구현 자체는 전반적으로 잘 나왔고, 경로(/api/v1/user/challenges/history)와 Swagger 예제도 읽기 편합니다. 다만 페이지네이션 스펙과 문서의 일관성에서 두 가지 정도 정리가 필요합니다.

  1. Slice vs Page 선택 재확인

    • 현재 구현은 SliceResponseDtoSlice<T>를 사용하고 있어, 응답에 totalCount/totalPages가 없습니다.
    • 이는 count 쿼리를 절약하는 성능 이점이 있지만, 프론트에서 "전체 n건, m/n 페이지" 같은 UI를 구현할 수 없습니다.

    현재 상태를 PM/프론트와 재확인해서:

    • A안: Slice 유지 + Swagger 문서에 "totalCount/totalPages는 제공하지 않음" 명시
    • B안: Page<T>로 변경해서 totalCount/totalPages 제공
  2. 응답 currentPage 필드의 기준 통일

    • SliceResponseDto 코드(line 21)에는 slice.getNumber() + 1로 1-기반 변환이 구현되어 있고, 필드 주석도 "1부터 시작"이라고 명시되어 있습니다.
    • 그런데 Swagger 예제에는 currentPage: 0으로 되어 있어, 클라이언트 개발자가 혼동할 수 있습니다.

    개선 방향:

    • Swagger 예제를 currentPage: 1로 수정 (DTO의 변환 로직과 일치)
    • 또는 DTO 변환 로직을 제거하고 문서/주석에 "0-기반"으로 명시
  3. 비즈니스 규칙 확인 완료

    • VerificationStatus.COMPLETED 필터 ✓
    • verifiedAt DESC 정렬 ✓
    • 두 규칙 모두 리포지토리에서 올바르게 구현되어 있습니다.
🤖 Prompt for AI Agents
In src/main/java/com/hrr/backend/domain/user/controller/UserController.java
around lines 41-42, the pagination/design consistency needs clarifying: confirm
with PM/frontend whether to keep Slice (no totalCount/totalPages) or switch to
Page (provide totals); if you choose Slice, update Swagger and API docs to
explicitly state totalCount/totalPages are not provided and keep current DTO
conversion; if you choose Page, change service/repo/controller and response DTOs
to use Page<T> and include totalCount/totalPages in the response; also fix the
currentPage convention mismatch by either adjusting the SliceResponseDto to
return 0-based paging to match the Swagger example or update the Swagger example
to currentPage: 1 so it matches the DTO (and ensure comments and examples are
consistent).

Comment on lines 38 to 43
// Repository에서 인증 기록 조회
Slice<UserVerificationResponseDto.VerificationItemDto> slice =
userVerificationRepository.findVerificationHistoryByUser(user, pageable);

// SliceResponseDto로 변환하여 반환
return new SliceResponseDto<>(slice);
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

🧩 Analysis chain

🏁 Script executed:

# First, let's find and examine the UserVerificationResponseDto structure
find . -type f -name "*UserVerificationResponseDto*" | head -10

Repository: Hrr-HabbitRoutineResult/hrr-server

Length of output: 158


🏁 Script executed:

# Search for photoUrl and imageUrl usage across the codebase
rg -n "photoUrl|imageUrl" --type java -B 2 -A 2 | head -100

Repository: Hrr-HabbitRoutineResult/hrr-server

Length of output: 10212


🏁 Script executed:

# Examine UserServiceImpl to see the pattern referenced in the comment
rg -n "getOngoingChallenges" --type java -A 50 | head -80

Repository: Hrr-HabbitRoutineResult/hrr-server

Length of output: 8365


🏁 Script executed:

# Check s3UrlUtil usage patterns
rg -n "s3UrlUtil\.toFullUrl" --type java -B 2 -A 2

Repository: Hrr-HabbitRoutineResult/hrr-server

Length of output: 5543


🏁 Script executed:

# Look for the actual UserVerificationServiceImpl implementation
find . -type f -name "UserVerificationServiceImpl.java" -exec cat -n {} \;

Repository: Hrr-HabbitRoutineResult/hrr-server

Length of output: 2135


🏁 Script executed:

# Examine UserVerificationResponseDto structure
cat -n ./src/main/java/com/hrr/backend/domain/user/dto/UserVerificationResponseDto.java

Repository: Hrr-HabbitRoutineResult/hrr-server

Length of output: 1823


🏁 Script executed:

# Also search for how VerificationItemDto is used elsewhere
rg -n "VerificationItemDto" --type java -B 2 -A 5

Repository: Hrr-HabbitRoutineResult/hrr-server

Length of output: 8613


🏁 Script executed:

# Examine the full projection mapping in UserVerificationRepositoryCustomImpl
sed -n '25,60p' ./src/main/java/com/hrr/backend/domain/user/repository/UserVerificationRepositoryCustomImpl.java

Repository: Hrr-HabbitRoutineResult/hrr-server

Length of output: 1917


🏁 Script executed:

# Check if photoUrl is indeed stored as S3 key in Verification entity
rg -n "photoUrl" ./src/main/java/com/hrr/backend/domain/verification/entity/Verification.java -B 2 -A 2

Repository: Hrr-HabbitRoutineResult/hrr-server

Length of output: 931


S3 이미지 URL 변환 누락 필요

Verification.photoUrl은 S3 키로 저장되며, 다른 Service 및 Converter에서 s3UrlUtil.toFullUrl()로 변환하는 패턴이 일관되게 적용되어 있습니다 (VerificationConverter 참고). 현재 UserVerificationServiceImpl.getVerificationHistory()에서는 이 변환이 누락되어 있습니다.

두 가지 해결 방안이 있습니다:

방안 1: Repository 레이어에서 변환 (권장)
UserVerificationRepositoryCustomImpl 라인 41의 projection에서 직접 변환:

- qVerification.photoUrl.as("imageUrl"),
+ s3UrlUtil.toFullUrl(qVerification.photoUrl).as("imageUrl"),

방안 2: Service 레이어에서 변환
VerificationItemDto@Setter 추가 후 UserVerificationServiceImpl에서 URL 변환 (단, 현재 @Getter만 있어 setter가 없음):

+ private final S3UrlUtil s3UrlUtil;
+
  // Repository에서 인증 기록 조회
  Slice<UserVerificationResponseDto.VerificationItemDto> slice =
          userVerificationRepository.findVerificationHistoryByUser(user, pageable);

+ slice.getContent().forEach(dto ->
+         dto.setImageUrl(s3UrlUtil.toFullUrl(dto.getImageUrl()))
+ );

Committable suggestion skipped: line range outside the PR's diff.

Copy link
Contributor

@yc3697 yc3697 left a comment

Choose a reason for hiding this comment

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

  1. Verification이라는 테이블에 관한 DTO, Repository, Service이기 때문에 불필요한 prefix인 User는 제거하는 것이 좋아보입니다. 지금은 없지만 혹시 나중에 UserVerification이라는 테이블이 생기면 혼동이 생기니깐요.
  2. 확인해보니 VerificationRepository에 구현된 것들이 있어서 중복된 건 삭제하고 새로 구현된 것들만 해당 클래스에 추가해주세요.
  3. 반환 결과에 '링크 포함 여부'도 필요합니다.

userVerificationRepository.findVerificationHistoryByUser(user, pageable);

// SliceResponseDto로 변환하여 반환
return new SliceResponseDto<>(slice);
Copy link
Contributor

Choose a reason for hiding this comment

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

url의 변환 작업이 필요하기 때문에 객체 생성 방식이 아닌 빌더 방식으로 반환 데이터를 생성해주세요.

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: 2

♻️ Duplicate comments (1)
src/main/java/com/hrr/backend/domain/user/controller/UserController.java (1)

173-220: Swagger 예제의 currentPage 값을 수정하세요

Line 209에서 Swagger 예제의 currentPage: 0으로 표시되어 있지만, 실제 SliceResponseDtoslice.getNumber() + 1을 사용해 1-based 페이지 번호를 반환합니다(src/main/java/com/hrr/backend/global/response/SliceResponseDto.java line 21 참조).

이는 과거 리뷰에서도 지적된 사항으로, API 문서와 실제 응답이 불일치하여 클라이언트 개발자를 혼란스럽게 만듭니다.

수정 방법:

                                        ],
-                                       "currentPage": 0,
+                                       "currentPage": 1,
                                        "size": 10,
🧹 Nitpick comments (1)
src/main/java/com/hrr/backend/domain/verification/repository/VerificationRepository.java (1)

162-175: 쿼리의 상태 값을 파라미터화하여 일관성을 개선하세요

Line 170에서 'COMPLETED'를 문자열로 하드코딩했는데, 같은 파일 내 다른 메서드들(lines 24, 44, 59, 77, 90, 138, 152, 158)은 모두 @Param("status") VerificationStatus status 파라미터를 사용합니다.

현재 구현도 동작하지만, 파라미터화하면:

  • 필터링 조건 변경 시 유연성 확보
  • 코드 스타일 일관성 유지
  • 향후 다른 상태 조회 요구사항 대응 용이
🔎 제안하는 리팩토링
 /**
  * 사용자의 전체 챌린지 인증 기록 조회 (페이징)
  */
 @Query("SELECT v FROM Verification v " +
         "JOIN FETCH v.roundRecord rr " +
         "JOIN FETCH rr.userChallenge uc " +
         "JOIN FETCH uc.challenge c " +
         "WHERE uc.user = :user " +
-        "AND v.status = 'COMPLETED' " +
+        "AND v.status = :status " +
         "ORDER BY v.createdAt DESC")
 Slice<Verification> findVerificationHistoryByUser(
         @Param("user") User user,
+        @Param("status") VerificationStatus status,
         Pageable pageable
 );

그리고 호출부(VerificationServiceImpl line 288)도 수정:

 Slice<Verification> verificationSlice =
-        verificationRepository.findVerificationHistoryByUser(user, pageable);
+        verificationRepository.findVerificationHistoryByUser(user, VerificationStatus.COMPLETED, pageable);
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f35b7ee and 2b58415.

📒 Files selected for processing (6)
  • src/main/java/com/hrr/backend/domain/user/controller/UserController.java
  • src/main/java/com/hrr/backend/domain/verification/converter/VerificationConverter.java
  • src/main/java/com/hrr/backend/domain/verification/dto/VerificationResponseDto.java
  • src/main/java/com/hrr/backend/domain/verification/repository/VerificationRepository.java
  • src/main/java/com/hrr/backend/domain/verification/service/VerificationService.java
  • src/main/java/com/hrr/backend/domain/verification/service/VerificationServiceImpl.java
🧰 Additional context used
🧬 Code graph analysis (3)
src/main/java/com/hrr/backend/domain/verification/converter/VerificationConverter.java (1)
src/main/java/com/hrr/backend/domain/verification/dto/VerificationResponseDto.java (1)
  • VerificationResponseDto (16-176)
src/main/java/com/hrr/backend/domain/verification/dto/VerificationResponseDto.java (4)
src/main/java/com/hrr/backend/domain/verification/dto/VerificationRequestDto.java (1)
  • Getter (9-26)
src/main/java/com/hrr/backend/domain/verification/dto/VerificationRequestPhotoDto.java (1)
  • Getter (8-24)
src/main/java/com/hrr/backend/domain/verification/dto/VerificationListResponseDto.java (3)
  • Getter (12-51)
  • Getter (15-40)
  • Getter (43-50)
src/main/java/com/hrr/backend/domain/verification/dto/VerificationMyResponseDto.java (2)
  • Getter (16-38)
  • Getter (43-49)
src/main/java/com/hrr/backend/domain/user/controller/UserController.java (1)
src/main/java/com/hrr/backend/domain/verification/dto/VerificationResponseDto.java (1)
  • VerificationResponseDto (16-176)
🔇 Additional comments (4)
src/main/java/com/hrr/backend/domain/verification/service/VerificationService.java (1)

58-65: LGTM!

인터페이스 정의가 명확하고 Javadoc도 제공되어 있습니다. 반환 타입도 적절하게 선택되었습니다.

src/main/java/com/hrr/backend/domain/verification/service/VerificationServiceImpl.java (1)

270-296: LGTM!

구현이 명확하고 에러 처리도 적절합니다. Repository → Converter → SliceResponseDto 흐름이 깔끔하게 구성되어 있습니다.

src/main/java/com/hrr/backend/domain/user/controller/UserController.java (2)

168-172: 엔드포인트 경로가 이슈 요구사항과 다릅니다

이슈 #128에서는 엔드포인트를 GET /api/v1/user/challenges/history로 명시했지만, 구현된 경로는 /api/v1/user/me/verifications/history입니다.

두 경로 모두 의미적으로는 타당하지만, PM/프론트엔드와 합의된 경로를 사용해야 클라이언트 구현이 혼란스럽지 않습니다. 의도적으로 변경한 것이라면 이슈를 업데이트하시고, 그렇지 않다면 이슈 명세에 맞춰 수정하세요.


221-238: 엔드포인트 구조가 잘 설계되었습니다

JWT 인증 기반으로 사용자를 식별하고, 페이지네이션 파라미터 검증(@Min, @Max)도 적절하게 적용되어 있습니다. 서비스 레이어로의 위임도 깔끔합니다.

Comment on lines 141 to 175
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Schema(description = "사용자 전체 인증 기록 DTO")
public static class HistoryDto {

@Schema(description = "인증 ID", example = "1")
private Long verificationId;

@Schema(description = "챌린지 ID", example = "101")
private Long challengeId;

@Schema(description = "챌린지 제목", example = "미라클 모닝")
private String challengeTitle;

@Schema(description = "인증 타입", example = "TEXT", allowableValues = {"TEXT", "CAMERA"})
private String type;

@Schema(description = "인증 제목", example = "해피뉴이어! 올해 마지막 인증 올립니다")
private String title;

@Schema(description = "인증 내용", example = "여기엔 상세내용이 들어가유~")
private String content;

@Schema(description = "사진 URL (사진 인증)", example = "https://example.com/verification_image_1.jpg")
private String photoUrl;

@Schema(description = "글 URL (글 인증)", example = "https://blog.example.com/post/123")
private String textUrl;

@Schema(description = "인증 일시", example = "2025-09-18T08:00:00Z")
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'")
private LocalDateTime verifiedAt;
}
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

🧩 Analysis chain

🏁 Script executed:

# First, let's find and check the VerificationResponseDto.java file
find . -name "VerificationResponseDto.java" -type f

Repository: Hrr-HabbitRoutineResult/hrr-server

Length of output: 162


🏁 Script executed:

# Check all @JsonFormat patterns in the project
rg -n '@JsonFormat.*pattern' --type java -A1 -B1

Repository: Hrr-HabbitRoutineResult/hrr-server

Length of output: 2109


🏁 Script executed:

# Let's check the exact content around line 173 and also look at the CreateResponseDto section
sed -n '140,175p' ./src/main/java/com/hrr/backend/domain/verification/dto/VerificationResponseDto.java

Repository: Hrr-HabbitRoutineResult/hrr-server

Length of output: 1294


🏁 Script executed:

# Also check the CreateResponseDto section (around line 125-129)
sed -n '110,135p' ./src/main/java/com/hrr/backend/domain/verification/dto/VerificationResponseDto.java

Repository: Hrr-HabbitRoutineResult/hrr-server

Length of output: 1021


🏁 Script executed:

# Let's also check if there are any ZonedDateTime or Instant fields to understand the full picture
rg 'ZonedDateTime|Instant' --type java ./src/main/java/com/hrr/backend/domain/verification/dto/VerificationResponseDto.java -n

Repository: Hrr-HabbitRoutineResult/hrr-server

Length of output: 60


🏁 Script executed:

# Check for any timezone-related configuration in the project
rg 'TimeZone|ZoneId|spring.jackson' --type java --type properties -n | head -20

Repository: Hrr-HabbitRoutineResult/hrr-server

Length of output: 112


🏁 Script executed:

# Check for any application.properties or application.yml files with Jackson configuration
find . -name "application*.properties" -o -name "application*.yml" -o -name "application*.yaml" | head -5

Repository: Hrr-HabbitRoutineResult/hrr-server

Length of output: 242


🏁 Script executed:

# Let's also see the entire HistoryDto class to understand the context better
sed -n '141,175p' ./src/main/java/com/hrr/backend/domain/verification/dto/VerificationResponseDto.java | cat -n

Repository: Hrr-HabbitRoutineResult/hrr-server

Length of output: 1538


🏁 Script executed:

# Check the Jackson configuration in application.yml
cat ./src/main/resources/application.yml | grep -A 20 "jackson:" || echo "No jackson config found"

Repository: Hrr-HabbitRoutineResult/hrr-server

Length of output: 428


verifiedAt의 JsonFormat 패턴에서 타임존 표현을 수정하세요

Line 173의 @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'") 패턴이 문제입니다. verifiedAtLocalDateTime 타입(타임존 정보 없음)인데, 'Z' 리터럴을 추가하면 UTC를 의미하는 신호를 보냅니다.

실제 상황:

  • 프로젝트 전역 Jackson 설정은 time-zone: Asia/Seoul (KST)
  • LocalDateTime 값이 "2025-09-18T08:00:00Z" 형태로 직렬화되지만, 실제 타임존은 KST
  • API 소비자는 'Z'를 보고 UTC로 잘못 해석할 가능성이 높음

같은 DTO 파일의 CreateResponseDto (line 126-129)는 "yyyy-MM-dd HH:mm:ss" 패턴을 사용하여 일관성도 떨어집니다.

개선 방향:

  1. 권장: 패턴에서 'Z' 제거 → "yyyy-MM-dd'T'HH:mm:ss" (다른 timestamp 필드와도 통일)
  2. 또는: 타임존 정보가 필요하면 필드를 Instant 또는 ZonedDateTime으로 변경하고 명확한 타임존 설정

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: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/main/java/com/hrr/backend/domain/verification/service/VerificationServiceImpl.java (1)

279-315: 메서드 시그니처가 누락된 고아 코드 블록이 파이프라인 실패 원인입니다 🚨

Line 278에서 determineTargetDateTime 메서드가 종료된 후, line 279부터 메서드 선언 없이 메서드 본문 코드가 바로 시작됩니다. 이는 getVerificationDetail 메서드를 제거하는 과정에서 메서드 시그니처만 삭제하고 본문은 남겨둔 것으로 보입니다.

이로 인해 Java 컴파일러가 "illegal start of type" 오류를 발생시키며, 이것이 파이프라인 실패의 근본 원인입니다.

해결 방법:

  1. Line 59의 인터페이스에서 getVerificationDetail 메서드 선언을 완전히 제거하거나
  2. Line 279-315의 고아 코드 블록을 완전히 삭제해야 합니다
🔧 제안하는 수정안 (코드 블록 제거)
     private LocalDateTime determineTargetDateTime(Challenge challenge, Long roundId) {
         LocalTime now = LocalTime.now();
         LocalTime start = challenge.getVerifyStartTime();
         LocalTime end = challenge.getVerifyEndTime();
 
         boolean isVerificationTime;
         if (start.isBefore(end)) {
             isVerificationTime = !now.isBefore(start) && !now.isAfter(end);
         } else {
             isVerificationTime = !now.isBefore(start) || !now.isAfter(end);
         }
 
         if (isVerificationTime) {
             return LocalDateTime.now();
         } else {
             return verificationRepository.findLatestVerificationTime(
                     roundId,
                     VerificationStatus.COMPLETED
             );
         }
     }
 
-		// 차단된 게시글 접근 시 예외 발생
-		if (verification.getStatus() == VerificationStatus.BLOCKED) {
-			throw new GlobalException(ErrorCode.ACCESS_DENIED_REPORTED_POST);
-		}
-
-        RoundRecord roundRecord = verification.getRoundRecord();
-        UserChallenge userChallenge = roundRecord.getUserChallenge();
-        User author = userChallenge.getUser();
-
-        boolean isMine = currentUserId != null && author.getId().equals(currentUserId);
-        boolean isResolved = Boolean.TRUE.equals(verification.getIsResolved());
-        boolean canEdit = isMine && !isResolved;
-        boolean canDelete = isMine && !isResolved;
-
-        boolean canSelectComment =
-                isMine
-                        && Boolean.TRUE.equals(verification.getIsQuestion())
-                        && !isResolved;
-        Pageable pageable = PageRequest.of(page, size);
-        CommentListResponseDto comments = commentService.getComments(verificationId, pageable);
-
-        Long adoptedCommentId = comments.getComments().stream()
-                .filter(CommentResponseDto::isAdopted)
-                .map(CommentResponseDto::getCommentId)
-                .findFirst()
-                .orElse(null);
-
-        return verificationConverter.toDetailDto(
-                verification,
-                comments,
-                isMine,
-                canEdit,
-                canDelete,
-                canSelectComment,
-                adoptedCommentId
-        );
-    }
 
     @Transactional
     @Override
♻️ Duplicate comments (1)
src/main/java/com/hrr/backend/domain/verification/converter/VerificationConverter.java (1)

172-187: photoUrl과 textUrl의 S3 URL 변환이 누락되었습니다

이전 리뷰에서 이미 지적된 사항입니다. 같은 클래스 내 다른 변환 메서드들(toFeedDto line 35-36, toResponseDto line 79, toDetailDto line 120)은 모두 s3UrlUtil.toFullUrl()을 사용하여 S3 키를 전체 URL로 변환하는데, toHistoryDto만 line 183, 184에서 직접 getter를 호출하고 있습니다.

프론트엔드가 S3 키가 아닌 전체 URL을 기대한다면 일관성을 맞춰야 합니다.

🔧 제안하는 수정안
 public VerificationResponseDto.HistoryDto toHistoryDto(Verification verification) {
+    String photoUrl = verification.getPhotoUrl() != null 
+            ? s3UrlUtil.toFullUrl(verification.getPhotoUrl()) 
+            : null;
+    String textUrl = verification.getTextUrl() != null
+            ? s3UrlUtil.toFullUrl(verification.getTextUrl())
+            : null;
+
     return VerificationResponseDto.HistoryDto.builder()
             .verificationId(verification.getId())
             .challengeId(verification.getRoundRecord().getUserChallenge().getChallenge().getId())
             .challengeTitle(verification.getRoundRecord().getUserChallenge().getChallenge().getTitle())
             .type(verification.getType().name())
             .title(verification.getTitle())
             .content(verification.getContent())
-            .photoUrl(verification.getPhotoUrl())
-            .textUrl(verification.getTextUrl())
+            .photoUrl(photoUrl)
+            .textUrl(textUrl)
             .verifiedAt(verification.getCreatedAt())
             .build();
 }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2b58415 and 8cadf98.

📒 Files selected for processing (4)
  • src/main/java/com/hrr/backend/domain/verification/converter/VerificationConverter.java
  • src/main/java/com/hrr/backend/domain/verification/repository/VerificationRepository.java
  • src/main/java/com/hrr/backend/domain/verification/service/VerificationService.java
  • src/main/java/com/hrr/backend/domain/verification/service/VerificationServiceImpl.java
🧰 Additional context used
🧬 Code graph analysis (1)
src/main/java/com/hrr/backend/domain/verification/converter/VerificationConverter.java (1)
src/main/java/com/hrr/backend/domain/verification/dto/VerificationResponseDto.java (1)
  • VerificationResponseDto (16-176)
🪛 GitHub Actions: CI
src/main/java/com/hrr/backend/domain/verification/service/VerificationServiceImpl.java

[error] 280-465: gradlew clean build -x test failed: Java compilation errors in VerificationServiceImpl.java (illegal start of type and cascading errors likely due to mismatched braces or misplaced code). See compiler output for details.

🔇 Additional comments (2)
src/main/java/com/hrr/backend/domain/verification/service/VerificationService.java (1)

67-74: 인증 이력 조회 메서드 시그니처가 명확합니다

메서드 시그니처가 깔끔하고, 파라미터 구성도 적절합니다. SliceResponseDto 사용으로 커서 기반 페이징을 지원하는 것도 좋은 선택입니다.

src/main/java/com/hrr/backend/domain/verification/service/VerificationServiceImpl.java (1)

439-465: 인증 이력 조회 로직이 잘 구현되었습니다

사용자 검증, 페이징 처리, 엔티티-DTO 변환, 그리고 SliceResponseDto 래핑까지 모든 단계가 명확하게 구현되어 있습니다. 코드 가독성도 좋고 주석도 적절합니다.

단, line 279-315의 고아 코드 블록을 제거하면 정상적으로 컴파일될 것입니다.

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: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/main/java/com/hrr/backend/domain/verification/service/VerificationServiceImpl.java (1)

279-315: 🚨 [빌드 실패] 메서드 시그니처 없이 본문만 남아있음

Pipeline 로그에서 다수의 컴파일 에러가 발생하고 있습니다. Line 279-315 코드가 메서드 선언 없이 클래스 본문에 직접 작성되어 있습니다.

AI 요약에 따르면 getVerificationDetail 메서드가 삭제되었는데, 메서드 시그니처만 삭제되고 본문은 그대로 남아있는 상태입니다.

해결 방안:

  1. 해당 메서드가 필요한 경우: 메서드 시그니처를 복원
  2. 해당 메서드가 불필요한 경우: lines 279-436의 orphaned 코드 전체 삭제
#!/bin/bash
# 확인: getVerificationDetail 메서드가 다른 곳에서 사용되는지 검색
rg -n "getVerificationDetail" --type java
🧹 Nitpick comments (1)
src/main/java/com/hrr/backend/domain/verification/dto/VerificationResponseDto.java (1)

157-158: type 필드를 VerificationPostType enum으로 변경 권장

같은 파일의 FeedDto(line 29)와 relevant_code_snippetsListItemVerificationPostType enum을 사용합니다. 일관성과 타입 안전성을 위해 enum 사용을 권장합니다.

🔧 제안하는 수정안
-        @Schema(description = "인증 타입", example = "TEXT", allowableValues = {"TEXT", "CAMERA"})
-        private String type;
+        @Schema(description = "인증 타입", example = "TEXT")
+        private VerificationPostType type;
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8cadf98 and b0b579d.

📒 Files selected for processing (4)
  • src/main/java/com/hrr/backend/domain/verification/converter/VerificationConverter.java
  • src/main/java/com/hrr/backend/domain/verification/dto/VerificationResponseDto.java
  • src/main/java/com/hrr/backend/domain/verification/repository/VerificationRepository.java
  • src/main/java/com/hrr/backend/domain/verification/service/VerificationServiceImpl.java
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/com/hrr/backend/domain/verification/converter/VerificationConverter.java
🧰 Additional context used
🧬 Code graph analysis (1)
src/main/java/com/hrr/backend/domain/verification/dto/VerificationResponseDto.java (4)
src/main/java/com/hrr/backend/domain/verification/dto/VerificationRequestDto.java (1)
  • Getter (9-26)
src/main/java/com/hrr/backend/domain/verification/dto/VerificationRequestPhotoDto.java (1)
  • Getter (8-24)
src/main/java/com/hrr/backend/domain/verification/dto/VerificationListResponseDto.java (3)
  • Getter (12-51)
  • Getter (15-40)
  • Getter (43-50)
src/main/java/com/hrr/backend/domain/verification/dto/VerificationMyResponseDto.java (2)
  • Getter (16-38)
  • Getter (43-49)
🪛 GitHub Actions: CI
src/main/java/com/hrr/backend/domain/verification/service/VerificationServiceImpl.java

[error] 280-280: illegal start of type


[error] 306-313: expected / syntax error likely due to previous brace/missing context in return verificationConverter.toDetailDto( ... ) block


[error] 319-319: class, interface, enum, or record expected


[error] 326-331: class, interface, enum, or record expected


[error] 338-343: class, interface, enum, or record expected


[error] 350-356: class, interface, enum, or record expected


[error] 361-368: class, interface, enum, or record expected


[error] 389-399: class, interface, enum, or record expected


[error] 405-468: class, interface, enum, or record expected

🔇 Additional comments (2)
src/main/java/com/hrr/backend/domain/verification/service/VerificationServiceImpl.java (1)

439-468: LGTM! 인증 기록 조회 로직이 잘 구현되었습니다 👍

사용자 조회 → 페이지네이션 → Repository 조회 → DTO 변환 → 응답 반환 흐름이 명확하고, 기존 패턴(getMyVerificationProfile 등)과 일관성 있게 구현되었습니다.

src/main/java/com/hrr/backend/domain/verification/repository/VerificationRepository.java (1)

174-188: 쿼리 구현이 적절합니다. BLOCKED 필터는 호출처에서 상태를 제어하는 방식으로 처리됩니다.

FETCH JOIN과 파라미터화된 status 조건이 잘 구현되었습니다. 같은 파일의 일부 쿼리(findByRoundIdAndUserChallengeId, findByRoundId, findByUserIdAndChallengeId)는 v.status != 'BLOCKED'를 하드코딩하지만, 이 쿼리는 의도적으로 다른 패턴을 따릅니다.

현재 구현은 파라미터화된 상태 필터를 사용하여 호출처(VerificationServiceImpl)가 명시적으로 COMPLETED 상태를 전달함으로써 BLOCKED 레코드를 제외합니다. 이는 하드코딩된 필터보다 유연한 설계이며, 향후 다른 상태로 필터링할 필요가 있을 때 더 쉽게 확장할 수 있습니다.

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

Labels

예린 🌟 feat 새로운 기능 개발

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEAT] 내 인증기록 조회 API 구현

3 participants