Skip to content

[FEAT] 사용자 마이페이지 정보 조회/수정 api 구현#13

Merged
buzz0331 merged 14 commits into
developfrom
feat/#11-my-page-crud
Sep 16, 2025
Merged

[FEAT] 사용자 마이페이지 정보 조회/수정 api 구현#13
buzz0331 merged 14 commits into
developfrom
feat/#11-my-page-crud

Conversation

@buzz0331

@buzz0331 buzz0331 commented Sep 15, 2025

Copy link
Copy Markdown
Contributor

#️⃣연관된 이슈

closes #11

📝작업 내용

마이페이지 정보에서 약관 동의 항목이 존재해서 사용자 테이블에 약관 동의 여부를 판단하는 컬럼을 추가했습니다!
그것말고는 딱히 특이사항은 없습니다~

스크린샷

스크린샷 2025-09-15 오후 5 07 12

💬리뷰 요구사항(선택)

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

ex) 메서드 XXX의 이름을 더 잘 짓고 싶은데 혹시 좋은 명칭이 있을까요?

Summary by CodeRabbit

  • 신기능

    • 마이페이지 API 추가: 내 정보 조회(GET /users/me) 및 수정(PUT /users/me)
    • 사용자 서비스 및 요청/응답 DTO 추가: UserService, UpdateUserInfoRequest, UserResponse
    • 프로필 이미지·이름·이메일·성별·약관 동의(termAgreed) 수정 및 저장 지원
    • 성별 변환 로직(Gender.from) 추가
  • 오류 처리

    • 유효하지 않은 성별 입력에 대해 USER_GENDER_MISMATCH 오류 반환
    • 존재하지 않는 사용자 접근 시 USER_NOT_FOUND 처리
  • 문서

    • Swagger에 사용자 조회/수정 문서화 및 관련 응답 설명 추가
    • 토큰 발급 응답 설명 수정

@coderabbitai

coderabbitai Bot commented Sep 15, 2025

Copy link
Copy Markdown

Walkthrough

사용자 마이페이지 조회(GET /users/me) 및 수정(PUT /users/me) API가 추가됨. UserService·UserController·요청/응답 DTO들이 도입되며 User 도메인에 termsAgreed 필드와 update(...)가 추가되고, Gender 문자열 매핑/검증과 관련 에러코드 및 Swagger 응답 설명이 확장됨.

Changes

Cohort / File(s) Summary
User API (Controller, Service, DTOs)
src/main/java/konkuk/chacall/domain/user/presentation/UserController.java, src/main/java/konkuk/chacall/domain/user/application/UserService.java, src/main/java/konkuk/chacall/domain/user/presentation/dto/request/UpdateUserInfoRequest.java, src/main/java/konkuk/chacall/domain/user/presentation/dto/response/UserResponse.java
마이페이지 조회(GET) 및 수정(PUT) 엔드포인트 추가. UserService(기본 readOnly, 수정 메서드는 쓰기 트랜잭션)와 컨트롤러, 요청/응답 DTO(검증·OpenAPI 메타데이터 포함) 추가 및 매핑/위임 로직 구현.
User 도메인 모델 확장
src/main/java/konkuk/chacall/domain/user/domain/model/User.java, src/main/java/konkuk/chacall/domain/user/domain/model/Gender.java
UsertermsAgreed 필드 추가(널 불허) 및 update(...) 메서드 추가. Gender.from(String) 정적 팩토리 추가(문자열->enum 매핑, 불일치 시 DomainRuleException 발생).
오류 코드 및 Swagger 정비
src/main/java/konkuk/chacall/global/common/exception/code/ErrorCode.java, src/main/java/konkuk/chacall/global/common/swagger/SwaggerResponseDescription.java, src/main/java/konkuk/chacall/global/common/security/oauth2/auth/AuthController.java
에러코드 USER_GENDER_MISMATCH 추가. SwaggerResponseDescription에 GET_USER_INFO, UPDATE_USER_INFO 항목 추가 및 ISSUE_TOKEN 초기화 문법 수정. AuthController#getToken의 ExceptionDescription 상수 값 변경.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant C as UserController (GET /users/me)
  participant S as UserService
  participant R as UserRepository
  participant U as User
  C->>S: getUserInfo(userId)
  S->>R: findById(userId)
  alt found
    R-->>S: User
    S->>C: BaseResponse(UserResponse.from(User))
  else not found
    R-->>S: empty
    S-->>C: throws EntityNotFoundException(USER_NOT_FOUND)
  end
