-
Notifications
You must be signed in to change notification settings - Fork 0
[feat] : 가이드 확인 여부를 조회/저장/삭제한다 #300
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Walkthrough사용자 가이드 조회 로그 기능을 추가합니다: GuideViewLog 엔티티·레포지토리·DTO·GuideType 열거형을 도입하고, UserService와 UserController에 생성/조회/삭제 엔드포인트 및 로직을 추가하며, 관련 성공/오류 상태와 테스트·회원탈퇴 정리 로직을 확장했습니다. Changes
Sequence Diagram(s)sequenceDiagram
actor Client
participant UserController
participant UserService
participant GuideViewLogRepository
participant Database
rect rgb(235,247,255)
Note over Client,Database: 생성 흐름
Client->>UserController: POST /guides/view-log (guideType)
UserController->>UserService: createGuideViewLog(request)
UserService->>UserService: 현재 사용자 조회
UserService->>GuideViewLogRepository: existsByUserAndGuideType(user, guideType)
GuideViewLogRepository->>Database: SELECT exists...
Database-->>GuideViewLogRepository: 존재 여부
alt 이미 조회됨
GuideViewLogRepository-->>UserService: true
UserService-->>UserController: throw CustomException(_IS_ALREADY_VIEWED_GUIDE)
UserController-->>Client: 409 CONFLICT
else 미조회
GuideViewLogRepository-->>UserService: false
UserService->>GuideViewLogRepository: save(GuideViewLog)
GuideViewLogRepository->>Database: INSERT
Database-->>GuideViewLogRepository: 저장 완료
UserService-->>UserController: 성공
UserController-->>Client: 201 CREATED
end
end
rect rgb(235,255,235)
Note over Client,Database: 조회 흐름
Client->>UserController: GET /guides/view-log?guide_type=...
UserController->>UserService: getGuideViewLog(guideType)
UserService->>UserService: 현재 사용자 조회
UserService->>GuideViewLogRepository: existsByUserAndGuideType(user, guideType)
GuideViewLogRepository->>Database: SELECT exists...
Database-->>GuideViewLogRepository: boolean
GuideViewLogRepository-->>UserService: boolean
UserService-->>UserController: GetGuideViewLogResponse(isViewed)
UserController-->>Client: 200 OK
end
rect rgb(255,245,235)
Note over Client,Database: 삭제 흐름
Client->>UserController: DELETE /guides/view-log
UserController->>UserService: deleteGuideViewLog()
UserService->>UserService: 현재 사용자 조회
UserService->>GuideViewLogRepository: findByUser(user)
GuideViewLogRepository->>Database: SELECT ...
Database-->>GuideViewLogRepository: Optional<GuideViewLog>
alt 존재
GuideViewLogRepository-->>UserService: GuideViewLog
UserService->>GuideViewLogRepository: delete(guideViewLog)
GuideViewLogRepository->>Database: DELETE
Database-->>GuideViewLogRepository: 삭제 완료
UserService-->>UserController: 성공
UserController-->>Client: 200 OK
else 미존재
GuideViewLogRepository-->>UserService: empty
UserService-->>UserController: throw CustomException(_NOT_FOUND_GUIDE)
UserController-->>Client: 404 NOT FOUND
end
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🧹 Nitpick comments (5)
src/main/java/side/onetime/domain/GuideViewStatus.java (3)
42-48: 엔티티 생성자에서LocalDateTime.now()사용을 고려해보세요.엔티티 생성자 내에서
LocalDateTime.now()를 직접 호출하면 테스트 작성이 어려워지고 시간대 관련 문제가 발생할 수 있습니다. 서비스 계층에서 타임스탬프를 생성하여 전달하거나, 별도의 시간 제공 컴포넌트를 사용하는 것을 권장합니다.다음과 같이 리팩토링할 수 있습니다:
@Builder -public GuideViewStatus(User user, GuideType guideType) { +public GuideViewStatus(User user, GuideType guideType, LocalDateTime viewedAt) { this.user = user; this.guideType = guideType; this.isViewed = true; - this.viewedAt = LocalDateTime.now(); + this.viewedAt = viewedAt; }그리고 서비스 계층에서 호출 시:
GuideViewStatus guideViewStatus = GuideViewStatus.builder() .user(user) .guideType(guideType) .viewedAt(LocalDateTime.now()) .build();
36-37:Boolean래퍼 타입 대신boolean원시 타입 사용을 고려하세요.
nullable = false제약 조건이 있으므로Boolean래퍼 타입 대신boolean원시 타입을 사용하는 것이 더 적합합니다.-@Column(name = "is_viewed", nullable = false) -private Boolean isViewed; +@Column(name = "is_viewed", nullable = false) +private boolean isViewed;
36-40:isViewed필드의 필요성을 재검토하세요.현재 설계에서
GuideViewStatus엔티티가 생성되면isViewed는 항상true로 설정됩니다. 엔티티의 존재 자체가 가이드를 확인했음을 의미한다면, 이 필드는 중복될 수 있습니다.viewedAt필드만으로도 확인 여부와 시점을 모두 표현할 수 있습니다.향후 "미확인" 상태를 추적할 계획이 없다면, 이 필드를 제거하고 엔티티 존재 여부로 확인 상태를 판단하는 것을 고려해보세요.
src/main/java/side/onetime/service/UserService.java (2)
206-231: 변수명을 더 명확하게 변경하는 것을 고려하세요.Line 220의
isViewed변수명이 다소 혼란스럽습니다.existsByUserAndGuideType메서드는 레코드의 존재 여부를 반환하므로,exists또는alreadyExists같은 이름이 더 의도를 명확히 전달합니다.-boolean isViewed = guideViewStatusRepository.existsByUserAndGuideType(user, guideType); -if (isViewed) { +boolean exists = guideViewStatusRepository.existsByUserAndGuideType(user, guideType); +if (exists) { throw new CustomException(UserErrorStatus._IS_ALREADY_VIEWED_GUIDE); }
233-248: 변수명을 더 명확하게 변경하는 것을 고려하세요.Line 246의
isViewed변수명이 혼란스러울 수 있습니다.existsByUserAndGuideType은 레코드 존재 여부를 확인하므로, 변수명을exists로 변경하면 코드 의도가 더 명확해집니다. 다만 최종 반환값은 존재 여부가 곧 확인 여부를 의미하므로 로직은 정확합니다.-boolean isViewed = guideViewStatusRepository.existsByUserAndGuideType(user, guideType); -return GetGuideViewStatusResponse.from(isViewed); +boolean exists = guideViewStatusRepository.existsByUserAndGuideType(user, guideType); +return GetGuideViewStatusResponse.from(exists);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (11)
src/main/java/side/onetime/controller/UserController.java(2 hunks)src/main/java/side/onetime/domain/GuideViewStatus.java(1 hunks)src/main/java/side/onetime/domain/enums/GuideType.java(1 hunks)src/main/java/side/onetime/dto/user/request/CreateGuideViewStatusRequest.java(1 hunks)src/main/java/side/onetime/dto/user/response/GetGuideViewStatusResponse.java(1 hunks)src/main/java/side/onetime/exception/status/UserErrorStatus.java(1 hunks)src/main/java/side/onetime/global/common/status/SuccessStatus.java(1 hunks)src/main/java/side/onetime/repository/GuideViewStatusRepository.java(1 hunks)src/main/java/side/onetime/repository/custom/UserRepositoryImpl.java(2 hunks)src/main/java/side/onetime/service/UserService.java(3 hunks)src/test/java/side/onetime/user/UserControllerTest.java(2 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/main/java/side/onetime/exception/status/UserErrorStatus.java (4)
src/main/java/side/onetime/global/common/status/ErrorStatus.java (1)
Override(36-44)src/main/java/side/onetime/exception/status/FixedErrorStatus.java (2)
Override(22-29)Getter(9-40)src/main/java/side/onetime/exception/status/AdminErrorStatus.java (2)
Override(31-38)Override(40-48)src/main/java/side/onetime/exception/status/EventErrorStatus.java (1)
Getter(9-41)
src/main/java/side/onetime/service/UserService.java (1)
src/main/java/side/onetime/util/UserAuthorizationUtil.java (1)
UserAuthorizationUtil(9-32)
⏰ 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: Build and Push to ECR
🔇 Additional comments (7)
src/main/java/side/onetime/domain/enums/GuideType.java (1)
1-7: 구현이 올바릅니다GuideType enum이 적절하게 정의되었습니다. 단일 상수로 시작하는 것은 합리적이며, 향후 추가 가이드 타입을 쉽게 확장할 수 있는 구조입니다.
src/main/java/side/onetime/exception/status/UserErrorStatus.java (1)
16-16: 적절한 에러 상태 정의이미 조회한 가이드에 대한 에러 상태가 올바르게 정의되었습니다. HTTP 409 CONFLICT 상태 코드는 중복 리소스 생성 시나리오에 적합합니다.
src/main/java/side/onetime/dto/user/response/GetGuideViewStatusResponse.java (1)
13-15: 간결한 팩토리 메서드 구현
from메서드가 명확하고 간결하게 구현되었습니다.src/main/java/side/onetime/repository/GuideViewStatusRepository.java (1)
1-11: 올바른 Repository 구현Spring Data JPA 네이밍 컨벤션을 따르는 적절한 repository 인터페이스입니다.
existsByUserAndGuideType메서드는 중복 체크에 효율적입니다.src/main/java/side/onetime/global/common/status/SuccessStatus.java (1)
56-57: 적절한 성공 상태 정의가이드 조회 상태 API에 대한 성공 상태가 올바르게 정의되었습니다. HTTP 상태 코드가 적절하게 사용되었습니다 (생성: 201, 조회: 200).
src/main/java/side/onetime/controller/UserController.java (1)
176-191: 가이드 조회 상태 API 구현 확인가이드 확인 여부 조회 엔드포인트가 적절하게 구현되었습니다. query parameter의 snake_case 네이밍(
guide_type)은 프로젝트의 JSON 네이밍 전략과 일관성이 있습니다.src/test/java/side/onetime/user/UserControllerTest.java (1)
460-539: 테스트 구현이 잘 되어 있습니다!두 개의 새로운 테스트 메서드(
createGuideViewStatus,getGuideViewStatus)가 모두 적절하게 구현되어 있습니다:
- 적절한 모킹 사용
- 응답 검증 포함
- REST Docs 설정 완료
- 기존 테스트 패턴 준수
src/main/java/side/onetime/dto/user/request/CreateGuideViewStatusRequest.java
Outdated
Show resolved
Hide resolved
src/main/java/side/onetime/dto/user/response/GetGuideViewStatusResponse.java
Outdated
Show resolved
Hide resolved
src/main/java/side/onetime/repository/custom/UserRepositoryImpl.java
Outdated
Show resolved
Hide resolved
bbbang105
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
코드가 깔끔하게 잘 짜진 것 같습니다 👍🏻
| .build() | ||
| ) | ||
| )); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
여기에 400 409 예외 처리 테스트 코드도 추가해주시면 좋을 것 같아요~!
제가 이번에 에타 기능 개선하면서 예외 케이스도 테스트 코드로 추가해봤는데 가능하더라구요
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
400
{
"code": "E_BAD_REQUEST",
"message": "올바르지 않은 enum 값입니다. 허용되지 않은 값: SCHEDULE_GUIDE_MODAL_0013232",
"is_success": false
}There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
409
{
"code": "USER-005",
"message": "이미 조회한 가이드입니다.",
"is_success": false
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
src/test/java/side/onetime/user/UserControllerTest.java (1)
561-600: 가이드 조회 테스트에 payload 검증과 문서 필드를 조금만 보강하면 좋겠습니다현재 성공 메타데이터(
is_success,code,message)만 검증하고 있어, 실제 페이로드인payload.is_viewed값도 함께 검증하면 회귀를 더 잘 잡을 수 있습니다. 또한 다른 테스트들처럼payload객체 자체에 대한 필드 설명을 추가하면 RestDocs 문서도 더 일관됩니다. 예시는 아래처럼 수정할 수 있습니다.@@ - mockMvc.perform(RestDocumentationRequestBuilders.get("/api/v1/users/guides/view-status") + mockMvc.perform(RestDocumentationRequestBuilders.get("/api/v1/users/guides/view-status") .queryParam("guide_type", guideType.name()) .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(jsonPath("$.is_success").value(true)) .andExpect(jsonPath("$.code").value("200")) .andExpect(jsonPath("$.message").value("유저 가이드 확인 여부 조회에 성공했습니다.")) + .andExpect(jsonPath("$.payload.is_viewed").value(true)) @@ - .responseFields( - fieldWithPath("is_success").type(JsonFieldType.BOOLEAN).description("성공 여부"), - fieldWithPath("code").type(JsonFieldType.STRING).description("응답 코드"), - fieldWithPath("message").type(JsonFieldType.STRING).description("응답 메시지"), - fieldWithPath("payload.is_viewed").type(JsonFieldType.BOOLEAN).description("가이드 확인 여부") - ) + .responseFields( + fieldWithPath("is_success").type(JsonFieldType.BOOLEAN).description("성공 여부"), + fieldWithPath("code").type(JsonFieldType.STRING).description("응답 코드"), + fieldWithPath("message").type(JsonFieldType.STRING).description("응답 메시지"), + fieldWithPath("payload").type(JsonFieldType.OBJECT).description("응답 데이터"), + fieldWithPath("payload.is_viewed").type(JsonFieldType.BOOLEAN).description("가이드 확인 여부") + )
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
src/main/java/side/onetime/controller/UserController.java(2 hunks)src/main/java/side/onetime/exception/status/UserErrorStatus.java(1 hunks)src/main/java/side/onetime/global/common/status/SuccessStatus.java(1 hunks)src/main/java/side/onetime/repository/GuideViewStatusRepository.java(1 hunks)src/main/java/side/onetime/service/UserService.java(3 hunks)src/test/java/side/onetime/user/UserControllerTest.java(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
- src/main/java/side/onetime/repository/GuideViewStatusRepository.java
- src/main/java/side/onetime/exception/status/UserErrorStatus.java
- src/main/java/side/onetime/controller/UserController.java
- src/main/java/side/onetime/service/UserService.java
⏰ 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: Deploy to Server
🔇 Additional comments (7)
src/test/java/side/onetime/user/UserControllerTest.java (6)
18-27: 가이드 뷰 상태 기능을 위한 import 구성 적절합니다새로 추가된
GuideType, 요청/응답 DTO,CustomException,UserErrorStatus,parameterWithName정적 import 모두 아래 테스트들에서 실제로 사용되고 있어 불필요한 의존성 없이 잘 정리된 것 같습니다.
462-500: 가이드 확인 여부 저장 성공 플로우 테스트 구조가 일관적입니다성공 케이스에서
201응답, 코드"201", 메시지와 RestDocs 요청/응답 스펙을 모두 검증하고 있어 기존 User API 테스트들과 일관되고 충분한 수준으로 보입니다.
502-527: 잘못된 GuideType에 대한 400 오류 테스트가 명확합니다유효하지 않은 enum 값을 직접 JSON 문자열로 구성해서
E_BAD_REQUEST코드와 상세 메시지까지 검증하고 있어, enum 바인딩 실패 시의 동작을 안정적으로 커버하고 있습니다.
529-559: 이미 조회한 가이드 409 충돌 케이스 테스트도 적절합니다
CustomException(UserErrorStatus._IS_ALREADY_VIEWED_GUIDE)를 모킹해 409,"USER-005", 메시지까지 검증하는 흐름이 명확하고, 에러 응답 포맷까지 잘 확인하고 있습니다.
602-632: 가이드 확인 여부 삭제 성공 케이스 테스트가 간결하게 잘 작성되었습니다서비스 모킹, 200 응답/코드/메시지 검증, 공통 성공 응답 스키마 문서화까지 깔끔하게 정리되어 있어 추가로 손볼 부분은 없어 보입니다.
634-659: 가이드 미존재 시 404 처리 테스트가 기대 동작을 잘 검증합니다
_NOT_FOUND_GUIDE예외를 통해 404,"USER-006", 메시지까지 모두 확인하고 있고, 실패 케이스에 대한 RestDocs 스니펫도 추가되어 있어 에러 플로우 커버리지가 충분합니다.src/main/java/side/onetime/global/common/status/SuccessStatus.java (1)
56-58: 가이드 뷰 상태용 SuccessStatus 상수들이 컨트롤러/테스트와 잘 정합됩니다
_CREATE_GUIDE_VIEW_STATUS(201),_GET_GUIDE_VIEW_STATUS(200),_DELETE_GUIDE_VIEW_STATUS(200)의 HTTP 상태, 코드 문자열, 한글 메시지가 각각 대응하는 컨트롤러 응답 및 테스트에서 기대하는 값과 정확히 일치해 일관성이 좋습니다.
There was a problem hiding this 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
🧹 Nitpick comments (3)
src/main/java/side/onetime/repository/GuideViewLogRepository.java (1)
10-15: 향후 GuideType 확장 시findByUser사용부 설계 점검 필요지금 구조(GuideType 값이 1개)에서는
findByUser(User user)로 단일 로그를 조회/삭제해도 문제가 없지만,
엔티티 제약 조건이(users_id, guide_type)복합 유니크인 만큼, 추후 GuideType 이 늘어나면 한 유저가 여러 가이드 로그를 가질 수 있게 됩니다.그 시점에는:
- 삭제/조회 용도로
findByUserAndGuideType(User user, GuideType guideType)또는- “해당 유저의 모든 가이드 로그 삭제” 용도로
void deleteAllByUser(User user)와 같이 의도를 더 명확히 드러내는 메서드를 추가하는 쪽이 안전할 것 같습니다. 현재 PR 범위에서는 그대로 두셔도 동작에는 문제가 없고, 확장 시점에 함께 리팩터링하는 것을 추천드립니다.
src/main/java/side/onetime/service/UserService.java (1)
250-264: 삭제 대상 가이드 범위(단일/전체)에 대한 스펙 명확화와 시그니처 개선 여지현재
deleteGuideViewLog()는:
- guideType 파라미터 없이 “해당 유저의 가이드 조회 로그 하나”를 찾기 위해
findByUser(user)를 사용하고,- 없으면
_NOT_FOUND_GUIDE예외를 던지는 구조입니다.지금은
GuideType이 1개뿐이라 동작에는 문제가 없지만, 추후 타입이 늘어나면:
- “특정 guideType 의 로그를 삭제하는 API” 인지,
- “해당 유저의 모든 가이드 로그를 일괄 삭제하는 API” 인지
스펙을 다시 정해야 할 것 같습니다.
그에 따라:
- 전자라면
deleteGuideViewLog(GuideType guideType)+findByUserAndGuideType(user, guideType)형태로 좁히고,- 후자라면
guideViewLogRepository.deleteAllByUser(user)처럼 “전체 삭제” 를 명확하게 드러내는 쪽이 이해하기 더 쉬울 것 같습니다.현재 PR 범위에서는 그대로 두셔도 되지만, GuideType 확장 시점에 함께 리팩터링하는 것을 권장드립니다.
src/test/java/side/onetime/user/UserControllerTest.java (1)
561-600: getGuideViewLog 테스트에서 payload 내용 및 문서 스키마를 조금 더 엄밀히 검증하면 좋겠습니다현재 테스트는 상태 코드·공통 필드만 검증하고 있어, 실제 비즈니스 값인
payload.is_viewed에 대한 보장이 없습니다. 또한 RestDocs 에서는payload.is_viewed만 정의하고payload객체 자체는 누락되어 있어 기존 문서들과 약간 불균형해 보입니다.아래처럼 작은 수정 제안드립니다.
mockMvc.perform(RestDocumentationRequestBuilders.get("/api/v1/users/guides/view-log") .queryParam("guide_type", guideType.name()) .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(jsonPath("$.is_success").value(true)) .andExpect(jsonPath("$.code").value("200")) .andExpect(jsonPath("$.message").value("유저 가이드 조회 로그 조회에 성공했습니다.")) + .andExpect(jsonPath("$.payload.is_viewed").value(true)) .andDo(MockMvcRestDocumentationWrapper.document("user/get-guide-view-log", @@ - .responseFields( + .responseFields( fieldWithPath("is_success").type(JsonFieldType.BOOLEAN).description("성공 여부"), fieldWithPath("code").type(JsonFieldType.STRING).description("응답 코드"), fieldWithPath("message").type(JsonFieldType.STRING).description("응답 메시지"), + fieldWithPath("payload").type(JsonFieldType.OBJECT).description("응답 데이터"), fieldWithPath("payload.is_viewed").type(JsonFieldType.BOOLEAN).description("가이드 조회 여부") )이렇게 하면 실제 반환 모델과 테스트/문서가 더 강하게 동기화될 것 같습니다.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
src/main/java/side/onetime/controller/UserController.java(2 hunks)src/main/java/side/onetime/domain/GuideViewLog.java(1 hunks)src/main/java/side/onetime/dto/user/request/CreateGuideViewLogRequest.java(1 hunks)src/main/java/side/onetime/dto/user/response/GetGuideViewLogResponse.java(1 hunks)src/main/java/side/onetime/global/common/status/SuccessStatus.java(1 hunks)src/main/java/side/onetime/repository/GuideViewLogRepository.java(1 hunks)src/main/java/side/onetime/repository/custom/UserRepositoryImpl.java(2 hunks)src/main/java/side/onetime/service/UserService.java(3 hunks)src/test/java/side/onetime/user/UserControllerTest.java(2 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
src/main/java/side/onetime/domain/GuideViewLog.java (3)
src/main/java/side/onetime/domain/User.java (1)
Entity(17-122)src/main/java/side/onetime/global/common/dao/BaseEntity.java (1)
EntityListeners(15-28)src/main/java/side/onetime/global/config/JpaConfig.java (1)
Configuration(6-9)
src/main/java/side/onetime/service/UserService.java (1)
src/main/java/side/onetime/util/UserAuthorizationUtil.java (1)
UserAuthorizationUtil(9-32)
src/main/java/side/onetime/global/common/status/SuccessStatus.java (2)
src/main/java/side/onetime/global/common/status/ErrorStatus.java (1)
Getter(9-45)src/main/java/side/onetime/domain/enums/Status.java (1)
Status(3-6)
⏰ 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: Build and Push to ECR
🔇 Additional comments (13)
src/main/java/side/onetime/repository/custom/UserRepositoryImpl.java (1)
25-25: 탈퇴 시 GuideViewLog 삭제 로직 일관성 좋습니다
withdraw안에서guideViewLog를 다른 엔티티들과 동일한 패턴으로 정리해 주셔서, 유저 탈퇴 시 가이드 조회 로그가 남지 않는 구조가 명확합니다. 조건도guideViewLog.user.eq(activeUser)로 잘 잡혀 있습니다.Also applies to: 100-102
src/main/java/side/onetime/dto/user/response/GetGuideViewLogResponse.java (1)
7-14: 가이드 조회 여부 응답 DTO 설계 적절합니다
isViewed하나만을 노출하는 레코드 + SnakeCase 설정으로, 클라이언트 입장에서is_viewed플래그만 보면 되는 단순한 응답이 잘 정의되어 있습니다. 정적 팩토리from도 다른 DTO들과 일관된 패턴이라 유지보수에 좋습니다.src/main/java/side/onetime/dto/user/request/CreateGuideViewLogRequest.java (1)
9-14: 가이드 타입 요청 DTO와 검증 설정이 명확합니다
guide_type를 enumGuideType으로 받고@NotNull로 강제하는 구조라, 서비스 레이어에서 null 체크 분기가 필요 없고 API 계약도 분명합니다. Jackson 설정도 다른 User 관련 DTO들과 일관되어 보입니다.src/main/java/side/onetime/global/common/status/SuccessStatus.java (1)
56-58: 가이드 조회 로그용 성공 상태 코드 정의 적절합니다
CREATE/GET/DELETE각각에 대해 HTTP status(201/200)와 한글 메시지가 역할에 맞게 잘 분리되어 있고, User 도메인의 다른 성공 코드들과도 naming/pattern 이 일관적입니다.src/main/java/side/onetime/service/UserService.java (1)
29-31: 가이드 조회 여부를 “행 존재 여부”로 모델링한 서비스 로직이 요구사항에 잘 맞습니다
createGuideViewLog에서 로그인 유저 조회 →(user, guideType)기준 중복 여부 체크 → 중복 시 도메인 에러, 아니면 새 로그를 생성하는 플로우가 자연스럽습니다.getGuideViewLog는 단순히existsByUserAndGuideType결과를GetGuideViewLogResponse.from(isViewed)로 감싸 주기만 해서, “가이드 확인 여부 조회/저장” 이라는 요구사항을 과하지 않게 구현한 형태입니다.- 별도의
isViewed컬럼 없이, 레코드 존재 여부 = 조회 여부 로 처리하는 방향도 지금 도메인(조회 시점만 기록하면 되는 로그 성격)에는 잘 어울립니다.현재 범위 내에서는 비즈니스 로직과 트랜잭션 설정 모두 무난해 보입니다.
Also applies to: 206-231, 241-248
src/main/java/side/onetime/controller/UserController.java (1)
158-191: 가이드 조회 로그 생성/조회 엔드포인트 설계가 서비스 로직과 잘 맞습니다
- POST
/guides/view-log는@Valid CreateGuideViewLogRequest를 받아 별도 응답 바디 없이 상태 코드만 내려주는 패턴으로, 다른 User API들과 일관적입니다.- GET
/guides/view-log에서@RequestParam("guide_type") GuideType guideType으로 타입을 받는 부분도 DTO/enum 의 SnakeCase 설정(guide_type)과 잘 맞고,GetGuideViewLogResponse를 그대로 내려줘서 클라이언트가is_viewed만 보면 되도록 단순하게 정리되어 있습니다.컨트롤러 레이어에서는 특별한 이슈 없이 무난해 보입니다.
src/main/java/side/onetime/domain/GuideViewLog.java (1)
12-44: 엔티티와 응답 구조 간 혼동 – 실제 불일치 없음이 엔티티는 일관되게
guide_view_logs테이블로 매핑되어 있으며, 응답 DTO의is_viewed필드는 서비스 레이어에서 조회 여부를 boolean 값으로 계산하여 전달하는 것입니다. 엔티티에isViewed컬럼이 필요하지 않으며, "행이 존재하면 조회한 상태"라는 설계는 적절합니다.현재 코드베이스에서는
guide_view_status테이블이나 대체 DDL에 대한 참조를 찾을 수 없으며, 엔티티 매핑과 실제 사용 구조 간 불일치는 확인되지 않습니다.src/test/java/side/onetime/user/UserControllerTest.java (6)
18-27: 가이드 뷰 로그 테스트를 위한 import 추가 적절함추가된
GuideType, DTO wildcard,CustomException,UserErrorStatus,parameterWithNameimport 들이 아래 신규 테스트에서 모두 사용되고 있어 불필요한 의존성 없이 잘 정리된 상태입니다.
462-500: 가이드 조회 로그 생성 성공 케이스 테스트/문서화가 일관되게 잘 추가되었습니다정상 플로우에서 201 응답, 공통 응답 랩퍼 필드(
is_success,code,message)를 모두 검증하고, RestDocs 로 request/response 필드까지 문서화한 부분이 기존 User API 테스트들과 스타일도 잘 맞습니다.
502-527: 잘못된 GuideType 입력에 대한 400 케이스 테스트가 기대 스펙을 잘 커버합니다enum 바인딩 실패 시
E_BAD_REQUEST코드와 상세 메시지 포맷까지 검증해서, 글로벌 예외 핸들러 동작을 안정적으로 보장해 줄 수 있을 것 같습니다. JSON 문자열을 직접 구성한 것도 enum 직렬화 로직 변화에 독립적이라 괜찮은 선택입니다.
529-559: 이미 조회한 가이드(409) 예외 플로우 테스트 적절함
CustomException(UserErrorStatus._IS_ALREADY_VIEWED_GUIDE)를 직접 던지도록 모킹해서 409 +USER-005+ 한글 메시지를 모두 검증하고 있어, 서비스/예외 매핑이 깨질 경우 바로 감지할 수 있을 것 같습니다.
602-632: 가이드 조회 로그 삭제 성공 케이스 테스트/문서화도 기존 패턴과 잘 맞습니다
userService.deleteGuideViewLog()모킹 후 200 응답과 공통 응답 필드를 검증하고,CommonSuccessResponse스키마로 문서화한 부분이 다른 API들과 통일되어 있어 유지보수에 좋아 보입니다.
634-659: 가이드 조회 로그 없음(404) 예외 플로우 테스트가 적절히 추가되었습니다
_NOT_FOUND_GUIDE예외를 모킹해 404 +USER-006+ 한글 메시지를 검증하고 있어, 삭제 API의 에러 응답 계약을 충분히 커버하고 있습니다. 실패 케이스 RestDocs 스니펫까지 포함된 점도 좋습니다.
✅ PR 유형
🚀 작업 내용
📝️ 관련 이슈
💬 기타 사항 or 추가 코멘트
Summary by CodeRabbit
새로운 기능
버그 수정
✏️ Tip: You can customize this high-level summary in your review settings.