Daily Dev Q&A: Spring의 예외 처리 방식

2025. 12. 29. 19:48·Archive/Daily Dev Q&A

Topic (오늘의 주제)

Spring의 우아한 예외 처리: @ExceptionHandler와 @ControllerAdvice

Why (왜 사용하는가? 왜 중요한가?)

  • 실무: 컨트롤러마다 중복되는 try-catch 블록을 제거하고, 클라이언트에게 **일관된 포맷(JSON)**의 에러 응답을 내려주기 위해 필수적입니다.
  • 구조적 의미: **관심사의 분리(SoC)**를 실현합니다. 비즈니스 로직(성공 케이스)과 예외 처리 로직(실패 케이스)을 완전히 분리하여 코드 가독성을 높입니다.
  • 면접 의도: 단순한 자바 예외 처리(try-catch)를 넘어, 프레임워크가 제공하는 AOP 기반의 전역 예외 처리 전략을 설계할 수 있는지 확인합니다.

Core Concept (핵심 개념 정리)

스프링의 예외 처리는 발전 과정에 따라 크게 3가지 단계(방식)로 나뉩니다.

요소 내용
1. @ExceptionHandler 개념: 특정 Controller 클래스 내부에서 발생하는 예외만 잡아내는 애노테이션.

특징: 해당 컨트롤러 안에서만 유효하므로, 여러 컨트롤러에 똑같은 예외 처리 코드를 복사해야 하는 단점이 있음.
2. @ControllerAdvice 개념: 전역(Global) 예외 처리를 위한 AOP 기반 애노테이션.

동작: 모든 컨트롤러에서 발생한 예외를 가로채서(Interception) 한 곳에서 처리할 수 있게 함.

구조: 보통 @ControllerAdvice 클래스 안에 @ExceptionHandler 메서드들을 모아둠.
3. @RestControllerAdvice 개념: @ControllerAdvice + @ResponseBody의 합체.

특징: API 서버(REST API) 개발 시 주로 사용하며, 에러 응답을 View(HTML)가 아닌 JSON 객체로 바로 반환함.
동작 흐름 예외 발생(throw) → HandlerExceptionResolver가 탐색 → 적합한 @ExceptionHandler가 있는지 확인 → 있으면 해당 메서드 실행 및 응답 반환.
비교 기존 방식: 메서드마다 try-catch로 감싸서 지저분함.

Spring 방식: 로직 구현부는 예외를 던지기만 하고(throw), 별도의 GlobalExceptionHandler 클래스가 받아서 처리.

Interview Answer Version (면접 답변식 요약)

"Spring의 예외 처리는 @ControllerAdvice (또는 @RestControllerAdvice)를 활용한 전역 처리 방식을 주로 사용합니다.

컨트롤러 별로 중복되는 @ExceptionHandler를 한곳에 모아 관리함으로써 비즈니스 로직과 예외 처리 코드를 분리할 수 있고, 클라이언트에게 **일관된 에러 응답 포맷(Custom Error Response)**을 제공할 수 있기 때문입니다.

과거에는 HandlerExceptionResolver를 직접 구현하기도 했으나, 현재는 애노테이션 기반 처리가 표준입니다."

Practical Tip (사용시 주의할 점 or 활용 예)

1. 구체적인 예외를 먼저 선언 (우선순위 문제)

예외 처리도 구체적인 것(자식)이 먼저, 포괄적인 것(부모)이 나중에 처리되어야 합니다.

  • Bad Case: Exception.class를 처리하는 핸들러가 위에 있으면, 구체적인 예외 핸들러가 무시될 수 있음(순서 의존적일 경우) 혹은 스프링 내부 로직에 의해 덜 구체적인 것이 선택될 위험.
  • Good Case: 구체적인 예외를 명시하고, 마지막에 Exception으로 안전망 설치.
Java
@RestControllerAdvice
public class GlobalExceptionHandler {

    // 1. 구체적인 예외 (ex: 비즈니스 로직 상의 잘못된 요청)
    @ExceptionHandler(IllegalArgumentException.class)
    public ResponseEntity<ErrorResponse> handleBadReq(IllegalArgumentException e) {
        return ResponseEntity.status(400).body(new ErrorResponse("BAD_REQUEST", e.getMessage()));
    }

