HTTP 프로토콜은 서버와 클라이언트가 통신하는 메시지를 구체적으로 정의하고 있습니다.
메시지는 다섯가지 파트로 이뤄집니다 :
이 중 리퀘스트 메서드는 클라이언트가 서버에게 어떤 동작을 수행하도록 요청하는 것을 말합니다.
마치 함수를 호출할 때처럼, 특정 메소드로 서버에 요청을 보내면 서버는 정의된 동작을 수행해 그 결과를 클라이언트에 리턴해줍니다.
| Method | Description | 안전성 (Safe) | 멱등성 (Idempotent) | 캐시가능성 (Cacheable) |
|---|---|---|---|---|
| GET | 타겟 리소스를 리턴한다. | Yes | Yes | Yes |
| HEAD | Get과 같지만 status line과 header만 리턴한다. | Yes | Yes | Yes |
| POST | 서버가 타겟 리소스에 대해 정의한 로직대로 리퀘스트 페이로드에 보내진 데이터를 처리한다. 주로 데이터 생성에 사용된다. | No | No | Yes |
| PUT | 타겟 리소스 전체를 리퀘스트 페이로드의 데이터로 교체한다. | No | Yes | No |
| PATCH | 타겟 리소스의 일부분을 리퀘스트에 명시된 지침대로 교체한다. | No | No | No |
| DELETE | 타겟 리소스를 삭제한다. | No | Yes | No |
| CONNECT | 타겟 리소스에 명시된 서버로의 tunnel을 구축한다. | No | No | No |
| OPTIONS | 타겟 리소스에 대한 커뮤니케이션 옵션을 설명한다. | Yes | Yes | No |
| TRACE | 타겟 리소스로의 경로를 따라 메시지 루프백 테스트를 수행한다. | Yes | Yes | No |
이 중 자주 쓰이는 메서드는 GET, POST, PUT, PATCH, DELETE입니다.
메서드가 읽기 전용, 즉 서버에 어떠한 변경도 요청하지 않는 경우 이 메서드를 '안전하다(safe)'고 합니다.
안전한 메서드로는 GET, HEAD, OPTIONS, TRACE가 있습니다.
서버 상태를 변경하지 않는 것이 보장되는 것이 필요한 경우가 있어 이러한 속성이 사용됩니다.
예를 들어 캐시 최적화를 위해 사전에 데이터를 가져올 때, 안전하게 동작하기 위해서는 서버 상태가 변경되지 않는 것이 보장되어야 합니다.
웹 스파이더와 같은 자동화 프로그램 또한 안전한 메서드를 사용함으로써 의도치 않게 서버 상태를 변경하지 않을 수 있습니다.
보안적으로 사용되기도 합니다. 신뢰할 수 없는 컨텐츠를 처리할 때 안전하지 않은 메서드에 대해서 제약을 둘 수 있습니다.
안전한 메서드가 안전한 동작만 하도록 하는 것은 서버 관리자의 의무입니다. 예를 들어 서버에서 GET 메서드임에도 쿼리 파라미터 등을 통해 다른 동작을 하도록 할 수도 있는데(예: page?do=delete) 이러한 동작은 금지됩니다.
동일한 메서드를 한 번 수행했을 때와 여러 번 수행했을 때 서버의 상태가 동일하다면 그 메서드는 멱등성이 있다고 할 수 있습니다.
멱등성이 보장되는 메서드로는 안전한 메서드에 더해 PUT과 DELETE가 있습니다.
멱등성이 중요한 이유는 네트워크의 불안정성과 관련이 있습니다. 응답이 돌아오지 않을 때, 네트워크의 문제로 요청이 서버에 도달하지 못한것인지 서버의 문제로 응답이 오지 않는 것인지 확신할 수 없어 재요청을 보내는 경우가 생길 수 있습니다.
이 때 멱등성이 보장되어야만 안전하게 다시 요청을 보낼 수 있습니다.
POST 메서드의 경우 요청 될 때마다 데이터가 생성되므로 멱등성을 보장하지 않습니다. 서버로부터 응답을 받지 못해 다시 요청을 보낸다면, 동일한 데이터가 중복 생성될 것입니다.
결제 시스템과 같이 예민한 시스템에서 동일한 데이터가 중복 생성될 경우, 사용자가 한 번 구매한 상품이 여러번 결제될 수 있어 이러한 성질에 주의해야 합니다.
이런 경우 멱등성을 직접 구현해야 하는데 이 방법을 잘 설명한 글이 있어 링크로 달아두겠습니다.
멱등성이 뭔가요?
PATCH 메서드는 구현에 따라 멱등성이 보장될수도, 그렇지 않을 수도 있습니다.
만약 PATCH 메서드가 리소스에 대해 연산을 해서 그 리소스의 현재 '상태'가 어떤지에 따라 결과가 달라진다면 멱등성이 보장되지 않습니다.
하지만 연산을 하지 않고, 특정한 값으로 set 하도록 하면 멱등성을 보장할 수 있습니다.
예를 들어, 리소스를 1 증가시키는 PATCH 메서드는 보낼 때마다 값이 1 증가되므로 멱등성이 보장되지 않습니다.
하지만 리소스를 2로 set 하는 PATCH 메서드는 여러 번 요청을 보내도 한 번 요청을 보냈을 때와 같이 리소스의 값이 2가 될 것이기 때문에 멱등성을 보장할 수 있습니다.
상태애 따라 결과가 달라지는 PATCH 메서드라도, HTTP 헤더를 이용해 멱등성이 보장되도록 구현할 수 있습니다.
헤더의 If-Match 필드와 ETag를 사용해 이를 구현할 수 있습니다.
PATCH 요청을 보내기 전 GET 요청으로 해당 리소스의 ETag를 수령하고, E-Tag를 포함해 PATCH 요청을 보냅니다.캐시 가능성은 해당 메서드에 대한 응답이 향후 재사용을 위해 저장될 수 있는지 여부를 나타냅니다.
일반적으로 안전한 메서드인 GET, HEAD, OPTIONS, TRACE 메서드가 캐시 가능한 것으로 정의되지만, 실제 대다수의 캐시 구현체들은 GET과 HEAD 만을 저장하는 경우가 많습니다.
reference
rfc7231 - section 4. Request Methods
rfc5789(PATCH)