Custom Exception Design

도메인 규칙 검증 실패 시 IllegalArgumentException 같은 범용 런타임 예외만 던지면, 로그에는 예외 이름만 보이고 정확히 어떤 도메인의 어떤 규칙을 위반했는지 로그나 테스트 코드에서 구분할 수 없다.[1] 다양한 검증 로직(길이 제한, 형식 오류, 빈 값 체크 등)이 도메인 모델 내에 여러 개 존재하고, 미션 요구사항 등에서 발생시켜야 하는 표준 예외 타입(IllegalArgumentException 등)이 정해져 있으면서 동시에 에러 원인의 세부 컨텍스트도 제공해야 하는 상황에 적용된다.

설계: ErrorCode Enum + 상속 커스텀 예외

ErrorCode Enum으로 검증 실패 원인을 세분화하고, 이를 포함하는 커스텀 예외 클래스가 표준 예외를 상속(IS-A)하도록 설계한다.

원문 설계도 에러 메시지를 ErrorCode enum으로 관리하고, 도메인 예외를 상속 계층으로 구성하는 방식을 제시한다.[2]

  1. ErrorCode Enum 정의: 도메인별 구체적인 에러 메시지와 코드를 관리한다.
  2. 커스텀 예외 클래스 작성: IllegalArgumentException과 같은 범용 표준 예외를 상속받아 호환성과 요구사항을 만족시키되, 내부적으로 ErrorCode를 받아 세부 에러 컨텍스트를 명확히 한다.[3]
// 1. ErrorCode Enum 정의
public enum ErrorCode {
    INVALID_CAR_NAME("[ERROR] 자동차 이름은 5자 이하여야 합니다."),
    EMPTY_CARS("[ERROR] 자동차 이름이 비어 있습니다.");

    private final String message;
    ErrorCode(String message) { this.message = message; }
    public String getMessage() { return message; }
}

// 2. 범용 예외를 상속하는 커스텀 예외 정의
public class CarRacingException extends IllegalArgumentException {
    public CarRacingException(ErrorCode code) {
        super(code.getMessage());
    }
}

// 3. 사용 예시
if (name.length() > 5) {
    throw new CarRacingException(ErrorCode.INVALID_CAR_NAME);
}

// 4. 처리 로직 (UI 등)
try {
    // ...
} catch (CarRacingException e) {
    System.out.println(e.getMessage());
}

이 구조는 단순한 문자열 메시지 대신, ErrorCode라는 타입-세이프한 Enum으로 에러 원인을 규격화한다고 볼 수 있다. 프레임워크나 외부 클라이언트가 요구하는 표준 예외(IllegalArgumentException 등)와의 상호 운용성을 유지하려고 IS-A 상속 모델을 취하는 것이 이 설계의 핵심이다.

절충점

실패 모드

관련

출처

테스트 질문


  1. 커스텀 예외로 검증 실패 세분화.md — "도메인별 세부적인 에러 컨텍스트와 메시지를 담아내지 못하는 기본 예외를 일괄 사용.", "로그에 IllegalArgumentException만 보임 → 원인 파악 어려움. 테스트 코드에서 어떤 케이스인지 구분 불가" ↩︎

  2. 객체지향 설계 실전 — ErrorCode enum으로 메시지를 관리하고 도메인 예외를 상속으로 구성하는 예시를 제시한다. ↩︎

  3. 커스텀 예외로 검증 실패 세분화.md — "ErrorCode Enum + 커스텀 예외 클래스 도입. 미션 요구사항(IllegalArgumentException) 충족을 위해 커스텀 예외가 상속받도록 설계.", "IllegalArgumentException 상속 → 요구사항 + 명시성 동시 만족" ↩︎