안정적인 API를 위한 HTTP 멱등성 이해하기
3분 읽기
안정적인 API를 위한 HTTP 메서드의 멱등성 이해하기
| Method | Safe | Idempotent |
|---|---|---|
| CONNECT | X | X |
| DELETE | X | O |
| GET | O | O |
| HEAD | O | O |
| OPTIONS | O | O |
| POST | X | X |
| PUT | X | O |
| TRACE | O | O |
PATCH 메서드는 이후 RFC 5789에서 추가되었습니다.
* 참고: RFC 7231 (HTTP/1.1)
멱등성(Idempotency)
멱등법칙 또는 멱등성은 동일한 연산을 여러 번 적용하더라도 결과가 달라지지 않는 성질을 의미한다.
예를 들어, 어떤 숫자에 1을 곱하는 연산은 몇 번을 반복해도 처음 1을 곱했을 때와 결과가 동일하기 때문에 멱등성을 가진다고 볼 수 있다.
이러한 멱등성을 가진 함수나 연산은 시스템의 안정성과 예측 가능성을 높여주기 때문에 소프트웨어 개발에서도 중요한 역할을 한다.
HTTP 명세에서 안전함(Safe)
HTTP 명세에서, 일부 메서드는 서버의 상태를 변경하지 않도록 정의되어 있다.
서버의 상태를 변경하지 않거나, 다른 말로 읽기 전용(read-only) 메서드일 경우, 해당 메서드는 "안전하다(Safe)"고 표현한다.
안전한 메서드
GETHEADOPTIONSTRACE
HTTP/1.1 명세에 따르면, GET, HEAD, OPTIONS, TRACE 메서드는 안전하다.
안전한 메서드는 클라이언트가 서버에 요청을 보내더라도 서버의 리소스를 수정하거나 상태를 변경하지 않기 때문에, 요청을 여러 번 보내도 서버에 미치는 영향이 없고 부작용(side-effects)이 발생하지 않는다.
또한, 안전한 메서드는 기본적으로 멱등적이다. 클라이언트가 GET이나 HEAD 요청을 여러 번 반복하더라도 서버 상태는 변하지 않는다.
HTTP 명세에서 멱등함(Idempotent)
동일한 요청을 여러 번 보내더라도 결과가 동일하게 유지되는 메서드의 경우, 해당 메서드는 "멱등하다(Idempotent)"고 표현한다.
여기서 결과란, 상태 코드가 아닌 서버의 리소스 상태를 의미한다. 응답이 달라도 서버 상태가 변하지 않으면 멱등성이 유지된다.
멱등한 메서드
DELETEGETHEADOPTIONSPUTTRACE
HTTP/1.1 명세에 따르면,DELETE, GET, HEAD, OPTIONS, PUT, TRACE 메서드는 멱등하다.
안전한 메서드는 멱등성 또한 갖지만, 모든 멱등성을 지닌 메서드가 안전한 것은 아니다. PUT, DELETE는 멱등성을 가지지만, 리소스에 변화를 일으키기 때문에 안전하지는 않다.
멱등성을 보장하기 위한 PATCH, POST 메서드 사용법
PATCH 메서드의 두 가지 사용법
PATCH 메서드는 기존의 PUT 메서드로 처리하기 어려운 리소스의 부분 업데이트 문제를 해결하기 위해 추가되었다.
일반적으로 PATCH 요청은 변경이 필요한 필드만 요청 본문(request body)으로 보내고, 변경하고 싶지 않은 필드는 생략한다.
RFC 2616의 9.1에서 정의된 안전함(Safe)과 멱등성(Idempotency)의 개념에 따라, PATCH 메서드는 멱등하지 않고, 안전하지 않다.
하지만 PATCH 메서드는 사용 방식에 따라 멱등성을 보장할 수도 있고 보장하지 못할 수도 있다.
멱등한 사용법
예를 들어, 다음과 같은 PATCH 요청은 멱등성을 유지할 수 있다.
이 요청은 여러 번 보내도 항상 같은 데이터를 동일한 방식으로 수정하므로, name 필드는 항상 "John Doe"로 유지되며, 결과적으로 멱등성이 성립한다.
PATCH /users/{userNo}
{
"name": "John Doe"
}멱등하지 않은 사용법
반면, 다음과 같은 PATCH 요청은 멱등성을 유지할 수 없다.
이 요청은 여러 번 보내면 매번 age 필드의 값을 1씩 증가시킨다.
이로 인해 의도하지 않은 요청에서도 서버 상태가 계속 변경되므로, 멱등성이 깨질 수 있다.
PATCH /users/{userNo}
[
{ "op": "add", "path": "/age", "value": 1 }
]멱등키를 활용한 PATCH, POST 메서드의 중복 요청 방지
앞서 살펴본 바와 같이, PATCH, POST 메서드는 멱등하지 않고, 안전하지 않다.
그럼에도 불구하고, 안정적이고 결함 없는 API를 구축하기 위해서는 멱등성을 보장할 수 있는 장치가 필요하다.
최악의 시나리오를 상상해보자. 결제를 처리하는 API에서 네트워크 오류, 타임아웃 혹은 실수로 중복 요청이 발생하는 경우가 있을 수 있다.
커스텀 헤더에 멱등키 실어 보내기
멱등키는 일반적으로 UUID v4와 같은 무작위적이고 고유한 값이어야 한다.
fetch('/api/v1/payments', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Idempotency-Key': '1063ef6e-267b-48fc-b874-dcf1e861a49d' // 멱등키
},
body: JSON.stringify({ data: 'example' })
});멱등성이 보장된 API의 처리 흐름
멱등키가 없는 요청을 처리하는 방식은 비즈니스 로직이나 요구 사항에 따라 달라질 수 있다.
- 클라이언트는 요청을 서버로 전송할 때, 요청 본문과 함께 헤더에 멱등키를 포함시켜 요청한다.
- 서버는 요청 헤더에 포함된 멱등키를 확인한다.
- 멱등키가 존재할 경우
- 해당 멱등키가 이미 처리된 요청인지 확인하기 위해 서버 내에 저장된 응답 캐시 혹은 DB를 조회한다.
- 처음 들어온 요청이라면, 요청을 정상적으로 처리하고, 멱등키와 응답 데이터를 저장한다.
- 이미 처리된 요청인 경우, 이미 저장된 응답을 반환한다.
- 해당 멱등키가 이미 처리된 요청인지 확인하기 위해 서버 내에 저장된 응답 캐시 혹은 DB를 조회한다.
- 멱등키가 존재할 경우
이처럼 멱등키(Idempotency Key)를 API 요청의 커스텀 헤더에 포함하면 각 요청에 "고유성"을 부여할 수 있으며,
사용자가 의도치 않게 동일한 요청을 여러 번 보내더라도, 중복 처리로 인한 문제를 방지하고 일관된 응답을 받을 수 있다.
관련 글
6분 읽기
이벤트 기반 아키텍처(Event-Driven Architecture)
이벤트 기반 아키텍처의 개념, 브로커·중재자 토폴로지 비교, Event Notification·ECST·Event Sourcing·CQRS 패턴을 정리합니다.
4분 읽기
Stateful vs Stateless
Stateful과 Stateless 아키텍처의 개념과 각각의 장단점을 정리하고, 모든 것을 무상태로 설계할 수 없는 이유를 살펴봅니다.
4분 읽기
왜 리액트는 단방향 데이터 흐름을 채택했을까?
양방향·단방향 데이터 바인딩의 차이를 MVC 아키텍처의 한계와 함께 살펴보며, React가 단방향 데이터 흐름을 채택한 배경과 이유를 알아봅니다.