문제 인식
회원가입 완료 후 JWT 토큰을 응답으로 제공하는 기존 로직은 회원가입 직후 자동 로그인이 되어야 할 경우에는 편리하지만, 더 자연스러운 흐름은 로그인 요청 시 토큰을 발행하는 방식이라고 생각합니다.
문제 정의
회원가입 성공 여부보다는 인증 정보(JWT)를 제공하게 되어, 가입 절차가 끝난 후 직접 로그인을 요청하는 흐름과는 어색해졌습니다. 회원가입의 순수한 결과를 응답하고, 토큰 발급은 로그인 시점에 맡기는 구조로 변경하려고 합니다.
해결 방안
- 의사결정 과정
- A 선택지: 회원가입 응답에 JWT를 포함하여 반환
- 장점: 회원가입 직후 바로 인증할 수 있으므로 편리성 제공
- 단점: 회원가입과 로그인의 책임이 분리되지 않으며, 보안 측면에서 회원가입 후 자동 로그인 로직이 불필요한 경우 JWT 발행이 오히려 어색한 결과를 초래함
- B 선택지: 회원가입 결과만 반환하고 로그인 요청 시에만 토큰 발행
- 장점: 회원가입과 로그인 책임이 명확히 분리되며, 순수한 회원가입 결과 응답이 가능
- 단점: 자동 로그인을 고려한 경우라면 별도의 로그인 요청이 추가로 필요하게 됨
- 결정: 회원가입과 로그인 로직을 명확히 분리하기 위해 B 선택지를 채택했습니다. 회원가입 이후 사용자가 직접 로그인 절차를 거치는 구조가 더 자연스럽고 책임이 분리되어 유지보수 시에도 더 일관성이 있을 것으로 판단했습니다.
- A 선택지: 회원가입 응답에 JWT를 포함하여 반환
해결 과정
- 회원가입 요청 후 JWT가 아닌 순수한 회원가입 결과(회원 ID, 이메일, 역할 )를 응답하도록 SignUpResponse를 개선했습니다.
- 토큰 발급은 로그인 API에만 한정하여 로그인 시에만 발급되도록 수정했습니다.
기존 SignUpResponse, AuthService
@Getter
public class SignUpResponse {
private final String bearerToken;
public SignUpResponse(String bearerToken) {
this.bearerToken = bearerToken;
}
}
@Transactional
public SignUpResponse signUp(SignUpRequest signupRequest) {
if (userRepository.existsByEmail(signupRequest.getEmail())) {
throw new InvalidRequestException("이미 존재하는 이메일입니다.");
}
String encodedPassword = passwordEncoder.encode(signupRequest.getPassword());
UserRole userRole = UserRole.of(signupRequest.getUserRole());
User newUser = new User(
signupRequest.getEmail(),
encodedPassword,
userRole
);
User savedUser = userRepository.save(newUser);
String bearerToken = jwtUtil.createToken(savedUser.getId(), savedUser.getEmail(), userRole);
return new SignUpResponse(bearerToken);
개선한 SignUpResponse, AuthService
@Getter
public class SignUpResponse {
private final Long userId;
private final String email;
private final String userRole;
public SignUpResponse(final Long userId, final String email, final String userRole) {
this.userId = userId;
this.email = email;
this.userRole = userRole;
}
}
@Transactional
public SignUpResponse signUp(SignUpRequest signupRequest) {
if (userRepository.existsByEmail(signupRequest.getEmail())) {
throw new InvalidRequestException("이미 존재하는 이메일입니다.");
}
String encodedPassword = passwordEncoder.encode(signupRequest.getPassword());
UserRole userRole = UserRole.of(signupRequest.getUserRole());
User newUser = new User(
signupRequest.getEmail(),
encodedPassword,
userRole
);
User savedUser = userRepository.save(newUser);
return new SignUpResponse(savedUser.getId(), savedUser.getEmail(), savedUser.getUserRole().name());
}
해결 완료
- 회고
- 회원가입과 로그인 기능의 역할이 명확하게 분리되어 기능별 책임이 구분되었습니다.
- 보안 및 응답 구조 측면에서 사용자 경험이 일관되고 직관적으로 개선되었습니다.
- 전후 데이터 비교
- 변경 전: 회원가입 시 SignUpResponse에서 JWT를 응답.
- 변경 후: 회원가입 시 SignUpResponse에서 JWT 대신 사용자 정보(회원 ID, 이메일, 역할)를 반환하고, 토큰 발급은 로그인 시점으로 이동.
'WEB' 카테고리의 다른 글
3N+1 문제와 프록시 강제 초기화 해결 (0) | 2024.10.23 |
---|---|
날씨 API 사용과 리팩토링 (0) | 2024.10.15 |
JPA Update 실패 해결기 (0) | 2024.10.10 |
소프트 딜리트란? (1) | 2024.09.27 |
Spring Data JPA로 된 코드를 JDBC로 다시 짜보기 (1) | 2024.09.25 |
MDC를 이용한 로깅 도입기 (0) | 2024.09.23 |
@SpringBootTest vs @Mock (0) | 2024.09.12 |
스프링부트의 Tomcat과 Thread Pool (0) | 2024.09.10 |