HTTP 메소드의 멱등성과 캐시 개념

Posted by , November 16, 2022
HTTP

이번 포스팅에서는 HTTP 메소드의 특성인 안전, 멱등(Idempotent), 캐시(Cacheable) 에 대해 알아보겠습니다.


안전(Safe)

여러번 해당 메소드를 호출해도 리소스(resource) 를 변경하지 않는것을 안전하다라고 표현하는 것입니다.

  • GET 메소드 : 안전한 메소드 (리소스를 변경하지 않으므로)
  • POST, PUT, PATCH, DELETE 메소드 : 안전하지 않는 메소드 (리소스를 변경시키므로)

즉 여러번 메소드를 여러번 호출하면 안전하지 않다는 것으로, GET 을 제외한 POST, PUT, DELETE 와 같은 메소드들을 호출하는 것은 안전하지 않다는 것입니다. 반대로 여러번 호출해도 변경사항이 없는 것을 안전하다고 표현합니다.

그런데 아래와 같은 질문을 할 수 있다.

계속 호출을해서 서버에 로그같은 것들이 쌓여서 터져서 서버에 장애가 발생할 수 있는데, 이에 대해 안전이라는 개념은 고려를 하지 않습니다. 즉, 안전이라는 개념은 해당 리소스가 변하냐 변하지 않느냐만을 고려하지, 세부적인 사항들은 고려하지 않습니다.


멱등(Idempotent)

멱등이라는 것은 한번 호출하든, 수백번 여러번 호출하든 결과가 계속 똑같은것을 의미합니다. 수학에서 많이 보셨을 개념인데, 기호로 표현하자면 "f(f(x)) = f(x)" 가 되는 것입니다.

저희는 멱등인 메소드와, 멱등이 아닌 메소드로 구분지을 수 있습니다.

1.멱등 메소드 : GET, PUT, DELETE

  • GET : 한번 조회하든, 두번 조회하든 같은 결과가 조회되므로 멱등입니다.
  • PUT : 결과를 대체한다. 따라서 같은 요청을 여러번 해도 최종 결과는 같다.
  • DELETE : 결과를 삭제한다. 같은 요청을 여러번 해도 리소스가 삭제된 결과는 똑같다.

PUT 이 왜 멱등 메소드일까?

여기서 PUT 은 왜 멱등 메소드일까요? PUT 은 기존것을 아예 날려버리고 내가 새롭게 보낸것으로 내용을 새롭게 덮어버리는 특성을 지닙니다.

PUT 요청을 첫번째로 보낼경우 그에 맞춰서 데이터가 생성이 될겁니다. 그 뒤로 2번째 PUT 요청을 인풋값을 동일하게 맞추어서 보내면 첫번쨰와 두번쨰 결과가 동일할겁니다. 이렇게 동일한 인풋을 기반으로 계속 PUT 요청을 수백번 보내도, 결과적으로 생성되는 데이터 결과는 동일합니다.

DELETE 는 왜 멱등 메소드일까?

DELETE 도 생각해봅시다. 원하는 리소스에 대해 삭제하는 DELETE 요청을 보내면 리소스가 삭제가 될겁니다. 그런데 또 동일하게 DELETE 를 요청하면, 그대로 리소스는 이전의 DELETE 요청과 동일하게 리소스가 삭제된 상태가 동일하게 됩니다.

2.멱등이 아닌 메소드 : POST

  • POST : 멱등이 아니다. 결제 기능을 생각해보면, 1번 결제하는것과 100번 결제하는 것은 다르다.

POST 는 멱등이 아닙니다. 결제 기능을 POST 요청으로 처리하는 것을 생각해봅시다. 앨범을 구매하는 결제를 1번하는 것과 2번 하는 결과가 동일할까요? 당연히 아닙니다. POST 요청으로 결제를 1번한다면 1개의 앨범이 생성되고, 2번한다면 2개의 앨범이 생성됩니다.


멱등을 언제 사용하는가? : 자동복구 메커니즘

멱등이라는 개념을 언제 활용하면 좋을지 생각해본다면, 동일한 메소드를 또 다시 호출해야하는 상황에서 호출해도 상관없는지 여부를 판단할떄 활용할 수 있습니다.

예륻들어 자동복구 메커니즘을 생각해봅시다. DELETE 를 호출했는데 서버에서 응답이 없는경우, DELETE 메소드가 수행이 잘 된것인지 판단할 떄 클라이언트가 또 다시 한번 DELETE 를 호출해도 딥니다.

왜냐하면 DELELE 메소드는 멱등 메소드로써, 똑같은 요청을 다시해도 어짜피 동일한 결과가 나와서 결과가 이전 DELETE 메소드 호출 결과와 달라지지 않기 떄문입니다.


멱등의 유의사항 : 외부요인으로 리소스가 변경된다면?

멱등을 더 정확히 정의하면, 아래와 같습니다.

멱등은 외부 요인으로 인해 중간에 갑자기 리소스가 변경되는 것 까지는 멱등에서 고려하지 않는다.

  • 내가 요청한 것을 또 내가 다시 요청했을 떄만 결과가 동일한것을 멱등이라 칭합니다. (타인이 리소스를 변경해서 리턴된 결과가 달라지는 것은 따지지 않는다)

상황을 가정해봅시다.

  • 사용자1이 GET 을 요청했을 때 나오는 정보가 age:20 이라고 해봅시다.
  • 그런데, 사용자2가 (외부에서) PUT 요청을 통해 age 필드를 30으로 수정했다고 해봅시다.
  • 그러고 사용자1이 다시 GET 을 요청한다면 age:20 이 아닌, age:30 이 결과로 나올겁니다.

=> 이렇게 중간에 내가아닌 외부요인으로 인해 리소스가 변경되는 상황은 멱등에서 제외합니다.


캐시가능(Cacheable)

응답 결과 리소스를 캐시에서 사용 가능한지를 생각해봅시다.

만일 대용량의 큰 데이터(리소스)를 웹브라우저에게 보내달라고 요청을 하는 상황을 가정해봅시다. 한번 요청하고나면, 그 다음으로 또 그렇게나 큰 데이터 소스를 달라고 다시 재요청하고 인터넷으로부터 다운로드 받는것은 비효율적일 것이다.

그래서 내 로컬에 응답 결과 리소스를 저장하고 있는 것이 캐시라고 한다.

  • GET, POST, PATCH, HEAD 가 캐시가 가능하다.
  • 그런데 실제 실무에서는 GET, HEAD 정도만 캐시로 사용한다.

=> 실제로는 GET, HEAD 만 캐시로 사용한다. 왜냐면 캐시를 하려면 똑같은 리소스에 대해서 캐시 KEY 가 정확히 맞아야한다. POST, PATCH 는 본문(Body) 내용까지 캐시 키로 고려해야 하는데, 구현이 쉽지 않아서 그렇습니다.