-
Notifications
You must be signed in to change notification settings - Fork 0
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
리프레시 토큰 재발급 오류 수정 및 관련 코드 리팩토링, 일반 회원가입 기능 추가 #61
base: main
Are you sure you want to change the base?
Conversation
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.
네이버 컨벤션 스타일 적용되어있는지 확인 부탁드립니다.
고생하셨습니다
@PostMapping("/signup") | ||
@Operation(summary = "일반 회원가입") | ||
public ResponseEntity<String> signUp(@Valid @RequestBody SignUpRequestDTO signUpRequestDTO) { | ||
authService.signUp(signUpRequestDTO); | ||
return ResponseEntity.status(HttpStatus.CREATED).body("회원가입이 완료되었습니다."); |
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.
멘토님이 리뷰해주신 내용이 있습니다.
응답에 대해서는 꼭 필요한 데이터만 반환하는 정책을 많은 기업들도 사용하고 있다고 합니다.
프론트에게 필요하지 않는 데이터는 굳이 안보내줘도 될 것 같습니다 Ex) "회원가입 완료되었습니다"
그 외 API들도 공통적입니다.
public ResponseEntity<String> login( | ||
@Valid @RequestBody LoginRequestDTO loginRequestDTO, | ||
HttpServletResponse response) { | ||
log.debug("로그인 시도 - email: {}", loginRequestDTO.email()); |
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.
이 로그는 꼭 필요한 Log라서 작성하신건가요?
그 외에 다른 클래스들에서도 쓰인 Log들도 어떠한 목적이 있어서 사용하신건가요? 당장은 괜찮지만 후에 무분별한 log사용은 성능 저하의 원인이 된다고 합니다
try { | ||
// 로그인 처리 및 토큰 발급 | ||
Map<String, String> tokens = authService.login(loginRequestDTO); | ||
|
||
// Access Token 쿠키 설정 | ||
ResponseCookie accessTokenCookie = cookieUtil.createAccessTokenCookie(tokens.get("accessToken")); | ||
ResponseCookie refreshTokenCookie = cookieUtil.createRefreshTokenCookie(tokens.get("refreshToken")); | ||
|
||
response.addHeader(HttpHeaders.SET_COOKIE, accessTokenCookie.toString()); | ||
response.addHeader(HttpHeaders.SET_COOKIE, refreshTokenCookie.toString()); | ||
|
||
log.debug("로그인 성공 - email: {}", loginRequestDTO.email()); | ||
return ResponseEntity.status(HttpStatus.OK).body("로그인 성공"); | ||
|
||
} catch (Exception e) { | ||
log.error("로그인 실패 - email: {}, error: {}", loginRequestDTO.email(), e.getMessage()); | ||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(e.getMessage()); | ||
} |
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.
AccessToken도 쿠키로 만들어서 보내주는 이유가 있나요?
public void logout(HttpServletRequest request, HttpServletResponse response) { | ||
log.info("로그아웃 요청 수신"); | ||
|
||
String logoutRefreshToken = cookieUtil.extractRefreshTokenFromCookie(request); | ||
String logoutAccessToken = cookieUtil.extractAccessTokenFromCookie(request); | ||
|
||
try { | ||
// 1. RefreshToken에서 사용자 ID 추출 | ||
Long userId = jwtTokenProvider.getUserIdFromRefreshToken(logoutRefreshToken); | ||
log.debug("로그아웃 userId: {}" , userId); | ||
|
||
public String refreshAccessToken(String accessToken) { | ||
// 1. Access Token 블랙리스트 체크 | ||
validateAccessToken(accessToken); | ||
// 2. AccessToken 이 유효하면 블랙리스트 추가 | ||
if (jwtTokenProvider.validateToken(logoutAccessToken)) { | ||
jwtTokenProvider.addToBlacklist(logoutAccessToken); | ||
log.info("AccessToken 블랙리스트에 추가 완료 - userId: {}", userId); | ||
} |
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.
블랙 리스트에 등록된 accessToken은 계속 redis에 남아있는건가요?
@Transactional | ||
public void signUp(SignUpRequestDTO signUpRequestDTO) { | ||
// 중복 검사 | ||
if (memberRepository.findByEmail(signUpRequestDTO.email()).isPresent()) { | ||
throw new JwtAuthenticationException("이미 가입된 이메일입니다."); | ||
} |
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.
일반 로그인한 사용자와 소셜 로그인한 사용자의 이메일이 같은 경우에는 어떻게 처리되나요?
Member member = new Member( | ||
signUpRequestDTO.name(), | ||
signUpRequestDTO.email(), | ||
passwordEncoder.encode(signUpRequestDTO.password()), | ||
signUpRequestDTO.imageUrl()); | ||
|
||
// 2. 토큰에서 사용자 정보 추출 | ||
Long userId = jwtTokenProvider.getUserIdFromExpiredToken(accessToken); | ||
memberRepository.save(member); |
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.
해당 코드 관련 내용도 멘토님께서 남겨주신 내용이 있습니다.
Member member = memberRepository.findByEmail(loginRequestDTO.email()) | ||
.orElseThrow(() -> { | ||
log.warn("로그인 실패 - 존재하지 않는 이메일: {}", loginRequestDTO.email()); | ||
return new JwtAuthenticationException("가입되지 않은 이메일입니다."); |
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.
서비스 로직에 대한 예외 처리는 CustomException을 사용하면 예외를 일관되게 관리할 수 있고, 추후 확장성 및 예외 처리 로직을 쉽게 개선할 수 있습니다.
.issuedAt(now) | ||
.expiration(validity) | ||
.signWith(key) | ||
.compact(); | ||
.subject(String.valueOf(userId)) | ||
.issuedAt(now) | ||
.expiration(validity) | ||
.signWith(key) | ||
.compact(); |
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.
혹시 네이버 컨벤션 스타일이 적용되어있는 상태인가요? 이런 현상은 컨벤션이 안맞아서 나타나는 것 같습니다.
public String refreshToken(String refreshToken) { | ||
try { | ||
// 1. 리프레시 토큰 유효성 검사 | ||
jwtTokenProvider.validateToken(refreshToken); |
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.
이미 필터에서 해당 토큰 유효성 검사하지 않나요?
📌 과제 설명
👩💻 요구 사항과 구현 내용
1. 일반 회원가입 및 로그인
2. 엑세스 토큰 재발급 오류 수정
[현황]
[문제점]
[해결방안]
a. accessToken 재발급 로직 수정
b. 만료 안된 accessToken 처리
3. 기타 관련 코드 리팩토링
a. CookieUtil.java,
b. JwtAuthenticationFilter.java
c. authController 및 authService 레이어 역할에 따른 코드 리팩토링
d. 코드 가독성을 위해 refreshToken 검증 로직과, 삭제 로직을 분리
✅ 피드백 반영사항
✅ PR 포인트 & 궁금한 점