본문 바로가기

BE/Network

멱등(Idempotent)이란?

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 요청이 지연이나 손실에 의해 실패했을 경우 재전송 된다 하더라도 이전 요청의 상태를 파악하지 않은 상황에서 재전송된 요청의 처리가 되어선 안된다.

그러나 멱등 속성의 메서드의 경우 재전송 온 요청을 일단 처리하고 봐도된다는 점이 있다.

'BE > Network' 카테고리의 다른 글

Stateful 과 Stateless 의 차이와 극단적인 예  (0) 2021.11.15