CS/네트워크

HTTP 메서드(GET, POST, PUT, PATCH, DELETE ...)와 멱등성(Idempotent)에 대한 정리

개발자 May 2024. 8. 6.

REST(Representational State Transfer)

  • URI로 자원을 명시하고, HTTP 메서드로 CRUD 연산을 하는 소프트웨어 아키텍처이다.
  • HTTP를 따르는 플랫폼에서 별도의 인프라 구축 없이 REST를 사용할 수 있다.
  • 구성 요소
    1. 자원: URI를 이용해 클라이언트에서 서버로 자원 조작을 요청할 수 있다.
    2. 행위: HTTP 메서드로 자원에 대한 연산을 수행하게 한다.(CRUD 연산)
    3. 표현: JSON 또는 XML로 데이터를 주고받는다.

멱등성(Idempotency)이란?

멱등성은 수학과 컴퓨터 과학에서 사용되는 개념으로, 연산을 여러 번 수행하더라도 결과가 달라지지 않는 특성을 의미한다.

즉, 요청을 한 번 보내는 것과 여러 번 연속으로 보내는 것이 같은 효과를 지니고, 서버의 상태도 동일하게 남을 때, HTTP 메서드가 멱등성을 가졌다고 말한다.

멱등성을 지키는 것은 네트워크 장애나 클라이언트의 중복 요청으로 인해 발생할 수 있는 예기치 않은 문제를 방지하는 것에 중요하다. POST는 멱등성이 없기에 서버 측에서 중복 확인을 위한 로직을 구현하거나, 클라이언트 측에서 일정 시간 동안 추가 요청을 막는 등의 작업을 통해 해당 상황을 방지할 수 있다.

HTTP 메서드

연산 HTTP 메서드 멱등성
Create POST X
Read GET O
Update PUT O
Delete DELETE O

아래와 같은 유저 데이터가 있다고 할 때, 각 메서드별로 어떻게 응답, 혹은 변경되는지 살펴보자.

[
  { "id": 1, "age": 20, "name": "김철수" },
  { "id": 2, "age": 25, "name": "이영희" }
]

1. GET

  • 역할: 서버로부터 리소스를 요청할 때 사용
  • 특징: 데이터를 가져오는 데 사용되며, 서버의 상태를 변경하지 않는다. URL에 쿼리 문자열을 포함할 수 있으며, 캐시가 가능하여 브라우저에 의해 캐싱될 수 있다.
  • 멱등성: 같은 요청을 여러 번 해도 결과가 같다. 멱등성이 있다.
  • 캐싱:
    • Cache-Control 헤더: 서버가 응답에 Cache-Control 헤더를 포함하여 캐시 정책을 명시할 수 있다. 예를 들어, max-age, no-cache, no-store 등의 지시자를 통해 캐싱을 제어한다.
    • ETag 및 Last-Modified: 서버는 ETag(엔터티 태그)와 Last-Modified 헤더를 사용하여 캐시의 유효성을 검증할 수 있다. 클라이언트는 조건부 요청(If-None-Match, If-Modified-Since)을 통해 서버에 리소스가 변경되었는지 확인할 수 있다.
// 요청
GET /users/1

// 결과
{
  "id": 1,
  "age": 20,
  "name": "김철수"
}

2. POST

  • 역할: 서버에 데이터를 전송해서 리소스를 생성한다.
  • 특징: 요청의 BODY에 데이터를 포함해서 보낸다.
  • 멱등성: 멱등성이 없어서 같은 요청을 여러 번 보내면 서버의 상태가 계속 변한다.(ex. 신규 사용자 정보 추가가 여러 번 일어날 수 있다)
  • 캐싱:
    • 캐싱 가능성: POST 요청은 기본적으로 캐싱되지 않는다. 이는 POST가 주로 서버 상태를 변경하는 작업에 사용되기 때문이다.
    • 캐싱 예외: HTTP/1.1 사양에서는 POST 요청의 응답이 Cache-Control 헤더를 통해 캐싱 가능하다고 명시할 수 있지만, 실제로 대부분의 브라우저와 캐시 서버는 이를 지원하지 않는다.
    • 캐싱 대신 대안: 새로운 리소스를 생성한 후, 생성된 리소스를 GET 요청으로 확인하고 캐싱하는 방식이 일반적이다.
