실제 예외 처리 흐름

물론입니다! 아래는 Spring Boot REST API 프로젝트에서 Controller → Service → Exception 처리까지 전체 흐름을 보여주는 실제 사용 예시입니다. 주석과 함께 자세히 설명드릴게요.


✅ 예시 시나리오

사용자 등록 API에서 중복 이메일이 들어오면 DuplicateEmailException을 발생시키고, 이를 @RestControllerAdvice에서 처리합니다.


1. 사용자 정의 예외 클래스 (중복 이메일 예외)

package com.example.exception;

public class DuplicateEmailException extends RuntimeException {
    public DuplicateEmailException(String email) {
        super("이미 사용 중인 이메일입니다: " + email);
    }
}

2. 서비스 계층

package com.example.service;

import com.example.exception.DuplicateEmailException;
import com.example.model.User;
import com.example.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class UserService {

    private final UserRepository userRepository;

    public void registerUser(String email, String name) {
        if (userRepository.existsByEmail(email)) {
            throw new DuplicateEmailException(email);
        }

        User user = new User(email, name);
        userRepository.save(user);
    }
}

3. 컨트롤러 계층


4. 공통 예외 처리기 (@RestControllerAdvice)


🔁 실행 결과 예시

✅ 성공 시

❌ 중복 이메일 예외


이 예시는 실무에서 매우 자주 사용하는 구조입니다.

✅ 1. @RestControllerAdvice가 하는 일

  • @RestControllerAdvice는 전체 애플리케이션에서 발생한 예외를 가로채어 처리해주는 글로벌 예외 처리기입니다.

  • @ExceptionHandler(SomeException.class)와 함께 사용되어, 특정 예외 타입이 발생했을 때 자동으로 해당 메서드로 우회되며 처리됩니다.


✅ 2. 왜 Controller에서 throws가 없어도 동작하는가?

  • throws체크 예외 (checked exception) 처리 시 컴파일러가 요구합니다.

  • 하지만 대부분의 애플리케이션 예외 (RuntimeException 계열)는 **언체크 예외 (unchecked exception)**이며, throws를 명시하지 않아도 됩니다.

  • 따라서, 예외가 Controller 내부에서 발생하면 자동으로 컨트롤러 바깥으로 전파되고, @RestControllerAdvice에서 캐치하여 응답합니다.


✅ 3. 왜 "마지막에 예외 처리"라고 말하는가?

  • @RestControllerAdvice최종 예외 처리자입니다. → 즉, 중간에서 try-catch 하지 않는 이상, 예외는 계속 위로 올라가 @RestControllerAdvice에서 처리됩니다.

  • Spring MVC가 요청을 처리하는 DispatcherServlet → Controller → Service → 예외 발생 순서에서, 예외가 어디서 터지든 결국 @RestControllerAdvice로 모이게 되는 구조입니다.


✅ 요약

질문
답변

@RestControllerAdvice 때문에 예외가 마지막에 처리됨?

✅ 네, 전역 예외 핸들러 역할

Controller에 throws 없어도 되는 이유는?

✅ RuntimeException은 언체크 예외라 명시적 throws 불필요

어디서 던져도 @RestControllerAdvice가 잡나?

✅ 중간에 catch 안 하면 모두 거기서 처리됨

Last updated