    // 2. 최후의 보루 (알 수 없는 에러)
    @ExceptionHandler(Exception.class)
    public ResponseEntity<ErrorResponse> handleException(Exception e) {
        log.error("Unhandled Exception", e); // 로깅 필수!
        return ResponseEntity.status(500).body(new ErrorResponse("INTERNAL_SERVER_ERROR", "서버 에러 발생"));
    }
}

2. Custom Exception과 ErrorResponse 객체 정의

그냥 String 메시지만 보내지 말고, 프론트엔드와 약속된 **JSON 구조(DTO)**를 정의해서 내려줘야 합니다.

  • 추천 구조: timestamp, status, error_code (내부 관리용 코드), message

3. @Transactional과 예외

  • Checked Exception (ex: Exception, IOException) 발생 시 기본적으로 롤백되지 않습니다.
  • Unchecked Exception (ex: RuntimeException) 발생 시에만 롤백됩니다.
  • 만약 Checked Exception에서도 롤백하고 싶다면 @Transactional(rollbackFor = Exception.class) 옵션을 줘야 합니다.

예상 꼬리질문 정리

  1. Q: @ControllerAdvice와 @RestControllerAdvice의 차이는 무엇인가요?
    • 핵심 키워드: @ResponseBody의 유무. 전자는 ViewResolver를 타서 HTML 등을 반환하려 하고, 후자는 MessageConverter를 타서 JSON 데이터를 반환합니다.
  2. Q: 필터(Filter)나 인터셉터(Interceptor)에서 발생한 예외는 @ControllerAdvice가 잡을 수 있나요?
    • 핵심 키워드: 못 잡습니다. @ControllerAdvice는 DispatcherServlet 내부(컨트롤러 진입 후)의 예외를 처리합니다. 필터(DispatcherServlet 진입 전)의 예외는 별도의 필터 내 예외 처리 로직이 필요합니다.
  3. Q: Checked Exception과 Unchecked Exception의 트랜잭션 롤백 처리 차이에 대해 설명해주세요.
    • 핵심 키워드: RuntimeException(Unchecked)은 자동 롤백, Exception(Checked)은 커밋됨(롤백 안 됨).

'Archive > Daily Dev Q&A' 카테고리의 다른 글

Daily Dev Q&A: Spring Security의 인증과 인가  (0) 2025.12.31
Daily Dev Q&A: @SpringBootApplication은 필수인가?  (1) 2025.12.30
Daily Dev Q&A: Spring Stereotype Annotations  (0) 2025.12.29
Daily Dev Q&A: Spring Bean  (0) 2025.12.26
Daily Dev Q&A: Spring Boot  (0) 2025.12.26
'Archive/Daily Dev Q&A' 카테고리의 다른 글
  • Daily Dev Q&A: Spring Security의 인증과 인가
  • Daily Dev Q&A: @SpringBootApplication은 필수인가?
  • Daily Dev Q&A: Spring Stereotype Annotations
  • Daily Dev Q&A: Spring Bean
tlsgkstj
tlsgkstj
짱구의 성장 일기
  • tlsgkstj
    코딩하는 짱구
    tlsgkstj
  • 전체
    오늘
    어제
    • 분류 전체보기 (159)
      • About (1)
      • Projects (35)
        • Personal Projects (21)
        • Team Projects (14)
      • Engineering (20)
        • CS & Tools (0)
        • Backend Core (15)
        • Frontend (1)
        • Infra & Cloud (2)
        • AI & Tools (1)
      • Trouble Shooting & Issues (0)
      • Growth & Career (38)
        • Interview Prep (0)
        • Retrospectives (38)
      • Archive (65)
        • TIL (8)
        • Daily Dev Q&A (56)
  • 블로그 메뉴

    • 홈
    • About
    • Projects
    • Tech Stack
    • Dev Log
    • GitHub
  • 링크

    • github
  • 공지사항

  • 인기 글

  • 태그

    REACT
    데브페스트
    devlog
    spring
    경기기후바이브코딩
    backend
    network
    Spring비교
    클로드코드
    프로젝트회고
    java
    aws_s3
    til
    프로덕트개발자
    OrphanRemova
    커리어리셋
    jpa
    Project_Review
    SpringBoot
    DevFestIncheon2025
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
tlsgkstj
Daily Dev Q&A: Spring의 예외 처리 방식
상단으로

티스토리툴바