// 요청
POST /users
Content-Type: application/json

{
  "age": 30,
  "name": "박영희"
}

// 결과
[
  { "id": 1, "age": 20, "name": "김철수" },
  { "id": 2, "age": 25, "name": "이영희" },
  { "id": 3, "age": 30, "name": "박영희" }
]

3. PUT

  • 역할: 서버의 지정된 리소스를 대체하거나 새로 만들 때 사용한다.
  • 특징: 요청의 BODY에 리소스의 전체 내용을 포함해서 보낸다.
  • 멱등성: 멱등성이 있다. 같은 요청을 여러번 해도 결과는 동일하다.
  • 캐싱: 요청을 처리한 후 상태가 일관되게 유지되어야 하므로, 캐싱이 아닌 즉각적인 반영이 필요하다.
// 요청
PUT /users/1
Content-Type: application/json

{
  "age": 21,
  "name": "김민수"
}

// 결과
[
  { "id": 1, "age": 21, "name": "김민수" },
  { "id": 2, "age": 25, "name": "이영희" },
  { "id": 3, "age": 30, "name": "박영희" }
]

4. PATCH

  • 역할: 서버의 지정된 리소스를 부분적으로 업데이트할 때 사용한다.
  • 특징: 요청의 BODY에 리소스의 변경할 부분만 포함해서 보낸다.
  • 멱등성: 멱등성이 있을 수도, 없을 수도 있다. 일반적으로 같은 요청을 반복하면 결과가 같아야 하지만, 서버 구현에 따라 달라질 수 있다.
  • 캐싱: PATCH 요청도 마찬가지로 클라이언트의 특정 요청에 따라 리소스가 변경되기 때문에 캐싱보다는 실시간 업데이트가 중요하다.
// 요청
PATCH /users/2
Content-Type: application/json

{
  "name": "이수정"
}

// 결과
[
  { "id": 1, "age": 21, "name": "김민수" },
  { "id": 2, "age": 25, "name": "이수정" },
  { "id": 3, "age": 30, "name": "박영희" }
]

5. DELETE

  • 역할: 서버의 지정된 리소스를 삭제할 때 사용한다.
  • 특징: 일반적으로 요청 BODY를 포함하지 않는다.
  • 멱등성: 멱등성이 있다. 삭제 요청을 여러 번 해도 결과는 동일하게 리소스가 존재하지 않게 된다. 상태 코드는 응답마다 달라질 수 있지만, 그럼에도 멱등성을 가진다. (첫 삭제 시 200, 반복 시 404)
  • 캐싱: 명확한 상태 변경을 일으키며, 즉각적으로 데이터베이스나 리소스 상태를 반영해야 하므로 캐싱되지 않는다.
// 요청
DELETE /users/1

// 결과
[
  { "id": 2, "age": 25, "name": "이수정" },
  { "id": 3, "age": 30, "name": "박영희" }
]

6. HEAD

  • 역할: GET 메서드와 유사하지만, 응답 본문 없이 헤더 정보만 요청할 때 사용한다.

7. OPTIONS

  • 역할: 서버에서 지원하는 HTTP 메서드의 목록을 요청할 때 사용한다.

8. TRACE

  • 역할: 요청을 따라 서버로부터의 경로를 진단할 때 사용한다.

9. CONNECT

  • 역할: 클라이언트와 서버 간에 터널을 설정해서 주로 HTTPS 프로토콜을 위한 SSL 연결을 수립할 때 사용한다.

참고

MDN Web Docs 용어 사전: 웹 용어 정의 > 멱등성

MDN Web Docs 개발자를 위한 웹 기술 > HTTP > HTTP 요청 메서드

댓글