Spring @ControllerAdvice / @RestControllerAdvice 완벽 이해하기
이전 글에서 설명한:
@ExceptionHandler
는 특정 예외를 처리하는 매우 강력한 기능입니다.
하지만 큰 프로젝트에서는 문제가 하나 있습니다.
예를 들어 Controller가 50개 있다고 가정해 봅시다.
UserController
OrderController
ProductController
PaymentController
...
모든 Controller에:
@ExceptionHandler(...)
를 작성하면?
중복 코드 폭발
이 발생합니다.
그래서 Spring이 제공하는 전역 예외 처리 기능이 바로:
@ControllerAdvice
입니다.
실무 Spring 프로젝트에서는 거의 반드시 사용한다고 봐도 됩니다.
1. @ControllerAdvice란?
ControllerAdvice 는
여러 Controller에 공통 적용되는 기능을 정의하는 컴포넌트
입니다.
대표적으로:
- 전역 예외 처리
- 공통 모델 데이터 추가
- 바인딩 설정
등을 담당합니다.
2. 가장 많이 사용하는 목적
사실상 대부분:
전역 예외 처리
용도입니다.
3. 구조 비교
Controller마다 처리
@Controller
public class UserController {
@ExceptionHandler(...)
}
@Controller
public class OrderController {
@ExceptionHandler(...)
}
문제
중복
중복
중복
4. ControllerAdvice 적용
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(...)
}
결과
모든 Controller 공통 적용
5. 실행 흐름
HTTP 요청
↓
Controller
↓
예외 발생
↓
DispatcherServlet
↓
HandlerExceptionResolver
↓
@ControllerAdvice 탐색
↓
@ExceptionHandler 실행
↓
HTTP 응답 생성
6. 기본 예제
예외
public class UserNotFoundException
extends RuntimeException {
}
Controller
@RestController
@RequestMapping("/users")
public class UserController {
@GetMapping("/{id}")
public String findUser(
@PathVariable Long id) {
throw new UserNotFoundException();
}
}
7. 전역 처리
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(
UserNotFoundException.class
)
public ResponseEntity<?> handle() {
return ResponseEntity
.status(404)
.body("회원 없음");
}
}
8. 결과
GET /users/1
↓
404 Not Found
"회원 없음"
반환.
9. @ControllerAdvice vs @RestControllerAdvice
면접 단골.
@ControllerAdvice
@ControllerAdvice
실제로는
@ControllerAdvice
+
@ResponseBody 없음
상태.
따라서
return "error";
이면
뷰 이름
으로 해석 가능.
10. @RestControllerAdvice
@RestControllerAdvice
는
실제로
@ControllerAdvice
+
@ResponseBody
입니다.
11. 그래서 REST API에서는?
거의 무조건
@RestControllerAdvice
사용.
12. 실무 ErrorResponse 구조
보통 문자열 안 씀.
DTO 생성
public record ErrorResponse(
String code,
String message
) {}
13. 응답
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(
UserNotFoundException.class
)
public ResponseEntity<ErrorResponse>
handle() {
return ResponseEntity
.status(404)
.body(
new ErrorResponse(
"USER_NOT_FOUND",
"회원이 존재하지 않습니다."
)
);
}
}
14. 결과
{
"code":"USER_NOT_FOUND",
"message":"회원이 존재하지 않습니다."
}
15. 여러 예외 처리 가능
@ExceptionHandler({
UserNotFoundException.class,
ProductNotFoundException.class
})
16. 상위 예외 처리
예:
@ExceptionHandler(
BusinessException.class
)
그러면
UserNotFoundException
OrderException
ProductException
전부 처리 가능.
17. 우선순위
매우 중요.
예:
@ExceptionHandler(
UserNotFoundException.class
)
@ExceptionHandler(
RuntimeException.class
)
둘 다 존재.
발생
throw new UserNotFoundException();
결과
UserNotFoundException
핸들러가 실행.
이유
더 구체적인 타입 우선
18. Exception.class 처리
보통 마지막 안전망.
@ExceptionHandler(
Exception.class
)
역할
예상하지 못한 예외 처리
19. 로그는 어디서 남길까?
실무 핵심.
좋은 예
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<?> handle(
Exception e) {
log.error("시스템 오류", e);
...
}
}
20. 왜 여기서?
모든 예외가 여기 도착.
따라서
로그 1회
만 남길 수 있음.
21. Repository에서 로그?
catch(Exception e) {
log.error(...);
throw e;
}
Service에서도
log.error(...)
Advice에서도
log.error(...)
결과
같은 예외
3번 기록
22. 실무 패턴
Repository
↓
Service
↓
Controller
↓
ControllerAdvice
로그는 여기서만
23. Validation 예외 처리
실무 매우 중요.
DTO
public record UserRequest(
@NotBlank
String name
) {}
검증 실패
MethodArgumentNotValidException
발생.
24. 처리
@ExceptionHandler(
MethodArgumentNotValidException.class
)
public ResponseEntity<?> handle(
MethodArgumentNotValidException e) {
...
}
25. 비즈니스 예외 + 시스템 예외 분리
실무 추천.
비즈니스 예외
@ExceptionHandler(
BusinessException.class
)
↓
400 계열
시스템 예외
@ExceptionHandler(
Exception.class
)
↓
500 계열
26. 추천 구조
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(
BusinessException.class
)
public ResponseEntity<?> business(
BusinessException e) {
...
}
@ExceptionHandler(
Exception.class
)
public ResponseEntity<?> system(
Exception e) {
...
}
}
27. 실무 전체 흐름
Controller
↓
Service
↓
Repository
예외 발생
↓
RuntimeException
↓
전파
↓
@ControllerAdvice
↓
ErrorResponse 생성
↓
로그 기록
↓
HTTP 응답
28. 자주 하는 실수
1. Controller마다 @ExceptionHandler 작성
중복 증가.
2. Exception.class만 처리
세부 예외 구분 불가.
3. 로그 중복 기록
Repository
↓
Service
↓
Advice
전부 기록.
4. 500만 반환
회원 없음
↓
500
잘못된 설계.
29. 면접 단골 질문
Q. @ControllerAdvice는 언제 사용하나요?
여러 Controller에 공통 적용되는
예외 처리 기능 구현 시
Q. @ControllerAdvice 와 @RestControllerAdvice 차이는?
@RestControllerAdvice
=
@ControllerAdvice
+
@ResponseBody
Q. 로그는 어디서 남기는 것이 좋은가?
최상위 예외 처리 지점
@ControllerAdvice
30. 가장 중요한 핵심 한 줄
@ControllerAdvice는
애플리케이션 전체의 예외 처리 정책을
한 곳에서 관리하기 위한 Spring의 전역 예외 처리 메커니즘이다.
다음 글은
Spring MVC 예외 처리 전체 흐름
(DispatcherServlet → HandlerAdapter → Controller → ExceptionResolver → ControllerAdvice)
를 다루는 것이 좋습니다.
이걸 이해하면 Spring 예외 처리가 "왜 그렇게 동작하는지" 내부 원리까지 완전히 연결됩니다.
'language > java' 카테고리의 다른 글
| 프로세스(Process) vs 스레드(Thread) 완벽 이해하기 (0) | 2026.05.29 |
|---|---|
| Spring MVC 예외 처리 전체 흐름 완벽 이해하기 (0) | 2026.05.29 |
| Spring @ExceptionHandler 완벽 이해하기 (0) | 2026.05.29 |
| Java/Spring 실무 예외 처리 패턴 완벽 이해하기 (0) | 2026.05.29 |
| Java 예외 로그 전략 완벽 이해하기 (0) | 2026.05.29 |
댓글