-
Spring Boot 시리즈 7편 – API 응답 구조 표준화 전략: 성공과 실패를 구분하는 통일 설계기술과 산업/언어 및 프레임워크 2025. 4. 23. 20:00728x90
Spring Boot REST API의 응답 구조를 표준화하는 전략을 소개합니다. 성공/실패 응답 포맷 통일, 공통 응답 객체 설계, 예외 처리 통합까지 포함합니다.
Spring Boot 시리즈 7편 – API 응답 구조 표준화 전략: 성공과 실패를 구분하는 통일 설계
REST API에서 가장 흔한 실수 중 하나는 각 API마다 다른 응답 구조입니다.
예를 들어 성공 응답은 그냥 JSON 객체로, 실패 응답은 상태 코드만 주거나,
경우에 따라 메시지 형태도 제각각이라면 프론트엔드와 앱 개발자는 매번 예외 처리를 따로 해야 하는 불편함을 겪게 됩니다.이번 편에서는 Spring Boot 환경에서 API 응답을 성공/실패 케이스 모두 포함하여 통일된 형식으로 설계하고,
예외 상황까지 일관성 있게 처리하는 방법을 소개합니다.
📌 1. 왜 응답 구조를 표준화해야 하나?
- 프론트/앱 개발자와 협업이 쉬워짐
- 에러 발생 시 원인 추적과 디버깅 속도 증가
- API 명세(Swagger)에서 응답 구조 일관성 확보
- 테스트 코드에서 응답 구조 검증이 단순화됨
✅ 2. 통일된 공통 응답 포맷 설계
가장 많이 쓰이는 형식은 다음과 같습니다:
{ "success": true, "code": "S200", "message": "정상 처리되었습니다.", "data": { "id": 1, "name": "홍길동" } }
🔁 실패 응답 예시
{ "success": false, "code": "C001", "message": "필수 파라미터 누락", "errors": [ { "field": "email", "message": "이메일은 필수입니다." } ] }
🧱 3. 공통 응답 객체 클래스 구성
1️⃣ ApiResponse<T> 클래스
@Getter @AllArgsConstructor @NoArgsConstructor public class ApiResponse<T> { private boolean success; private String code; private String message; private T data; public static <T> ApiResponse<T> success(T data) { return new ApiResponse<>(true, "S200", "요청이 성공적으로 처리되었습니다.", data); } public static <T> ApiResponse<T> fail(String code, String message, T errorDetail) { return new ApiResponse<>(false, code, message, errorDetail); } }
2️⃣ FieldErrorResponse
@Getter @AllArgsConstructor public class FieldErrorResponse { private String field; private String message; }
🛠️ 4. Controller에서의 적용 예시
@PostMapping public ResponseEntity<ApiResponse<UserDto>> register(@Valid @RequestBody RegisterUserRequest request) { UserDto result = userService.register(request); return ResponseEntity.ok(ApiResponse.success(result)); }
❌ 예외 응답 통합 처리
1️⃣ BusinessException 기반 커스텀 예외 정의
@Getter public class BusinessException extends RuntimeException { private final ErrorCode errorCode; public BusinessException(ErrorCode errorCode) { super(errorCode.getMessage()); this.errorCode = errorCode; } }
2️⃣ ErrorCode Enum 예시
@Getter @AllArgsConstructor public enum ErrorCode { INVALID_INPUT("C001", "입력값이 올바르지 않습니다."), DUPLICATE_EMAIL("U001", "이미 사용 중인 이메일입니다."), INTERNAL_ERROR("S500", "서버 내부 오류"); private final String code; private final String message; }
3️⃣ GlobalExceptionHandler 통합 처리
@RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(BusinessException.class) public ResponseEntity<ApiResponse<?>> handleBusinessException(BusinessException e) { ErrorCode code = e.getErrorCode(); return ResponseEntity.badRequest().body(ApiResponse.fail(code.getCode(), code.getMessage(), null)); } @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity<ApiResponse<List<FieldErrorResponse>>> handleValidationException(MethodArgumentNotValidException ex) { List<FieldErrorResponse> errors = ex.getBindingResult().getFieldErrors().stream() .map(err -> new FieldErrorResponse(err.getField(), err.getDefaultMessage())) .toList(); return ResponseEntity.badRequest().body(ApiResponse.fail("C001", "유효성 검사 실패", errors)); } @ExceptionHandler(Exception.class) public ResponseEntity<ApiResponse<Void>> handleAll(Exception ex) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) .body(ApiResponse.fail("S500", "알 수 없는 오류가 발생했습니다.", null)); } }
🧠 실무 설계 팁
항목 설계 전략
공통 응답 구조 success, code, message, data 필드 유지 Swagger 문서화 @ApiResponse에 응답 구조 통일 오류 코드 관리 ErrorCode Enum으로 체계적 관리 테스트 코드 JSON 구조 검증 → jsonPath("success").value(true) 등 코드 통일 모든 Controller는 ApiResponse<T>로 반환 통일
✅ 마무리 요약
항목 요약
핵심 클래스 ApiResponse<T>, ErrorCode, FieldErrorResponse 예외 통합 처리 @RestControllerAdvice + BusinessException 구조 표준 응답 포맷 성공/실패 구조를 동일하게 유지 협업 효과 프론트/앱 개발자, QA 모두 예측 가능한 처리 가능 Swagger 연계 명세 자동화와 테스트 연계에 유리
📌 다음 편 예고
Spring Boot 시리즈 8편: 입력값 검증 전략 – @Valid, 커스텀 Validator, 도메인 유효성 설계까지
728x90'기술과 산업 > 언어 및 프레임워크' 카테고리의 다른 글
Spring Boot 시리즈 9편 – 로그인 및 인증 처리 전략: JWT 기반 인증 흐름과 보안 설계 (0) 2025.04.24 Spring Boot 시리즈 8편 – 입력값 검증 전략: @Valid부터 도메인 중심 유효성 설계까지 (0) 2025.04.24 Spring Boot 시리즈 6편 – Swagger를 활용한 API 문서 자동화 전략 (0) 2025.04.23 Spring Boot 고급 시리즈 10편 – 멀티 모듈 아키텍처 전략: 실무 서비스 구조 분리 가이드 (0) 2025.04.23 Spring Boot 고급 시리즈 9편 – API 버전 없이 유연한 기능 확장: Feature Flag와 조건 분기 전략 (0) 2025.04.22