-
Spring Boot 시리즈 28편 – 예외 처리 전략 고도화: 에러 응답 표준화와 API 일관성 유지기술과 산업/언어 및 프레임워크 2025. 5. 9. 14:39728x90
Spring Boot에서 전역 예외 처리(@ControllerAdvice)를 중심으로 API 에러 응답을 통일된 형식으로 설계하는 전략을 소개합니다. 실무용 커스텀 예외 구조와 응답 UX 개선 팁 포함.
Spring Boot 시리즈 28편 – 예외 처리 전략 고도화: 에러 응답 표준화와 API 일관성 유지
API 품질을 결정짓는 핵심 요소 중 하나는 에러 응답의 일관성입니다.
"왜 에러가 났는지", "어떻게 대응해야 하는지"가 명확하지 않다면
클라이언트는 혼란스러워지고, 유지보수 비용은 기하급수적으로 늘어납니다.Spring Boot의 전역 예외 처리 기능을 활용해,
정형화된 에러 응답 구조와 상황별 커스텀 예외 처리 전략을 체계적으로 정리합니다.
📌 1. 에러 응답 구조 통일의 필요성
문제 상황 통일된 구조가 없다면?
유효성 검사 실패 400, 422 등 중구난방 코드 + 메시지 누락 존재하지 않는 ID HTTP 500으로 통일되어 내부 에러처럼 보임 인증/인가 실패 로그인 실패와 권한 없음이 구분되지 않음 → 클라이언트 입장에선 API마다 에러 해석을 다르게 해야 함
→ 서버 개발자 입장에서도 디버깅/로깅/모니터링 어려움
✅ 2. 통일된 에러 응답 포맷 설계
예시: 공통 에러 응답 스펙
{ "success": false, "code": "USER_NOT_FOUND", "message": "해당 사용자가 존재하지 않습니다.", "timestamp": "2025-04-28T14:35:20", "status": 404, "path": "/api/users/99" }
필드 설명
success 성공 여부 (false) code 식별 가능한 오류 코드 message 사용자에게 보여줄 메시지 status HTTP 상태 코드 timestamp 에러 발생 시간 path 요청 경로
🛠️ 3. 커스텀 예외 클래스 설계
@Getter public class CustomException extends RuntimeException { private final ErrorCode errorCode; public CustomException(ErrorCode code) { super(code.getMessage()); this.errorCode = code; } }
ErrorCode enum 설계
@Getter @AllArgsConstructor public enum ErrorCode { USER_NOT_FOUND(404, "해당 사용자가 존재하지 않습니다."), INVALID_INPUT(400, "입력값이 올바르지 않습니다."), INTERNAL_SERVER_ERROR(500, "서버 오류가 발생했습니다."); private final int status; private final String message; }
→ 각 예외는 명확한 code + message + status 조합을 갖게 됨
🧩 4. 전역 예외 처리기 구성 (@ControllerAdvice)
@RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(CustomException.class) public ResponseEntity<ErrorResponse> handleCustomException(CustomException e, HttpServletRequest request) { ErrorCode code = e.getErrorCode(); ErrorResponse response = ErrorResponse.of(code, request.getRequestURI()); return ResponseEntity.status(code.getStatus()).body(response); } @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity<ErrorResponse> handleValidation(MethodArgumentNotValidException e, HttpServletRequest request) { ErrorResponse response = ErrorResponse.of(ErrorCode.INVALID_INPUT, request.getRequestURI(), e); return ResponseEntity.status(400).body(response); } @ExceptionHandler(Exception.class) public ResponseEntity<ErrorResponse> handleGeneral(Exception e, HttpServletRequest request) { ErrorResponse response = ErrorResponse.of(ErrorCode.INTERNAL_SERVER_ERROR, request.getRequestURI()); return ResponseEntity.status(500).body(response); } }
🧾 5. ErrorResponse DTO 설계
@Getter @Builder public class ErrorResponse { private final boolean success = false; private final String code; private final String message; private final int status; private final String path; private final String timestamp; public static ErrorResponse of(ErrorCode code, String path) { return ErrorResponse.builder() .code(code.name()) .message(code.getMessage()) .status(code.getStatus()) .path(path) .timestamp(LocalDateTime.now().toString()) .build(); } public static ErrorResponse of(ErrorCode code, String path, Exception e) { return of(code, path); // 필요 시 e.getMessage() 등을 확장 가능 } }
🎯 6. 응답 UX 향상을 위한 전략
상황 UX 전략
유효성 오류 상세 필드 정보까지 함께 반환 (fieldErrors) 인증 실패 401 Unauthorized + 재로그인 유도 메시지 인가 실패 403 Forbidden + 접근 불가 안내 시스템 에러 500 내부 메시지는 숨기고 외부 메시지는 명확히
✅ 마무리 요약
항목 요약
공통 구조 code + message + status + path + timestamp 구성 예외 클래스 CustomException, ErrorCode enum으로 표준화 전역 처리 @RestControllerAdvice로 공통 처리 UX 향상 유저와 개발자 모두를 위한 구조화된 메시지 제공 확장 전략 ResponseEntity 외 API Gateway 표준과 통합 가능
📌 다음 편 예고
Spring Boot 시리즈 29편: RestTemplate vs WebClient – 외부 API 통신 전략 비교와 적용 가이드
728x90'기술과 산업 > 언어 및 프레임워크' 카테고리의 다른 글
NestJS 마스터 시리즈 12화. 모듈 간 의존성 순환 문제와 해결 전략 (0) 2025.05.09 FastAPI 시리즈 8화 - 의존성 주입 시스템(Depends) 실전 활용법 (0) 2025.05.09 전자정부 표준프레임워크 시리즈 6화 – 개발환경 세팅하기: IDE, 빌드툴, 배포 구조까지 한 번에 이해하기 (1) 2025.05.09 Java JSON 처리 실전 시리즈 1화 – Jackson vs Gson: Java JSON 라이브러리 비교와 선택 기준 (1) 2025.05.09 Jmix 실전 마스터 시리즈 1화 - Jmix란 무엇인가? CUBA의 진화, Spring Boot의 확장 (0) 2025.05.07