[FEAT] 유저 엔티티 구현#18
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (8)
🚧 Files skipped from review as they are similar to previous changes (4)
📝 WalkthroughWalkthrough사용자 도메인에 JPA 엔티티와 관련 열거형·오류 상태가 추가되었습니다. Changes사용자 도메인 모델
Estimated code review effort: 3 (Moderate) | ~20 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/main/java/com/mr/domain/user/entity/User.java`:
- Around line 30-31: Update User.updateProfile to validate nickname length
before assigning or persisting it, enforcing the existing maximum of 10
characters. Apply `@Size`(max = 10) with Bean Validation in the updateProfile call
path, or add equivalent explicit validation inside the method so values longer
than 10 are rejected immediately.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 6395bb9c-fd80-47a9-a62e-c411c567d8f8
📒 Files selected for processing (4)
src/main/java/com/mr/domain/user/entity/User.javasrc/main/java/com/mr/domain/user/entity/enums/InstrumentType.javasrc/main/java/com/mr/domain/user/entity/enums/SkillLevel.javasrc/main/java/com/mr/domain/user/entity/enums/UserRole.java
There was a problem hiding this comment.
닉네임 유효성 검증 로직함수 만드시는게 좋을 것 같습니다!
There was a problem hiding this comment.
updateNickname() 호출 시 값을 바로 저장하지 않고 validateNickname()이라는 검증 함수를 먼저 거치도록 수정했습니다. 닉네임이 비어있거나 공백, 10자 초과 시 예외 던지도록 만들었습니다~
public void updateNickname(String nickname) {
validateNickname(nickname);
this.nickname = nickname;
}
private static void validateNickname(String nickname) {
if (nickname == null || nickname.isBlank()) {
throw new GeneralException(UserErrorStatus.NICKNAME_REQUIRED);
}
if (nickname.length() > NICKNAME_MAX_LENGTH) {
throw new GeneralException(UserErrorStatus.NICKNAME_TOO_LONG);
}
}예외 타입은 IllegalArgumentException이 아니라 프로젝트에서 쓰고 있는 GeneralException과 UserErrorStatus를 사용했습니다. (이렇게 해야 GlobalExceptionHandler가 정확한 HTTP 상태코드와 메시지를 함께 응답해준대서 했어용...)
확인 부탁드립니다!!
There was a problem hiding this comment.
IllegalArgumentException 대신 GeneralException 활용하신 것 좋습니다~!
다만 저희 대면 회의 때 정책으로 가능한 닉네임 양식 정해뒀었던 걸로 기억해요~! 지금은 null이나 빈 값을 방어하고, 최댓값을 방어하고 있는데, (1) 한글인 경우 자모음만 들어오는 것 방어 + (2) 한글/영어/숫자 외 문자 방어 + (3) 최소 글자수(2글자) 제한을 같이 검증하는 방안으로 수정해주실 수 있으신가요?!
회의록에서 긁어왔습니당...ㅎㅎ
- 자음만 / 모음만 안 됨
- 한글, 영어, 숫자만 가능 (특수문자 X, 공백 제외)
- 2글자~10글자 사이 제한
There was a problem hiding this comment.
넵 반영했습니다!
min/max @Size에 추가했고 제가 빼먹은 회의록 규칙(자음/모음 단독 금지, 한글·영어·숫자만 허용, 2~10자)
정규식 하나로 같이 처리했습니다.
private static final Pattern NICKNAME_PATTERN =
Pattern.compile("^[가-힣a-zA-Z0-9]{2,10}$");한글 완성형(가-힣)만 허용해서 자음/모음 단독 입력은 유니코드 범위가 달라 자동으로 막히고
공백·특수문자도 같은 이유로 걸러집니다.
형식이 틀리면 UserErrorStatus.NICKNAME_INVALID_FORMAT로 통일된 메시지가 나갑니다.
There was a problem hiding this comment.
🧹 Nitpick comments (2)
src/main/java/com/mr/domain/user/entity/Student.java (2)
45-50: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win빠른 실패(Fail-fast)를 위한 필수 파라미터 검증 제안
정적 팩토리 메서드로 객체 생성을 깔끔하게 캡슐화한 점이 아주 멋집니다! 🚀
여기에 조금 더 견고함을 더하기 위해,user나theoryLevel처럼 반드시 필요한 파라미터가null로 들어오는 경우를 대비하여Objects.requireNonNull을 추가해보는 건 어떨까요?이렇게 하면 잘못된 값이 들어왔을 때 데이터베이스 에러까지 기다릴 필요 없이 애플리케이션 계층에서 즉시 예외가 발생하므로 디버깅이 훨씬 수월해집니다. Java 공식 문서나 'Fail-fast 원칙'에 대해 살펴보시면 안정적인 코드를 작성하는 데 큰 도움이 될 거예요.
💡 향상된 팩토리 메서드 예시
+import java.util.Objects; + public static Student create(User user, TheoryLevel theoryLevel) { + Objects.requireNonNull(user, "user는 필수 값입니다."); + Objects.requireNonNull(theoryLevel, "theoryLevel은 필수 값입니다."); return Student.builder() .user(user) .theoryLevel(theoryLevel) .build(); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/main/java/com/mr/domain/user/entity/Student.java` around lines 45 - 50, Update the Student.create factory method to validate both required parameters, user and theoryLevel, with Objects.requireNonNull before invoking Student.builder, so null inputs fail immediately while preserving the existing object construction flow.
20-24: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win엔티티 감사(Audit) 정보 추가 제안
새로 추가된 엔티티들에 데이터 생성 및 수정 시간을 추적하는 로직이 누락되어 있습니다. 데이터베이스의 원활한 유지보수와 장애 조사를 위해,
User엔티티처럼 공통 부모 클래스인BaseTimeEntity를 상속받아 감사(Audit) 정보를 남기는 것을 추천드려요! 🕵️♂️ 관련하여 Spring Data JPA Auditing 공식 문서를 참고하시면 시스템을 더욱 체계적으로 관리할 수 있는 좋은 기반이 될 것입니다.
src/main/java/com/mr/domain/user/entity/Student.java#L20-L24:extends BaseTimeEntity를 선언하여 감사 정보를 포함해 주세요.src/main/java/com/mr/domain/user/entity/Instrument.java#L14-L18:extends BaseTimeEntity를 선언하여 감사 정보를 포함해 주세요.src/main/java/com/mr/domain/user/entity/StudentInstrument.java#L18-L28:extends BaseTimeEntity를 선언하여 감사 정보를 포함해 주세요.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/main/java/com/mr/domain/user/entity/Student.java` around lines 20 - 24, Student.java (lines 20-24), Instrument.java (lines 14-18), and StudentInstrument.java (lines 18-28) must inherit from the common BaseTimeEntity so their creation and modification audit fields are recorded; update each entity declaration accordingly, preserving their existing JPA annotations and behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@src/main/java/com/mr/domain/user/entity/Student.java`:
- Around line 45-50: Update the Student.create factory method to validate both
required parameters, user and theoryLevel, with Objects.requireNonNull before
invoking Student.builder, so null inputs fail immediately while preserving the
existing object construction flow.
- Around line 20-24: Student.java (lines 20-24), Instrument.java (lines 14-18),
and StudentInstrument.java (lines 18-28) must inherit from the common
BaseTimeEntity so their creation and modification audit fields are recorded;
update each entity declaration accordingly, preserving their existing JPA
annotations and behavior.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 47051d72-d259-4e58-a491-1b5a84e270c7
📒 Files selected for processing (6)
src/main/java/com/mr/domain/user/entity/Instrument.javasrc/main/java/com/mr/domain/user/entity/Student.javasrc/main/java/com/mr/domain/user/entity/StudentInstrument.javasrc/main/java/com/mr/domain/user/entity/User.javasrc/main/java/com/mr/domain/user/entity/enums/TheoryLevel.javasrc/main/java/com/mr/domain/user/entity/enums/UserErrorStatus.java
There was a problem hiding this comment.
updateNickname() 호출 시 값을 바로 저장하지 않고 validateNickname()이라는 검증 함수를 먼저 거치도록 수정했습니다. 닉네임이 비어있거나 공백, 10자 초과 시 예외 던지도록 만들었습니다~
public void updateNickname(String nickname) {
validateNickname(nickname);
this.nickname = nickname;
}
private static void validateNickname(String nickname) {
if (nickname == null || nickname.isBlank()) {
throw new GeneralException(UserErrorStatus.NICKNAME_REQUIRED);
}
if (nickname.length() > NICKNAME_MAX_LENGTH) {
throw new GeneralException(UserErrorStatus.NICKNAME_TOO_LONG);
}
}예외 타입은 IllegalArgumentException이 아니라 프로젝트에서 쓰고 있는 GeneralException과 UserErrorStatus를 사용했습니다. (이렇게 해야 GlobalExceptionHandler가 정확한 HTTP 상태코드와 메시지를 함께 응답해준대서 했어용...)
확인 부탁드립니다!!
| public void updateNickname(String nickname) { | ||
| validateNickname(nickname); | ||
| this.nickname = nickname; | ||
| } | ||
|
|
||
| private static void validateNickname(String nickname) { | ||
| if (nickname == null || nickname.isBlank()) { | ||
| throw new GeneralException(UserErrorStatus.NICKNAME_REQUIRED); | ||
| } | ||
| if (nickname.length() > NICKNAME_MAX_LENGTH) { | ||
| throw new GeneralException(UserErrorStatus.NICKNAME_TOO_LONG); | ||
| } | ||
| } |
There was a problem hiding this comment.
현재는 updateNickname()에만 validateNickname()을 거치고 있는데, 유저 생성 시 닉네임을 함께 전달받을 때를 고려해 생성자 내부 또는 닉네임 할당 시 항상 validateNickname()을 거치도록 처리하는 것은 어떨지 의견 여쭙습니다!
There was a problem hiding this comment.
확인해보니 현재 User는 @Builder(access = PRIVATE)로 막혀 있어서
nickname을 바꿀 수 있는 경로가 updateNickname() 하나뿐입니다 (생성자/빌더 자체가 nickname을 안 받음).
그래서 최초 설정이든 이후 프로필 수정이든 둘 다 이 메서드를 거치게 되어 있어 지금 구조에선 검증이 빠지는 경로가 없습니다!
혹시 나중에 nickname을 직접 받는 생성 경로가 추가되면 그때도 반드시 validateNickname()을 거치도록 하겠습니다!
There was a problem hiding this comment.
IllegalArgumentException 대신 GeneralException 활용하신 것 좋습니다~!
다만 저희 대면 회의 때 정책으로 가능한 닉네임 양식 정해뒀었던 걸로 기억해요~! 지금은 null이나 빈 값을 방어하고, 최댓값을 방어하고 있는데, (1) 한글인 경우 자모음만 들어오는 것 방어 + (2) 한글/영어/숫자 외 문자 방어 + (3) 최소 글자수(2글자) 제한을 같이 검증하는 방안으로 수정해주실 수 있으신가요?!
회의록에서 긁어왔습니당...ㅎㅎ
- 자음만 / 모음만 안 됨
- 한글, 영어, 숫자만 가능 (특수문자 X, 공백 제외)
- 2글자~10글자 사이 제한
| @Builder(access = AccessLevel.PRIVATE) | ||
| private User(String profileImgUrl) { | ||
| this.profileImgUrl = profileImgUrl; | ||
| } | ||
|
|
||
| public static User createFromOAuth(String profileImgUrl) { | ||
| return User.builder() | ||
| .profileImgUrl(profileImgUrl) | ||
| .build(); | ||
| } |
There was a problem hiding this comment.
@Builder에서 profileImgUrl만 먼저 받는 이유는 OAuth 가입 단계와 닉네임 설정 단계가 분리되어 있기 때문으로 이해했는데, 맞을까요? 그렇다면 OAuth 로그인은 완료했지만 닉네임 설정을 마치지 않은 사용자가 일반 API를 호출하지 못하도록 온보딩 완료 여부를 구분할 필요가 있어 보입니다! 현재 닉네임 설정이 유일한 필수 온보딩 단계라면 아래처럼 nickname을 기준으로 완료 여부를 판단할 수 있을 것 같습니다.
public boolean isOnboardingCompleted() {
return nickname != null;
}다만 실제 검사를 인증/인가 로직, 필터 또는 각 API의 공통 사용자 조회 로직 중 어디에서 처리할지는 전체 로그인 흐름과 연관된 부분이라, 해당 로직을 추후 구현할 예정인지 궁금합니다. 이 부분은 인증 쪽 담당하시는 예원님과 함께 정책을 정해보면 좋을 것 같습니다! 백엔드 전체 회의 때 안건으로 올려도 좋을 것 같고...!
There was a problem hiding this comment.
말씀하신 대로 isOnboardingCompleted()는 추가했습니다.
public boolean isOnboardingCompleted() {
return nickname != null;
}다만 이걸 필터/인터셉터에서 전역으로 막을지 각 API에서 개별 검사할지는
인증 흐름 전체(JWT 필터, Spring Security 설정)와 얽혀 있어서 이 PR 범위에선 결정하지 않았습니다...!
스레드 파서 다른 팀원분들 의견 듣고 결정되면 수정해보겠습니다!
ownue
left a comment
There was a problem hiding this comment.
src/main/java/com/mr/domain/auth/exception/AuthErrorStatus.java (예원님 코드 참조)
확인해 보시면, domain 내 exception 패키지를 파서 해당 패키지에 ErrorStatus를 넣고 있어서요! 지금은 enums에 ErrorStatus를 모두 모아둔 것 같아 분리해 주시면 좋겠습니다!
넵 수정 했습니다 |
📍 개요
⛓️💥 관련 이슈
🛠️ 작업 내용
유저 엔티티 구현 (ERD 수정 후 다시 ERD에 맞게 수정)
권한, 숙련도, 악기종류 Enum 타입 추가학생, 악기, 학생-악기 엔티티 구현
화성학 숙련도(TheoryLevel) enum 및 닉네임 검증 예외코드(UserErrorStatus) 추가
User는 하드 딜리트 정책에 맞춰 email 제거, deletedAt 제거(BaseTimeEntity로 변경)
🔥 리뷰 요청 사항
...이렇게 만드는 거 맞나요?✅ 체크리스트
📎 참고 사항
Summary by CodeRabbit
새로운 기능
오류 처리