기존의 비대했던 ErrorResponse와 GlobalExceptionHandler를 전략 패턴(Strategy Pattern)으로 개편하여 유지보수성, 가독성, 확장성을 극대화한 구조입니다.
이 시스템은 예외가 발생하면 ErrorDispatcher가 등록된 모든 전략 중 적절한 것을 찾아 처리하고, 일관된 ErrorResponse를 반환하는 구조입니다.
ExceptionStrategy모든 예외 처리 로직의 규격입니다.
각 예외별로 "내가 처리할 수 있는가?"(isSupport)와 "어떤 에러 코드/상세를 반환할 것인가?"를 정의합니다.
public interface ExceptionStrategy<T extends Exception> {
boolean isSupport(Exception e); // 처리 가능 여부 확인
ErrorCode getErrorCode(T e); // 에러 코드 매핑
default Map<String, Object> getDetails(T e) { // 상세 정보 (선택적)
return Collections.emptyMap();
}
}
수많은 예외 타입을 단 3가지 유형의 핵심 전략으로 대표하여 관리할 수 있습니다.
CustomExceptionStrategy (비즈니스 예외)개발자가 의도적으로 던지는 모든 비즈니스 예외를 처리합니다. 예외 객체 내부에 포함된 ErrorCode와 커스텀 details를 그대로 추출합니다.
@Component
public class CustomExceptionStrategy implements ExceptionStrategy<CustomException> {
@Override
public boolean isSupport(Exception e) { return e instanceof CustomException; }
@Override
public ErrorCode getErrorCode(CustomException e) { return e.getErrorCode(); }
@Override
public Map<String, Object> getDetails(CustomException e) { return e.getDetails(); }
}
AuthenticationStrategy (보안 인증 예외)Spring Security 인증 과정에서 발생하는 복잡한 예외 계층을 분석합니다. BadCredentialsException, LockedException 등을 각각의 ErrorCode로 정밀하게 매핑합니다.
@Component
public class AuthenticationStrategy implements ExceptionStrategy<AuthenticationException> {
@Override
public boolean isSupport(Exception e) { return e instanceof AuthenticationException; }
@Override
public ErrorCode getErrorCode(AuthenticationException e) {
// 내부 원인 예외가 있다면 이를 추출하여 정확한 에러 코드 반환
Throwable target = (e.getCause() instanceof AuthenticationException ae) ? ae : e;
if (target instanceof UsernameNotFoundException) return ErrorCode.USER_NOT_FOUND;
if (target instanceof BadCredentialsException) return ErrorCode.INVALID_USER_CREDENTIALS;
if (target instanceof LockedException) return ErrorCode.ACCOUNT_LOCKED;
return ErrorCode.INVALID_TOKEN; // 기본 보안 에러
}
}