예외처리 보충자료
REST API 에러 처리
Produces와 ResponseEntity를 활용한 에러 처리
Produces 우선 처리
클라이언트 요청의
Accept
헤더에 따라 반환 타입을 결정합니다.application/json
: JSON 형식으로 반환.text/html
: HTML 형식으로 반환.
@RequestMapping
또는@GetMapping
에서produces
를 설정하여 반환 형식을 지정할 수 있습니다.
ResponseEntity
HTTP 응답 바디에 직접 데이터를 넣어 반환합니다.
상태 코드와 객체를 함께 반환할 수 있습니다.
ResponseEntity 예시
@GetMapping(value = "/example", produces = "application/json")
public ResponseEntity<String> exampleEndpoint() {
String response = "{\"message\": \"Hello, World!\"}";
return ResponseEntity.ok(response);
}
서버 에러 설정
application.properties 설정
에러 메시지 출력 옵션:
server.error.include-binding-errors=always
server.error.include-exception=true
위 설정을 통해 바인딩 에러나 예외를 자세히 출력할 수 있습니다.
HandlerExceptionResolver
개요
HandlerExceptionResolver
를 구현하여 MVC 컨트롤러 밖에서 발생한 예외를 처리할 수 있습니다.예외를 WAS까지 전달하지 않고 Spring MVC에서 해결합니다.
HandlerExceptionResolver 활용
HTML과 JSON 반환 나누기
클라이언트 요청의
Accept
헤더를 확인하여 반환 형식을 결정합니다.
Spring MVC에서 모든 예외를 처리하고 WAS로 전달하지 않음
에러가 깔끔하게 처리되어 관리가 용이해집니다.
HandlerExceptionResolver 예시
@Component
public class CustomExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(
HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex
) {
String accept = request.getHeader("Accept");
if (accept.contains("application/json")) {
try {
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
response.setContentType("application/json");
response.getWriter().write("{\"error\": \"" + ex.getMessage() + "\"}");
response.getWriter().flush();
} catch (Exception e) {
e.printStackTrace();
}
return new ModelAndView();
} else {
ModelAndView modelAndView = new ModelAndView("error");
modelAndView.addObject("message", ex.getMessage());
return modelAndView;
}
}
}
Spring이 제공하는 ExceptionResolver
ExceptionHandlerExceptionResolver
대부분의 API에서 발생하는 예외를 처리합니다.
ResponseStatusExceptionResolver
예외에 대해 HTTP 상태 코드를 지정합니다.
DefaultHandlerExceptionResolver
스프링 내부에서 발생하는 기본 예외를 처리합니다.
@ResponseStatus
를 활용한 예외 처리
@ResponseStatus
를 활용한 예외 처리@ResponseStatus
@ResponseStatus
특정 예외에 HTTP 상태 코드를 부여할 수 있습니다.
messages.properties
와 함께 사용자 정의 메시지를 설정할 수 있습니다.
사용 예시
@ResponseStatus(HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException {
public ResourceNotFoundException(String message) {
super(message);
}
}
messages.properties
resource.not.found=Resource not found.
컨트롤러에서 사용
@GetMapping("/user/{id}")
public ResponseEntity<User> getUser(@PathVariable Long id) {
User user = userService.findById(id)
.orElseThrow(() -> new ResourceNotFoundException("User with ID " + id + " not found."));
return ResponseEntity.ok(user);
}
@ExceptionHandler
로 예외 처리
@ExceptionHandler
로 예외 처리개요
컨트롤러 또는 서비스에서 발생하는 예외를 처리합니다.
반환값을
ResponseEntity
로 설정하여 클라이언트가 원하는 형식으로 에러를 반환할 수 있습니다.
컨트롤러 단위 예시
@RestController
@RequestMapping("/api/users")
public class UserController {
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<Map<String, String>> handleResourceNotFound(ResourceNotFoundException ex) {
Map<String, String> error = new HashMap<>();
error.put("error", ex.getMessage());
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error);
}
@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
return userService.findById(id)
.orElseThrow(() -> new ResourceNotFoundException("User not found"));
}
}
전역 예외 처리
@ControllerAdvice
및 @RestControllerAdvice
@ControllerAdvice
및 @RestControllerAdvice
모든 컨트롤러 또는 특정 컨트롤러에서 발생한 예외를 처리합니다.
전역 예외 처리 예시
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<Map<String, String>> handleResourceNotFound(ResourceNotFoundException ex) {
Map<String, String> error = new HashMap<>();
error.put("error", ex.getMessage());
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error);
}
@ExceptionHandler(Exception.class)
public ResponseEntity<Map<String, String>> handleGenericException(Exception ex) {
Map<String, String> error = new HashMap<>();
error.put("error", "An unexpected error occurred: " + ex.getMessage());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);
}
}
컨트롤러 적용 범위 지정
특정 컨트롤러 또는 패키지 하위 적용
@ControllerAdvice(assignableTypes = {UserController.class})
public class UserControllerAdvice {
// 특정 컨트롤러(UserController)만 적용
}
@ControllerAdvice(basePackages = "com.example.api")
public class ApiControllerAdvice {
// 특정 패키지(com.example.api) 하위 컨트롤러만 적용
}
Last updated