통합적인 예외 처리
예외 처리 에서 알아본 내용을 기반으로 실제로 Spring Boot / Restful Api Controller 기반으로 구현
1. @RestControllerAdvice란?
@RestControllerAdvice는 @ControllerAdvice와 유사하지만, REST API 전용이다. 기본적으로 @ResponseBody가 포함되어 있어 예외를 JSON 형식으로 반환하며 응답 형식을 통일하고, 예외 처리를 중앙 집중화할 수 있다.
2. 예외 처리 설정
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
@RestControllerAdvice
public class GlobalRestExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<Map<String, Object>> handleAllExceptions(Exception ex){
Map<String, Object> response = new HashMap<>();
response.put("timestamp", LocalDateTime.now());
response.put("message", ex.getMessage());
response.put("status", HttpStatus.INTERNAL_SERVER_ERROR.value());
return new ResponseEntity<>(response, HttpStatus.INTERNAL_SERVER_ERROR);
}
@ExceptionHandler(IllegalArgumentException.class)
public ResponseEntity<Map<String, Object>> handleIllegalArgumentException(IllegalArgumentException ex) {
Map<String, Object> response = new HashMap<>();
response.put("timestamp", LocalDateTime.now());
response.put("message", ex.getMessage());
response.put("status", HttpStatus.BAD_REQUEST.value());
return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST);
}
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<Map<String, Object>> handleResourceNotFoundException(ResourceNotFoundException ex) {
Map<String, Object> response = new HashMap<>();
response.put("timestamp", LocalDateTime.now());
response.put("message", ex.getMessage());
response.put("status", HttpStatus.NOT_FOUND.value());
return new ResponseEntity<>(response, HttpStatus.NOT_FOUND);
}
}@RestControllerAdvice 어노테이션을 사용해 Handler를 설정한다.
3. REST 컨트롤러
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/test")
public class TestController {
@GetMapping("/null")
public String getNullPointer() {
throw new NullPointerException("NullPointerException 발생!");
}
@GetMapping("/illegal-argument")
public String getIllegalArgument() {
throw new IllegalArgumentException("IllegalArgumentException 발생!");
}
@GetMapping("/not-found")
public String getResourceNotFound() {
throw new ResourceNotFoundException("리소스를 찾을 수 없습니다.");
}
@PostMapping("/validate")
public String validateInput(@RequestBody TestDTO testDTO) {
if (testDTO.getValue() == null || testDTO.getValue().isEmpty()) {
throw new IllegalArgumentException("값은 필수입니다!");
}
return "유효한 값입니다.";
}
}
// 내가 직접 만든 Custom Exception 등록
@ResponseStatus(HttpStatus.NOT_FOUND)
class ResourceNotFoundException extends RuntimeException {
public ResourceNotFoundException(String message) {
super(message);
}
}
// 테스트용 DTO
class TestDTO {
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}테스트용 Controller 작성
Test 결과
- 테스트는 Postman환경을 활용했습니다.
- RestApi이기 때문에 결과는 모두 JSON
- NullPointerException { “timestamp”: “2024-11-12T12:34:56”, “message”: “NullPointerException 발생!”, “status”: 500 }
- IllegalArgumentException
{ “timestamp”: “2024-11-12T12:35:56”, “message”: “IllegalArgumentException 발생!”, “status”: 400 } - ResourceNotFoundException { “timestamp”: “2024-11-12T12:36:56”, “message”: “리소스를 찾을 수 없습니다.”, “status”: 404 }
- 유효성 검증 예외
-
Body { “value”: "" }
-
결과 { “timestamp”: “2024-11-12T12:37:56”, “message”: “값은 필수입니다!”, “status”: 400 }
-