Custom Exception Design
도메인 규칙 검증 실패 시 IllegalArgumentException 같은 범용 런타임 예외만 던지면, 로그에는 예외 이름만 보이고 정확히 어떤 도메인의 어떤 규칙을 위반했는지 로그나 테스트 코드에서 구분할 수 없다.[1] 다양한 검증 로직(길이 제한, 형식 오류, 빈 값 체크 등)이 도메인 모델 내에 여러 개 존재하고, 미션 요구사항 등에서 발생시켜야 하는 표준 예외 타입(IllegalArgumentException 등)이 정해져 있으면서 동시에 에러 원인의 세부 컨텍스트도 제공해야 하는 상황에 적용된다.
설계: ErrorCode Enum + 상속 커스텀 예외
ErrorCode Enum으로 검증 실패 원인을 세분화하고, 이를 포함하는 커스텀 예외 클래스가 표준 예외를 상속(IS-A)하도록 설계한다.
원문 설계도 에러 메시지를 ErrorCode enum으로 관리하고, 도메인 예외를 상속 계층으로 구성하는 방식을 제시한다.[2]
ErrorCodeEnum 정의: 도메인별 구체적인 에러 메시지와 코드를 관리한다.- 커스텀 예외 클래스 작성:
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 상속 모델을 취하는 것이 이 설계의 핵심이다.
절충점
- 장점: 에러 상황에 대한 테스트가 쉬워지고(어떤 에러 코드가 떨어졌는지 확인 가능), 클라이언트나 UI 계층에서 에러 메시지를 일관성 있게 꺼내 쓸 수 있다.
- 단점: 커스텀 예외 클래스와 에러 코드 Enum을 매번 생성하고 관리해야 하므로 초기 설계 비용과 클래스 수가 늘어난다.
실패 모드
- 과도한 예외 생성: 모든 사소한 에러마다 개별 예외 클래스를 만드는 경우. 대신 하나의 커스텀 예외 클래스와 다양한 Enum 상태로 처리하는 편이 낫다.
- 상속 규칙 위반: 표준 예외를 상속받지 않고 독자적인 Exception/RuntimeException 트리를 구성해, 기존 라이브러리나 미션 요구사항에서 예외를 캐치하지 못하는 경우.
관련
- First Class Collection: 컬렉션 생성·조작 과정에서 도메인 검증 실패를 예외로 표현할 때의 대표 사용처다.
- 콘솔 MVC 설계 원칙: 에러 메시지를 OutputView 등으로 전달해 사용자에게 보여주는 설계 방식.
출처
테스트 질문
- 범용 표준 예외(예:
IllegalArgumentException)를 사용할 때 발생하는 에러 식별·디버깅의 어려움은 무엇인가? - 커스텀 예외가 표준 예외를 상속(IS-A)하도록 설계할 때 얻을 수 있는 이점은 무엇인가?
ErrorCodeEnum을 커스텀 예외와 함께 사용하면 유지보수와 테스트 관점에서 어떤 장점이 있는가?
커스텀 예외로 검증 실패 세분화.md — "도메인별 세부적인 에러 컨텍스트와 메시지를 담아내지 못하는 기본 예외를 일괄 사용.", "로그에 IllegalArgumentException만 보임 → 원인 파악 어려움. 테스트 코드에서 어떤 케이스인지 구분 불가" ↩︎
객체지향 설계 실전 — ErrorCode enum으로 메시지를 관리하고 도메인 예외를 상속으로 구성하는 예시를 제시한다. ↩︎
커스텀 예외로 검증 실패 세분화.md — "ErrorCode Enum + 커스텀 예외 클래스 도입. 미션 요구사항(IllegalArgumentException) 충족을 위해 커스텀 예외가 상속받도록 설계.", "IllegalArgumentException 상속 → 요구사항 + 명시성 동시 만족" ↩︎