Loading
sequenceDiagram
  autonumber
  participant C as UserController (PUT /users/me)
  participant S as UserService
  participant R as UserRepository
  participant U as User
  C->>S: updateUserInfo(userId, UpdateUserInfoRequest)
  S->>R: findById(userId)
  alt found
    R-->>S: User
    S->>U: user.update(name, profileImageUrl, email, genderStr, termsAgreed)
    note right of U #d1f0d1: Gender.from(genderStr) 호출\n유효하지 않으면 DomainRuleException 발생
    S-->>C: BaseResponse<Void>
  else not found
    R-->>S: empty
    S-->>C: throws EntityNotFoundException(USER_NOT_FOUND)
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

깡충깡충 토끼가 말하네 🐇
내 정보 보여줘, 한 번 콕!
수정은 PUT으로 톡톡톡,
성별은 from()으로 확인하고,
약관은 체크했니? 당근 한 입! 🥕

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Out of Scope Changes Check ⚠️ Warning 대부분 변경은 이슈 범위 내이나 일부 변경은 목적과 직접 관련이 없어 보입니다; 예를 들어 AuthController#getToken의 Swagger 예외 설명 변경과 SwaggerResponseDescription의 ISSUE_TOKEN 문법 수정은 마이페이지 API 구현과 직접적인 관련이 없어 PR 범위를 벗어납니다. 해결: 비관련 변경은 별도 커밋이나 별도 PR로 분리하거나 PR 본문에 변경 이유를 명확히 기재해 주세요; 그렇지 않으면 관련 커밋을 분리하여 리뷰 범위를 좁혀 주시기 바랍니다.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.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 제목 "[FEAT] 사용자 마이페이지 정보 조회/수정 api 구현"은 변경사항의 핵심인 마이페이지 조회 및 수정 API 구현을 명확하고 간결하게 요약하고 있어 팀원이 히스토리를 빠르게 파악하기에 적절합니다; 불필요한 파일 나열이나 이모지, 모호한 표현이 없고 PR 범위와도 일치합니다.
Linked Issues Check ✅ Passed PR은 링크된 이슈 #11의 요구사항인 '사용자 마이페이지 조회 및 수정 API 구현'을 코드 수준에서 충족합니다; 컨트롤러의 GET/PUT 엔드포인트, 서비스 로직, DTO, 도메인 변경(termsAgreed 필드 및 update 메서드), 성별 파싱 메서드 및 관련 에러코드 추가가 포함되어 있어 목적을 달성하고 있으며 PR 본문에 closes #11이 명시되어 연결도 명확합니다.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/#11-my-page-crud

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6f9150a and 371b3c1.

📒 Files selected for processing (1)
  • src/main/java/konkuk/chacall/domain/user/presentation/UserController.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/konkuk/chacall/domain/user/presentation/UserController.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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (7)
src/main/java/konkuk/chacall/global/common/security/oauth2/auth/AuthController.java (1)

6-6: 불필요한 import 제거

현재 파일에서 사용되지 않는 import 입니다.

- import konkuk.chacall.domain.user.domain.repository.UserRepository;
@@
-import static konkuk.chacall.global.common.exception.code.ErrorCode.API_INVALID_PARAM;

Also applies to: 21-21

src/main/java/konkuk/chacall/domain/user/presentation/dto/request/UpdateUserInfoRequest.java (1)

17-19: 샘플/유효성 강화 제안

  • 이메일 예시 도메인 오탈자로 보입니다: konkuk.ac.kr?
  • URL 형식 검증은 @url(org.hibernate.validator.constraints.URL) 사용을 검토하세요. 의존성 상황에 따라 선택.
-        @Schema(description = "사용자 이메일", example = "chacall@kokuk.ac.kr")
+        @Schema(description = "사용자 이메일", example = "chacall@konkuk.ac.kr")

Also applies to: 9-11

src/main/java/konkuk/chacall/global/common/swagger/SwaggerResponseDescription.java (1)

29-31: UPDATE_USER_INFO에 검증 실패 코드 누락

성별 변환 실패 시 USER_GENDER_MISMATCH가 발생하므로 스웨거 응답 설명에 포함하세요.

-    UPDATE_USER_INFO(new LinkedHashSet<>(Set.of(
-            USER_NOT_FOUND
-    ))),
+    UPDATE_USER_INFO(new LinkedHashSet<>(Set.of(
+            USER_NOT_FOUND,
+            USER_GENDER_MISMATCH
+    ))),
src/main/java/konkuk/chacall/domain/user/domain/model/Gender.java (1)

19-29: null/blank 입력 방어 로직 추가 제안

컨트롤러 검증이 누락되거나 다른 경로에서 호출될 때 NPE를 방지하세요.

