Skip to content

Conversation

@se0hui
Copy link
Contributor

@se0hui se0hui commented Mar 1, 2025

💡 PR 요약

해당 PR의 변경사항, 해당 이슈 등에 대한 간략한 설명을 작성해주세요.

  • POST/auth/signup 엔드포인트를 통해 회원가입 기능을 구현하였습니다.
  • POST/auth/signin 엔드포인트를 통해 로그인 기능을 구현하였습니다.
  • PATCH/auth/refresh 엔드포인트를 통해 JWT 리프레시 토큰 갱신 기능을 구현하였습니다.
    Resolves: [Feat] Auth 관련 기능 구현 #11

📋 작업 내용

JWT를 활용한 로그인 및 인증/인가 시스템 구현을 포함하여, Spring Security와 JWT를 연동한 사용자 인증 처리 토큰 기반 인증 및 권한 부여, 리프레시 토큰 관리 등을 완료하였습니다.

🤝 리뷰 시 참고사항

Bcrypt를 이용하여 비밀번호 암호화를 진행하였고, redis를 활용하여 리프레시 토큰 저장 및 로테이션 적용하였습니다.

✅ 체크리스트

추가적으로 필요한 체크리스트가 있다면 추가적으로 작성해주세요.

  • 이 작업으로 인해 변경이 필요한 문서를 작성 또는 수정했나요? (e.g. README, .env.example)
  • 작업한 코드가 정상적으로 동작하는지 확인했나요?
  • 작업한 코드에 대한 테스트 코드를 작성하거나 수정했나요?
  • Merge 대상 브랜치를 올바르게 설정했나요?
  • 해당 PR과 관련 없는 작업이 포함되지는 않았나요?
  • PR의 올바른 라벨과 리뷰어를 설정했나요?

Copy link

@m2ri1 m2ri1 left a comment

Choose a reason for hiding this comment

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

추가적으로, 일반적인 Java의 패키지 네이밍 컨벤션은
소문자로 맞추어주는 것이 일반적입니다!

/auth/presentation/data 경로의 Response, Request등의 패키지를 소문자로 맞추어 작성해주시면 좋을 것 같아요

Comment on lines 31 to 34
UserDetails userDetails = customUserDetailsService.loadUserByUsername(email);
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
Copy link

Choose a reason for hiding this comment

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

customUserDetailsService.loadUserByUsername(email)에서 null이 반환되어 NPE가 발생되는 경우를 방지해주시면 더욱 안전한 코드가 될 것 같습니다!

아래와 같은 방식으로 userDetails의 null 여부 검증후 이어서 작업을 수행하도록 하고,
null일 경우의 예외처리까지 해주시면 좋을 것 같아요

if (userDetails != null) {
    UsernamePasswordAuthenticationToken authentication =
            new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
    SecurityContextHolder.getContext().setAuthentication(authentication);
}

Copy link
Contributor Author

@se0hui se0hui Mar 5, 2025

Choose a reason for hiding this comment

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

피드백 반영했습니다.
감사합니다!

d911405

Comment on lines 13 to 14
private final LocalDateTime accessTokenExpiredAt;
private final LocalDateTime refreshTokenExpiredAt;
Copy link

Choose a reason for hiding this comment

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

다른 DTO와 일관성을 위해서 accessTokenExpiresAt, refreshTokenExpiredAt등의 이름으로 맞춰주시는게 좋아보이는데, 혹시 다르게 네이밍하신 이유가 있을까요?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

오타 확인 후 피드백 반영했습니다!
리뷰 감사합니다.

24ad717

Comment on lines 27 to 32
public String createRefreshToken(String email) {
String refreshToken = generateToken(email, refreshTokenExpiration);
redisTemplate.opsForHash().delete("refresh_token", refreshToken);
redisTemplate.opsForHash().put("refresh_token", email, refreshToken);
return refreshToken;
}
Copy link

Choose a reason for hiding this comment

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

refreshToken을 저장할 때 email을 키로 사용하고 있으니,
삭제할 때도 email을 키로 사용해야 정상적으로 삭제가 될 것 같습니다

public String createRefreshToken(String email) {
    String refreshToken = generateToken(email, refreshTokenExpiration);
    redisTemplate.opsForHash().delete("refresh_token", email);
    redisTemplate.opsForHash().put("refresh_token", email, refreshToken);
    return refreshToken;
}

이런식으로요!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

피드백 반영했습니다.
리뷰 감사합니다!

de60b66

Copy link
Member

@snowykte0426 snowykte0426 left a comment

Choose a reason for hiding this comment

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

우선 수고하셨습니다

확인해주세요😁

Comment on lines 7 to 12
public interface AuthPort {

Optional<MemberJpaEntity> findByEmail(String email);

void save(MemberJpaEntity member);
}
Copy link
Member

Choose a reason for hiding this comment

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

Member 리소스를 찾는 행위는 Member Pesistence Port 같은 곳을 보면 이미 구현되어 있거나 관련 기능이 모여 있으니 이미 존재하는 것을 사용해도 될 것 같습니다

Copy link
Contributor Author

Choose a reason for hiding this comment

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

findMebersByCriteria 사용하여 피드백 반영하였습니다.
리뷰 감사합니다!

9c77f31

Comment on lines 34 to 36
if (email == null || password == null || email.isEmpty() || password.isEmpty() || email.length() > EMAIL_MAX_LENGTH || password.length() > PASSWORD_MAX_LENGTH) {
throw new EmailOrPasswordEmptyException();
}
Copy link
Member

Choose a reason for hiding this comment

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

Request DTO에 값 검증 관련 어노테이션으로 충분히 이미 검증이 가능한 로직인 것 같습니다

Copy link
Contributor Author

Choose a reason for hiding this comment

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

피드백 반영하였습니다!
리뷰 감사합니다.

0a2e410

Copy link
Member

@snowykte0426 snowykte0426 left a comment

Choose a reason for hiding this comment

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

수고하셨습니다😎

Copy link

@m2ri1 m2ri1 left a comment

Choose a reason for hiding this comment

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

고생하셨습니다! ☺️

@se0hui se0hui merged commit de07aad into develop Mar 5, 2025
1 of 2 checks passed
@snowykte0426 snowykte0426 added the ✨ Type: Feature 기능 추가 label Mar 8, 2025
@snowykte0426 snowykte0426 deleted the feature/auth-api branch March 25, 2025 13:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ Type: Feature 기능 추가

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants