HwangHub

[Spring] HTTP Method로 알아본 "멱등성"이야기 본문

DEV-STUDY/Spring

[Spring] HTTP Method로 알아본 "멱등성"이야기

HwangJerry 2023. 9. 28. 22:08

공부를 하다보면 "멱등성"이라는 단어를 마주칠 때가 있는데, 이전에는 멱등성에 대한 이해가 서칭 포인트가 아니였기에 넘어갔다.

 

그러다 오늘, 학습을 진행하다가 멱등성이 다시 등장했고, 오늘은 이 녀석을 한번 정리해볼까 한다.

 

멱등성, 출신이 어디인가?

조금이라도 관심있게 알아본 사람은 모두 알겠지만, 멱등성은 수학에서 나온 단어이다. 아래 정의를 보면 알 수 있듯, 연산을 여러 번 수행하더라도 그 결과가 동일할 때 "멱등성을 갖는다"고 한다.

멱등법칙(冪等法則) 또는 멱등성(冪等性, 영어: idempotent)은 수학이나 전산학에서 연산의 한 성질을 나타내는 것으로, 연산을 여러 번 적용하더라도 결과가 달라지지 않는 성질을 의미한다.

출처: 위키피디아

 

 

이를 서버의 관점에서 이해해보자.

 

우리는 보통 HTTP Method를 서버에 보내어 response를 받는다. 여기서, 클라이언트가 어떤 동일한 요청을 서버에 여러번 보내어 서버가 그 요청에 대한 연산을 여러번 수행하더라도 서버 입장에서 항상 동일한 결과를 얻는다면 이는 멱등하다고 할 수 있다. 여기서 중요한 점은 클라이언트가 받는 response가 동일한 것과는 관련이 없다는 것이다. 왜냐하면 그 response는 서버에서 그냥 설정하기 나름이니까...!

 

그러면 어떤 상황이 동일한 결과일까?

 

쉽게 생각하면 서버는 결국 데이터(리소스)를 다루는 역할을 수행하는 컴퓨터이므로 "어떤 연산이 한번 수행되든 두번 수행되든 무한대로 수행되든, DB가 갖는 결과는 동일할 때 멱등하다"고 할 수 있을 것이다. 엄격히 따지면 이 말은 멱등성을 설명하기에 맹점이 존재하지만, 기본적인 가정 하에서는 '멱등성'을 이해하기에 도움이 될 수 있다고 생각한다.

 

 

 

GET, POST, PUT, PATCH, DELETE 중 멱등한 메서드는?

 

위의 정리를 참고하면 쉽게 구분할 수 있을 것이다.

 

멱등한 메서드

  • GET
  • PUT
  • DELETE

멱등하지 않은 메서드

  • POST
  • PATCH

엄격히 말하면, PATCH는 정의하기에 따라서 그 결과가 멱등할수도, 아닐수도 있다. 즉, "PATCH는 멱등성을 보장하지 않는다"는 말이 가장 정확하다. 반면에, GET, PUT, DELETE는 멱등성을 보장한다. 이제부터 하나하나 그 내용을 짚어보자.

 

  • GET은 사실 예상하기 쉽다. GET 메서드를 아무리 많이 호출한다 한들 조회이기 때문에 DB에 변화가 없다. 따라서 멱등하다.
  • PUT은 멱등성을 이야기할때 (PATCH와 같이) 대표적으로 거론되는 메서드이다. PUT 메서드는 수정 API를 구성할 때 보통 사용하며, PUT 요청을 바탕으로 특정 튜플을 통째로 갈아끼운다는 특징이 있다. 즉, 요청에 담긴 arguments가 동일하다면 그 결과로 수정되는 레코드는 (요청된 값들로 통째로 수정되어) 항상 동일한 결과이므로 멱등하다고 할 수 있는 것이다.
  • DELETE 또한 단순하다. 특정 레코드에 대한 삭제 요청을 한번 보내든 여러번 보내든, 그 레코드가 DB에서 사라진 결과는 동일하고, 여러번 요청했을 때 "지울 데이터가 없습니다"는 response가 발생할 수 있을 뿐, DB에 추가로 다른 데이터가 삭제된다거나 하지 않으므로 멱등하다고 할 수 있다.

반면에,

 

  • POST는 여러번 수행하면 수행하는 만큼 계속 새로운 레코드가 생성된다. 즉, 가장 멱등하지 않은 대표적인 요청이라고 할 수 있겠다.
  • PATCH는 일부 칼럼에 대하여만 수정을 가할 수 있는 메서드이다. 따라서 특정 칼럼에 대하여 동일한 문자열로 수정 요청을 한다면 아무리 여러번 호출하여도 동일한 결과를 얻으므로 멱등하다.

PATCH는 두 가지 케이스가 존재하므로 예시 코드를 들어보겠다. 아래 user 데이터를 기준으로 두 가지 버전의 patch 요청이 있다고 가정한다.

// GET "/users/1"
{
  "id": 1,
  "name": "Sam Kwee",
  "email": "skwee357@olddomain.example",
  "address": "123 Mockingbird Lane",
  "city": "New York",
  "state": "NY",
  "zip": "10001",
  "age": 20
}

 

멱등한 PATCH

아래 요청은 user 레코드의 email 데이터를 replace하는 요청을 한다. 이 경우 아무리 많이 요청하여도 똑같은 결과 데이터를 얻으므로 멱등하다고 할 수 있다.

// PATCH "/users/1"
{
  "operation": "replace",
  "email": "skwee357@newdomain.example"
}

// GET "/users/1"
{
  "id": 1,
  "name": "Sam Kwee",
  "email": "skwee357@newdomain.example",    // the email changed, yay!
  "address": "123 Mockingbird Lane",
  "city": "New York",
  "state": "NY",
  "zip": "10001",
  "age": 20
}

 

멱등하지 않은 PATCH

아래 요청은 age 칼럼의 데이터를 10씩 증가하도록 수정하는 요청이다. 이는 여러번 수행할 경우 어느새 Sam Kwee씨는 100살을 훌쩍 넘길 것이므로 멱등하지 않다고 할 수 있다.

// PATCH "/users/1"
{
  "operation": "add",
  "age": 10
}

// GET "/users/1"
{
  "id": 1,
  "name": "Sam Kwee",
  "email": "skwee357@newdomain.example",    
  "address": "123 Mockingbird Lane",
  "city": "New York",
  "state": "NY",
  "zip": "10001",
  "age": 30		// the age got 10 yrs older just by one request
}

 


 

이로써, 우리가 주로 사용하는 HTTP method에 대해서는 멱등성을 확실히 이해할 수 있었다. 위 가정은 '수정 일자'나 '조회수' 등의 필드를 제외한 경우에 멱등성을 보장한다. 추가로 HTTP method 중에서 HEAD, OPTIONS 또한 멱등성을 보장한다고 알려져 있다. 하지만 필자의 경우 해당 메서드를 전문적으로 사용해본 적은 없으므로, 추후 사용 경험을 가진 이후 해당 내용을 보충해보도록 하겠다.

 

 

출처:

https://hudi.blog/http-method-idempotent/

https://stackoverflow.com/questions/28459418/use-of-put-vs-patch-methods-in-rest-api-real-life-scenarios

 

Comments