-    public static Gender from(String value) {
-        return Arrays.stream(Gender.values())
-                .filter(genderVal -> genderVal.getValue().equals(value.trim()))
+    public static Gender from(String value) {
+        if (value == null || value.isBlank()) {
+            throw new DomainRuleException(ErrorCode.USER_GENDER_MISMATCH,
+                    new IllegalArgumentException("존재하지 않는 성별입니다. value: " + value));
+        }
+        final String v = value.trim();
+        return Arrays.stream(Gender.values())
+                .filter(genderVal -> genderVal.getValue().equals(v))
                 .findFirst()
                 .orElseThrow(
                         () -> new DomainRuleException(ErrorCode.USER_GENDER_MISMATCH,
                                 new IllegalArgumentException(
                                         String.format("존재하지 않는 성별입니다. value: %s", value)
                                 ))
                 );
     }
src/main/java/konkuk/chacall/domain/user/presentation/UserController.java (3)

33-36: PATCH 엔드포인트의 미디어 타입 명시 권장

클라이언트-서버 간 계약을 명확히 하기 위해 consumes를 지정하는 것을 권장합니다.

-    @PatchMapping("/me")
+    @PatchMapping(value = "/me", consumes = "application/json")

또는 MediaType.APPLICATION_JSON_VALUE 사용 시 import org.springframework.http.MediaType; 추가.


40-41: 응답 규약 정렬: 200+null 대신 204 No Content 고려

성공 시 본문이 없는 수정 요청은 HTTP 204가 더 적합합니다. BaseResponse 컨벤션을 유지해야 한다면 OK+명시적 메시지 등 일관된 규약을 문서화해 주세요.

원하시면 ResponseEntity로 전환하는 패치도 제안드릴게요.


17-21: 검증/보안 메타데이터 보강 제안

  • 클래스에 @validated 추가 시 DTO 메서드 파라미터 검증 패턴과 일관성이 좋아집니다.
  • 스웨거에 보안 스킴을 노출하려면 @securityrequirement(name = "BearerAuth") 등을 붙이세요(프로젝트 설정에 맞게 이름 조정).
 @RequiredArgsConstructor
+@org.springframework.validation.annotation.Validated
 public class UserController {

보안 스킴 이름/설정은 실제 OpenAPI 구성에 맞는지 확인 부탁드립니다.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 028e6b5 and 1b50db1.

📒 Files selected for processing (9)
  • src/main/java/konkuk/chacall/domain/user/application/UserService.java (1 hunks)
  • src/main/java/konkuk/chacall/domain/user/domain/model/Gender.java (2 hunks)
  • src/main/java/konkuk/chacall/domain/user/domain/model/User.java (1 hunks)
  • src/main/java/konkuk/chacall/domain/user/presentation/UserController.java (1 hunks)
  • src/main/java/konkuk/chacall/domain/user/presentation/dto/request/UpdateUserInfoRequest.java (1 hunks)
  • src/main/java/konkuk/chacall/domain/user/presentation/dto/response/GetUserInfoResponse.java (1 hunks)
  • src/main/java/konkuk/chacall/global/common/exception/code/ErrorCode.java (1 hunks)
  • src/main/java/konkuk/chacall/global/common/security/oauth2/auth/AuthController.java (1 hunks)
  • src/main/java/konkuk/chacall/global/common/swagger/SwaggerResponseDescription.java (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/main/java/konkuk/chacall/domain/user/application/UserService.java (1)
src/main/java/konkuk/chacall/global/common/exception/EntityNotFoundException.java (1)
  • EntityNotFoundException (6-11)
src/main/java/konkuk/chacall/domain/user/domain/model/Gender.java (1)
src/main/java/konkuk/chacall/domain/user/domain/model/User.java (1)
  • Getter (7-62)
🔇 Additional comments (7)
src/main/java/konkuk/chacall/global/common/security/oauth2/auth/AuthController.java (1)

38-38: ISSUE_TOKEN으로의 전환 LGTM

엔드포인트 동작과 예외 설명이 일치합니다.

src/main/java/konkuk/chacall/global/common/exception/code/ErrorCode.java (1)

36-36: 신규 에러코드(USER_GENDER_MISMATCH) 추가 LGTM

업데이트 API의 검증 실패 케이스에 적절합니다.

src/main/java/konkuk/chacall/global/common/swagger/SwaggerResponseDescription.java (1)

21-23: ISSUE_TOKEN 구문 수정 LGTM

트레일링 콤마 제거로 초기화 일관성이 좋아졌습니다.

src/main/java/konkuk/chacall/domain/user/presentation/dto/response/GetUserInfoResponse.java (1)

12-20: DTO 매핑 LGTM

null‑safe 성별 문자열 변환과 약관 동의 노출이 의도와 일치합니다.

src/main/java/konkuk/chacall/domain/user/domain/model/User.java (1)

55-61: update 로직 LGTM

도메인 내부에서 변환·검증을 캡슐화(Gender.from)하여 일관성이 좋습니다.

src/main/java/konkuk/chacall/domain/user/application/UserService.java (2)

20-24: getUserInfo 흐름 LGTM

조회 → DTO 변환 → 404 매핑이 간결합니다.


26-32: updateUserInfo 트랜잭션/더티체킹 사용 LGTM

엔티티 조회 후 도메인 메서드 호출로 변경 추적이 명확합니다.

Comment on lines +40 to +43
// 약관 동의 여부 컬럼
@Column(nullable = false)
private boolean termsAgreed;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

기존 데이터가 있는 테이블에 NOT NULL 컬럼 추가 시 마이그레이션 필요

nullable=false boolean 컬럼 추가는 운영 DB에서 실패할 수 있습니다. 기본값/백필 전략을 포함한 마이그레이션을 선반영하세요.

예시 SQL(선반영 후 제약 강화):

-- 1) 컬럼 추가(임시 default)
ALTER TABLE users ADD COLUMN terms_agreed BOOLEAN DEFAULT FALSE;

-- 2) 기존 로우 백필(필요 시 조건부 업데이트)
UPDATE users SET terms_agreed = FALSE WHERE terms_agreed IS NULL;

-- 3) NOT NULL 제약 강화 및 기본값 제거(선택)
ALTER TABLE users ALTER COLUMN terms_agreed SET NOT NULL;
ALTER TABLE users ALTER COLUMN terms_agreed DROP DEFAULT;
🤖 Prompt for AI Agents
src/main/java/konkuk/chacall/domain/user/domain/model/User.java lines 40-43: 현재
nullable=false로 boolean 컬럼을 바로 추가하면 운영 DB 마이그레이션에서 실패할 수 있으니 마이그레이션을 선행해 처리하세요;
DB 마이그레이션 스크립트를 만들어(1) terms_agreed 컬럼을 DEFAULT FALSE로 추가하고(2) 기존 로우에 대해 NULL인
값들을 FALSE로 백필한 다음(3) ALTER로 NOT NULL 제약을 설정하고 필요하면 DEFAULT를 제거하는 단계를 적용하고,
애플리케이션 코드와 마이그레이션이 일관되도록 배포 전 로컬/스테이징에서 검증하세요.

