-
Notifications
You must be signed in to change notification settings - Fork 3
refactor : 유저 이미지 변경도 유저 정보 수정에 포함 #179
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
WalkthroughModifyUserInfoRequest에서 profileImageUrl 필드를 제거하고, 사용자 수정 API를 multipart로 변경해 텍스트(request 파트)와 이미지(image 파트)를 함께 처리하도록 통합했습니다. 이미지가 주어지면 S3에 업로드하고 이전 이미지는 삭제하며, UserGitubAutoPushResponse에 githubRepoName과 branch 필드를 추가했습니다. Changes
Sequence Diagram(s)sequenceDiagram
actor U as 사용자
participant C as UserController
participant S as UserService
participant ST as S3
participant E as User Entity
U->>C: PUT /api/users (multipart: request + optional image)
C->>S: modifyUserInfo(authUser, request, image)
S->>E: modifyUserInfo(nickname, githubUrl, blogUrl, introduction, age)
alt image 제공됨
S->>ST: upload(image)
ST-->>S: newProfileImageUrl
S->>E: modifyProfileImage(newProfileImageUrl)
opt 이전 이미지 존재
S->>ST: delete(oldProfileImageUrl)
ST-->>S: delete OK
end
else 이미지 없음
Note over S,E: 프로필 이미지 변경 없음
end
S-->>C: UserInfoResponse
C-->>U: 200 OK
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Tip 🔌 Remote MCP (Model Context Protocol) integration is now available!Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats. 📜 Recent review detailsConfiguration used: CodeRabbit UI 💡 Knowledge Base configuration:
You can enable these sources in your CodeRabbit configuration. 📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (2)
⏰ 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)
🔇 Additional comments (2)
✨ Finishing Touches
🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
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: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/main/java/org/ezcode/codetest/application/usermanagement/user/service/UserService.java (2)
153-160: 업로드 전 파일 검증(확장자/콘텐츠타입/용량) 추가 권장멀티파트 업로드는 악성 파일 업로드 리스크가 큽니다. 이미지 MIME/확장자 화이트리스트와 용량 제한을 적용하세요. 검증 실패 시 S3 업로드 전에 예외를 던지는 것이 안전합니다.
예시:
private String uploadProfileImage(MultipartFile image) { - try { + try { + // 간단 검증 예시: 10MB 이하, 이미지 MIME만 허용 + final long MAX_SIZE = 10L * 1024 * 1024; + if (image.getSize() <= 0 || image.getSize() > MAX_SIZE) { + throw new S3Exception(S3ExceptionCode.S3_UPLOAD_FAILED); + } + String contentType = image.getContentType(); + if (contentType == null || !contentType.startsWith("image/")) { + throw new S3Exception(S3ExceptionCode.S3_UPLOAD_FAILED); + } return s3Uploader.upload(image, S3Directory.PROFILE.getDir()); } catch (Exception e) { - log.error("프로필 이미지 업로드 실패 - image {}", image, e); + log.error("프로필 이미지 업로드 실패 - filename: {}, size: {}", + image.getOriginalFilename(), image.getSize(), e); throw new S3Exception(S3ExceptionCode.S3_UPLOAD_FAILED); } }
162-179: 삭제 실패 시 응답과 실제 상태 불일치 (클라이언트 오도 가능성)현재 코드는 S3 삭제가 실패하면 DB의 profileImageUrl도 유지되는데, 응답은 항상 null을 반환합니다. 실제 상태와 응답 불일치로 클라이언트가 삭제된 것으로 오인할 수 있습니다.
DB 포인터는 항상 null로 변경하고, S3 삭제는 베스트에포트로 처리하며, 응답은 실제 DB 값을 반영하도록 변경을 권장합니다.
@Transactional public UserProfileImageResponse deleteUserProfileImage(AuthUser authUser) { User user = userDomainService.getUserById(authUser.getId()); String oldImageUrl = user.getProfileImageUrl(); // S3에서 기존 이미지 파일 삭제 - if (oldImageUrl != null) { - try { - s3Uploader.delete(oldImageUrl, "profile"); - user.modifyProfileImage(null); - } catch (Exception e) { - log.warn("프로필 이미지 삭제 실패 - url: {}", oldImageUrl, e); - } - } - - return new UserProfileImageResponse(null); + if (oldImageUrl != null) { + // 1) 먼저 DB 포인터 제거 + user.modifyProfileImage(null); + // 2) S3 삭제는 실패해도 서비스는 계속 (로그만 남김) + try { + s3Uploader.delete(oldImageUrl, S3Directory.PROFILE.getDir()); + } catch (Exception e) { + log.warn("프로필 이미지 삭제 실패 - url: {}", oldImageUrl, e); + } + } + // 실제 DB 상태를 응답에 반영 + return new UserProfileImageResponse(user.getProfileImageUrl()); }
🧹 Nitpick comments (1)
src/main/java/org/ezcode/codetest/domain/user/model/entity/User.java (1)
156-160: 문자열 입력값 trim 권장 (불필요 공백 저장 방지)외부 입력에서 앞뒤 공백이 포함될 수 있어 저장 전에 trim하면 데이터 일관성이 좋아집니다.
다음과 같이 적용을 권장합니다.
- this.nickname = (nickname == null || nickname.isBlank()) ? this.nickname : nickname; - this.githubUrl = (githubUrl == null || githubUrl.isBlank()) ? this.githubUrl : githubUrl; - this.blogUrl = (blogUrl == null || blogUrl.isBlank()) ? this.blogUrl : blogUrl; - this.introduction = (introduction == null || introduction.isBlank()) ? this.introduction : introduction; + this.nickname = (nickname == null || nickname.isBlank()) ? this.nickname : nickname.trim(); + this.githubUrl = (githubUrl == null || githubUrl.isBlank()) ? this.githubUrl : githubUrl.trim(); + this.blogUrl = (blogUrl == null || blogUrl.isBlank()) ? this.blogUrl : blogUrl.trim(); + this.introduction = (introduction == null || introduction.isBlank()) ? this.introduction : introduction.trim();
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (4)
src/main/java/org/ezcode/codetest/application/usermanagement/user/dto/request/ModifyUserInfoRequest.java(0 hunks)src/main/java/org/ezcode/codetest/application/usermanagement/user/service/UserService.java(1 hunks)src/main/java/org/ezcode/codetest/domain/user/model/entity/User.java(1 hunks)src/main/java/org/ezcode/codetest/presentation/usermanagement/UserController.java(1 hunks)
💤 Files with no reviewable changes (1)
- src/main/java/org/ezcode/codetest/application/usermanagement/user/dto/request/ModifyUserInfoRequest.java
🔇 Additional comments (2)
src/main/java/org/ezcode/codetest/domain/user/model/entity/User.java (1)
155-161: 프로필 이미지 갱신 책임을 엔티티에서 분리한 점 좋습니다profileImageUrl을 modifyUserInfo에서 제거하고, 별도 메서드로 이미지 변경을 위임한 방향이 명확하고 유지보수에도 유리합니다. 문자열 필드들에 isBlank 체크로 기존 값 보존 로직도 자연스럽습니다.
src/main/java/org/ezcode/codetest/application/usermanagement/user/service/UserService.java (1)
75-107: 유저 정보 수정 로직과 이미지 갱신 통합 방향 좋습니다
- 엔티티의 modifyUserInfo 시그니처 변경과 잘 맞물리며, 멀티파트로 이미지가 올 경우에만 이미지 처리하는 분기 또한 자연스럽습니다.
- 전체 응답(UserInfoResponse)도 최신 엔티티 상태를 반영합니다.
| if (image != null && !image.isEmpty()) { | ||
| if (user.getProfileImageUrl()!=null) { | ||
| s3Uploader.delete(user.getProfileImageUrl(), "profile"); | ||
| } | ||
| String profileImageUrl = uploadProfileImage(image); | ||
|
|
||
| user.modifyProfileImage(profileImageUrl); | ||
| } |
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.
💡 Verification agent
🧩 Analysis chain
S3 삭제 시 디렉터리 상수 사용 및 업로드-삭제 순서 개선 제안
- 하드코딩된 "profile" 대신 S3Directory.PROFILE.getDir()을 사용해 일관성을 유지하세요.
- 안전한 교체 순서: 새 이미지 업로드 성공 후에 기존 이미지를 삭제하면 실패 시 사용자 이미지가 사라지는 리스크를 줄일 수 있습니다.
다음과 같이 수정 제안 드립니다.
- if (image != null && !image.isEmpty()) {
- if (user.getProfileImageUrl()!=null) {
- s3Uploader.delete(user.getProfileImageUrl(), "profile");
- }
- String profileImageUrl = uploadProfileImage(image);
- user.modifyProfileImage(profileImageUrl);
- }
+ if (image != null && !image.isEmpty()) {
+ // 1) 새 이미지 업로드
+ String profileImageUrl = uploadProfileImage(image);
+ String oldImageUrl = user.getProfileImageUrl();
+ // 2) DB 갱신
+ user.modifyProfileImage(profileImageUrl);
+ // 3) 기존 이미지 삭제(실패해도 서비스 흐름 유지)
+ if (oldImageUrl != null) {
+ try {
+ s3Uploader.delete(oldImageUrl, S3Directory.PROFILE.getDir());
+ } catch (Exception e) {
+ log.warn("기존 프로필 이미지 삭제 실패 - url: {}", oldImageUrl, e);
+ }
+ }
+ }검증이 필요하시면, s3Uploader.delete의 시그니처와 디렉터리 인자를 다음 스크립트로 확인해 주세요.
🏁 Script executed:
#!/bin/bash
# S3Uploader.delete 시그니처 및 사용처 확인
fd -t f -g '*S3Uploader*.java' | while read -r f; do
echo "=== $f ==="
rg -n -A2 -B4 -g "$f" -P '\bdelete\s*\('
done
# "profile" 하드코딩 사용 여부 점검
rg -n -C2 '"profile"' --type=javaLength of output: 2630
아래 스크립트로 S3Uploader.delete 메서드 정의(시그니처)와 호출부를 확인해주세요.
🏁 Script executed:
#!/bin/bash
# 1) delete 메서드 시그니처(오버로드 포함) 확인
echo "=== delete 메서드 정의 확인 ==="
rg -nE 'public\s+\S+\s+delete\s*\(' src/main/java/org/ezcode/codetest/infrastructure/s3/S3Uploader.java -C2 || echo ">> delete 메서드 정의를 찾을 수 없습니다."
# 2) delete 호출부 확인
echo
echo "=== delete 호출부 확인 ==="
rg -n -C1 'delete\s*\(' src/main/java/org/ezcode/codetest/infrastructure/s3/S3Uploader.javaLength of output: 536
S3 삭제 리팩토링: 디렉터리 상수 사용 및 안전한 업로드-삭제 순서 적용
s3Uploader.delete(String fileUrl, String dirName)시그니처 확인됨.- 하드코딩된
"profile"대신S3Directory.PROFILE.getDir()사용으로 일관성 확보. - 새 이미지 업로드→DB 갱신 후 기존 이미지 삭제(try-catch) 순으로 변경해 삭제 실패 시에도 사용자 이미지를 보존.
검토 후 아래와 같이 반영해주세요.
- if (image != null && !image.isEmpty()) {
- if (user.getProfileImageUrl() != null) {
- s3Uploader.delete(user.getProfileImageUrl(), "profile");
- }
- String profileImageUrl = uploadProfileImage(image);
- user.modifyProfileImage(profileImageUrl);
- }
+ if (image != null && !image.isEmpty()) {
+ // 1) 새 이미지 업로드
+ String profileImageUrl = uploadProfileImage(image);
+ String oldImageUrl = user.getProfileImageUrl();
+ // 2) DB에 새 URL 저장
+ user.modifyProfileImage(profileImageUrl);
+ // 3) 기존 이미지 삭제(실패해도 서비스 흐름 유지)
+ if (oldImageUrl != null) {
+ try {
+ s3Uploader.delete(oldImageUrl, S3Directory.PROFILE.getDir());
+ } catch (Exception e) {
+ log.warn("기존 프로필 이미지 삭제 실패 - url: {}", oldImageUrl, e);
+ }
+ }
+ }📝 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.
| if (image != null && !image.isEmpty()) { | |
| if (user.getProfileImageUrl()!=null) { | |
| s3Uploader.delete(user.getProfileImageUrl(), "profile"); | |
| } | |
| String profileImageUrl = uploadProfileImage(image); | |
| user.modifyProfileImage(profileImageUrl); | |
| } | |
| if (image != null && !image.isEmpty()) { | |
| // 1) 새 이미지 업로드 | |
| String profileImageUrl = uploadProfileImage(image); | |
| String oldImageUrl = user.getProfileImageUrl(); | |
| // 2) DB에 새 URL 저장 | |
| user.modifyProfileImage(profileImageUrl); | |
| // 3) 기존 이미지 삭제(실패해도 서비스 흐름 유지) | |
| if (oldImageUrl != null) { | |
| try { | |
| s3Uploader.delete(oldImageUrl, S3Directory.PROFILE.getDir()); | |
| } catch (Exception e) { | |
| log.warn("기존 프로필 이미지 삭제 실패 - url: {}", oldImageUrl, e); | |
| } | |
| } | |
| } |
🤖 Prompt for AI Agents
In
src/main/java/org/ezcode/codetest/application/usermanagement/user/service/UserService.java
around lines 86 to 93, replace the current logic to (1) call
uploadProfileImage(image) first and get the new profileImageUrl, (2) update the
user with user.modifyProfileImage(profileImageUrl) so the new image is preserved
even if deletion fails, and (3) if an old user.getProfileImageUrl() exists
attempt to delete it inside a try-catch using s3Uploader.delete(oldUrl,
S3Directory.PROFILE.getDir()) (matching the s3Uploader.delete(String, String)
signature) and log or ignore delete errors so they don’t roll back the update.
| @PutMapping("/users") | ||
| public ResponseEntity<UserInfoResponse> modifyUserInfo( | ||
| @AuthenticationPrincipal AuthUser authUser, | ||
| @RequestBody ModifyUserInfoRequest modifyUserInfoRequest | ||
| ){ | ||
| return ResponseEntity.status(HttpStatus.OK).body(userService.modifyUserInfo(authUser, modifyUserInfoRequest)); | ||
| } | ||
|
|
||
| //유저 프로필 이미지 등록 | ||
| @Operation( | ||
| summary = "프로필 이미지 등록", | ||
| description = "유저의 프로필 이미지를 등록합니다. 기존의 이미지가 있는 경우, 기존 이미지가 삭제되고 새로운 이미지로 교체됩니다.") | ||
| @PutMapping("/users/profile") | ||
| public ResponseEntity<UserProfileImageResponse> uploadUserProfileImage( | ||
| @AuthenticationPrincipal AuthUser authUser, | ||
| @RequestPart("request") ModifyUserInfoRequest request, | ||
| @RequestPart(value = "image", required = false) MultipartFile image | ||
| ){ | ||
| return ResponseEntity.status(HttpStatus.OK).body(userService.uploadUserProfileImage(authUser, image)); | ||
| return ResponseEntity.status(HttpStatus.OK).body(userService.modifyUserInfo(authUser, request, image)); | ||
| } |
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.
💡 Verification agent
❓ Verification inconclusive
컨텐츠 타입 매핑 명시 및 JSON/Multipart 동시 지원 제안
현재 시그니처는 멀티파트만 처리 가능하게 보입니다. 기존 클라이언트가 application/json으로 전송하면 415가 날 수 있습니다. 소비 타입을 명시하고, JSON 전용 오버로드를 추가하면 하위 호환을 유지할 수 있습니다.
멀티파트 메서드에 consumes를 명시:
- @PutMapping("/users")
+ @PutMapping(value = "/users", consumes = org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<UserInfoResponse> modifyUserInfo(
@AuthenticationPrincipal AuthUser authUser,
- @RequestPart("request") ModifyUserInfoRequest request,
+ @Valid @RequestPart("request") ModifyUserInfoRequest request,
@RequestPart(value = "image", required = false) MultipartFile image
){
return ResponseEntity.status(HttpStatus.OK).body(userService.modifyUserInfo(authUser, request, image));
}JSON 전용 오버로드 추가(동일 경로, 다른 consumes):
@PutMapping(value = "/users", consumes = org.springframework.http.MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<UserInfoResponse> modifyUserInfoJson(
@AuthenticationPrincipal AuthUser authUser,
@Valid @RequestBody ModifyUserInfoRequest request
) {
return ResponseEntity.status(HttpStatus.OK).body(userService.modifyUserInfo(authUser, request, null));
}구현 후 기존 프런트가 JSON 또는 멀티파트 모두 동작하는지 확인을 권장합니다.
다음 쿼리로 기존 @RequestBody ModifyUserInfoRequest 사용 흔적이 남아있는지 확인해 주세요.
🏁 Script executed:
#!/bin/bash
rg -nP '@RequestBody\s+ModifyUserInfoRequest' --type=java -C2Length of output: 63
멀티파트 및 JSON 요청 동시 지원을 위한 consumes 명시 및 오버로드 추가 제안
아래와 같이 Multipart 전용 핸들러에 consumes 를 명시하고, JSON 전용 오버로드를 추가해 하위 호환을 유지하세요.
스크립트 검증 결과(rg -nP '@RequestBody\s+ModifyUserInfoRequest' --type=java) JSON 전송 전용 핸들러는 아직 존재하지 않습니다.
- 파일:
src/main/java/org/ezcode/codetest/presentation/usermanagement/UserController.java - 변경 대상 라인: 52–59
- @PutMapping("/users")
+ @PutMapping(
+ value = "/users",
+ consumes = org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE
+ )
public ResponseEntity<UserInfoResponse> modifyUserInfo(
@AuthenticationPrincipal AuthUser authUser,
- @RequestPart("request") ModifyUserInfoRequest request,
+ @Valid @RequestPart("request") ModifyUserInfoRequest request,
@RequestPart(value = "image", required = false) MultipartFile image
) {
return ResponseEntity.status(HttpStatus.OK)
.body(userService.modifyUserInfo(authUser, request, image));
}@PutMapping(
value = "/users",
consumes = org.springframework.http.MediaType.APPLICATION_JSON_VALUE
)
public ResponseEntity<UserInfoResponse> modifyUserInfoJson(
@AuthenticationPrincipal AuthUser authUser,
@Valid @RequestBody ModifyUserInfoRequest request
) {
return ResponseEntity.status(HttpStatus.OK)
.body(userService.modifyUserInfo(authUser, request, null));
}구현 후 기존 프런트엔드에서 JSON 및 Multipart 요청 모두 정상 처리되는지 꼭 확인해 주세요.
🤖 Prompt for AI Agents
In
src/main/java/org/ezcode/codetest/presentation/usermanagement/UserController.java
around lines 52–59, the current single @PutMapping handler accepts multipart but
does not declare consumes and there is no JSON-only overload; modify the
existing multipart handler to declare consumes =
MediaType.MULTIPART_FORM_DATA_VALUE and then add a new JSON-only overloaded
handler annotated with @PutMapping(value = "/users", consumes =
MediaType.APPLICATION_JSON_VALUE) that accepts @Valid @RequestBody
ModifyUserInfoRequest and calls userService.modifyUserInfo(authUser, request,
null); ensure annotations (@AuthenticationPrincipal, @Valid) match and both
endpoints return the same ResponseEntity<UserInfoResponse> so both multipart and
JSON clients work.
src/main/java/org/ezcode/codetest/presentation/usermanagement/UserController.java
Outdated
Show resolved
Hide resolved
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 (5)
src/main/java/org/ezcode/codetest/application/usermanagement/user/dto/response/UserGitubAutoPushResponse.java (3)
15-18: repo/branch 필드 추가는 방향성 OK. 다만 null 응답 처리와 스웨거 명세 보완 권장
- 사용자 설정 전(레포/브랜치 미선택)에는
repo/branch가 null일 가능성이 높습니다. 현재 구조라면 null이 그대로 직렬화될 수 있으므로, 응답 일관성을 위해 아래 중 하나를 권장합니다.
- Jackson에서 null 필드 제외: 클래스 레벨에
@JsonInclude(Include.NON_NULL)추가- 스웨거 명세에 nullable 표시: 필드
@Schema(nullable = true)지정추가 예시(클래스 상단/필드에 적용):
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Getter; @Getter @AllArgsConstructor @JsonInclude(Include.NON_NULL) @Schema(description = "깃허브 자동 Push 여부 변경 후 응답") public class UserGitubAutoPushResponse { @Schema(description = "메세지", example = "변경되었습니다") private final String message; @Schema(description = "현재 상태", example = "true") private final boolean gitPushStatus; @Schema(description = "선택된 레포", example = "myRepo", nullable = true) private final String githubRepoName; @Schema(description = "선택된 브랜치", example = "dev", nullable = true) private final String branch; }
15-18: 생성자 파라미터 증가(4개)로 인한 실수 방지: @builder 도입 고려현재 시그니처가
(String, boolean, String, String)으로 오버로드/순서 실수 여지가 있습니다. Lombok@Builder를 추가하면 호출부 가독성과 안전성이 좋아집니다.호출부 변경은 서비스 코드 코멘트에 diff로 제안해두었습니다. DTO에는 아래와 같이
@Builder만 추가하면 됩니다:import lombok.Builder; @Getter @AllArgsConstructor @Builder public class UserGitubAutoPushResponse { // ... }
15-18: 네이밍 오타 정정:UserGitubAutoPushResponse→UserGithubAutoPushResponse
현재 서비스·컨트롤러에서는Github로 통일되어 있으나, 해당 DTO 클래스명만 ‘Gitub’ 오타가 있어 혼란을 초래합니다. 클래스/파일명과 전역 참조를 아래와 같이 일괄 수정해주세요.
- DTO 클래스명/파일명 변경
- src/main/java/org/ezcode/codetest/application/usermanagement/user/dto/response/UserGitubAutoPushResponse.java
→ UserGithubAutoPushResponse.java (클래스명도public class UserGithubAutoPushResponse로 수정)- UserGithubController 수정 (import 및 메소드 시그니처)
- import org.ezcode.codetest.application.usermanagement.user.dto.response.UserGitubAutoPushResponse;
→ UserGithubAutoPushResponse- public ResponseEntity … → ResponseEntity
- UserGithubService 수정 (import, 반환 타입, 생성자 호출)
- import org.ezcode.codetest.application.usermanagement.user.dto.response.UserGitubAutoPushResponse;
→ UserGithubAutoPushResponse- public UserGitubAutoPushResponse changeAutoPushSetting(…) → public UserGithubAutoPushResponse changeAutoPushSetting(…)
- return new UserGitubAutoPushResponse(…) → new UserGithubAutoPushResponse(…)
API 스펙에는 영향이 없으므로 서버 내부 호환성 정리를 위해 여유가 있을 때 적용을 권장드립니다.
src/main/java/org/ezcode/codetest/domain/user/service/UserGithubService.java (2)
127-127: 호출부 업데이트 OK. repo/branch 미설정(null) 시 응답 계약만 명확히현재 선택된 레포/브랜치가 없는 사용자의 경우
getRepo()/getBranch()가 null일 수 있습니다. DTO 쪽에서@JsonInclude(NON_NULL)또는@Schema(nullable = true)로 명세/직렬화를 정리하면 충분합니다.또한, DTO에
@Builder를 도입한다면 가독성과 안전성을 위해 아래와 같이 호출부를 변경하는 것을 추천합니다.아래 diff는 @builder 도입 시 적용 예시입니다.
- return new UserGitubAutoPushResponse("변경되었습니다", user.getGitPushStatus(), userGithubInfo.getRepo(), userGithubInfo.getBranch()); + return UserGitubAutoPushResponse.builder() + .message("변경되었습니다") + .gitPushStatus(user.getGitPushStatus()) + .githubRepoName(userGithubInfo.getRepo()) + .branch(userGithubInfo.getBranch()) + .build();
136-136: 자동 푸시 상태 조회 응답도 동일 패턴으로 통일 권장위와 동일하게 DTO의 빌더를 사용하면 인자 순서 실수를 줄이고 필드 매핑이 명확해집니다. 또한 null 처리 전략(필드 생략/nullable 표시)도 DTO 레벨에서 일괄 적용하는 것이 유지보수에 유리합니다.
빌더 도입 시 예시:
- return new UserGitubAutoPushResponse("현재 githubAutoPush 설정", user.getGitPushStatus(),userGithubInfo.getRepo(), userGithubInfo.getBranch()); + return UserGitubAutoPushResponse.builder() + .message("현재 githubAutoPush 설정") + .gitPushStatus(user.getGitPushStatus()) + .githubRepoName(userGithubInfo.getRepo()) + .branch(userGithubInfo.getBranch()) + .build();
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (2)
src/main/java/org/ezcode/codetest/application/usermanagement/user/dto/response/UserGitubAutoPushResponse.java(1 hunks)src/main/java/org/ezcode/codetest/domain/user/service/UserGithubService.java(2 hunks)
⏰ 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
🔇 Additional comments (1)
src/main/java/org/ezcode/codetest/application/usermanagement/user/dto/response/UserGitubAutoPushResponse.java (1)
15-18: 2-인자 생성자 호출 없음 확인
UserGitubAutoPushResponse에 대한 2-인자 호출은 발견되지 않았으며, 모든 호출부가 새로 추가된 4-인자 생성자를 사용하고 있습니다. 추가 검증이나 수정 없이 머지해도 안전합니다.
작업 내용
변경 사항
@RequestBody ModifyUserInfoRequest를@RequestPart("request") ModifyUserInfoRequest request로 변경userService.modifyUserInfo()메서드 내,image파라미터가 null이거나 비어 있는지(!image.isEmpty()) 확인참고 사항
코드 리뷰 전 확인 체크리스트
type :)Summary by CodeRabbit
New Features
Refactor
New Fields (API 응답)