실무에서 외부 시스템과 통신하는 코드는 필연적으로 다양한 예외를 마주합니다.
하지만 종종 이런 예외를 아래와 같이 직접적으로 던지는 경우를 봅니다:
java
복사편집
try {
// 외부 API 호출
} catch (IOException e) {
throw e;
}
이렇게 되면 무슨 문제가 생길까요?
IOException
같은 라이브러리/네트워크 예외가 서비스 레이어까지 흘러들어옴격벽 처리 는 외부 예외를 시스템 내부에서 완전히 캡슐화하여,
내부 도메인 또는 클라이언트로 전파하지 않는 설계 패턴입니다.
java
복사편집
// 외부 API → HTTP/IO 예외 → APIException (표준화)
// 서비스 레이어 → APIException → CustomException (도메인 에러에 매핑)
// 컨트롤러 → ErrorHandler → 사용자에게 명확한 메시지 전달
이렇게 되면 "외부 API는 실패할 수 있다"는 전제를 시스템이 안전하게 감싸는 구조가 됩니다.
장점 | 설명 |
---|---|
🧼 계층 간 책임 분리 | 외부 호출에 대한 실패는 인프라 계층에서 흡수, 도메인 계층은 순수하게 유지 |
📖 예외 추론이 쉬움 | CustomException 기반 메시지로 어떤 이유로 실패했는지 직관적으로 파악 가능 |
📦 라이브러리 의존 제거 | 컨트롤러나 서비스가 OkHttp , WebClient , IOException 등을 몰라도 됨 |
🧪 테스트 용이성 향상 | 특정 예외를 트리거해 다양한 시나리오 테스트 가능 (Mock APIException 등) |
🪵 로깅 일관성 | 모든 에러 발생 시 동일한 형태로 로그 출력 (request url, code, body 등) |
🔐 보안/회피 로직 통합 가능 | 민감한 메시지 마스킹, 리트라이 로직 삽입, 페일오버 처리 등 삽입 가능 |
🚀 확장성 확보 | 다수의 외부 API가 생겨도 동일한 패턴으로 격벽 처리 → 유지보수 쉬움 |
java
복사편집
try {
String res = get(url, headers);
return objectMapper.readValue(res, Custom.class);
} catch (APIException e) {
throw new CustomException(CustomError.getCustomError(e), e.getResMsg());
}
이 구조 하나로 다음을 동시에 만족시킵니다:
도메인에러
같은 의미 있는 에러 코드만 보고 판단 가능ErrorHandler
에서 통일된 메시지로 반환 가능