결국, 클라이언트의 요청에 따라 오류 처리하는것이 서버 프로그래밍의 한 부분이다. 오류 처리를 위해 각 컨트롤러 별로 개별 처리를 하는 방법, 그리고 모든 컨트롤러 오류를 통합하여 처리하는 방법이 있다. 두번째 방법을 많이 쓰므로, 두번째 방법에 대한 내용을 정리하고자 한다.
요약하면, @RestControllerAdvice 와 ResponseEntity 를 주로 이용하고, 이를 추천한다
1. 전역처리 (@ControllerAdvice)
- Controller 들에서 발생한 예외처리를 한군데서 모아서 관리 및 처리 하고 응답한다.
- 해당 어노테이션은 클래스 어노테이션이다.
- @ExceptionHandler 를 통해 특정 클래스에 발생한 오류를 다룰 수 있다.
- @ResponseStatus 를 통해 클라이언트에 리턴하는 에러 코드를 항상 같은값으로 유지할 수 있다.
- @ResponseEntity 를 통해 클라이언트에 리턴하는 에러코드를 통해 상황에 따라 에러코드를 바꾸어 리턴 할 수 있다.
- View 리턴을 할 때(html, 타임리프)는 그냥 쓰면 되고, json 형식으로 리턴하려면 메소드에 @ResponseBody를 붙여야 한다.
- @RestControllerAdvice 를 통해 json 전용 어노테이션을 쓸 경우 @ResponseBody를 쓸 필요 없다. (주로 사용)
@RestControllerAdvice
public class GlobalExceptionHandler {
// 400 잘못된 요청
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<Map<String, Object>> handleValidationException(MethodArgumentNotValidException ex) {
Map<String, Object> body = new HashMap<>();
body.put("error", "Validation Failed");
body.put("details", ex.getBindingResult()
.getFieldErrors()
.stream()
.map(e -> e.getField() + ": " + e.getDefaultMessage())
.toList());
return ResponseEntity.badRequest().body(body);
}
// 400 잘못된 타입 (예: UUID 형식 오류)
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
public ResponseEntity<Map<String, Object>> handleTypeMismatch(MethodArgumentTypeMismatchException ex) {
Map<String, Object> body = new HashMap<>();
body.put("error", "Type Mismatch");
body.put("details", ex.getName() + " should be of type " + ex.getRequiredType());
return ResponseEntity.badRequest().body(body);
}
// 404 리소스를 찾을 수 없음
@ExceptionHandler(NoSuchElementException.class)
public ResponseEntity<Map<String, Object>> handleNoSuchElement(NoSuchElementException ex) {
Map<String, Object> body = new HashMap<>();
body.put("error", "Resource Not Found");
body.put("details", ex.getMessage());
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(body);
}
// 405 지원하지 않는 메소드
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
public ResponseEntity<Map<String, Object>> handleMethodNotSupported(HttpRequestMethodNotSupportedException ex) {
Map<String, Object> body = new HashMap<>();
body.put("error", "Method Not Allowed");
body.put("details", ex.getMessage());
return ResponseEntity.status(HttpStatus.METHOD_NOT_ALLOWED).body(body);
}
// 409 중복 등 충돌 오류
@ExceptionHandler(DataIntegrityViolationException.class)
public ResponseEntity<Map<String, Object>> handleDataIntegrityViolation(DataIntegrityViolationException ex) {
Map<String, Object> body = new HashMap<>();
body.put("error", "Conflict");
body.put("details", ex.getMostSpecificCause().getMessage());
return ResponseEntity.status(HttpStatus.CONFLICT).body(body);
}
// 500 서버 내부 오류 (예상치 못한 모든 오류 처리)
@ExceptionHandler(Exception.class)
public ResponseEntity<Map<String, Object>> handleException(Exception ex) {
Map<String, Object> body = new HashMap<>();
body.put("error", "Internal Server Error");
body.put("details", ex.getMessage());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(body);
}
@ExceptionHandler(SpecificException.class)
public ResponseEntity<ErrorMessage> specificHandler(SpecificException ex)
{
...
return ResponseEntity.status(HttpStatus.코드).body(new ErrorMessage("코드",ex.getMessage());
}
}
1. 1. 특정 오류 클래스 정의하기
- 클래스를 생성하여 Exception 클래스를 상속 받고, 생성자를 구현하면 된다.
public class SpecificException extends RuntimeException
{
public SpecificException(String msg) {
super(msg);
}
}
2. 전역처리 - json특화 (@RestControllerAdvice)
- Json 형식 리턴에 사용되는 특화 어노테이션.
@RestControllerAdvice
public class GlobalRestExceptionHandler {
@ExceptionHandler(RuntimeException.class)
public ResponseEntity<Map<String, Object>> handleException(SpecificException ex) {
Map<String, Object> body = new HashMap<>();
body.put("error", "Internal Server Error");
body.put("details", ex.getMessage());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(body);
}
}
3. ErrorResponse 용 클래스 만들기
public record ErrorResponse(
String code,
String message
)
{
}
정리해보면,
- ErrorResponse 전용 DTO 생성
- RuntimeException 을 상속 받는 커스텀 Exception 클래스 생성
- ExceptionHandler 클래스 생성
- @RestControllerAdvice 어노테이션을 이용하여 한데 모아서 처리할 수 있도록 선언
- @ExceptionHandler(커스텀Exception.class) 들을 매핑할 메소드들을 각각 생성
- 특정 오류만 처리하는 메소드들로 세분화
- 상황에 맞는 오류코드 설정
- ResponseEntity를 이용하여 ErrorResponse를 작성 후 리턴
- 컨트롤러 혹은 이후 서비스 등에서 해당 상황에 맞는 오류 발생시 커스텀 Exception을 throw
하는 단계로 처리할 수 있다.
'Backend > SpringBoot' 카테고리의 다른 글
| @RequestBody, @ResponseBody (0) | 2025.09.15 |
|---|---|
| 상태코드 반환. @ResponseStatus, ResponseEntity (0) | 2025.09.15 |
| Controller 에서 각종 파라메터 받기 + Cookie (0) | 2025.09.12 |
| Main DB (Postgresql) + Cache (Redis) 사용하기 (0) | 2025.09.03 |
| yaml 이나 env 에서 설정값 가져오기 (0) | 2025.09.03 |