OAuth2를 연결하기 전에...
예외 메시지가 너무 중구난방이고 내가 영어로 쓴 것도 있고 한글로 쓴 것도 있었다
얼마 안되지만 예외 메시지를 좀 통합해서 한글로 적고 싶었다
전 포스트에서 TokenService에 InvalidTokenException을 사용하였다
// 리프레시 토큰 검증
public void validateRefreshToken(String token) {
if (token == null) {
throw new InvalidTokenException("리프레시 토큰이 없습니다.");
}
try {
jwtUtil.isExpired(token);
} catch (ExpiredJwtException e) {
throw new InvalidTokenException("만료된 리프레시 토큰입니다.");
}
String category = jwtUtil.getCategory(token);
if (!category.equals("refresh")) {
throw new InvalidTokenException("유효하지 않은 카테고리의 토큰입니다.");
}
if (!existsByTokenValue(token)) {
throw new InvalidTokenException("DB에 존재하지 않는 리프레시 토큰입니다.");
}
}
이 클래스를 만들어서 예외 처리를 전역적으로 관리한다
public class InvalidTokenException extends RuntimeException {
public InvalidTokenException(String message) {
super(message);
}
}
오류 메시지를 깔끔하게 JSON 형태로 만들어서 보여주고 싶었다
ErrorResponseDto를 하나 만들어서 형태를 정의하였다
발생 시간, http 상태 코드, 에러, 메시지를 JSON으로 표현
/**
* 예외 발생 시 클라이언트에게 반환되는 표준 오류 응답 DTO
*/
@Getter
@Builder
public class ErrorResponseDto {
private final String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
private final int status;
private final String error;
private final String message;
public static ResponseEntity<ErrorResponseDto> toResponseEntity(int status, String error, String message) {
return ResponseEntity
.status(status)
.body(ErrorResponseDto.builder()
.status(status)
.error(error)
.message(message)
.build());
}
}
그리고 DTO를 사용해서 실제로 오류 메시지를 반환하는 전역 핸들러를 만들었다
@RestControllerAdvice: 모든 @RestController에서 발생하는 예외를 한 곳에서 처리해주는 전역 예외 처리기
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(InvalidTokenException.class)
public ResponseEntity<ErrorResponseDto> handleInvalidTokenException(InvalidTokenException ex) {
return ErrorResponseDto.toResponseEntity(HttpStatus.UNAUTHORIZED.value(), "토큰 오류", ex.getMessage());
}
@ExceptionHandler(BadCredentialsException.class)
public ResponseEntity<ErrorResponseDto> handleBadCredentialsException(BadCredentialsException ex) {
return ErrorResponseDto.toResponseEntity(HttpStatus.UNAUTHORIZED.value(), "로그인 실패", "비밀번호가 일치하지 않습니다.");
}
@ExceptionHandler(RuntimeException.class)
public ResponseEntity<ErrorResponseDto> handleRuntimeException(RuntimeException ex) {
// "이미 가입되어 있는 회원입니다." 와 같은 회원가입 시의 예외를 처리
if ("이미 가입되어 있는 회원입니다.".equals(ex.getMessage())) {
return ErrorResponseDto.toResponseEntity(HttpStatus.CONFLICT.value(), "회원가입 오류", ex.getMessage());
}
// 그 외 다른 런타임 예외는 일반적인 서버 오류로 처리
return ErrorResponseDto.toResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR.value(), "서버 오류", "알 수 없는 런타임 오류가 발생했습니다.");
}
}
@ExceptionHandler(InvalidTokenException.class)UNAUTHORIZED(401) 반환@ExceptionHandler(BadCredentialsException.class)UNAUTHORIZED(401) 반환@ExceptionHandler(BadCredentialsException.class)


다음은 진짜 OAuth2 연결!