Comment on lines +25 to +27
@Schema(description = "약관 동의 여부", example = "true")
@NotBlank(message = "약관 동의 여부는 비어 있을 수 없습니다.")
boolean termAgreed

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

boolean 필드에 @notblank 사용 → 런타임 검증 예외 위험

@notblank는 CharSequence 전용입니다. primitive boolean에 적용 시 UnexpectedTypeException이 발생할 수 있습니다. 필드 타입을 Boolean으로 바꾸고 @NotNull을 적용하세요. 이메일은 @Email로 기본 검증 추가 권장.

 package konkuk.chacall.domain.user.presentation.dto.request;

 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Email;
+import jakarta.validation.constraints.NotNull;

@@
         @Schema(description = "사용자 이메일", example = "chacall@kokuk.ac.kr")
-        @NotBlank(message = "이메일은 비어 있을 수 없습니다.")
+        @NotBlank(message = "이메일은 비어 있을 수 없습니다.")
+        @Email(message = "올바른 이메일 형식이 아닙니다.")
         String email,
@@
         @Schema(description = "약관 동의 여부", example = "true")
-        @NotBlank(message = "약관 동의 여부는 비어 있을 수 없습니다.")
-        boolean termAgreed
+        @NotNull(message = "약관 동의 여부는 비어 있을 수 없습니다.")
+        Boolean termAgreed
 ) {
 }
📝 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.

Suggested change
@Schema(description = "약관 동의 여부", example = "true")
@NotBlank(message = "약관 동의 여부는 비어 있을 수 없습니다.")
boolean termAgreed
package konkuk.chacall.domain.user.presentation.dto.request;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotNull;
public record UpdateUserInfoRequest(
@Schema(description = "사용자 이메일", example = "chacall@kokuk.ac.kr")
@NotBlank(message = "이메일은 비어 있을 수 없습니다.")
@Email(message = "올바른 이메일 형식이 아닙니다.")
String email,
@Schema(description = "약관 동의 여부", example = "true")
@NotNull(message = "약관 동의 여부는 비어 있을 수 없습니다.")
Boolean termAgreed
) {
}
🤖 Prompt for AI Agents
In
src/main/java/konkuk/chacall/domain/user/presentation/dto/request/UpdateUserInfoRequest.java
around lines 25-27, the primitive boolean field annotated with @NotBlank is
invalid (UnexpectedTypeException) because @NotBlank is for CharSequence; change
the field type from boolean to Boolean and replace @NotBlank with @NotNull to
allow proper validation, and additionally add @Email to the email field (where
applicable) to enforce basic email format validation.

