RFC 10008: 새로운 HTTP QUERY 메서드
1 week ago
11
- RFC 10008은 요청 본문에 담긴 질의를 대상 리소스가 안전하고 멱등적으로 처리한 뒤 결과를 반환하는 HTTP QUERY 메서드를 정의함
- QUERY는 GET의 safe/idempotent 성격과 POST의 본문 전달 방식을 결합해, 긴 URI·URI 인코딩 비용·로그 노출·질의 조합별 리소스화 부담을 줄임
- 서버는 QUERY 요청의 Content-Type과 본문이 일관되어야 처리할 수 있으며, 미지원 타입·본문 불일치·처리 불가능한 질의는 각각 다른 4xx 응답으로 구분될 수 있음
- 성공 응답은 Content-Location으로 질의 결과 리소스를, Location으로 같은 질의를 다시 수행할 equivalent resource를 알려줄 수 있음
- QUERY 응답은 캐시 가능하지만 캐시 키가 본문과 메타데이터까지 포함해야 하며, CORS 환경에서는 safelisted method가 아니어서 preflight가 필요함
QUERY가 해결하려는 HTTP 질의 패턴
- RFC 10008은 HTTP QUERY 요청 메서드를 정의하는 Internet Standards Track 문서임
- QUERY는 대상 리소스가 요청 본문을 처리하고 그 결과를 응답하도록 요청함
- POST처럼 본문을 쓰지만 safe와 idempotent로 정의되어 자동 재시도나 재시작이 가능함
- 기존 GET 질의는 URI에 입력을 넣는 방식이 일반적임
- GET /feed?q=foo&limit=10&sort=-published HTTP/1.1
- URI에 질의 데이터를 넣으면 데이터가 커질수록 제약이 커짐
- 여러 독립 시스템을 거치기 때문에 실제 URI 크기 제한을 미리 알기 어려움
- HTTP는 송신자와 수신자가 최소 8000 octets를 지원하도록 권장하지만, 경로상의 모든 시스템을 보장하지는 않음
- 일부 데이터는 유효한 URI로 인코딩하는 비용이 큼
- 요청 URI는 요청 본문보다 로그에 남거나 북마크에 포함될 가능성이 큼
- 질의를 URI에 직접 인코딩하면 가능한 입력 조합마다 별도 리소스로 취급됨
GET과 POST 사이의 의미를 명확히 하는 메서드
- 많은 구현은 GET 대신 POST 본문으로 질의를 전달함
- POST /feed
- Content-Type: application/x-www-form-urlencoded
- 본문: q=foo&limit=10&sort=-published
- 이 방식은 특정 리소스와 서버 지식 없이는 안전하고 멱등적인 질의인지 드러나지 않음
- QUERY는 같은 입력을 요청 본문으로 보내면서도, 메서드 자체가 안전하고 멱등적임
- QUERY /feed
- Content-Type: application/x-www-form-urlencoded
- 본문: q=foo&limit=10&sort=-published
- 이 명시적 의미 덕분에 캐싱과 자동 재시도 같은 HTTP 기능을 적용하기 쉬워짐
- 서버는 질의 자체나 특정 질의 결과에 URI를 부여해 이후 GET 요청에 사용할 수 있음
QUERY 메서드의 핵심 규칙
- QUERY는 서버 측 질의를 시작하는 데 사용됨
- GET은 대상 URI가 식별하는 리소스의 표현을 요청하지만, QUERY는 대상 리소스 범위 안에서 질의 작업을 수행하도록 요청함
- 요청 본문과 미디어 타입이 질의를 정의하고, origin server가 대상 리소스를 기준으로 작업 범위를 정함
- 서버는 Content-Type 요청 필드가 없거나 요청 본문과 일치하지 않으면 요청을 실패시켜야 함
- 대상 URI의 query part는 모든 HTTP 메서드와 마찬가지로 질의 대상 리소스 식별에 참여함
- 그 query part가 결과에 직접 영향을 주는지와 방식은 리소스별 동작이며 이 명세 범위 밖임
- QUERY는 대상 리소스 관점에서 안전함
- 클라이언트는 대상 리소스 상태 변경을 요청하거나 기대하지 않음
- 서버가 추가 정보를 조회할 수 있는 HTTP 리소스를 만드는 것은 금지되지 않음
- QUERY는 멱등적이어서 연결 실패 뒤 필요한 경우 재시도하거나 반복할 수 있음
- 200 OK 응답은 질의가 성공적으로 처리되었고 결과가 응답 본문에 포함되었음을 나타냄
미디어 타입, 협상, 오류 처리
- QUERY 요청의 의미는 요청 본문과 미디어 타입 같은 관련 메타데이터에 따라 달라짐
- 본문과 메타데이터가 일관되지 않은 요청은 일반적으로 4xx Client Error로 거부해야 함
- 오류 처리는 요청이 어디에서 잘못됐는지에 따라 달라짐
- 미디어 타입 정보가 없으면 요청이 정의상 잘못되었으므로 400 같은 4xx 상태 코드로 실패해야 함
- 미디어 타입이 지정되었지만 리소스가 지원하지 않으면 415 Unsupported Media Type이 적절함
- 미디어 타입이 원칙적으로 알려져 있어도 대상 리소스의 QUERY 의미가 없으면 415 대상이 됨
- 미디어 타입이 실제 요청 본문과 맞지 않으면 400 Bad Request를 반환할 수 있음
- 서버는 본문을 보고 미디어 타입을 추론해 누락되었거나 잘못된 값을 덮어쓰는 content sniffing을 할 수 없음
- 타입과 본문은 맞지만 실제 질의 내용 때문에 처리할 수 없으면 422 Unprocessable Content를 사용할 수 있음
- 문법적으로 올바른 SQL 질의가 존재하지 않는 테이블을 가리키는 경우가 422 예시임
- 클라이언트가 Accept로 요청한 응답 미디어 타입을 리소스가 지원하지 않으면 406 Not Acceptable이 적절함
- Accept-Query 응답 필드는 클라이언트에 지원되는 질의 미디어 타입을 알려줄 수 있음
equivalent resource, Content-Location, Location
- equivalent resource는 특정 QUERY 요청과 그 대상을 나타내고 GET 요청에 응답하는 리소스임
- equivalent resource는 요청 본문과 메타데이터를 모두 고려함
- 본문의 미디어 타입 같은 representation metadata가 포함됨
- 서버는 equivalent resource에 URI를 부여할 수 있지만 필수는 아님
- 성공 응답은 Content-Location 헤더로 질의 결과에 해당하는 리소스 식별자를 포함할 수 있음
- 클라이언트는 표시된 URI에 GET을 보내 방금 수행한 질의 작업의 결과를 가져올 수 있음
- 해당 리소스는 임시일 수 있음
- 성공 응답은 Location 헤더로 QUERY 요청의 equivalent resource URI를 포함할 수 있음
- 클라이언트는 질의 본문을 다시 보내지 않고 표시된 URI에 GET을 보내 같은 질의 작업을 반복할 수 있음
- 이 URI도 임시일 수 있음
- 이후 요청이 실패하면 클라이언트는 원래 QUERY 대상과 이전에 제출한 본문으로 다시 시도할 수 있음
리다이렉션과 조건부 요청
- 서버는 QUERY 요청에 대해 다른 URI로 사용자 에이전트를 리다이렉트하는 간접 응답을 선택할 수 있음
- 301 Moved Permanently와 308 Permanent Redirect는 대상 리소스가 Location이 가리키는 다른 URI로 영구 이동했음을 나타냄
- 302 Found와 307 Temporary Redirect는 대상 리소스의 임시 이동을 의미함
- 네 경우 모두 서버는 새 대상 URI로 유사한 QUERY 요청을 보내면 원래 요청을 수행할 수 있다고 제안함
- 301 또는 302 뒤 POST를 GET으로 리다이렉트하는 예외는 QUERY 요청에는 적용되지 않음
- QUERY에 대한 303 See Other는 원래 질의를 Location이 가리키는 URI에 대한 일반 조회 요청으로 수행할 수 있음을 나타냄
- HTTP에서는 새 대상 URI로 GET 요청을 보냄
- 조건부 QUERY에서 selected representation은 해당 QUERY 요청의 equivalent resource에 대한 GET과 같음
- 클라이언트는 조건부 헤더가 지정한 조건에서만 질의 결과를 응답으로 반환하도록 요청할 수 있음
캐싱과 Range 요청
- QUERY 메서드 응답은 캐시 가능하며, 캐시는 이후 QUERY 요청을 만족시키는 데 사용할 수 있음
- QUERY 요청의 캐시 키는 요청 본문과 관련 메타데이터를 포함해야 함
- 캐시는 캐시 키 생성을 위해 의미상 중요하지 않은 차이를 제거할 수 있음
- content encoding 제거
- +json 같은 미디어 subtype suffix가 나타내는 형식 관례에 따른 정규화
- Content-Type이 나타내는 본문 의미에 따른 정규화
- 이런 변환은 오직 캐시 키 생성을 위한 것이며 요청 자체를 변경하지 않음
- 클라이언트는 no-transform 캐시 지시어로 이런 변환을 원하지 않는다고 표시할 수 있지만, 이 지시어는 advisory임
- QUERY 응답 캐싱은 GET보다 본질적으로 더 복잡함
- 캐시 키를 결정하려면 요청 본문 전체를 읽어야 함
- QUERY 응답이 Location으로 equivalent resource URI를 제공하면 클라이언트는 이후 GET으로 전환해 처리를 단순화할 수 있음
- QUERY의 Range Request 의미는 GET과 같음
- 작성 시점에 정의된 유일한 range unit인 Byte Range Request는 QUERY 결과에는 가치가 작음
- SQL의 FETCH FIRST ... ROWS ONLY처럼 질의 형식 자체가 결과 제한이나 페이지네이션을 제공하는 경우가 많으며, 이런 내장 기능 사용이 기대됨
Accept-Query 응답 헤더
- Accept-Query 응답 헤더는 리소스가 QUERY 메서드를 지원함을 직접 알리고 사용할 수 있는 질의 형식 미디어 타입을 식별함
- Accept-Query는 Structured Fields 문법을 사용하는 media range 목록임
- media range는 매개변수 없는 media range 값을 담은 Token 또는 String의 List Structured Header Field로 표현됨
- 미디어 타입 매개변수는 Structured Field Parameters로 매핑됨
- String과 Token 선택은 의미상 중요하지 않음
- 수신자는 Token을 String으로 변환할 수 있지만, 받은 타입에 따라 다르게 처리해서는 안 됨
- 미디어 타입은 Token과 정확히 매핑되지 않으며, 선행 숫자를 허용하는 경우에는 String 형식을 사용해야 함
- 지원되는 wildcard는 */* 또는 xxxx/*뿐임
- 필드 값에 나열된 타입 순서는 중요하지 않음
- Accept-Query 값은 같은 path를 공유하는 서버의 모든 URI에 적용되며, query component는 무시됨
- 같은 리소스 요청이 다른 Accept-Query 값을 반환하면 가장 최근에 받은 fresh 값이 사용됨
- 예시는 다음과 같음
- Accept-Query: "application/jsonpath", application/sql;charset="UTF-8"
- Accept-Query는 Accept와 비슷해 보이지만 Structured Field이므로 RFC 9651의 Structured Fields 처리 규칙을 따라야 함
보안 고려사항과 CORS
- QUERY는 RFC 9110에 정의된 모든 HTTP 메서드의 일반 보안 고려사항을 따름
- QUERY는 요청 정보를 URI query component에 넣는 방식의 대안으로 사용할 수 있음
- URI는 요청 본문보다 로그에 남거나 중개자에 의해 처리될 가능성이 커서, 민감한 정보가 포함된 질의에서는 GET보다 QUERY 사용 동기가 될 수 있음
- 서버가 QUERY 결과를 나타내는 임시 리소스를 만들고 URI를 부여할 때, 원래 요청 본문에 로그에 남기면 안 되는 민감 정보가 있으면 그 URI에 민감한 부분을 포함하지 않아야 함
- 캐시가 QUERY 본문을 잘못 정규화하거나 리소스 처리 방식과 크게 다르게 정규화하면 false positive로 잘못된 응답을 반환할 수 있음
- CORS를 구현하는 사용자 에이전트의 QUERY 요청은 preflight 요청이 필요함
- QUERY는 CORS-safelisted methods 집합에 포함되지 않음
IANA 등록과 메서드 이름 선택
- IANA는 QUERY 메서드를 HTTP Method Registry에 추가함
- Method Name: QUERY
- Safe: yes
- Idempotent: yes
- Specification: RFC 10008 Section 2
- IANA는 Accept-Query 필드를 HTTP Field Name Registry에 추가함
- Field Name: Accept-Query
- Status: permanent
- Structured Type: List
- HTTP Method Registry에는 이미 safe와 idempotent 속성을 가진 PROPFIND, REPORT, SEARCH가 있었음
- 초기 단계에서는 SEARCH가 사용되었지만 최종 메서드 이름은 QUERY가 됨
- QUERY가 선택된 이유는 다음과 같음
- 대안들은 요청 본문에 일반 미디어 타입 application/xml을 사용하고 요청 의미가 전적으로 본문에 의존함
- 대안들은 모두 WebDAV 활동에서 비롯됨
- QUERY는 URI의 query component와의 관계를 잘 포착함
-
Homepage
-
Tech blog
- RFC 10008: 새로운 HTTP QUERY 메서드