-
Notifications
You must be signed in to change notification settings - Fork 0
feat(signup): 관리자 회원가입 기능 구현 #21
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
The head ref may contain hidden characters: "feature/#20-\uD68C\uC6D0\uAC00\uC785\uAD6C\uD604"
Conversation
signup API 구현
|
""" Walkthrough이번 변경사항은 관리자 회원가입 기능을 위한 전체적인 시스템 확장을 포함합니다. Redis 연동, 비밀번호 암호화, 회원가입 요청/응답 DTO, 엔티티 및 저장소, 서비스와 컨트롤러 계층의 구현이 추가 및 수정되었습니다. 그 외, 에러 메시지 코드와 권한(Role) Enum도 일관성 있게 조정되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant UserController
participant UserService
participant UserRepository
participant PasswordEncoder
Client->>UserController: POST /signup (ManagerSignupRequestDto)
UserController->>UserService: signup(dto)
UserService->>UserRepository: findByEmail(dto.email)
UserService->>UserRepository: findByNickname(dto.nickname)
UserService->>PasswordEncoder: encode(dto.password)
UserService->>UserRepository: save(User)
UserService-->>UserController: ManagerSignupResponseDto
UserController-->>Client: 201 Created + ApiUtils.success()
Poem
""" 📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
✨ Finishing Touches
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
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
🧹 Nitpick comments (10)
build.gradle (1)
53-55:Details
❓ Verification inconclusive
Redisson 의존성 추가 검토
Redisson Spring Boot Starter(org.redisson:redisson-spring-boot-starter:3.19.0)를 사용하기 위해서는spring-boot-starter-data-redis가 자동 포함되는지 확인이 필요합니다. 누락 시RedisTemplate빈 생성 시RedisConnectionFactory구현체가 없을 수 있습니다.아래 스크립트로 의존성 트리를 확인하거나, 필요 시 명시적으로 Spring Data Redis 스타터를 추가해주세요:
+// (선택) Redis 연동을 위한 Spring Data Redis 스타터 +implementation 'org.springframework.boot:spring-boot-starter-data-redis'
🏁 Script executed:
./gradlew dependencies --configuration runtimeClasspath | grep -C 2 redisLength of output: 265
🚨 JAVA_HOME 오류로 의존성 확인 실패: Redisson 자동 포함 여부 재검증 필요
현재 sandbox 환경에서JAVA_HOME설정 오류로spring-boot-starter-data-redis의존성 자동 포함 여부를 확인할 수 없었습니다.
로컬 환경에서 아래 명령어를 실행해 Redis 관련 의존성 트리를 재검증해주세요:export JAVA_HOME=/path/to/your/jdk ./gradlew dependencies --configuration runtimeClasspath | grep -C 2 redis– 만약
spring-boot-starter-data-redis가 자동으로 포함되지 않는다면,build.gradle에 아래 라인을 추가해주세요:+ implementation 'org.springframework.boot:spring-boot-starter-data-redis'src/main/java/com/example/gtable/global/config/RedisConfig.java (1)
12-19: RedisTemplate 초기화 개선 제안
현재 키/값 직렬화만 설정되어 있으며, 해시 직렬화 설정과afterPropertiesSet()호출이 누락되어 있습니다. 해시 연산 사용 시 직렬화 문제를 방지하고, 설정을 완전히 반영하기 위해 아래와 같은 개선을 고려해주세요.@@ public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) { template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); + // 해시 키/값 직렬화 설정 + template.setHashKeySerializer(new StringRedisSerializer()); + template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); + // 설정 반영을 위한 초기화 호출 + template.afterPropertiesSet(); return template; }src/main/java/com/example/gtable/user/repository/UserRepository.java (1)
11-11: 파라미터명 일관성을 확인해 주세요.메서드명은
findByNickname이지만 파라미터명은nickName으로 되어 있네요. 일관성을 위해 파라미터명을nickname으로 변경하는 것이 어떨까요?- Optional<User> findByNickname(String nickName); + Optional<User> findByNickname(String nickname);아니면 기존 코드베이스의 네이밍 컨벤션을 따라야 한다면 현재 상태로도 괜찮습니다.
src/main/java/com/example/gtable/user/entity/User.java (2)
44-46: 생성자 파라미터 순서를 일관성 있게 정리해보시면 좋겠습니다생성자에 password 파라미터가 추가되었는데, 파라미터 순서가 자연스럽지 않아 보입니다. email 다음에 password가 오는 것이 더 직관적일 것 같습니다.
- public User(String email,String password, String nickname, String profileImage, SocialType socialType, Role role){ + public User(String email, String password, String nickname, String profileImage, SocialType socialType, Role role){또한 email 뒤에 공백이 누락되어 있네요.
70-72: encodePassword 메서드 설계가 깔끔합니다패스워드 암호화 로직을 엔티티 내부에서 처리하도록 설계한 것이 좋습니다. 다만 한 가지 개선 제안이 있습니다:
메서드 호출 후 기존 평문 패스워드가 암호화된 값으로 대체되는데, 이미 암호화된 패스워드에 대해 중복 호출을 방지하는 안전장치가 있으면 더 견고할 것 같습니다.
public void encodePassword(PasswordEncoder passwordEncoder) { + if (password == null || password.isEmpty()) { + throw new IllegalStateException("패스워드가 설정되지 않았습니다."); + } password = passwordEncoder.encode(password); }src/main/java/com/example/gtable/user/controller/UserController.java (1)
32-41: 회원가입 엔드포인트 구현이 잘 되어있습니다HTTP 상태코드 201(Created) 사용과
@Valid어노테이션을 통한 요청 검증이 적절합니다. 다만 몇 가지 개선 사항을 제안드립니다:
- API 문서화: Swagger 어노테이션 추가 고려
- 예외 처리: 현재 GlobalExceptionHandler가 있지만, 회원가입 특화된 에러 메시지도 고려해볼 만합니다
+ @Operation(summary = "관리자 회원가입", description = "관리자 계정을 생성합니다") + @ApiResponses({ + @ApiResponse(responseCode = "201", description = "회원가입 성공"), + @ApiResponse(responseCode = "400", description = "잘못된 요청 데이터") + }) @PostMapping("/signup") public ResponseEntity<?> signup(@RequestBody @Valid ManagerSignupRequestDto managerSignupRequestDto) {src/main/java/com/example/gtable/user/service/UserService.java (1)
22-31: 회원가입 메서드의 전체적인 구조가 좋습니다
@Transactional어노테이션 사용과 전체적인 플로우가 깔끔합니다. 다만 한 가지 개선 제안이 있습니다:현재 검증 실패 시 로그가 남지 않아 디버깅이나 모니터링에 어려움이 있을 수 있습니다.
@Transactional public ManagerSignupResponseDto signup(ManagerSignupRequestDto managerSignupRequestDto) { + log.info("관리자 회원가입 시도: email={}", managerSignupRequestDto.getEmail()); validateEmailDuplicated(managerSignupRequestDto); validateNickNameDuplicated(managerSignupRequestDto.getNickname()); User user = managerSignupRequestDto.toEntity(); user.encodePassword(passwordEncoder); + log.info("관리자 회원가입 완료: userId={}", user.getId()); return ManagerSignupResponseDto.fromEntity(userRepository.save(user)); }src/main/java/com/example/gtable/user/dto/ManagerSignupResponseDto.java (1)
26-34: fromEntity 팩토리 메서드가 잘 구현되었습니다정적 팩토리 메서드 패턴을 사용하여 User 엔티티에서 DTO로의 변환이 깔끔하게 구현되었습니다. 빌더 패턴과 함께 사용하여 가독성도 좋네요.
다만 한 가지 고려사항이 있습니다: User 엔티티의 필드가 null일 가능성에 대한 방어 코드를 추가하면 더 안전할 것 같습니다.
public static ManagerSignupResponseDto fromEntity(User user) { + if (user == null) { + throw new IllegalArgumentException("User 엔티티가 null입니다"); + } return ManagerSignupResponseDto.builder() .id(user.getId()) .email(user.getEmail()) .nickname(user.getNickname()) .role(user.getRole()) .build(); }src/main/java/com/example/gtable/user/dto/ManagerSignupRequestDto.java (2)
18-22: 이메일 정규식을 좀 더 간단하고 읽기 쉽게 개선해보시면 어떨까요?현재 정규식이 매우 복잡해서 유지보수와 가독성 면에서 어려움이 있을 수 있습니다. Spring Boot의 기본 @Email 어노테이션만으로도 충분할 것 같습니다.
다음과 같이 간소화하는 것을 고려해보세요:
-@Email(regexp = "^(?=.{1,64}@)[A-Za-z0-9_-]+(\\.[A-Za-z0-9_-]+)*@" - + "[^-][A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*(\\.[A-Za-z]{2,})$") +@Email
24-27: 비밀번호 정규식에 대한 명확한 설명이 있으면 좋겠습니다!현재 정규식이 어떤 조건들을 검증하는지 주석이나 상수로 명시해주시면, 다른 개발자들이 이해하기 쉬울 것 같습니다.
다음과 같이 개선해보시는 건 어떨까요:
+// 숫자, 영문자, 특수문자 포함 8-20자 @Pattern(regexp = "(?=.*[0-9])(?=.*[a-zA-Z])(?=.*\\W)(?=\\S+$).{8,20}")또는 상수로 분리하여 재사용성을 높이는 방법도 좋습니다.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (11)
build.gradle(1 hunks)src/main/java/com/example/gtable/global/config/RedisConfig.java(1 hunks)src/main/java/com/example/gtable/global/config/SecurityConfig.java(3 hunks)src/main/java/com/example/gtable/global/security/exception/ErrorMessage.java(1 hunks)src/main/java/com/example/gtable/user/controller/UserController.java(2 hunks)src/main/java/com/example/gtable/user/dto/ManagerSignupRequestDto.java(1 hunks)src/main/java/com/example/gtable/user/dto/ManagerSignupResponseDto.java(1 hunks)src/main/java/com/example/gtable/user/entity/Role.java(1 hunks)src/main/java/com/example/gtable/user/entity/User.java(4 hunks)src/main/java/com/example/gtable/user/repository/UserRepository.java(1 hunks)src/main/java/com/example/gtable/user/service/UserService.java(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/main/java/com/example/gtable/user/service/UserService.java (1)
src/main/java/com/example/gtable/global/security/exception/GlobalExceptionHandler.java (1)
Slf4j(23-105)
🔇 Additional comments (15)
src/main/java/com/example/gtable/global/config/RedisConfig.java (3)
1-9: import 구간 확인 완료
필요한 패키지가 적절히 임포트되어 있어 문제없습니다.
10-11: 클래스 선언 및 설정 어노테이션
@Configuration어노테이션과 클래스 구조가 적절하게 정의되어 있습니다.
20-21: 클래스 종료부 확인
구조적으로 문제가 없으므로 이 부분은 그대로 두셔도 됩니다.src/main/java/com/example/gtable/user/entity/Role.java (1)
10-10:Details
❓ Verification inconclusive
ADMIN에서 MANAGER로의 변경에 대한 영향도를 확인해 주세요.
Role enum에서
ADMIN을MANAGER로 변경하신 것은 breaking change입니다. 다음 사항들을 꼼꼼히 확인해 주시기 바랍니다:
- 기존 데이터베이스에 ADMIN 역할로 저장된 사용자 데이터 마이그레이션
- 코드베이스 전체에서
Role.ADMIN을 참조하는 부분들의 업데이트- 권한 체크 로직에서 ADMIN 역할을 검사하는 부분들
다음 스크립트로 ADMIN 참조를 찾아보겠습니다:
🏁 Script executed:
#!/bin/bash # ADMIN 역할을 참조하는 코드를 찾습니다 rg -A 3 -B 3 "Role\.ADMIN|ADMIN" --type javaLength of output: 46
ADMIN 역할 참조 추가 검증 요청
현재
rg -A3 -B3 "Role\.ADMIN|ADMIN" --type java실행 시 결과가 없어 보이나, 파일 형식 제한으로 놓친 부분이 있을 수 있습니다. 아래 스크립트로 전체 코드 및 리소스 파일을 대상으로 한 번 더 확인해 주세요.• 위 스크립트 실행 후에도 참조가 전혀 없다면, 코드 레벨에서 ADMIN → MANAGER 변경 영향은 크지 않을 수 있습니다.
• 다만 기존 데이터베이스에 저장된'ADMIN'값이 있을 경우 JPA 매핑 오류가 발생할 수 있으므로, 마이그레이션 또는 enum-based converter 적용 여부를 수동으로 점검해 주세요.
• 권한 체크 로직(Express, Spring Security 등)에서 하드코딩된 ‘ADMIN’ 문자열이 있는지도 함께 확인이 필요합니다.추가 검증 후 결과를 공유해 주시면, 최종 검토를 도와드리겠습니다.
🏁 Script executed:
#!/bin/bash # 1) 모든 Java 파일에서 Role.ADMIN 참조 검색 rg -n "Role\.ADMIN" --glob '*.java' # 2) SQL, XML, YAML 등 리소스 파일에서 'ADMIN' 문자열 검색 rg -n "ADMIN" --glob '*.{sql,xml,yml,yaml}' # 3) 테스트 코드(Test) 폴더도 빠짐없이 검사 rg -n "Role\.ADMIN|ADMIN" --glob 'src/**/*Test.java'Length of output: 285
Role.ADMIN 참조 없음 – 추가 검증 요청
Role.ADMIN및 문자열"ADMIN"에 대한 전체 코드·리소스 검색 결과, Java 소스(.java), 테스트, SQL/XML/YAML 파일 어디에도 참조가 발견되지 않았습니다.- 그러나 데이터베이스에 기존에
'ADMIN'값이 저장된 레코드가 있을 경우 JPA 매핑 오류가 발생할 수 있으므로 반드시 확인이 필요합니다.- 또한 애플리케이션 설정(
.properties,.json, 스크립트 등)이나 보안 구성(예: Spring Security SpEL, @secured, hasRole) 에서 하드코딩된"ADMIN"문자열이 남아있지 않은지 점검해 주세요.– DB 마이그레이션 또는 enum-based converter 적용 여부
– 설정 파일·스크립트 전반의 ADMIN 하드코딩 유무위 항목을 검토하신 뒤 결과를 공유해 주시면 최종 승인 여부를 안내해 드리겠습니다.
src/main/java/com/example/gtable/global/config/SecurityConfig.java (3)
9-10: 적절한 import 추가입니다.비밀번호 암호화를 위한 BCryptPasswordEncoder 관련 import가 정확히 추가되었네요.
56-57: 회원가입 엔드포인트 보안 설정이 올바릅니다.
/api/users/signup엔드포인트를 permitAll에 추가하여 인증 없이 접근할 수 있도록 설정하신 것이 적절합니다. 회원가입 기능에 필수적인 설정이네요.
66-69: PasswordEncoder 빈 설정이 완벽합니다.BCryptPasswordEncoder를 사용한 비밀번호 인코더 빈 설정이 보안 모범 사례를 잘 따르고 있습니다. 이렇게 하면 서비스 레이어에서 의존성 주입을 통해 안전하게 비밀번호를 암호화할 수 있겠네요.
src/main/java/com/example/gtable/global/security/exception/ErrorMessage.java (1)
10-17:Details
✅ Verification successful
에러 코드 개선사항이 훌륭하지만 기존 참조 확인이 필요합니다.
에러 코드를 더 명확하고 일관성 있게 변경하신 것은 매우 좋은 개선사항이네요!
"g001"→"global001","a001"→"auth001"등으로 변경하여 가독성이 크게 향상되었습니다.다만 기존 코드에서 이 에러 코드들을 문자열로 직접 참조하는 부분이 있는지 확인이 필요합니다.
다음 스크립트로 기존 에러 코드 참조를 찾아보겠습니다:
🏁 Script executed:
#!/bin/bash # 기존 에러 코드를 참조하는 부분을 찾습니다 rg -A 2 -B 2 '"g001"|"a001"|"t001"|"t002"' --type javaLength of output: 56
추가로 자바 파일뿐만 아니라 전체 코드베이스에서 기존 에러 코드(
g001,a001,t001,t002) 참조 여부를 확인해보겠습니다.
🏁 Script executed:
#!/bin/bash # 전체 레포지토리에서 기존 에러 코드 문자열 참조 검색 rg -n 'g001|a001|t001|t002'Length of output: 29
기존 에러 코드 참조 없음 확인
전체 레포지토리에서
"g001","a001","t001","t002"에 대한 직접 참조를 검색한 결과, 어떠한 매치도 발견되지 않았습니다.
따라서 에러 코드 변경("g001"→"global001","a001"→"auth001", 등)은 코드베이스에 안전하게 적용된 것으로 보입니다.
추가 조치 불필요하며, 훌륭한 개선 감사합니다!src/main/java/com/example/gtable/user/entity/User.java (1)
53-64:Details
❌ Incorrect review comment
createUserWithId 메서드에서 password 처리가 누락되었습니다
기존
createUserWithId정적 팩토리 메서드에서 새로 추가된 password 필드가 처리되지 않고 있습니다. 이 메서드를 사용하는 코드에서 password가 항상 null이 될 가능성이 있습니다.메서드 사용처를 확인하여 password 파라미터 추가가 필요한지 검토해보시기 바랍니다.
다음 스크립트로 해당 메서드의 사용처를 확인해보겠습니다:
🏁 Script executed:
#!/bin/bash # createUserWithId 메서드 사용처 확인 rg -A 3 -B 3 "createUserWithId"Length of output: 1577
User 엔티티에
password필드가 실제로 추가되었는지 확인하기 위해 다음 스크립트를 실행 부탁드립니다:
🏁 Script executed:
#!/bin/bash # User.java에서 password 필드 검색 rg -n "password" src/main/java/com/example/gtable/user/entity/User.javaLength of output: 470
createUserWithId에서 password 누락은 의도된 설계입니다
현재
createUserWithId메서드는 JWT 필터(JwtAuthorizationFilter) 내에서 토큰 기반 인증용으로만 사용되며, 실제 비밀번호는 사용되지 않습니다.
등록 시에는 별도의 가입용 팩토리 메서드(또는 빌더)를 통해 password를 설정하고 있으므로, 해당 정적 메서드에 password 파라미터를 추가할 필요가 없습니다.Likely an incorrect or invalid review comment.
src/main/java/com/example/gtable/user/controller/UserController.java (1)
29-29: 의존성 주입이 올바르게 구성되었습니다UserService를 final 필드로 선언하고
@RequiredArgsConstructor와 함께 사용하신 것이 좋습니다. 불변성을 보장하는 깔끔한 설계네요.src/main/java/com/example/gtable/user/service/UserService.java (1)
39-42:Details
✅ Verification successful
UserRepository에 findByNickname 메서드 확인이 필요합니다
코드에서
userRepository.findByNickname()메서드를 사용하고 있는데, 이 메서드가 UserRepository에 정의되어 있는지 확인이 필요합니다.다음 스크립트로 UserRepository의 메서드 정의를 확인해보겠습니다:
🏁 Script executed:
#!/bin/bash # UserRepository에서 findByNickname 메서드 확인 ast-grep --pattern 'interface UserRepository { $$$ findByNickname($$$) { $$$ } $$$ }' # 또는 메서드 선언 패턴으로 검색 rg -A 2 -B 2 "findByNickname"Length of output: 1065
findByNickname 메서드 정의 확인 완료
UserRepository 인터페이스에Optional<User> findByNickname(String nickName)메서드가 정상적으로 정의되어 있어, 추가 조치가 필요하지 않습니다.
- 파일:
src/main/java/com/example/gtable/user/repository/UserRepository.javaOptional<User> findByNickname(String nickName);src/main/java/com/example/gtable/user/dto/ManagerSignupResponseDto.java (1)
16-24: DTO 필드 구성이 적절합니다회원가입 응답에 필요한 핵심 정보들(id, email, nickname, role)만 포함되어 있고, 보안상 민감한 password 필드는 제외되어 있어서 좋습니다. Swagger 어노테이션도 적절하게 설정되어 있네요.
src/main/java/com/example/gtable/user/dto/ManagerSignupRequestDto.java (3)
1-12: 패키지 구조와 임포트가 깔끔하게 정리되어 있네요!필요한 라이브러리들이 모두 적절히 임포트되어 있고, 패키지 구조도 전형적인 DTO 레이어 패턴을 잘 따르고 있습니다.
14-16: 클래스 구조가 표준 DTO 패턴을 잘 따르고 있습니다!Lombok 어노테이션을 활용해서 보일러플레이트 코드를 효과적으로 줄인 점이 좋습니다.
29-32: 닉네임 검증 로직이 한국어와 영어를 모두 지원해서 좋네요!2-12자 길이 제한과 함께 한글과 영문을 모두 허용하는 정규식이 적절해 보입니다.
| @Column(nullable = false, unique = true) | ||
| private String email; // 카카오 이메일 | ||
|
|
||
| private String password; // 관리자 패스워드 |
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.
🛠️ Refactor suggestion
password 필드에 대한 데이터베이스 제약조건 고려가 필요합니다
관리자 계정의 password 필드는 보안상 중요한 데이터입니다. 현재 어떤 제약조건도 없이 선언되어 있는데, 다음 사항들을 고려해보시는 것이 좋겠습니다:
@Column(nullable = false)어노테이션 추가로 NULL 값 방지- 소셜 로그인 사용자와 관리자 계정을 구분하기 위한 설계 검토
- private String password; // 관리자 패스워드
+ @Column(nullable = false)
+ private String password; // 관리자 패스워드🤖 Prompt for AI Agents
In src/main/java/com/example/gtable/user/entity/User.java at line 29, the
password field lacks database constraints. Add the @Column(nullable = false)
annotation to prevent null values for security. Additionally, review the design
to distinguish between social login users and admin accounts, possibly by adding
a field or mechanism to differentiate user types.
| private void validateEmailDuplicated(ManagerSignupRequestDto managerSignupRequestDto) { | ||
| userRepository.findByEmail(managerSignupRequestDto.getEmail()).ifPresent(member -> { | ||
| throw new IllegalArgumentException(); | ||
| } | ||
| ); | ||
| } | ||
| private void validateNickNameDuplicated(String nickName) { | ||
| userRepository.findByNickname(nickName).ifPresent(member -> { | ||
| throw new IllegalArgumentException(); | ||
| } | ||
| ); | ||
| } |
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.
🛠️ Refactor suggestion
중복 검증 로직에서 예외 메시지 개선이 필요합니다
현재 IllegalArgumentException을 메시지 없이 던지고 있어서, 클라이언트에서 구체적인 오류 원인을 파악하기 어렵습니다. GlobalExceptionHandler에서 처리하더라도 명확한 메시지가 있으면 더 좋겠습니다.
private void validateEmailDuplicated(ManagerSignupRequestDto managerSignupRequestDto) {
userRepository.findByEmail(managerSignupRequestDto.getEmail()).ifPresent(member -> {
- throw new IllegalArgumentException();
+ throw new IllegalArgumentException("이미 사용 중인 이메일입니다: " + managerSignupRequestDto.getEmail());
}
);
}
private void validateNickNameDuplicated(String nickName) {
userRepository.findByNickname(nickName).ifPresent(member -> {
- throw new IllegalArgumentException();
+ throw new IllegalArgumentException("이미 사용 중인 닉네임입니다: " + nickName);
}
);
}이렇게 하면 API 응답에서도 더 명확한 오류 메시지를 제공할 수 있습니다.
📝 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.
| private void validateEmailDuplicated(ManagerSignupRequestDto managerSignupRequestDto) { | |
| userRepository.findByEmail(managerSignupRequestDto.getEmail()).ifPresent(member -> { | |
| throw new IllegalArgumentException(); | |
| } | |
| ); | |
| } | |
| private void validateNickNameDuplicated(String nickName) { | |
| userRepository.findByNickname(nickName).ifPresent(member -> { | |
| throw new IllegalArgumentException(); | |
| } | |
| ); | |
| } | |
| private void validateEmailDuplicated(ManagerSignupRequestDto managerSignupRequestDto) { | |
| userRepository.findByEmail(managerSignupRequestDto.getEmail()).ifPresent(member -> { | |
| throw new IllegalArgumentException("이미 사용 중인 이메일입니다: " + managerSignupRequestDto.getEmail()); | |
| } | |
| ); | |
| } | |
| private void validateNickNameDuplicated(String nickName) { | |
| userRepository.findByNickname(nickName).ifPresent(member -> { | |
| throw new IllegalArgumentException("이미 사용 중인 닉네임입니다: " + nickName); | |
| } | |
| ); | |
| } |
🤖 Prompt for AI Agents
In src/main/java/com/example/gtable/user/service/UserService.java around lines
32 to 43, the IllegalArgumentException thrown in validateEmailDuplicated and
validateNickNameDuplicated methods lacks descriptive messages. Update these
exceptions to include clear, specific error messages indicating that the email
or nickname is already in use, so clients and logs can better understand the
cause of the error.
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.
Exception 처리 관련 정책이 명확하게 결정되면 수정 예정
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.
@HyemIin 좋은 접근 방식이네요! 예외 처리 정책을 먼저 수립한 후 일관성 있게 적용하는 것이 코드베이스 전체의 품질과 유지보수성에 더 도움이 될 것 같습니다. 정책이 결정되면 그때 함께 개선해보시면 되겠습니다. 👍
| public User toEntity() { | ||
| return User.builder() | ||
| .email(email) | ||
| .password(password) | ||
| .nickname(nickname) | ||
| .socialType(SocialType.KAKAO) | ||
| .role(Role.MANAGER) | ||
| .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.
🛠️ Refactor suggestion
보안과 설계 관점에서 몇 가지 중요한 개선사항이 있습니다!
현재 구현에서 발견된 주요 이슈들:
- 보안 이슈: 비밀번호가 평문으로 전달되고 있습니다
- 설계 이슈: 관리자 회원가입에서 SocialType.KAKAO가 하드코딩되어 있는 것이 적절하지 않아 보입니다
- 책임 분리: DTO에서 비즈니스 로직(역할 할당)을 결정하고 있습니다
다음과 같은 개선을 제안드립니다:
public User toEntity() {
return User.builder()
.email(email)
- .password(password)
+ .password(password) // 서비스 레이어에서 인코딩 처리
.nickname(nickname)
- .socialType(SocialType.KAKAO)
+ .socialType(SocialType.NONE) // 또는 적절한 관리자용 타입
.role(Role.MANAGER)
.build();
}비밀번호 인코딩은 서비스 레이어에서 처리하는 것이 더 안전하고 적절합니다.
📝 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.
| public User toEntity() { | |
| return User.builder() | |
| .email(email) | |
| .password(password) | |
| .nickname(nickname) | |
| .socialType(SocialType.KAKAO) | |
| .role(Role.MANAGER) | |
| .build(); | |
| } | |
| public User toEntity() { | |
| return User.builder() | |
| .email(email) | |
| .password(password) // 서비스 레이어에서 인코딩 처리 | |
| .nickname(nickname) | |
| .socialType(SocialType.NONE) // 또는 적절한 관리자용 타입 | |
| .role(Role.MANAGER) | |
| .build(); | |
| } |
🤖 Prompt for AI Agents
In src/main/java/com/example/gtable/user/dto/ManagerSignupRequestDto.java around
lines 34 to 43, the toEntity method currently passes the password in plain text,
hardcodes SocialType.KAKAO, and assigns the role within the DTO, mixing business
logic with data transfer. To fix this, remove password encoding and role
assignment from the DTO; instead, have the service layer handle password
encoding and role setting. Also, avoid hardcoding SocialType in the DTO by
passing it as a parameter or setting it in the service layer to maintain
separation of concerns and improve security.
비밀번호 DB 저장 시 notnull 제약조건 추가
작업 요약
signup API 구현
Issue Link
문제점 및 어려움
해결 방안
Reference
Summary by CodeRabbit
신규 기능
개선 사항
보안