Comment thread src/main/java/konkuk/chacall/domain/user/presentation/UserController.java Outdated
Comment thread src/main/java/konkuk/chacall/domain/user/presentation/UserController.java Outdated
Comment thread src/main/java/konkuk/chacall/domain/user/presentation/UserController.java Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 (2)
src/main/java/konkuk/chacall/domain/user/presentation/dto/response/UserResponse.java (2)

12-20: null 입력 방지: from(User)에서 명시적으로 가드하세요

user가 null이면 NPE가 발생합니다. 방어 로직을 추가해 원인 파악이 쉬운 예외로 전환하세요.

 public static UserResponse from(User user) {
+        Objects.requireNonNull(user, "user must not be null");
         return new UserResponse(
                 user.getProfileImageUrl(),
                 user.getName(),
                 user.getEmail(),
                 user.getGender() == null ? null : user.getGender().getValue(),
                 user.isTermsAgreed()
         );
 }

추가 import(파일 상단):

import java.util.Objects;

17-17: gender 직렬화 값의 안정성 확인(코드값 vs. 로컬라이즈드 값)

getValue()가 로케일에 따라 바뀌는 문자열(예: "남성/여성")이라면 프런트/문서와 불일치 위험이 있습니다. 변경 불가라면 허용 값 명세를 스웨거에 명시해 주세요.

선택사항 1: 스키마에 허용값 문서화

 public record UserResponse(
         String profileImageUrl,
         String name,
         String email,
-        String gender,
+        @io.swagger.v3.oas.annotations.media.Schema(description = "성별 코드: MALE|FEMALE|null")
+        String gender,
         boolean termsAgreed
 ) { ... }

선택사항 2: 값의 불변성이 중요하면 user.getGender().name()으로 코드값을 반환하는 방식을 검토하세요.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1b50db1 and 767c68b.

📒 Files selected for processing (3)
  • src/main/java/konkuk/chacall/domain/user/application/UserService.java (1 hunks)
  • src/main/java/konkuk/chacall/domain/user/presentation/UserController.java (1 hunks)
  • src/main/java/konkuk/chacall/domain/user/presentation/dto/response/UserResponse.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/main/java/konkuk/chacall/domain/user/application/UserService.java
  • src/main/java/konkuk/chacall/domain/user/presentation/UserController.java

Comment on lines +5 to +11
public record UserResponse(
String profileImageUrl,
String name,
String email,
String gender,
boolean termAgreed
) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

응답 필드명 일관성: termAgreed → termsAgreed로 변경 권장

도메인(User.isTermsAgreed()), PR 설명(컬럼명 termsAgreed)과 응답 DTO 필드(termAgreed)가 불일치합니다. API 계약 혼동을 막기 위해 복수형으로 통일하세요.

