요청 메서드
요청을 보낼 때 무엇을 해 달라는 것인지를 맨 앞에 적는 값입니다. 받는 쪽은 이 값을 보고 무슨 처리를 할지 정합니다. 같은 주소를 불러도 이 값이 다르면 다른 일이 됩니다.
상세
도서관 창구에 같은 청구기호를 내밀어도 앞에 붙이는 말에 따라 결과가 달라집니다. 빌려 달라고 하면 책이 나옵니다. 반납한다고 하면 책이 들어갑니다.
RFC(Request for Comments) 9110 은 요청 메서드 토큰을 요청 의미의 첫째 원천으로 정의합니다. 클라이언트가 이 요청을 무슨 목적으로 보냈는지, 성공한 결과로 무엇을 기대하는지를 이 값이 가리킵니다. 문법으로는 토큰 하나입니다. 요청에 헤더 필드가 함께 실리면 메서드의 뜻이 더 좁혀지기도 합니다. 다만 그 추가 의미가 메서드와 충돌하지 않을 때만 그렇습니다.
이 값은 대소문자를 가립니다. 대소문자를 가리는 메서드 이름을 쓰는 객체 기반 시스템으로 넘어가는 관문으로 쓰일 수 있기 때문입니다. 관례상 표준화된 메서드는 전부 대문자 US-ASCII(American Standard Code for Information Interchange) 글자로 정의합니다.
HTTP(HyperText Transfer Protocol)에서 표준화된 요청 메서드는 자원마다 따로 정해지지 않습니다. RFC 9110 은 한번 정해진 메서드가 어느 자원에 적용하든 같은 뜻을 갖는 편이 좋다고 적습니다. 다만 그 뜻을 실제로 구현할지 허용할지는 자원이 스스로 정합니다. 범용 서버는 GET 과 HEAD 를 반드시 지원해야 합니다. 나머지 메서드는 전부 선택입니다.
그래서 서버가 받은 메서드를 처리할지 말지는 두 번 갈립니다. 오리진 서버가 알아보지 못하거나 구현하지 않은 요청 메서드를 받으면 501 Not Implemented 상태 코드로 답하기를 권합니다. 알아보고 구현했지만 대상 자원에는 허용하지 않는 메서드라면 405 Method Not Allowed 로 답하기를 권합니다. 대상 자원이 허용하는 메서드 집합은 Allow 헤더 필드에 담아 알릴 수 있습니다. 다만 허용 집합은 도중에 바뀔 수 있습니다.
flowchart TD
A[요청 메서드를 받는다] --> B{알아보는 메서드인가}
B -->|아니다| C[501 Not Implemented]
B -->|그렇다| D{대상 자원에 허용되나}
D -->|아니다| E[405 Method Not Allowed]
D -->|그렇다| F[메서드의 뜻대로 처리한다]
배경
HTTP 는 분산 객체 시스템의 인터페이스로도 쓸 수 있게 설계됐습니다. 요청 메서드는 대상 자원에 적용할 동작을 부릅니다. 식별된 객체에 원격 메서드 호출을 보내는 것과 거의 같은 방식입니다. 이 자리를 두면 대상은 주소가 가리키고 동작은 메서드가 가리키게 됩니다.
값의 목록은 문서 하나가 못 박지 않았습니다. HTTP/1.0 을 적은 RFC 1945 는 그 판의 공통 메서드 집합을 정의합니다. 그 자리에 이 집합을 넓힐 수 있다고 적었습니다. 다만 따로 확장한 클라이언트와 서버 사이에서 추가된 메서드가 같은 의미를 공유한다고 가정할 수는 없다고 덧붙였습니다. 이름을 더할 자리는 열어 두되 뜻이 저절로 맞춰지지는 않는다는 말입니다.
그래서 더해진 이름을 한곳에 모으는 장치가 따로 생겼습니다. RFC 9110 은 이 명세의 범위 밖에서 HTTP 에 쓰라고 정해진 메서드가 더 있다고 적습니다. 그런 메서드는 전부 HTTP 메서드 레지스트리에 등재하는 편이 좋다고 적습니다. 레지스트리는 IANA(Internet Assigned Numbers Authority)가 관리합니다. 와일드카드 항목을 빼면 마흔 개 이름이 올라 있습니다. RFC 3253 · RFC 4918 · RFC 5789 · RFC 10008 처럼 여러 문서가 각자 이름을 더했습니다. 레지스트리는 그 이름과 각각의 안전 여부 · 멱등 여부를 한 표로 모읍니다.
보장과 가정
메서드 이름 하나를 고르면 세 가지 성질이 따라붙습니다. 안전한가, 멱등한가, 응답을 캐시할 수 있는가입니다. 셋은 별개의 축입니다. 그리고 셋 다 조건 위에 서 있습니다.
안전
보장은 이렇습니다. 어떤 요청 메서드의 정의된 의미가 본질적으로 읽기 전용이면 그 메서드는 안전합니다. 클라이언트는 안전한 메서드를 대상 자원에 적용해서 오리진 서버의 상태가 바뀌기를 요청하지 않습니다. 기대하지도 않습니다. 안전한 메서드를 상식적으로 쓰면 해를 끼치거나 재산을 잃게 하거나 오리진 서버에 이상한 부담을 주는 일도 없으리라고 봅니다. RFC 9110 이 정의한 메서드 중에서는 GET · HEAD · OPTIONS · TRACE 가 안전합니다.
가정은 이렇습니다. 안전하다는 것은 클라이언트가 요청한 범위에 대한 말입니다. 이 정의는 구현이 해로울 수 있는 동작이나 완전히 읽기 전용이 아닌 동작, 부수효과를 내는 동작을 안전한 메서드의 처리 중에 넣는 것을 막지 않습니다. 중요한 것은 클라이언트가 그 추가 동작을 요청하지 않았고 그에 대한 책임을 지지 않는다는 점입니다. 명세가 든 예가 접근 로그입니다. 대부분의 서버는 메서드와 무관하게 응답이 끝날 때마다 요청 정보를 접근 로그 파일에 덧붙입니다. 로그 저장 공간이 꽉 차서 서버가 죽을 수 있어도 이것은 안전한 것으로 봅니다. 웹의 광고를 골라 시작된 안전한 요청이 광고 계정에 요금을 매기는 부수효과를 내는 일도 흔합니다.
가정이 깨지는 자리도 명세가 짚습니다. 대상 URI(Uniform Resource Identifier) 안의 파라미터가 동작을 고르도록 자원을 만들었다면, 그 동작이 요청 메서드의 뜻과 맞는지는 자원 소유자가 책임집니다. 웹 기반 편집 소프트웨어가 page?do=delete 처럼 질의 파라미터 안에 동작을 넣는 방식이 흔합니다. 그런 자원의 목적이 안전하지 않은 동작이라면 자원 소유자는 안전한 요청 메서드로 접근할 때 그 동작을 반드시 막거나 허용하지 않아야 합니다. 그러지 않으면 링크 관리 · 미리 가져오기 · 검색 색인 구축 같은 목적으로 자동 처리가 모든 URI 참조에 GET 을 수행할 때 안타까운 부수효과가 생깁니다.
멱등
보장은 이렇습니다. 같은 메서드로 동일한 요청을 여러 번 보냈을 때 서버에 의도된 효과가 한 번 보낸 것과 같으면 그 메서드는 멱등합니다. RFC 9110 이 정의한 메서드 중에서는 PUT · DELETE 와 안전한 요청 메서드가 멱등합니다.
가정은 안전의 정의와 같은 모양입니다. 멱등하다는 성질도 사용자가 요청한 범위에만 걸립니다. 서버는 요청마다 따로 로그를 남겨도 됩니다. 개정 이력을 보관해도 됩니다. 멱등한 요청마다 멱등하지 않은 다른 부수효과를 구현해도 됩니다.
이 보장이 쓰이는 자리는 재시도입니다. 클라이언트가 서버 응답을 읽기 전에 통신이 끊기면 멱등한 요청은 자동으로 다시 보낼 수 있습니다. PUT 을 보낸 뒤 응답을 받기 전에 밑단 연결이 닫히면 클라이언트는 새 연결을 맺고 그 요청을 다시 보냅니다. 되풀이해도 의도된 효과가 같다는 것을 알기 때문입니다. 원래 요청이 성공했더라도 마찬가지입니다. 다만 돌아오는 응답은 다를 수 있습니다.
sequenceDiagram
participant 클라이언트
participant 서버
클라이언트->>서버: PUT 요청
Note over 클라이언트,서버: 응답을 읽기 전에 연결이 닫힌다
클라이언트->>서버: 새 연결을 맺고 같은 PUT 을 다시 보낸다
서버-->>클라이언트: 응답
Note over 클라이언트: 의도된 효과는 같습니다. 응답은 다를 수 있습니다
가정이 깨지면 이 재시도가 위험해집니다. 클라이언트는 멱등하지 않은 메서드의 요청을 자동으로 재시도하지 않기를 권합니다. 메서드와 무관하게 그 요청의 의미가 실제로 멱등하다는 것을 알 방법이 있거나, 원래 요청이 아예 적용되지 않았다는 것을 알아낼 방법이 있을 때는 예외입니다. 어떤 클라이언트는 더 위험한 길을 골라 자동 재시도가 가능한 때를 짐작하려 듭니다. 응답의 어느 부분도 받기 전에 밑단 전송 연결이 닫히면 POST 요청을 자동으로 재시도하는 식입니다. 놀고 있던 지속 연결을 썼을 때 특히 그렇습니다. 프록시는 멱등하지 않은 요청을 자동으로 재시도해서는 안 됩니다. 클라이언트는 실패한 자동 재시도를 다시 자동으로 재시도하지 않기를 권합니다.
캐시 가능
보장은 이렇습니다. 캐시가 응답을 저장하고 쓰려면 그 메서드 정의가 캐싱을 명시적으로 허용해야 합니다. 그리고 어떤 조건에서 그 응답으로 이후 요청을 만족시킬 수 있는지까지 밝혀야 합니다. 그렇게 하지 않은 메서드 정의는 캐시될 수 없습니다.
가정은 실제 구현 쪽에 있습니다. RFC 9110 은 GET · HEAD · POST 셋에 캐싱 의미를 정의합니다. 다만 캐시 구현의 압도적 다수는 GET 과 HEAD 만 지원합니다. 그래서 POST 응답이 캐시되리라고 전제하고 짜면 대다수 캐시 구현에서는 그 전제가 어긋납니다.
여덟 메서드의 성질
RFC 9110 이 레지스트리 등재분을 요약해 둔 표입니다. 안전 여부와 멱등 여부만 담습니다. 캐시 가능 여부는 이 표에 없습니다.
| 메서드 | 안전 | 멱등 |
|---|---|---|
| CONNECT | 아니다 | 아니다 |
| DELETE | 아니다 | 그렇다 |
| GET | 그렇다 | 그렇다 |
| HEAD | 그렇다 | 그렇다 |
| OPTIONS | 그렇다 | 그렇다 |
| POST | 아니다 | 아니다 |
| PUT | 아니다 | 그렇다 |
| TRACE | 그렇다 | 그렇다 |
예시
HTTP 요청줄의 첫 토큰
RFC 9112 는 HTTP/1.1 요청의 첫 줄을 세 토막으로 적어 둡니다. 메서드 토큰, 빈칸 하나, 요청 대상, 빈칸 하나, 프로토콜 판입니다.
request-line = method SP request-target SP HTTP-version
method = token
같은 문서가 실제 요청줄 두 개를 예로 듭니다.
GET http://www.example.org/pub/WWW/TheProject.html HTTP/1.1
CONNECT www.example.com:80 HTTP/1.1
Host: www.example.com
맨 앞의 GET 과 CONNECT 가 요청 메서드입니다. 뒤따르는 문자열은 요청 대상입니다. 개별 메서드의 뜻은 한 문장으로 정의됩니다. RFC 9110 은 POST 를 이렇게 적습니다. 대상 자원이 요청에 담긴 표현을 그 자원 고유의 의미에 따라 처리하기를 요청하는 메서드입니다.
WebDAV 가 더한 이름
RFC 4918 이 정한 WebDAV(Web Distributed Authoring and Versioning)는 같은 자리에 새 이름을 더했습니다. PROPFIND 는 요청 URI 가 가리키는 자원에 정의된 속성을 가져옵니다. 그 자원이 내부 멤버 URL(Uniform Resource Locator)을 가진 컬렉션이면 멤버 자원의 속성까지 가져올 수도 있습니다. MKCOL 은 요청 URI 가 지정한 자리에 새 컬렉션 자원을 만듭니다. 요청 URI 가 이미 자원에 매핑돼 있으면 MKCOL 은 반드시 실패해야 합니다. COPY 는 요청 URI 가 가리키는 원본 자원의 복제본을 Destination 헤더가 가리키는 자리에 만듭니다. MOVE 는 컬렉션이 아닌 자원에서는 COPY 뒤에 일관성 유지 처리를 하고 원본을 지우는 것과 논리적으로 같습니다. 세 동작이 한 연산으로 수행됩니다.
이 이름들은 성질까지 같은 틀로 적습니다. MKCOL · COPY · MOVE 는 각각 멱등하지만 안전하지는 않다고 명시합니다. 그리고 이 메서드들에 대한 응답은 캐시되어서는 안 된다고 적습니다.
CoAP 의 숫자 코드
RFC 7252 가 정한 CoAP(Constrained Application Protocol)는 HTTP 와 같은 네 이름을 씁니다. GET 은 요청 URI 가 가리키는 자원에 현재 대응하는 정보의 표현을 가져옵니다. GET 은 안전하고 멱등합니다. POST 는 요청에 담긴 표현이 처리되기를 요청합니다. POST 는 안전하지도 멱등하지도 않습니다. PUT 은 요청 URI 가 가리키는 자원이 담긴 표현으로 갱신되거나 생성되기를 요청합니다. PUT 은 안전하지 않지만 멱등합니다. DELETE 는 요청 URI 가 가리키는 자원이 삭제되기를 요청합니다. DELETE 도 안전하지 않지만 멱등합니다.
이름과 성질은 같아도 실려 나가는 모양이 다릅니다. CoAP 는 메서드를 텍스트 토큰이 아니라 작은 숫자 코드로 싣습니다.
| 코드 | 이름 |
|---|---|
| 0.01 | GET |
| 0.02 | POST |
| 0.03 | PUT |
| 0.04 | DELETE |
나머지 메서드 코드는 미할당입니다. 알아보지 못하거나 지원하지 않는 메서드 코드가 담긴 요청은 4.05 Method Not Allowed 를 피기백(piggybacked) 응답으로 반드시 만들어야 합니다. HTTP 의 405 와 같은 자리에 놓인 값입니다. 그래서 요청 메서드는 문자열이어야 하는 것이 아닙니다. 요청의 의미를 가리키는 값이면 됩니다.
관련 항목
HTTP 가 정한 여덟 이름
GET · HEAD · POST · PUT · DELETE · CONNECT · OPTIONS · TRACE
레지스트리에 더 올라온 이름
PATCH · QUERY · PRI · PROPFIND · PROPPATCH · MKCOL · COPY · MOVE · LOCK · UNLOCK · ACL · REPORT · SEARCH · BIND · UNBIND · REBIND · ORDERPATCH · VERSION-CONTROL · CHECKIN · CHECKOUT · UNCHECKOUT · MERGE · LABEL · UPDATE · MKWORKSPACE · MKACTIVITY · BASELINE-CONTROL · MKCALENDAR · MKREDIRECTREF · UPDATEREDIRECTREF · LINK · UNLINK
메서드에 적용되는 규칙·원칙
안전한 메서드 · 멱등성 · 캐시 가능 · 조건부 요청 · 재시도
메서드가 실리는 요청 구성 요소
요청줄 · 대상 자원 · Allow
메서드 판정 결과로 돌아오는 상태 코드
상태 코드 · HTTP 405 · HTTP 501
메서드를 보고 처리를 달리하는 참여자
사용자 에이전트 · 오리진 서버 · 프록시 · 캐싱 · 크롤러
안전 보장이 깨지는 실제 사례
메서드 이름을 관장하는 표준과 기관
IANA · HTTP 메서드 레지스트리 · RFC 9110 · RFC 9112 · RFC 4918 · RFC 7252 · RFC 3253 · RFC 5789 · RFC 10008
WebDAV 메서드가 다루는 자원 개념
메서드 이름을 공유하는 다른 규약
HTTP · WebDAV · CoAP
다른 이름: request method · method token · HTTP 메서드