본문 바로가기
language/java

Spring MVC 예외 처리 전체 흐름 완벽 이해하기

by 죄니안죄니 2026. 5. 29.
반응형

Spring MVC 예외 처리 전체 흐름 완벽 이해하기

이전 글에서:

  • @ExceptionHandler
  • @ControllerAdvice

를 배웠습니다.

그런데 실무에서는 여기서 반드시 나오는 질문이 있습니다.

@ExceptionHandler는 누가 호출하는가?

@ControllerAdvice는 언제 개입하는가?

예외가 발생하면 Spring 내부에서 무슨 일이 일어나는가?

이 질문에 답할 수 있어야 Spring 예외 처리 구조를 진짜 이해한 것입니다.

이번 글에서는 Spring MVC 내부에서 예외가 처리되는 전체 흐름을 설명합니다.


대표 이미지

Spring MVC 예외 처리 전체 흐름
Spring MVC 예외 처리 전체 흐름Spring MVC 예외 처리 전체 흐름
 
 

 


1. 전체 흐름 먼저 보기

Spring MVC에서 예외가 발생하면 아래 순서로 처리됩니다.

Client
 ↓
DispatcherServlet
 ↓
HandlerMapping
 ↓
HandlerAdapter
 ↓
Controller
 ↓
예외 발생
 ↓
HandlerExceptionResolver
 ↓
@ExceptionHandler
 ↓
@ControllerAdvice
 ↓
HTTP Response
 

2. DispatcherServlet이란?

Spring MVC의 핵심 진입점.

모든 요청은 먼저:

DispatcherServlet

으로 들어옵니다.


3. 예시 요청

 
GET /users/1
 

4. DispatcherServlet 동작

요청 수신
 ↓
어떤 Controller 호출할지 탐색
 ↓
Controller 실행
 

5. Controller 실행

 
@GetMapping("/{id}")
public User findUser(Long id) {

    throw new UserNotFoundException();
}
 

6. 예외 발생

여기서 중요한 점.

 
throw new UserNotFoundException();
 

발생 시

Controller가 직접 처리하지 않으면

예외가 DispatcherServlet까지 올라갑니다.


7. DispatcherServlet은 catch를 가지고 있다

실제로 내부적으로는

 
try {

    controller 실행

} catch(Exception e) {

    예외 처리 로직
}
 

구조를 가집니다.


8. 그 다음 누구를 호출할까?

바로

HandlerExceptionResolver

입니다.


9. HandlerExceptionResolver란?

한 줄 정의

예외를 HTTP 응답으로 변환하는 전략 객체
 

10. Resolver 체인

Spring은 여러 Resolver를 순서대로 실행합니다.

대표적으로:

ExceptionHandlerExceptionResolver

ResponseStatusExceptionResolver

DefaultHandlerExceptionResolver
 

11. 가장 중요한 Resolver

실무 기준 90% 이상.

ExceptionHandlerExceptionResolver
 

12. 역할

@ExceptionHandler 찾기
 

입니다.


13. 예시

 
@ExceptionHandler(
    UserNotFoundException.class
)
public ResponseEntity<?> handle() {

}
 

14. 내부 흐름

예외 발생
 ↓
ExceptionHandlerExceptionResolver
 ↓
해당 예외 처리 메서드 검색
 ↓
메서드 실행
 ↓
응답 반환
 

15. Controller 내부 먼저 탐색

Spring은 우선

 
UserController
 

안에 있는

 
@ExceptionHandler
 

를 찾습니다.


16. 없으면?

그 다음

 
@ControllerAdvice
 

탐색.


17. ControllerAdvice 등장

 
@RestControllerAdvice
public class GlobalExceptionHandler {

}
 

18. 역할

전역 예외 처리
 

19. 실무 구조

Controller
 ↓
Service
 ↓
Repository

예외 발생
 ↓
ControllerAdvice
 

20. 예시

 
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(
        UserNotFoundException.class
    )
    public ResponseEntity<?> handle() {

        return ResponseEntity
                .status(404)
                .build();
    }
}
 

