GET의 한계와 QUERY 메서드의 등장
검색 API를 설계할 때 자연스럽게 선택하는 메서드는 GET이다. 읽기 전용이고 멱등성을 가지며, HTTP 의미론적으로도 "조회"에 가장 잘 들어맞는다. 하지만 검색 조건이 복잡해지면서 문제가 드러난다. 필터가 늘어나고 중첩 조건이 생기면 URI 길이는 금방 한계에 부딪힌다. 더 심각한 문제는 보안이다. 민감한 쿼리 파라미터가 URI에 노출되면 서버 액세스 로그, 브라우저 히스토리, 리버스 프록시, 모니터링 시스템 어디서든 평문으로 읽힐 수 있다.
이를 우회하기 위해 GET 요청에 바디를 실어 보내는 방법이 사용되기도 한다. Elasticsearch가 대표적인 사례인데, Elastic 공식 문서조차 이 방식이 일부 HTTP 서버와 캐싱 프록시에서 지원되지 않는다고 명시하고 POST를 대안으로 제시한다. 즉, 비표준 동작에 시스템 설계를 의존하는 셈이다. POST를 대신 쓰면 바디 문제는 해결되지만, 이번엔 캐싱 가능성과 멱등성이라는 의미론적 속성을 잃는다.
RFC 10008: HTTP QUERY 메서드의 핵심 설계 원칙
RFC 10008로 표준화가 진행 중인 HTTP QUERY 메서드는 이 딜레마를 정면으로 해결하려는 시도다. 핵심 설계 목표는 두 가지다.
- GET의 의미론 유지: 읽기 전용이며 서버 상태를 변경하지 않는다. 멱등성을 보장하므로 캐싱 레이어가 이를 인식하고 응답을 캐시할 수 있다.
- 바디 허용: 복잡한 검색 조건, 중첩 필터, 집계 파라미터 등을 요청 바디에 구조화된 형태로 담을 수 있다.
결과적으로 QUERY는 GET의 캐시 가능성과 POST의 바디 유연성을 함께 가지는 절충안이다. 프록시, CDN, API 게이트웨이 레이어에서 이 메서드를 인식하면 POST와 달리 응답을 캐시 대상으로 처리할 수 있어 대규모 검색 트래픽 최적화에도 기여한다.
QUERY /products HTTP/1.1
Content-Type: application/json
{
"filter": {
"category": "electronics",
"price": { "gte": 100, "lte": 500 }
},
"sort": "price:asc",
"page": 1
}
Quarkus 구현 사례와 생태계 현황
Quarkus에서는 JAX-RS 표준에 없는 커스텀 HTTP 메서드를 애노테이션으로 직접 정의해 QUERY를 구현할 수 있다.
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@HttpMethod("QUERY")
public @interface QUERY {}
// 리소스 클래스에서 사용
@QUERY
@Path("/products")
@Consumes(MediaType.APPLICATION_JSON)
public Response searchProducts(SearchRequest request) {
// 검색 로직
}
이처럼 일부 프레임워크에서는 이미 구현 사례가 나오고 있지만, 생태계 전반의 채택은 아직 초기 단계다. 프로덕션 도입을 고려한다면 반드시 확인해야 할 사항이 있다. 서비스 앞단의 API 게이트웨이, 로드밸런서, CDN이 QUERY 메서드를 허용하는지, 혹은 알 수 없는 메서드로 분류해 차단하거나 오동작하는지 검증이 필요하다. 미들웨어 스택 전반의 호환성 검토 없이 도입하면 예기치 않은 405 응답이나 캐시 무효화 문제를 마주할 수 있다.
정리
- HTTP QUERY 메서드는 GET의 멱등성·캐싱 가능성을 유지하면서 요청 바디로 복잡한 검색 조건을 전달하는 RFC 10008 표준화 진행 중인 메서드다.
- GET-with-body는 비표준 동작이며, POST는 캐싱 의미론을 잃는다는 각각의 한계를 QUERY가 절충한다.
- 현재 생태계 채택이 초기 단계이므로, 프로덕션 적용 전 API 게이트웨이·프록시·CDN 등 미들웨어의 호환성을 반드시 검증해야 한다.