HTTP 메서드의 속성, 멱등(Idempotent)이란?
짧고 심플하게, 멱등은 같은 요청을 여러번 보내도 기존의 의도와 똑같이 작동한다는 것을 의미합니다.
HTTP 메서드엔 안전, 멱등, 캐시가능으로 크게 세가지 속성이 존재합니다. 이 중 단어부터 생소한 멱등에 대해서 알아보도록 합시다.
요약
- 멱등한 메서드는 여러번 실행해도 의도한 바와 같이 같은 작동을 보장해야합니다.
- 멱등한 메서드는 네트워크 오류 제어 등 재전송에 의한 요청에 안전해야합니다.
HTTP 메서드의 속성
- 안전 - RFC 7231에 따르면, 본질적으로 읽기 전용이며 원본 서버의 리소스에 영향을 주지 않는 속성을 의미
- 멱등 - 요청을 재시도, 재실행해도 원래 의도한 바와 같이 동일하게 작동하는 속성을 의미
- 캐시가능 - 요청한 응답의 리소스를 향후 재사용을 위해 저장할 수 있는 속성을 의미
멱등한 메서드는?
요청을 재시도, 재실행해도 원래 의도한 바와 같이 동일하게 작동한다는 것이 무슨 말인지 이해하기 위해서 HTTP 메서드의 대표적인 HTTP 메서드 4가지로 생각해봅시다.
- GET <멱등> : 클라이언트가 같은 요청을 한번을 하든 백번을 하든 결국 클라이언트가 원한 결과 대로 작동합니다.
- POST <멱등하지 않음> : 클라이언트가 요청을 반복할 경우 클라이언트의 의도대로 작동하지 않을 수 있습니다.
- PUT <멱등> : 클라이언트가 요청을 반복할 경우 PUT 의 특성상 클라이언트가 원한 결과대로 무조건 리소스가 갱신되거나 생성됩니다.
- DELETE <멱등> : 클라이언트가 요청을 반복할 경우 클라이언트가 원한 결과대로 삭제됩니다.
POST 메서드는 멱등하지 않다. 왜?
왜 POST 메서드는 멱등하지 않을까요? 이는 HTTP 메서드에서 POST 가 담당하는 일을 곰곰히 생각해보면 알 수 있습니다. POST 는 HTTP BODY 에 어떠한 내용을 담아서 전송합니다. 서버에서 해당 요청을 받아서, 비즈니스 로직을 처리하게 되고 서버엔 변경이 일어납니다. 다음을 생각해봅니다.
클라이언트는 어떤 상품을 결제하려하는 상황입니다.
클라이언트 : POST 를 사용해 결제를 요청합니다.
서버 : 요청을 받아들여 결제 로직을 수행합니다.
아무 문제 없어보입니다. 근데 이를 동일하게 백번 수행한다고 생각해봅시다. 백번 결제를 눌렀더니 백번 결제가 되었습니다…오,이런..
아주 심각한 문제가 발생했습니다. 사용자(클라이언트)는 한번 결제를 원했지만 백번 결제가 되버린 것입니다.
재시도 했을 때 사용자의 의도대로 작동하지 않는 것입니다. 이런 이유에서 POST 가 멱등하지 않다는 것은 확실해졌습니다.
그런데, 의문이 생깁니다. PUT, DELETE 메서드도 서버에 변경이 일어나는 요청입니다. 결국 무언가를 지우거나 생성하는 행동을합니다. 왜 이건 멱등한 것일까요?
PUT, DELETE 메서드는 왜 멱등한가?
이것을 이해하기 위해선 PUT 과 DELETE 요청이 무슨 의도로 사용하는지 알아야할 필요가 있습니다.
- PUT - 리소스를 생성합니다. 단, 현재 생성하려했던 리소스가 경로에 존재할 경우 요청한 리소스로 갱신합니다.
- DELETE - 리소스를 삭제합니다. 단, 삭제하려는 리소스가 존재하지 않을 경우 삭제를 처리하지 않습니다.
어떤 의도로 두 메소드가 사용되는지 알았다면 바로 예를들어 생각해봅시다. 클라이언트가 자신이 보내는 리소스를 생성하길 원합니다.
<경우 A>
클라이언트 : PUT 메서드를 사용해 hello.jpg 를 전송
서버 : 요청을 받아드려 hello.jpg 리소스를 생성
<경우 B>
클라이언트 : PUT 메서드를 사용해 hello.jpg 를 전송
서버 : 요청을 받아드려 hello.jpg 리소스를 생성.
하지만, hello.jpg 라는 리소스가 이미 존재하므로 사용자가 요청한 hello.jpg 로 리소스 갱신
자, 두가지 경우를 살펴봤습니다. 위의 상황대로 생각해보면 사용자가 결국 같은 요청을 한번 실행하든 백번 실행하든, 결국 자신이 보낸 리소스가 정상적으로 서버에 반영되는 것입니다. DELETE 의 경우에도 같은 의미로 멱등한 것이라 생각할 수 있습니다.
이렇게 멱등이 무엇인지, 왜 멱등인지 알아보았습니다. 그럼 마지막으로 멱등한 속성은 왜 구분하는 것인지 알고싶어질 것입니다. 그래야합니다.
왜 멱등을 구분하는가?
생각외로 HTTP 메서드가 멱등인지 아닌지 구분하는 이유는 간단합니다. 네트워크 상에서 어떤 요청을 했을 때, 네트워크 상에서 다양한 변수에 의해(패킷 유실, 패킷 손실, 지연 등 수많은 이유) 요청이 실패할 수 있습니다. 보통 이런 예외에 의해 실패할 경우 재전송을 통해 해결하려하는데 이 경우에 멱등인지 아닌지가 매우 중요하다 볼 수 있겠습니다.
예를 들어 주문에 대한 POST 요청이 지연이나 손실에 의해 실패했을 경우 재전송 된다 하더라도 이전 요청의 상태를 파악하지 않은 상황에서 재전송된 요청의 처리가 되어선 안됩니다.
그러므로 멱등 속성의 메서드의 경우 재전송 온 요청을 일단 처리하고 봐도된다는 점이 있습니다.