[refactor] 로그인/회원가입 구현 관련 리팩토링 진행 #51
Conversation
## Walkthrough
이 변경 사항은 사용자 인증 및 회원가입 로직에서 이메일과 로그인 타입의 조합으로 사용자 고유성을 검증하도록 전체적으로 수정했으며, JWT 인증 필터와 토큰 제공자의 보안 컨텍스트 처리 및 키 캐싱 로직도 개선되었습니다. 또한, 로그인 요청 DTO에 로그인 타입 필드가 추가되었습니다.
## Changes
| 파일/경로 요약 | 변경 내용 요약 |
|---|---|
| .../jwt/JwtAuthenticationFilter.java, .../jwt/JwtTokenProvider.java, .../jwt/JwtAuthentication.java | JWT 인증 필터가 토큰이 유효하지 않거나 헤더가 없을 때 보안 컨텍스트를 명시적으로 초기화하도록 수정, JwtTokenProvider에서 서명 키 캐싱 및 토큰 유효성 검사 강화, JwtAuthentication 클래스가 이메일 대신 userId(Long)를 주체로 사용하도록 변경 |
| .../user/dto/UserLoginRequestDto.java | 로그인 요청 DTO에 `@NotNull`이 적용된 `loginType` 필드 추가 |
| .../user/entity/User.java | User 엔티티에 이메일과 로그인 타입의 복합 유니크 제약 조건 추가, 이메일 단일 유니크 제약 삭제 |
| .../user/repository/UserRepository.java | 이메일 단일 쿼리 메서드 제거, 이메일+로그인 타입 조합 쿼리 메서드로 대체 |
| .../user/service/UserService.java, .../user/service/auth/AuthService.java | 사용자 중복 체크 및 로그인 시 이메일+로그인 타입 조합으로 사용자 조회 방식 변경, JWT 토큰 생성 시 이메일 대신 userId 사용 |
## Sequence Diagram(s)
```mermaid
sequenceDiagram
participant Client
participant AuthService
participant UserRepository
participant JwtTokenProvider
Client->>AuthService: login(email, password, loginType)
AuthService->>UserRepository: findByEmailAndLoginType(email, loginType)
UserRepository-->>AuthService: User or NotFound
AuthService->>JwtTokenProvider: generateToken(userId, role)
JwtTokenProvider-->>AuthService: JWT Token
AuthService-->>Client: TokenResponseDtoPossibly related PRs
Suggested reviewers
Poem
|
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
src/main/java/com/wayble/server/common/config/security/jwt/JwtTokenProvider.java (1)
44-50: 토큰 유효성 검증 개선이 보안을 향상시킵니다.명시적인 토큰 검증을 통해 fail-fast 동작을 구현한 것은 좋은 보안 개선사항입니다.
다만,
validateToken()이 두 번 호출되는 중복을 최적화할 수 있습니다:public String getEmail(String token) { - if (!validateToken(token)) { - throw new IllegalArgumentException("Invalid token"); - } - return Jwts.parserBuilder().setSigningKey(getSigningKey()).build() - .parseClaimsJws(token).getBody().getSubject(); + try { + return Jwts.parserBuilder().setSigningKey(getSigningKey()).build() + .parseClaimsJws(token).getBody().getSubject(); + } catch (JwtException | IllegalArgumentException e) { + throw new IllegalArgumentException("Invalid token"); + } }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
src/main/java/com/wayble/server/common/config/security/jwt/JwtAuthenticationFilter.java(1 hunks)src/main/java/com/wayble/server/common/config/security/jwt/JwtTokenProvider.java(2 hunks)src/main/java/com/wayble/server/user/dto/UserLoginRequestDto.java(2 hunks)src/main/java/com/wayble/server/user/entity/User.java(2 hunks)src/main/java/com/wayble/server/user/repository/UserRepository.java(1 hunks)src/main/java/com/wayble/server/user/service/UserService.java(1 hunks)src/main/java/com/wayble/server/user/service/auth/AuthService.java(1 hunks)
🧰 Additional context used
🧠 Learnings (1)
src/main/java/com/wayble/server/user/entity/User.java (1)
Learnt from: seung-in-Yoo
PR: Wayble-Project/wayble-spring#37
File: src/main/java/com/wayble/server/user/entity/User.java:61-62
Timestamp: 2025-07-13T15:08:59.288Z
Learning: Java에서 같은 패키지 내의 클래스들은 import 구문 없이 서로를 참조할 수 있다. com.wayble.server.user.entity 패키지 내의 클래스들은 명시적인 import 없이 사용 가능하다.
🔇 Additional comments (13)
src/main/java/com/wayble/server/user/dto/UserLoginRequestDto.java (2)
3-3: 새로운 import 구문 추가 확인LoginType과 @NotNull import가 적절히 추가되었습니다.
Also applies to: 6-6
17-21: LoginType 필드 추가 및 검증 로직 확인로그인 타입 필드가 적절한 검증 어노테이션(@NotNull)과 함께 추가되었습니다. 이메일과 로그인 타입의 복합 고유성 제약 조건을 지원하기 위한 변경사항이 올바르게 구현되었습니다.
src/main/java/com/wayble/server/user/service/UserService.java (1)
21-21: 복합 고유성 제약 조건을 위한 중복 검사 로직 업데이트이메일과 로그인 타입을 함께 고려하여 사용자 중복을 검사하도록 변경되었습니다. 이는 전체 리팩토링 목표와 일치합니다.
src/main/java/com/wayble/server/user/service/auth/AuthService.java (1)
23-24: 로그인 로직에서 복합 키 사용으로 업데이트이메일과 로그인 타입을 함께 사용하여 사용자를 조회하도록 변경되었습니다. 이는 새로운 복합 고유성 제약 조건과 일치합니다.
src/main/java/com/wayble/server/common/config/security/jwt/JwtAuthenticationFilter.java (2)
32-35: 토큰 검증 실패 시 보안 컨텍스트 클리어 로직 추가유효하지 않은 토큰에 대해 명시적으로 SecurityContext를 클리어하는 로직이 추가되었습니다. 이는 보안을 강화하는 좋은 개선사항입니다.
36-39: Authorization 헤더 부재 시 보안 컨텍스트 클리어 로직 추가Authorization 헤더가 없거나 Bearer 토큰이 아닌 경우에도 SecurityContext를 클리어하도록 개선되었습니다. 이는 잠재적인 보안 취약점을 방지합니다.
src/main/java/com/wayble/server/user/entity/User.java (3)
21-24: 복합 고유성 제약 조건 데이터베이스 레벨 구현email과 login_type의 복합 고유성 제약 조건이 @table 어노테이션에 올바르게 추가되었습니다. 이는 데이터베이스 레벨에서 중복을 방지하는 효과적인 방법입니다.
36-37: 이메일 필드의 개별 고유성 제약 조건 제거이메일 필드에서 unique=true 속성이 제거되었습니다. 이는 복합 고유성 제약 조건으로 변경되면서 적절한 수정사항입니다.
21-24: UserRepository 메서드 일관성 확인 완료
- UserRepository 인터페이스에
existsByEmailAndLoginType,findByEmailAndLoginType메서드가 구현되어 있습니다.- AuthService와 UserService에서도 해당 메서드를 사용 중이어서 엔티티의 복합 고유 제약 조건(
login_type)과 일치합니다.추가 조치가 필요 없습니다.
src/main/java/com/wayble/server/common/config/security/jwt/JwtTokenProvider.java (2)
16-16: 성능 최적화를 위한 키 캐싱 필드 추가가 적절합니다.서명 키를 캐싱하여 매번 재생성하는 오버헤드를 줄이는 좋은 개선사항입니다.
18-23: 스레드 안전성 문제를 검토해 주세요.지연 초기화 패턴이 올바르게 구현되었지만, 멀티스레드 환경에서 동시 접근 시 경합 조건이 발생할 수 있습니다.
다음과 같은 해결책을 고려해 보세요:
- private Key getSigningKey() { - if (signingKey == null) { - signingKey = Keys.hmacShaKeyFor(jwtProperties.getSecret().getBytes()); - } - return signingKey; - } + private synchronized Key getSigningKey() { + if (signingKey == null) { + signingKey = Keys.hmacShaKeyFor(jwtProperties.getSecret().getBytes()); + } + return signingKey; + }또는 더 효율적인 double-checked locking 패턴을 사용하거나,
@PostConstruct를 사용하여 초기화를 고려해 보세요.src/main/java/com/wayble/server/user/repository/UserRepository.java (2)
3-3: LoginType 임포트 추가가 적절합니다.새로운 메서드 시그니처에 필요한 올바른 임포트입니다.
11-12: 기존 메서드 호출 사용처 없음 확인 및 변경 승인
findByEmail(,existsByEmail(호출이 코드베이스 전체에서 더 이상 발견되지 않았습니다.- 이메일 + 로그인 타입 조합을 반영한 메서드 시그니처 변경이 복합 고유 제약 조건 요구사항을 충족하며, Spring Data JPA 네이밍 규칙에도 부합합니다.
위 확인을 바탕으로 해당 변경을 승인합니다.
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
src/main/java/com/wayble/server/common/config/security/jwt/JwtAuthentication.java(1 hunks)src/main/java/com/wayble/server/common/config/security/jwt/JwtAuthenticationFilter.java(1 hunks)src/main/java/com/wayble/server/common/config/security/jwt/JwtTokenProvider.java(2 hunks)src/main/java/com/wayble/server/user/service/auth/AuthService.java(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- src/main/java/com/wayble/server/user/service/auth/AuthService.java
- src/main/java/com/wayble/server/common/config/security/jwt/JwtAuthenticationFilter.java
🔇 Additional comments (3)
src/main/java/com/wayble/server/common/config/security/jwt/JwtAuthentication.java (1)
8-18: 이메일 기반에서 사용자 ID 기반 인증으로의 깔끔한 전환입니다.주체 식별자를
String email에서Long userId로 변경한 것이 일관성 있고 올바르게 구현되었습니다. 생성자와getPrincipal()메서드가 모두 적절히 업데이트되었습니다.src/main/java/com/wayble/server/common/config/security/jwt/JwtTokenProvider.java (2)
16-23: 서명 키 캐싱으로 성능이 개선되었습니다.서명 키를 지연 초기화하고 캐싱하는 것은 좋은 성능 최적화입니다. 매번 키를 재생성하는 오버헤드를 방지합니다.
25-33: 토큰 생성 로직이 userId 기반으로 올바르게 변경되었습니다.
generateToken메서드가 이메일 대신 사용자 ID를 받도록 변경되었고, 토큰 주체가 적절히String.valueOf(userId)로 설정되었습니다.
#️⃣ 연관된 이슈
#41
📝 작업 내용
💬 리뷰 요구사항 (선택)
refreshToken 관련 로직은 이후에 확장 및 구현하겠습니다!
Summary by CodeRabbit
신규 기능
버그 수정
개선 사항