
개발을 시작한 지 한 달이 지났다. 백엔드 개발자 승준이와 준규는 각자 열심히 API를 만들고 있었다. 프론트엔드 개발자 윤표가 합류하면서 개발 속도는 더 빨라졌다. 그런데 문제가 생겼다. 승준이의 API 응답과 준규의 API 응답이... 달랐다.
이유은 아주 단순하게도 둘 다 한 번도 **“응답 규격을 맞춰본 경험”**이 없었던 것이다.
매주 회의 때마다 "이 API는 어떤 형식이야?" 라는 질문이 반복됐고, 윤표는 API를 쓸 때마다 응답 구조를 새로 파악해야 했다. 소통 비용이 쌓이기 시작했다.
이 글은 그 문제를 해결하는 과정과, 최종적으로 ResponseEntity + @RestControllerAdvice 를 선택한 이유를 기록한다.
승준이는 제네릭 DTO로 감싸서 전달했다.
public class ApiResponseDto {
@Data
@AllArgsConstructor
public static class ApiResponse<T> {
private T data; // data 필드 하나만 존재
}
}
준규는 영속성 컨텍스트에서 캐싱되는 DTO를 그대로 전달했다.
결과는 이랬다.
// 승준이 API
{ "data": { ... } }
// 준규 API
{ "id": 1, "name": "..." }
프론트 입장에서는 API마다 응답 구조가 달라 매번 확인이 필요했다. 성공인지 실패인지도 응답만 봐서는 알 수 없었다.
어떻게 해결할 수 있을까?
ResponseEntity + 정적 팩토리 메소드ResponseEntity는 스프링에서 HTTP 응답 전체를 표현하는 클래스다.
단순히 데이터만 보내는 게 아니라 상태 코드, 헤더, 본문을 모두 담아 보낼 수 있다.
생성자를 **private**으로 막고, 상황별 정적 팩토리 메소드만 열어둔다.