230206 항해99 92일차 멱등성

요니링 컴터 공부즁·2023년 2월 22일
0
post-custom-banner

멱등(Idempotent)하다는 것

  • 첫 번째 수행을 한 뒤 여러 차례 적용해도 결과를 변경시키지 않는 작업 또는 기능의 속성. 즉, 멱등한 작업의 결과는 한 번 수행하든 여러 번 수행하든 같다.
  • 예를 들어, 어떤 숫자에 1을 곱하는 연산은 여러 번 수행해도 처음 1을 곱한 것과 같은 숫자가 되기 때문에 멱등하다. 마찬가지로 숫자의 절대값을 계산하는 절대값 함수는 같은 값에 대해 여러 번 수행해도 처음과 항상 같은 숫자가 돌아오기 때문에 멱등 함수라고 부른다.

HTTP 메서드의 멱등성

  • HTTP 메서드에도 멱등성이 있다. 예를 들어 GET은 여러 번 호출해도 같은 결과가 돌아오고, 리소스에 변화를 일으키지 않기 때문에 멱등성이 보장된 메서드이다.
  • GET, PUT처럼 리소스를 조회하거나 대체하는 메서드는 멱등하다. PUT은 여러 번 호출해도 매번 같은 리소스로 업데이트되기 때문에 결과가 달라지지 않는다. DELETE 역시 여러 번 호출해도 삭제된 리소스에 대한 결과는 달라지지 않는다. 반면 서버 데이터를 변경하는 POST, PATCH는 호출할 때마다 응답이 달라지기 때문에 멱등한 메서드가 아니다. 이렇게 멱등하지 않은 메서드에 멱등성을 제공하려면 서버에서 멱등성을 구현해야 한다.

API 관점에서 바라보기

  • 멱등한 API라면 두 번 이상 요청해도 결과는 처음 요청과 똑같이 돌아온다. 단순히 돌아온 값이 같을 뿐 아니라 서버 상태(DB)에도 영향을 미치지 않는다. 이렇게 시스템에 의도하지 않은 문제를 일으키지 않고 요청을 재시도할 수 있기 때문에, 멱등성은 결함 없고 안전한 API를 만드는데 중요하다.
  • 사용자가 결제하는 시점에 네트워크 오류나 타임아웃으로 인해 결과를 받지 못하는 시나리오를 생각해보자. 멱등성이 보장되지 않은 결제 API라면 실제로 결제가 성공했는지 수동으로 확인해야 하고, 확인해 보니 실제로 결제가 되지 않았다면 고객이 같은 결제를 다시 시도해야 한다. 반면 결제 API가 멱등하다면 다시 같은 요청을 보내지 않고 전에 받지 못한 결과만 다시 받을 수 있을 때 편리하다. 또 실수로 중복 요청이 되더라도(일명 ‘따닥’) 실제로는 결제가 되지 않아서 안심하고 여러 번 요청할 수 있다.

멱등한 요청인지 알 수 있는 방법

  • 멱등성을 보장하려면 멱등키를 API 요청에 포함하면 된다. 이전 요청과 동일한 멱등키를 가진 요청을 받으면 서버에서 이 요청을 중복으로 판단한 뒤 실제로 처리하지 않고 첫 요청과 같은 응답을 반환하는 방식이다. 요청 본문, URL 쿼리 매개변수, 헤더 중 하나에 멱등키를 포함해서 보내면 되는데, IETF에서는 요청 헤더에 포함하는 방법을 표준으로 제안하고 있다.

  • 그런데 헤더에 키를 추가하는 것 만으로 같은 요청이 반복된 건지 어떻게 식별해서 처리할 수 있을까? 예시로 결제 취소 플로우를 살펴보자.

    Step 1. API 서버는 취소 요청마다 헤더에 멱등키가 있는지 확인한다.
    Step 2. 또 멱등키를 저장하기 위해 DB를 만들어둔다. 멱등키가 포함된 취소 요청이 들어왔을 때 이 DB를 쿼리 해서 요청이 들어온 멱등키와 매칭되는 요청 기록이 있는지 확인한다.
    멱등한 요청 기록을 DB에 저장하는 기간을 정해둘 수 있다. 그 기간이 지나면 DB에 저장된 멱등키와 기록이 없기 때문에 같은 멱등키를 사용해서 새로운 요청을 보낼 수 있다. 사용하는 입장에서는 멱등키의 유효 기간이라고 할 수 있다.
    Step 3-1. 만약 이전에 같은 멱등키로 들어온 요청이 있었다면, 서버에서 실제 요청을 실행하지 않고 저장되어 있던 응답 데이터를 돌려준다.
    Step 3-2. 만약 멱등키와 매칭되는 이전 기록이 없다면, 새로 생성된 응답을 저장하는 새로운 기록을 만들고 응답을 클라이언트에 돌려준다.

  • 도메인 서버 로직의 복잡도가 높다면 멱등성 로직을 추가했을 때 API 성능 개선에 도움이 되기도 한다. 멱등키를 가진 요청은 도메인 서버로 바로 처리되지 않기 때문이다.

참조: 멱등성이 뭔가요?

post-custom-banner

0개의 댓글