Conversation
Walkthrough인증된 사용자가 자신의 프로필 이름을 수정할 수 있는 PATCH 엔드포인트(/api/v1/users/me)와 관련 DTO, 도메인 메서드, 서비스 로직, 에러/성공 코드, 및 단위 테스트가 추가되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant C as Client
participant Ctrl as UserController
participant Svc as UserService
participant Repo as UserRepository
participant U as User Entity
C->>Ctrl: PATCH /api/v1/users/me\n{name: "새 이름"}
activate Ctrl
Ctrl->>Ctrl: `@Valid` 검증
Ctrl->>Ctrl: 인증정보에서 userId 추출
Ctrl->>Svc: updateUserProfile(userId, request)
deactivate Ctrl
activate Svc
Svc->>Repo: findById(userId)
Repo-->>Svc: User (or null)
alt User 존재
Svc->>U: updateProfile(name)
U-->>Svc: name 업데이트 (검증 실패 시 예외)
Svc->>Repo: (트랜잭션 커밋으로 영속성 반영)
Svc-->>Ctrl: UpdateUserProfileResponse(success=true)
else 없음
Svc-->>Ctrl: BaseException(USER_NOT_FOUND)
end
deactivate Svc
Ctrl-->>C: 200 OK / 4xx 에러 응답
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
src/main/java/com/almang/inventory/user/dto/response/UpdateUserProfileResponse.java (1)
3-5: 응답 필드명 일관성을 검토해보세요.현재 코드베이스에서 유사한 응답 DTO들의 필드명이 일관되지 않습니다:
LogoutResponse:boolean successChangePasswordResponse:boolean isChangedUpdateUserProfileResponse:boolean success(현재 파일)
LogoutResponse패턴을 따르고 있지만, 전체적으로 일관된 네이밍 컨벤션을 정하는 것을 고려해보세요. 예를 들어, 모든 변경 작업 응답에isXXXed형태를 사용하거나, 모두success로 통일하는 방식입니다.참고: 단순 boolean 필드보다는 HTTP 상태 코드로 충분한 경우가 많습니다.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
src/main/java/com/almang/inventory/global/api/SuccessMessage.java(1 hunks)src/main/java/com/almang/inventory/user/controller/UserController.java(2 hunks)src/main/java/com/almang/inventory/user/domain/User.java(1 hunks)src/main/java/com/almang/inventory/user/dto/request/UpdateUserProfileRequest.java(1 hunks)src/main/java/com/almang/inventory/user/dto/response/UpdateUserProfileResponse.java(1 hunks)src/main/java/com/almang/inventory/user/service/UserService.java(2 hunks)src/test/java/com/almang/inventory/user/controller/UserControllerTest.java(5 hunks)src/test/java/com/almang/inventory/user/service/UserServiceTest.java(2 hunks)
🧰 Additional context used
🧬 Code graph analysis (6)
src/main/java/com/almang/inventory/user/dto/response/UpdateUserProfileResponse.java (2)
src/main/java/com/almang/inventory/user/auth/dto/response/ChangePasswordResponse.java (1)
ChangePasswordResponse(3-5)src/main/java/com/almang/inventory/user/auth/dto/response/LogoutResponse.java (1)
LogoutResponse(3-5)
src/main/java/com/almang/inventory/user/controller/UserController.java (2)
src/test/java/com/almang/inventory/user/auth/controller/AuthControllerTest.java (1)
Test(150-173)src/main/java/com/almang/inventory/user/auth/controller/AuthController.java (1)
PostMapping(67-80)
src/main/java/com/almang/inventory/user/dto/request/UpdateUserProfileRequest.java (2)
src/main/java/com/almang/inventory/user/auth/dto/request/ChangePasswordRequest.java (1)
ChangePasswordRequest(5-7)src/main/java/com/almang/inventory/user/auth/dto/request/LoginRequest.java (1)
LoginRequest(5-8)
src/test/java/com/almang/inventory/user/controller/UserControllerTest.java (1)
src/test/java/com/almang/inventory/user/auth/controller/AuthControllerTest.java (6)
Test(150-173)WebMvcTest(38-261)Test(50-67)Test(87-103)Test(120-134)Test(136-148)
src/test/java/com/almang/inventory/user/service/UserServiceTest.java (1)
src/test/java/com/almang/inventory/user/auth/service/AuthServiceTest.java (2)
Test(135-148)Test(69-82)
src/main/java/com/almang/inventory/user/service/UserService.java (2)
src/main/java/com/almang/inventory/user/repository/UserRepository.java (1)
UserRepository(7-12)src/main/java/com/almang/inventory/user/auth/service/AuthService.java (2)
Transactional(41-51)Transactional(29-39)
🔇 Additional comments (8)
src/test/java/com/almang/inventory/user/service/UserServiceTest.java (2)
83-100: 테스트 검증이 잘 작성되었습니다! 🎯DB에서 실제 변경사항을 재조회하여 확인하는 부분(97-99번 줄)이 특히 좋습니다. 영속성 검증까지 포함된 탄탄한 테스트네요.
참고로, 95번 줄에서
assertThat(response).isNotNull()대신assertThat(response.success()).isTrue()로 명확하게 성공 여부를 검증하는 것도 고려해보세요.
102-112: 예외 처리 테스트가 적절합니다.기존 테스트 패턴(73-81번 줄)과 동일한 구조로 일관성이 유지되고 있습니다. 에러 케이스 커버리지도 충분합니다.
src/main/java/com/almang/inventory/global/api/SuccessMessage.java (1)
16-16: 성공 메시지 추가가 적절합니다.기존 패턴을 잘 따르고 있으며, 메시지 내용도 명확합니다.
src/test/java/com/almang/inventory/user/controller/UserControllerTest.java (3)
45-51: 좋은 리팩토링입니다! 👍중복된 인증 객체 생성 로직을 헬퍼 메서드로 추출하여 테스트 코드의 가독성이 향상되었습니다.
100-119: 컨트롤러 테스트가 꼼꼼하게 작성되었습니다.응답의 모든 필드를 검증하고 있으며, 인증 처리도 적절합니다. 기존 패턴을 잘 따르고 있네요.
140-154: 입력값 검증 테스트가 적절합니다.빈 문자열에 대한
@NotBlank검증을 테스트하고 있습니다.참고: User.java 리뷰에서 언급한 최대 길이 검증(
@Size(max = 20))을 DTO에 추가하면, 여기에도 길이 초과 케이스를 테스트하는 것을 권장합니다.src/main/java/com/almang/inventory/user/controller/UserController.java (1)
46-59: 컨트롤러 구현이 깔끔합니다! ✨기존 코드 패턴(AuthController의 changePassword)을 잘 따르고 있으며, 다음 사항들이 모두 적절하게 처리되었습니다:
@Valid를 통한 요청 검증@AuthenticationPrincipal을 통한 인증 사용자 정보 추출- 적절한 로깅
- 일관된 응답 구조
단,
UpdateUserProfileRequest에 최대 길이 검증(@Size(max = 20))이 추가되면 여기서 자동으로 검증이 수행됩니다.src/main/java/com/almang/inventory/user/service/UserService.java (1)
34-43: 서비스 로직이 탄탄하게 구현되었습니다! 💪다음 사항들이 모두 적절합니다:
@Transactional설정 (readOnly가 아님)findUserById를 통한 예외 처리- 적절한 로깅 (요청 시작/성공)
- 기존
AuthService.changePassword패턴과의 일관성트랜잭션 컨텍스트에서 엔티티 변경이 자동으로 영속화되는 JPA의 더티 체킹을 잘 활용하고 있습니다.
| public record UpdateUserProfileRequest( | ||
| @NotBlank String name | ||
| ) {} |
There was a problem hiding this comment.
최대 길이 검증이 누락되었습니다.
User 엔티티의 name 컬럼이 length = 20으로 제한되어 있지만(src/main/java/com/almang/inventory/user/domain/User.java:46), 요청 DTO에 최대 길이 검증이 없습니다.
20자를 초과하는 이름이 입력되면 데이터베이스 제약 조건 위반이 발생합니다.
해결 방법:
public record UpdateUserProfileRequest(
- @NotBlank String name
+ @NotBlank
+ @Size(max = 20, message = "이름은 20자를 초과할 수 없습니다")
+ String name
) {}필요한 import:
import jakarta.validation.constraints.Size;참고 자료:
- Bean Validation @Size 문서
- 기존 프로젝트의
LoginRequest나ChangePasswordRequest도 유사한 검증 패턴을 참고할 수 있습니다.
🤖 Prompt for AI Agents
In
src/main/java/com/almang/inventory/user/dto/request/UpdateUserProfileRequest.java
around lines 5 to 7, the DTO is missing a max-length validation for name which
can exceed the User entity column length (20) and cause DB constraint
violations; add jakarta.validation.constraints.Size(max = 20) to the name
parameter and add the import statement import
jakarta.validation.constraints.Size; so the record parameter becomes annotated
with @NotBlank and @Size(max = 20) to enforce the same limit at the request
level.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
src/main/java/com/almang/inventory/global/exception/ErrorCode.java (1)
24-24: 에러 메시지 일관성 개선을 고려하세요.에러 메시지 끝에 마침표가 있는 것(10-11번 줄)과 없는 것(17-23번 줄)이 혼재되어 있습니다. 전체 에러 코드에서 일관된 스타일을 유지하는 것이 좋습니다.
권장사항: 프로젝트의 메시지 스타일 가이드를 정하고 모든 에러 메시지에 적용하세요.
src/test/java/com/almang/inventory/user/controller/UserControllerTest.java (1)
100-173: 프로필 수정 테스트 커버리지가 잘 구성되어 있습니다.성공 케이스, 사용자 미존재, 빈 값 검증, 길이 초과 등 주요 시나리오를 모두 테스트하고 있습니다.
추가 개선 제안:
경계값 테스트를 추가하면 더욱 견고해집니다:
- 정확히 20자인 경우 (성공해야 함)
- 19자인 경우 (성공해야 함)
@Test void 사용자_프로필_수정_이름이_정확히_20자일_때_성공한다() throws Exception { // given UpdateUserProfileRequest request = new UpdateUserProfileRequest("12345678901234567890"); // 정확히 20자 UpdateUserProfileResponse response = new UpdateUserProfileResponse(true); when(userService.updateUserProfile(anyLong(), any(UpdateUserProfileRequest.class))) .thenReturn(response); // when & then mockMvc.perform(patch("/api/v1/users/me") .with(authentication(auth())) .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(request))) .andExpect(status().isOk()) .andExpect(jsonPath("$.data.success").value(true)); }참고: 경계값 테스트는 off-by-one 에러를 잡아내는 데 효과적입니다.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
src/main/java/com/almang/inventory/global/exception/ErrorCode.java(1 hunks)src/main/java/com/almang/inventory/user/domain/User.java(2 hunks)src/test/java/com/almang/inventory/user/controller/UserControllerTest.java(5 hunks)src/test/java/com/almang/inventory/user/service/UserServiceTest.java(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- src/test/java/com/almang/inventory/user/service/UserServiceTest.java
🔇 Additional comments (1)
src/test/java/com/almang/inventory/user/controller/UserControllerTest.java (1)
45-51: 훌륭한 리팩토링입니다! 👍중복 코드를 제거하고 테스트 가독성을 높이는 헬퍼 메서드를 추가했습니다. 인증 객체 생성 로직이 한 곳에 집중되어 유지보수가 쉬워졌네요.
✨ 작업 내용
📝 적용 범위
/user📌 참고 사항
Summary by CodeRabbit