[Spring] @ExceptionHandler에 여러 예외를 묶을 때의 파라미터 선언 규칙

joyful·2026년 2월 8일

Java/Spring

목록 보기
37/47

@ExceptionHandler를 사용하면 다음과 같이 여러 예외를 배열로 묶어 한꺼번에 처리할 수 있다.

@ExceptionHandler({AException.class, BException.class})
public String ex(Exception e) {
	log.info("exception e", e);
    return "error";
}

그런데 코드를 작성하다 보니 문득 의문이 생겼다. 처리해야 할 예외는 AB 두 개인데, 파라미터는 왜 굳이 상위 타입인 Exception으로 선언해야 할까? 혹시 파라미터를 아예 생략해도 되는 건지, 아니면 반드시 둘을 아우르는 부모 클래스를 적어야만 하는 건지 궁금해졌다.

결론부터 말하자면 "둘 다 가능하지만, 선택의 기준은 명확하다"는 것이다.


1. 파라미터 생략하기: "정보가 필요 없다면 비워라"

스프링은 예외 객체 자체를 로직에서 쓸 일이 없다면 파라미터를 아예 생략하는 것을 허용한다.

@ExceptionHandler({AException.class, BException.class})
public ModelAndView ex() {
	// 예외 객체를 안 써도 된다면 이렇게만 써도 무방함
    log.info("A 또는 B 예외 발생");
    return new ModelAndView("error/4xx");
}

구체적인 에러 메시지나 스택 트레이스를 로그로 남길 필요가 없는 단순한 에러 페이지 이동 등에 사용한다.


2. 상위 타입으로 받기: "로그와 다형성"

실무에서 가장 권장되는 방식은 공통 부모 타입(Exception이나 RuntimeException 등)을 파라미터로 선언하는 것이다.

@ExceptionHandler({AException.class, BException.class})
public ErrorResult ex(Exception e) {
	// A나 B 중 무엇이 터져도 e로 들어옴 (다형성)
    log.error("[exceptionHandle] 발생한 예외: {}", e.getClass());
    return new ErrorResult("BAD_REQUEST", e.getMessage());
}

어떤 예외가 들어왔는지 로그를 남겨야 하거나, 예외 객체에서 메시지를 추출해 공통 에러 응답 객체를 만들어야 할 때 사용한다.


3. 주의: 특정 자식 타입을 적으면 안 되는 이유

만약 여러 예외를 묶어두고 파라미터만 특정 자식 타입인 AException으로 고정하면 문제가 생긴다.

@ExceptionHandler({AException.class, BException.class})
public String ex(AException e) { ... }	// 위험!

AException이 터지면 잘 작동하지만, BException이 터지면 파라미터 타입 불일치 문제가 발생한다. 스프링 내부에서 예외 해결에 실패하게 되므로, 여러 개를 묶을 때는 반드시 공통 조상을 쓰거나 생략해야 한다.


4. 실무적인 선택 기준 요약

✅ 로그를 남기거나 응답 메시지를 써야 한다면?

공통 부모 타입(Exception, RuntimeException 등)을 파라미터로 선언한다. (가장 권장)

✅ 예외 정보와 상관없이 단순 처리만 하면 된다면?

파라미터를 생략한다.

✅ 만약 예외마다 처리 로직이 완전히 달라야 한다면?

하나로 묶지 말고 메서드를 분리해서 각각의 구체적인 타입을 파라미터로 쓴다.


💡 마치며

단순히 "동작한다"는 사실을 넘어, "내가 예외 객체를 로직에서 사용할 것인가?"에 따라 파라미터 선언 방식이 달라진다. 실무에서는 디버깅을 위해 로그를 남겨야 하는 경우가 대부분이므로, 다형성을 활용해 공통 부모 타입을 받아두는 것이 가장 유연한 대응이라고 할 수 있다.

profile
기쁘게 코딩하고 싶은 백엔드 개발자

0개의 댓글