아래 diff 적용 후, 해당 접근자(termsAgreed())를 사용하는 컨트롤러/테스트/문서도 함께 갱신해 주세요.

 public record UserResponse(
         String profileImageUrl,
         String name,
         String email,
         String gender,
-        boolean termAgreed
+        boolean termsAgreed
 ) {

검증 스크립트:


🏁 Script executed:

#!/bin/bash
# 'termAgreed' 잔존 사용처 점검
rg -nP -C2 '\btermAgreed\b|\.termAgreed\(\)'

Length of output: 1782


필드명 일관성 확보 — termAgreed → termsAgreed로 전파 (필수)

아래 파일들이 아직 termAgreed를 사용중이므로 UserResponse 필드명 변경 시 모든 참조(요청 DTO, 서비스 호출, 테스트, 문서 등)를 일괄 갱신해야 함.

  • 수정 대상(발견된 참조):
    • src/main/java/konkuk/chacall/domain/user/presentation/dto/response/UserResponse.java — boolean termAgreed → boolean termsAgreed (record 생성자 및 from(User) 매핑)
    • src/main/java/konkuk/chacall/domain/user/presentation/dto/request/UpdateUserInfoRequest.java — boolean termAgreed → boolean termsAgreed
    • src/main/java/konkuk/chacall/domain/user/application/UserService.java — request.termAgreed() → request.termsAgreed() (user.update(...) 호출부)

원본 diff(적용 필요):

 public record UserResponse(
         String profileImageUrl,
         String name,
         String email,
         String gender,
-        boolean termAgreed
+        boolean termsAgreed
 ) {
📝 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.

Suggested change
public record UserResponse(
String profileImageUrl,
String name,
String email,
String gender,
boolean termAgreed
) {
public record UserResponse(
String profileImageUrl,
String name,
String email,
String gender,
boolean termsAgreed
) {
🤖 Prompt for AI Agents
In
src/main/java/konkuk/chacall/domain/user/presentation/dto/response/UserResponse.java
around lines 5 to 11, rename the record field and constructor parameter
termAgreed to termsAgreed, update any internal mapping (e.g., from(User)
factory/mapping) to call user.isTermsAgreed() or equivalent, and then propagate
this rename to referenced files:
src/main/java/konkuk/chacall/domain/user/presentation/dto/request/UpdateUserInfoRequest.java
(boolean termAgreed → boolean termsAgreed and accessor rename), and
src/main/java/konkuk/chacall/domain/user/application/UserService.java
(request.termAgreed() → request.termsAgreed() where user.update(...) is
invoked); run and update related tests and any docs that reference termAgreed to
use termsAgreed.

ksg1227
ksg1227 previously approved these changes Sep 15, 2025

@ksg1227 ksg1227 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

수고하셨습니다~ 👍🏻

Comment on lines +23 to +40
@Operation(summary = "[마이페이지] 회원 정보 조회", description = "사용자(고객)의 정보를 조회합니다. (사장님, 일반유저 무관)")
@ExceptionDescription(SwaggerResponseDescription.GET_USER_INFO)
@GetMapping("/me")
public BaseResponse<UserResponse> getUserInfo() {
// todo 추후에 토큰 추가될 시 id 값은 토큰에서 추출하여 전달
return BaseResponse.ok(userService.getUserInfo(1L));
}

@Operation(summary = "[마이페이지] 회원 정보 수정", description = "사용자(고객)의 정보를 수정합니다. (사장님, 일반유저 무관)")
@ExceptionDescription(SwaggerResponseDescription.UPDATE_USER_INFO)
@PatchMapping("/me")
public BaseResponse<Void> updateUserInfo(
final @RequestBody @Valid UpdateUserInfoRequest request
) {
// todo 추후에 토큰 추가될 시 id 값은 토큰에서 추출하여 전달
userService.updateUserInfo(1L, request);

return BaseResponse.ok(null);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@userid 적용해둬도 될 것 같습니다!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

넵 🫡

Comment on lines +26 to +27
@NotBlank(message = "약관 동의 여부는 비어 있을 수 없습니다.")
boolean termAgreed

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

어차피 프리미티브 타입으로 설정해둬서 null 이 들어갈 수 없기 때문에 여기에는 별도의 Validation 은 걸지 않아도 될 것 같아요!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

맞네요. 뭐지 그러면 래퍼 객체로 선언하고 NotNull로 수정할까요??

@ksg1227 ksg1227 Sep 15, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

이 부분은 그냥 검증을 없애도 될 것 같슴다. 아예 @notblank 도 없애버리기

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 (1)
src/main/java/konkuk/chacall/domain/user/presentation/UserController.java (1)

36-37: PATCH 소비 미디어 타입(consumes) 명시로 415/모호성 예방

JSON PATCH 요청임을 명시하면 클라이언트·게이트웨이에서 콘텐츠 협상이 명확해집니다.

-    @PatchMapping("/me")
+    @PatchMapping(value = "/me", consumes = org.springframework.http.MediaType.APPLICATION_JSON_VALUE)

(선호 시 import 추가)

+import org.springframework.http.MediaType;
-@PatchMapping("/me")
+@PatchMapping(value = "/me", consumes = MediaType.APPLICATION_JSON_VALUE)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 767c68b and 09ee15f.

📒 Files selected for processing (2)
  • src/main/java/konkuk/chacall/domain/user/presentation/UserController.java (1 hunks)
  • src/main/java/konkuk/chacall/domain/user/presentation/dto/request/UpdateUserInfoRequest.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/konkuk/chacall/domain/user/presentation/dto/request/UpdateUserInfoRequest.java
🔇 Additional comments (2)
src/main/java/konkuk/chacall/domain/user/presentation/UserController.java (2)

25-32: 하드코딩 제거 및 사용자 컨텍스트 주입이 잘 반영됨

@userid로 인증 사용자 ID를 주입하고 Swagger 파라미터를 숨긴 처리, 적절합니다.


3-15: 불필요 — OpenAPI 전역 보안 스키마/요구가 이미 설정되어 있음

src/main/java/konkuk/chacall/global/config/OpenApiConfig.java에서 securitySchemaName="JWT"로 SecurityScheme를 등록하고 openAPI()에서 .addSecurityItem(setSecurityItems())로 전역 SecurityRequirement를 설정하고 있습니다. 따라서 컨트롤러에 @securityrequirement를 추가할 필요가 없습니다. (개별 표기를 원하면 @securityrequirement(name = "JWT") 사용)

Likely an incorrect or invalid review comment.

ksg1227
ksg1227 previously approved these changes Sep 15, 2025

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (1)
src/main/java/konkuk/chacall/domain/user/presentation/dto/request/UpdateUserInfoRequest.java (1)

18-20: 이메일 형식 검증 추가 (@Email) 제안

현재 @notblank만으로는 형식 검증이 되지 않습니다. 기본 수준의 형식 검증을 위해 @Email 추가를 권장합니다.

 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.constraints.NotBlank;
 import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Email;

@@
         @Schema(description = "사용자 이메일", example = "chacall@kokuk.ac.kr")
-        @NotBlank(message = "이메일은 비어 있을 수 없습니다.")
+        @NotBlank(message = "이메일은 비어 있을 수 없습니다.")
+        @Email(message = "올바른 이메일 형식이 아닙니다.")
         String email,

Also applies to: 3-6

🧹 Nitpick comments (5)
src/main/java/konkuk/chacall/domain/user/presentation/dto/request/UpdateUserInfoRequest.java (5)

22-24: 성별 값 제약 명시 필요 (Enum 또는 허용값/패턴 지정)

현재 String + @notblank만으로는 허용값이 열려 있습니다. 서비스 단의 Gender.from(...) 규칙과 일치하도록 다음 중 하나를 권장합니다:

  • 요청 DTO에서 Enum 타입 사용, 또는
  • @Schema(allowableValues=...) 혹은 @pattern으로 허용값 제한.
    또한 예시 값("남성")이 실제 허용 토큰과 일치하는지 확인 바랍니다.

10-12: 프로필 이미지 URL 형식 검증 추가 권장

URL 필드에는 형식 검증이 있으면 좋습니다. Hibernate Validator 사용 중이라면 @url을, 아니라면 간단한 @pattern이라도 고려해 주세요.

+import org.hibernate.validator.constraints.URL;
@@
         @Schema(description = "프로필 이미지 URL", example = "https://example.com/profile.jpg")
-        @NotBlank(message = "프로필 이미지 URL은 비어 있을 수 없습니다.")
+        @NotBlank(message = "프로필 이미지 URL은 비어 있을 수 없습니다.")
+        @URL(message = "올바른 URL 형식이 아닙니다.")
         String profileImageUrl,

8-29: PATCH 의미상 필드 ‘전부 필수’인지 확인 필요

현재 @NotBlank/@NotNull로 모든 컴포넌트가 필수입니다. PATCH(/users/me)라면 부분 업데이트 허용이 일반적입니다. 요구사항이 ‘전체 갱신’인지 확인 부탁드립니다. 부분 업데이트라면 필드 Nullable 허용 + 서비스 레벨에서 null 무시 처리(merge) 또는 별도 Partial DTO 도입을 권장합니다.


18-18: 예시 도메인 오타 추정: kokuk → konkuk

패키지명은 konkuk인데 예시 이메일 도메인은 kokuk으로 보입니다. 오타라면 교정해 주세요.

-        @Schema(description = "사용자 이메일", example = "chacall@kokuk.ac.kr")
+        @Schema(description = "사용자 이메일", example = "chacall@konkuk.ac.kr")

10-28: Swagger에서 ‘필수 여부’가 확실히 드러나야 합니다

springdoc가 Bean Validation을 반영하긴 하지만, 명확성을 위해 필수 항목에는 @Schema(requiredMode = REQUIRED) 지정도 고려해 주세요.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 09ee15f and 8917088.

📒 Files selected for processing (1)
  • src/main/java/konkuk/chacall/domain/user/presentation/dto/request/UpdateUserInfoRequest.java (1 hunks)
🔇 Additional comments (1)
src/main/java/konkuk/chacall/domain/user/presentation/dto/request/UpdateUserInfoRequest.java (1)

26-28: Boolean 필드 전환(+@NotNull) 적용은 적절합니다

primitive → 래퍼(Boolean)로 전환하고 @NotNull을 둔 점은 검증·문서화 측면에서 타당합니다.

단, 도메인 모델 필드명이 termsAgreed로 알려져 있습니다(AI 요약). 요청 DTO의 termAgreed와 naming이 다르면 혼동 여지 있습니다. 의도된 불일치인지 확인 바랍니다.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
src/main/java/konkuk/chacall/domain/user/presentation/dto/request/UpdateUserInfoRequest.java (1)

28-30: 지난 코멘트 반영 굿: boolean → Boolean + @NotNull 적용

이전 리뷰에서 지적됐던 @NotBlank/primitive boolean 문제를 정확히 수정하셨습니다. DTO-검증 관점에서 안정적입니다.

🧹 Nitpick comments (4)
src/main/java/konkuk/chacall/domain/user/presentation/dto/request/UpdateUserInfoRequest.java (4)

19-22: 스웨거 예시 오타로 보임: kokuk → konkuk

학교 도메인 표기가 패키지명과 상이합니다. 오타라면 예시를 교정해 주세요.

-        @Schema(description = "사용자 이메일", example = "chacall@kokuk.ac.kr")
+        @Schema(description = "사용자 이메일", example = "chacall@konkuk.ac.kr")

11-30: 검증 메시지 i18n 리소스 분리 제안

하드코딩된 한글 메시지는 다국어/운영 변경에 취약합니다. 메시지 코드를 사용해 messages.properties로 분리하는 것을 권장합니다.


28-30: 필드명 일관성: termAgreed ↔ termsAgreed 통일 필요

DTO/응답(src/main/java/konkuk/chacall/domain/user/presentation/dto/request/UpdateUserInfoRequest.java, src/main/java/konkuk/chacall/domain/user/presentation/dto/response/UserResponse.java)은 termAgreed, 도메인/서비스(src/main/java/konkuk/chacall/domain/user/domain/model/User.java, src/main/java/konkuk/chacall/domain/user/application/UserService.java)는 termsAgreed로 불일치합니다 — 팀 규약(단수/복수)에 맞춰 명명 통일하세요.


24-26: 성별 값 검증 강화 — 허용값을 '남성'/'여성'로 제한하세요

Gender.from(String)는 enum Gender { M("남성"), F("여성") }의 value("남성"/"여성")를 기대합니다. 현재 UpdateUserInfoRequest.gender는 String + @notblank로 임의 문자열이 통과해 런타임에 DomainRuleException이 발생할 수 있습니다.

  • 권장(명확): DTO의 gender 타입을 Gender로 변경. (주의: 기본 바인딩은 enum 이름(M/F)을 사용하므로 클라이언트 또는 컨버터 조정 필요)
  • 대안: UpdateUserInfoRequest.gender에 @Schema(allowableValues = {"남성","여성"}) 및/또는 @pattern(regexp="^(남성|여성)$", message="허용값: 남성 또는 여성") 추가로 문서·검증 반영

파일: src/main/java/konkuk/chacall/domain/user/presentation/dto/request/UpdateUserInfoRequest.java
참고: src/main/java/konkuk/chacall/domain/user/domain/model/Gender.java

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8917088 and 6f9150a.

📒 Files selected for processing (1)
  • src/main/java/konkuk/chacall/domain/user/presentation/dto/request/UpdateUserInfoRequest.java (1 hunks)
🔇 Additional comments (2)
src/main/java/konkuk/chacall/domain/user/presentation/dto/request/UpdateUserInfoRequest.java (2)

15-17: 이름 길이 상한을 DB 스키마와 일치시키세요

UpdateUserInfoRequest.name 필드에 @SiZe(max=...)를 추가해 DB의 name 컬럼 길이와 일치시키세요. 저장소에서 User 엔티티/DDL의 name 컬럼 길이를 찾지 못했으니(검색 결과 없음) 먼저 DB/schema 또는 User 엔티티에서 실제 컬럼 길이를 확인하고 그 값으로 max를 설정하세요.


11-13: 프로필 이미지 URL에 URL 형식 검증 추가 — 의존성 확인 필요

프로필 이미지 URL 필드에 @url 어노테이션으로 URL 형식 검증을 추가하세요. 레포 루트(pom.xml 또는 build.gradle(.kts))에 hibernate-validator 또는 spring-boot-starter-validation 의존성 포함 여부를 확인하세요(제공된 스크립트 실행 결과 'pom.xml: No such file or directory'로 자동 확인 실패).

import org.hibernate.validator.constraints.URL;

@Schema(description = "프로필 이미지 URL", example = "https://example.com/profile.jpg")
@NotBlank(message = "프로필 이미지 URL은 비어 있을 수 없습니다.")
@URL(message = "유효한 URL 형식이 아닙니다.")
String profileImageUrl,

확인 예시 명령: 루트에서
rg -n 'hibernate-validator|spring-boot-starter-validation' -S
또는 pom.xml / build.gradle(.kts) 파일 내용을 제공.

@CHA-CALL CHA-CALL deleted a comment from coderabbitai Bot Sep 16, 2025

@ksg1227 ksg1227 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

메서드 PUT 으로 바꾸는 걸로 통일하시져 굿

@buzz0331 buzz0331 merged commit 226ab90 into develop Sep 16, 2025
2 checks passed
@buzz0331 buzz0331 deleted the feat/#11-my-page-crud branch September 16, 2025 07:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEAT] 사용자 마이페이지 조회 및 수정 api 구현

2 participants