21. Spring이 찾는 순서

매우 중요.

Controller 내부
 ↓
ControllerAdvice
 ↓
상위 예외
 ↓
Exception.class
 

22. 가장 구체적인 예외 우선

예:

 
@ExceptionHandler(
    UserNotFoundException.class
)
 
 
@ExceptionHandler(
    RuntimeException.class
)
 

동시 존재.


발생

 
throw new UserNotFoundException();
 

결과

UserNotFoundException 핸들러 실행
 

23. ResponseStatusExceptionResolver

두 번째 Resolver.


예외

 
@ResponseStatus(
    HttpStatus.NOT_FOUND
)
public class UserNotFoundException
 

발생

 
throw new UserNotFoundException();
 

Spring이 자동으로

 
404 Not Found
 

반환.


24. DefaultHandlerExceptionResolver

Spring 기본 예외 처리기.


예:

 
HttpRequestMethodNotSupportedException
 

발생

 
POST만 가능한 API에 GET 호출
 

자동 응답

 
405 Method Not Allowed
 

25. Spring Boot에서는?

여기서도 처리 못하면

Spring Boot가 개입.


등장하는 것이

BasicErrorController


26. BasicErrorController

최후의 안전망.


예외 처리 실패 시

기본 응답 반환.

 
{
  "timestamp":"...",
  "status":500,
  "error":"Internal Server Error"
}
 

27. 그래서 실무에서는?

대부분

 
@RestControllerAdvice
 

로 직접 처리.


28. 실제 실무 흐름

Controller
 ↓
Service
 ↓
Repository

SQLException
 ↓
DataAccessException
 ↓
BusinessException
 ↓
ControllerAdvice
 ↓
ErrorResponse
 ↓
JSON 반환
 

29. 로그는 어디서 남길까?

실무 기준.

 
@RestControllerAdvice
 

에서 한 번.


예:

 
@ExceptionHandler(Exception.class)
public ResponseEntity<?> handle(
        Exception e) {

    log.error(
        "시스템 오류",
        e
    );

    ...
}
 

30. 왜 한 번만?

예외를

Repository
 ↓
Service
 ↓
Controller
 

모두 log.error() 하면

같은 예외가 여러 번 출력됨.


31. 실무 최종 구조

HTTP 요청
 ↓
DispatcherServlet
 ↓
HandlerMapping
 ↓
HandlerAdapter
 ↓
Controller
 ↓
Exception 발생
 ↓
HandlerExceptionResolver
 ↓
ExceptionHandlerExceptionResolver
 ↓
@ControllerAdvice
 ↓
ErrorResponse 생성
 ↓
JSON 응답
 

32. 면접 단골 질문

Q. @ExceptionHandler는 누가 호출하나요?

DispatcherServlet
 ↓
HandlerExceptionResolver
 ↓
ExceptionHandlerExceptionResolver
 

이 호출.


Q. @ControllerAdvice는 언제 실행되나요?

Controller 내부에서 처리 못한 예외 발생 시
 

실행.


Q. Spring Boot 기본 에러 응답은 누가 만들까요?

BasicErrorController
 

Q. 실무에서 로그는 어디서 남기나요?

@ControllerAdvice
 

최상위 처리 지점.


33. 가장 중요한 핵심 한 줄

Spring MVC 예외 처리는
DispatcherServlet이 예외를 잡고,
HandlerExceptionResolver가 적절한 @ExceptionHandler 또는 @ControllerAdvice를 찾아 HTTP 응답으로 변환하는 구조이다.
 

이제 예외 처리 카테고리는 완전히 끝났고, 다음부터는 원래 목차대로

7. 동시성 & 멀티스레드

의 첫 번째 글인

프로세스(Process) vs 스레드(Thread)

로 넘어가면 됩니다. 이것부터 JVM의 Stack, Heap, synchronized, CAS, Atomic, ThreadPool, Virtual Thread까지 모두 연결되기 시작합니다.

반응형

댓글