📌 문제 상황
Spring Cloud 기반 MSA 프로젝트에서 예외 처리 통일을 위해
common-library 모듈에 GlobalExceptionHandler를 정의했지만,
user-service, order-service 등 개별 서비스에서는
예외가 발생해도 해당 핸들러가 작동하지 않고 기본 Spring 오류 포맷으로 응답되는 문제가 있었습니다.
공통 라이브러리에서 정의한 핸들러가 정상 작동하지 않는 현상
🧠 원인 분석
1️⃣ @RestControllerAdvice는 Spring의 컴포넌트 스캔 대상이어야만 빈으로 등록됩니다.
그러나 common-library는 외부 모듈(jar)이기 때문에,
서비스의 @SpringBootApplication 기본 스캔 범위 밖에 있어 자동 등록되지 않았습니다.
2️⃣ 서비스 내에서 별도로 정의된 UserNotFoundException 등과 공통 모듈의 예외 클래스가 중복되면,
예외 매핑이 일어나지 않아 핸들러가 무시됩니다.
🔨 해결 과정
✅ 1. 공통 라이브러리에서 핸들러 정의
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(UserNotFoundException.class)
public ResponseEntity<ApiResponse<Object>> handleUserNotFound(UserNotFoundException e) {
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(ApiResponse.fail(e.getMessage()));
}
@ExceptionHandler(Exception.class)
public ResponseEntity<ApiResponse<Object>> handleGeneral(Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(ApiResponse.fail("서버 내부 오류가 발생했습니다."));
}
}
✅ 2. 각 서비스에서 명시적으로 등록
방법: @Import(GlobalExceptionHandler.class) 사용
@SpringBootApplication
@Import(GlobalExceptionHandler.class)
public class UserServiceApplication { ... }
✅ 3. 중복 예외 클래스 제거 및 통일
서비스 내에 정의되어 있던 UserNotFoundException을 제거하고,
common-library에 정의된 클래스를 단일 소스로 사용하도록 정리했습니다.
📈 결과 & 정리
항목 | 개선 전 | 개선 후 |
예외 응답 | Spring 기본 오류 형식 | 공통 ApiResponse.fail(...) 포맷 |
메시지 일관성 | 없음 | 서비스 전체 통일된 메시지 |
핸들러 재사용성 | 서비스마다 중복 정의 | 공통 라이브러리로 통합 |
유지보수성 | 낮음 | 변경 시 단일 위치에서 관리 가능 |
💡 배운 점
- 공통 모듈에 선언된 @RestControllerAdvice는 자동 등록되지 않는다 → @Import나 @ComponentScan 필요
- 예외 클래스는 중복 정의되면 매핑이 깨질 수 있으므로 반드시 통합 관리
- MSA 환경에서 예외 처리 흐름은 초기에 구조로 설계해두는 것이 중요
- 커스텀 어노테이션을 활용하면 반복 설정 없이 쉽게 확장 가능
📚 추가 자료
- 실습 예제 및 서비스 코드 👉 GitHub - mingstagram/spring-cloud-demo
- 설정 파일(Config) 👉 GitHub - mingstagram/spring-cloud-demo-config
'B2C 플랫폼 설계 > 트러블슈팅' 카테고리의 다른 글
🛠️ [트러블슈팅] Redis 장바구니 직렬화 오류 해결 (2) | 2025.05.31 |
---|---|
🛠️ [트러블슈팅] JPA @Enumerated(EnumType.STRING) 사용 시 Data truncated for column 오류 해결 (0) | 2025.05.28 |
🛠️ [트러블슈팅] Redis에 저장된 RefreshToken이 갱신되지 않아 발생한 토큰 충돌 문제 (1) | 2025.05.23 |
🛠️ [트러블슈팅] 로그인 시 비밀번호 일치하지 않는 문제 - Feign 응답 DTO 누락 이슈 (0) | 2025.05.23 |
🛠️ [트러블슈팅] 사용자 존재 여부 검증 실패로 인한 주문 오류 대응기 (0) | 2025.05.20 |