@ExceptionHandler

코딩냥이·2024년 9월 10일

Annotation

목록 보기
25/34

@ExceptionHandler

@ExceptionHandler는 스프링 MVC에서 컨트롤러 내부에서 발생하는 예외를 처리하기 위해 사용되는 어노테이션입니다.

기능

  • 특정 예외가 발생했을 때 이를 처리할 메서드를 지정합니다.
  • 컨트롤러 레벨에서 예외를 처리할 수 있게 해줍니다.
  • 예외 발생 시 사용자에게 적절한 응답을 제공할 수 있습니다.

사용 방법

기본적인 사용 방법은 다음과 같습니다:

import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    @ExceptionHandler(UserNotFoundException.class)
    public ResponseEntity<String> handleUserNotFound(UserNotFoundException ex) {
        return new ResponseEntity<>(ex.getMessage(), HttpStatus.NOT_FOUND);
    }

    // 컨트롤러의 다른 메서드들...
}

주요 특징

  1. 특정 예외 처리: 특정 예외 클래스를 지정하여 처리할 수 있습니다.
  2. 다중 예외 처리: 여러 예외를 한 메서드에서 처리할 수 있습니다.
  3. 응답 커스터마이징: 예외 발생 시 반환할 응답을 커스터마이즈할 수 있습니다.
  4. 로컬 범위: 해당 컨트롤러 내에서만 동작합니다.

고급 사용법

1. 다중 예외 처리

여러 예외를 한 메서드에서 처리할 수 있습니다:

@ExceptionHandler({UserNotFoundException.class, UserNotAuthorizedException.class})
public ResponseEntity<String> handleUserExceptions(Exception ex) {
    if (ex instanceof UserNotFoundException) {
        return new ResponseEntity<>(ex.getMessage(), HttpStatus.NOT_FOUND);
    } else if (ex instanceof UserNotAuthorizedException) {
        return new ResponseEntity<>(ex.getMessage(), HttpStatus.FORBIDDEN);
    }
    return new ResponseEntity<>("An unexpected error occurred", HttpStatus.INTERNAL_SERVER_ERROR);
}

2. 예외 계층 활용

예외의 계층 구조를 활용하여 처리할 수 있습니다:

@ExceptionHandler(RuntimeException.class)
public ResponseEntity<String> handleRuntimeExceptions(RuntimeException ex) {
    // RuntimeException과 그 하위 예외들을 모두 처리
    return new ResponseEntity<>("A runtime error occurred: " + ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
}

3. 응답 본문 커스터마이징

예외 발생 시 반환할 응답 본문을 커스터마이즈할 수 있습니다:

@ExceptionHandler(UserNotFoundException.class)
public ResponseEntity<ErrorResponse> handleUserNotFound(UserNotFoundException ex) {
    ErrorResponse error = new ErrorResponse("USER_NOT_FOUND", ex.getMessage());
    return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
}

@ControllerAdvice와의 조합

@ExceptionHandler@ControllerAdvice와 함께 사용하면 전역 예외 처리가 가능합니다:

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(UserNotFoundException.class)
    public ResponseEntity<String> handleUserNotFound(UserNotFoundException ex) {
        return new ResponseEntity<>(ex.getMessage(), HttpStatus.NOT_FOUND);
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity<String> handleAllExceptions(Exception ex) {
        return new ResponseEntity<>("An error occurred: " + ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

예외 처리 우선순위

  1. 컨트롤러 내부의 @ExceptionHandler
  2. @ControllerAdvice 클래스 내부의 @ExceptionHandler
  3. 기본 예외 처리기

테스트

@ExceptionHandler가 적용된 컨트롤러를 테스트할 때:

@WebMvcTest(UserController.class)
class UserControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    void testHandleUserNotFound() throws Exception {
        mockMvc.perform(get("/users/999"))
               .andExpect(status().isNotFound())
               .andExpect(content().string("User not found with id: 999"));
    }
}

주의사항

  1. 예외 처리 범위: @ExceptionHandler는 해당 컨트롤러 내에서만 동작합니다. 전역 처리가 필요하면 @ControllerAdvice를 사용하세요.
  2. 예외 계층: 더 구체적인 예외를 먼저 처리하도록 순서를 고려해야 합니다.
  3. 로깅: 예외 처리 시 적절한 로깅을 하는 것이 중요합니다.

베스트 프랙티스

  1. 명확한 예외 분류: 애플리케이션의 예외를 명확히 분류하고 적절한 처리 방법을 정의하세요.
  2. 일관된 응답 형식: 예외 응답의 형식을 일관되게 유지하여 클라이언트 측의 처리를 용이하게 하세요.
  3. 보안 고려: 민감한 정보가 예외 메시지를 통해 노출되지 않도록 주의하세요.
  4. HTTP 상태 코드 활용: 적절한 HTTP 상태 코드를 사용하여 예외의 성격을 명확히 전달하세요.
  5. 문서화: API 문서에 발생 가능한 예외와 그에 대한 응답을 명확히 기술하세요.

결론

@ExceptionHandler는 스프링 MVC에서 예외를 우아하게 처리할 수 있게 해주는 강력한 도구입니다. 이를 통해 개발자는 예외 상황에 대해 세밀하게 대응할 수 있으며, 사용자에게 더 나은 경험을 제공할 수 있습니다. @ControllerAdvice와 결합하여 사용하면 애플리케이션 전반의 일관된 예외 처리 전략을 구현할 수 있습니다. 적절한 예외 처리는 애플리케이션의 안정성과 사용자 경험을 크게 향상시킬 수 있으므로, 이 기능을 효과적으로 활용하는 것이 중요합니다.

연관 포스팅

@ControllerAdvice
@RestController
@ResponseStatus
@ResponseBody
@RequestMapping

profile
HelloMeow~!

0개의 댓글