멱등성(Idempotency)
멱등성이라는 용어부터 살펴보자. 멱등성은 수학에서 유래된 개념으로, 같은 작업을 여러 번 반복해도 결과가 달라지지 않는 성질을 뜻한다. 이 개념은 HTTP Method에서도 중요한 역할을 한다.
예를 들어, 같은 GET 요청을 서버에 1번 보내든 10번 보내든, 서버에서 반환되는 데이터는 항상 동일하다. 하지만 POST 요청은 어떨까? 여러 번 실행하면 새로운 데이터가 계속 추가될 수 있다. 바로 이런 차이가 멱등성과 관련이 있다.
HTTP Method의 멱등성
위에서 언급한 것처럼, HTTP Method에도 멱등성을 적용할 수 있다. RFC 7231 문서에는 여러 번 동일한 요청을 보냈을 때 서버에 미치는 의도된 영향이 동일한 경우 멱등성을 가진다고 정의되어있다.
아래 표는, RFC 7231에서 정의한 HTTP Method의 멱등성을 정리해보았다.
Method | 멱등성 | 안전여부 | 설명 |
GET | ✅ | ✅ | 리소스를 조회한다. 여러 번 호출해도 같은 데이터를 반환한다. |
HEAD | ✅ | ✅ | 리소스의 헤더 정보를 조회한다. GET과 비슷하지만 본문 데이터는 반환하지 않는다. |
PUT | ✅ | ❌ | 리소스를 생성하거나 업데이트한다. 같은 데이터를 여러 번 요청해도 결과가 동일하다. |
DELETE | ✅ | ❌ | 리소스를 삭제한다. 같은 요청을 반복해도 추가로 삭제되지 않는다. |
POST | ❌ | ❌ | 리소스를 생성한다. 반복 호출 시 리소스가 중복으로 생성될 수 있다. |
PATCH | ❌ | ❌ | 리소스의 일부를 업데이트한다. 요청에 따라 결과가 달라질 수 있다. |
TRACE | ✅ | ✅ | 요청을 그대로 반환한다. 요청을 여러 번 보내도 동일한 결과를 가져온다. |
여러 번 요청이 전송될 수 있는 네트워크 환경에서는 같은 요청이 중복으로 처리되지 않도록 하는 것이 중요하다. 멱등성을 가진 Method는 이런 문제를 방지하여 시스템의 안정성을 높여준다.
예를 들어, 결제 시스템에서 같은 요청이 여러 번 실행되어도 금액이 중복으로 차감되지 않도록 해야하며 데이터 삭제 작업에서 이미 삭제된 리소스에 대해 추가로 요청이 들어오더라도 오류가 발생하지 않아야한다.
리소스와 표현(Representation)
포스팅 전반에 리소스라는 단어가 계속해서 등장하는데 표현(Representation)이라는 것도 있다.
표현이란 요청마다 변할 수 있는 리소스를 전달하는 형태이다.
Resource: /posts/123
Representation(JSON):
{
"id": 123,
"title": "REST Representation",
"content": "This explains representation in REST."
}
Representation(XML):
<post>
<id>123</id>
<title>REST Representation</title>
<content>This explains representation in REST.</content>
</post>
Representation(HTML):
<article>
<h1>REST Representation</h1>
<p>This explains representation in REST.</p>
</article>
REST에서는 표현 방식을 클라이언트와 서버가 콘텐츠 협상(Content Negotiation)을 통해 결정하도록 설계되어있다. 우리가 아는 Accept 헤더를 통해 말이다.
# Request
GET /posts/123 HTTP/1.1
Host: example.com
Accept: application/json
# Response
HTTP/1.1 200 OK
Content-Type: application/json
{
"id": 123,
"title": "REST Representation",
"content": "This explains representation in REST."
}
안전한 메소드란?
RFC 7231 문서에서는 읽기 전용 작업인 메서드를 안전한 메서드로 정의한다. 즉 안전한 메서드란 클라이언트가 서버 상태의 변화를 요청하거나 기대하지 않는다. 또한 합리적으로 사용되었을 때, 서버에 손해를 끼치거나 클라이언트의 손실 혹은 과도한 부하를 발생시키지 않아야 한다고 정의한다.
이 개념은 네트워크와 애플리케이션에서 클라이언트 요청이 불필요한 영향을 미치지 않도록 보장하기 위해 매우 중요한 개념이다. 예를 들어 GET은 단순 데이터를 조회할 뿐 서버에 영향을 미치지 않으므로 안전한 메서드로 분류된다.
GET
GET은 서버에서 리소스를 조회하기 위한 요청이다. 같은 요청을 여러 번 보내더라도 서버의 데이터는 변경되지 않기 때문에 멱등하다. 또한 GET은 서버의 상태를 변경하지 않으므로 안전한 요청이다.
하지만 외부 요인에 의한 리소스가 변경되어, 조회 결과가 멱등성을 보장하지 않는다는 말은 틀렸다. 외부 요인에 의해 변경되는 경우 멱등성 보장의 범위 밖이기 때문이다.
# 1. 최초 GET 요청
GET /posts/123
# 응답
{
"id": 123,
"title": "Hello World",
"content": "This is the original post."
}
# 2. PUT 요청으로 게시물 수정
PUT /posts/123
{
"id": 123,
"title": "Updated Title",
"content": "This is the updated post."
}
# 3. 다시 GET 요청
GET /posts/123
# 응답
{
"id": 123,
"title": "Updated Title",
"content": "This is the updated post."
}
위처럼 PUT 메서드인 클라이언트(외부) 에 의해 데이터가 변경되어 GET 요청을 다시 보냈을 때, 데이터가 변경된 것은 고려하지 않는다.
POST
POST는 멱등하지도 안전하지도 않은 메서드다. 주로 서버 리소스를 생성하는데 사용되므로, 새로운 리소스가 중복으로 생성되고 서버의 상태를 변경하기 때문이다.
POST /posts
{
"title": "mag1c",
"content": "HAPPY 2025~"
}
새로운 posts가 생성되며 같은 요청을 반복하면 동일한 데이터의 posts가 여러 번 생성된다.
PUT
PUT은 리소스를 생성하거나 업데이트한다. 데이터가 있더라도 덮어 씌운다고 생각하면 쉽다. 같은 요청을 여러 번 보내더라도 최종 상태는 동일하기 때문에 멱등하지만, 서버의 데이터를 변경하므로 안전하지는 않다.
PUT /posts/123
{
"title": "mag1c",
"content": "HAPPY 2025~"
}
내부 정책으로 title에 unique를 적용했다고 가정해보자. 업데이트는 이루어지지 않을 것이다. 그렇다면 이는 멱등하지 않을까? 그렇지 않다. 정책에 의해 동작이 달라질 수 있지만, 이것은 HTTP 메서드의 멱등성과 무관한 서버의 설계나 정책이기 때문이다.
PATCH
리소스를 수정하기 때문에 안전하지 않다. 그렇다면 PUT처럼 수정하는 메서드인 PATCH는 멱등할까?
우리는 수정 이라는 키워드를 유심히 보아야한다.
PATCH /posts/123
{
"status": "published"
}
위처럼 상태를 변경하는 API는 계속해서 pubilshed로 수정하기 때문에 멱등한 것 같다. 하지만 아래 API를 보자.
PATCH /posts/123/views
# 최초 상태
{
"id": 123,
"title": "mag1c",
"views": 1
}
# 2회째
{
"id": 123,
"title": "mag1c",
"views": 1
}
# 3회째
{
"id": 123,
"title": "mag1c",
"views": 2
}
.
.
.
같은 값을 계속 추가해나가는 것도 마찬가지로 수정이다. 이러한 추가의 요청에도 PATCH가 사용된다. 요청을 반복할 때마다 조회수가 증가하므로 최종 결과가 요청 횟수에 따라 달라진다. 이러한 이유들 때문에 문서에서도 멱등하지 않다고 서술되어있는 듯 하다.
인프런에 영한님의 PATCH 메서드가 멱등이 아닌 이유에 대한 서술도 있으니 참고하면 좋을 것 같다.
DELETE
리소스를 삭제하기 때문에 안전하지 않고, 이미 삭제된 리소스는 영향을 받지 않기 때문에 멱등하다.
DELETE /posts/123
엑!? DELETE를 중복해서 보내니 404가 생기던데요??? 라는 질문은 위의 글을 제대로 보지 않은 것이다.
리소스가 있는지 없는지 판별하여 선택적으로 에러를 내뱉는 것은 개발자 또는 누군가의 설계의 몫이다. 멱등성은 서버 리소스가 계속해서 변하냐 안변하냐의 리소스 관점에서 생각한다면 쉽게 판단이 가능하다.
reference.
https://www.rfc-editor.org/rfc/rfc7230
https://www.rfc-editor.org/rfc/rfc7231
https://developer.mozilla.org/ko/docs/Glossary/Idempotent
https://ko.wikipedia.org/wiki/%EB%A9%B1%EB%93%B1%EB%B2%95%EC%B9%99
https://stackoverflow.com/questions/16273390/different-restful-representations-of-the-same-resource
2023.04 ~ 백엔드 개발자의 기록
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!