이전 글에서 Java에서 Exception을 checked exception
, unchecked exception
으로 나눌 수 있다고 했다.
이번 글은 둘 중 unchecked exception
를 핸들링한 코드를 정리한다.
이전 글에서 checked exception
은 컴파일 시점에 검증이 들어가기 때문에 명시적으로 예외 처리가 필요하다고 했다.
하지만 checked exception
가 실사용 시점에도 나올 수 있기 때문에 RuntimeException
을 상속받아 unchecked exception
처럼 런타임 시에도 예외를 처리할 수 있도록 한다.
ErrorCode
먼저 나올 수 있는 에러 코드를 HttpStatus와 함께 넘길 메시지를 ENUM
구조를 사용해 명시했다.
@AllArgsConstructor
@Getter
public enum ErrorCode {
/* code: 404 */
USER_NOT_FOUND(NOT_FOUND, "유저 정보가 존재하지 않습니다."),
REVIEW_NOT_FOUND(NOT_FOUND, "해당 리뷰가 존재하지 않습니다."),
MOVIE_NOT_FOUND(NOT_FOUND, "해당 영화가 존재하지 않습니다.");
private final HttpStatus httpStatus;
private final String detail;
}
ExceptionHandler
예외가 발생했을 때, 응답으로 보낼 데이터를 handleCustomException
메서드에서 가공해 반환하도록 설정했다.
@ExceptionHandler
는 controller 단에서 발생한 예외를 해당 어노테이션이 달린 메서드에서 처리한다는 의미
@Controller
class Super {
@ExceptionHandler(FileSystemException.class)
public ResponseEntity<String> handle(Exception e) {
...
}
}
FileSystemException
, Super
class와 같이 특정 예외에, 클래스에 대해서 처리할 수도 있다.
그런데 이렇게 되면 모든 클래스에 메서드를 만들게 되고 중복되는 코드도 많아진다.
그래서 스프링에서 제공되는 전역적으로 에러 처리를 도와주는 기술 을 사용했다.
RestControllerAdvice / ControllerAdvice
@RestControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler(CustomException.class)
public ResponseEntity<ErrorResponse> handleCustomException(CustomException e) {
ErrorCode errorCode = e.getErrorCode();
return ResponseEntity.status(HttpStatus.OK).body(
ErrorResponse.builder()
.name(errorCode.name())
.status(errorCode.getHttpStatus().value())
.code(errorCode.getHttpStatus().name())
.msg(errorCode.getDetail())
.build()
);
}
}
위와 같이 에러 핸들러에 @RestControllerAdvice
또는 @ControllerAdvice
를 명시하고, 그 안에 따로 ErrorCode
를 기반으로 에러 응답을 반환하도록 CustomException
을 매개변수로 전달했다.
CustomException
@AllArgsConstructor
@Getter
public class CustomException extends RuntimeException {
private final ErrorCode errorCode;
}
CustomException
은 RuntimeException
을 상속받고 ErrorCode
객체를 갖고있어, throw new CustomException(USER_NOT_FOUND)
처럼 unchecked exception을 발생시킬 수 있다.
그리고 GlobalExceptionHandler
에서 응답 데이터 포맷은 ErrorResponse
로 에러 이름, 코드, 따로 정한 메시지 등 원하는 데이터만을 뽑아 보낼 수 있도록 한다.
@Getter
@Builder
@RequiredArgsConstructor
public class ErrorResponse {
private final String name;
private final int status;
private final String code;
private final String msg;
}
참고
https://cheese10yun.github.io/checked-exception/
'Web > Spring' 카테고리의 다른 글
[ERROR] gradle - java version (0) | 2024.06.09 |
---|---|
[JPA] M:N 관계 (@ManyToMany) (2) | 2024.01.30 |
[Spring Security] OAuth, JWT .. 적용기 (1) (0) | 2024.01.05 |