노트

멱등성

Idempotency

백엔드#architecture#http · 연결된 개념 12개

쉽게 말하면

멱등성은 엘리베이터 호출 버튼처럼 한 번 누르든 열 번 누르든 결과가 같은 성질이에요. 네트워크가 끊겨 같은 요청을 다시 보내도 결제가 두 번 되지 않으려면 받는 쪽이 이래야 하죠.

비유가 깨지는 곳 버튼과 달리 응답까지 같을 필요는 없어요. DELETE는 첫 번째 204, 두 번째 404여도 멱등이에요. POST는 원래 멱등이 아니라서 멱등 키나 처리한 이벤트 ID 기록으로 멱등하게 만들어요.

멱등성(idempotency)은 같은 연산을 한 번 하든 여러 번 하든 결과가 같다는 성질이다. 네트워크는 실패하고 메시지는 중복되므로, 재시도가 안전하려면 받는 쪽이 멱등해야 한다.

HTTP 메서드

  • GET, PUT, DELETE는 명세상 멱등이다. 같은 PUT을 두 번 보내도 리소스는 같은 상태가 된다
  • POST는 멱등이 아니다. 결제 요청을 두 번 보내면 두 번 결제될 수 있다
  • 그래서 결제 같은 POST에는 클라이언트가 만든 멱등 키(Idempotency-Key)를 헤더로 보내게 하고, 서버는 같은 키의 두 번째 요청에 첫 결과를 그대로 돌려준다

메시지 소비자

Kafka 같은 브로커와 아웃박스 워커는 보통 at-least-once(최소 한 번 전달)로 전달한다. "최소 한 번"이라 같은 이벤트가 두 번 올 수 있다.

  • 같은 ID로 덮어쓰기: 검색 색인이나 캐시에 문서 ID 기준으로 upsert하면 중복이 와도 결과가 같다
  • 처리한 이벤트 ID 기록: 처리 테이블에 이벤트 ID를 유니크 키로 남기고, 이미 있으면 건너뛴다
  • 버전 비교: 이벤트에 버전·타임스탬프를 담아 현재보다 오래된 변경은 무시한다. 순서 꼬임도 함께 막는다
INSERT INTO processed_events (event_id) VALUES ($1)
ON CONFLICT (event_id) DO NOTHING;   -- 영향받은 행이 0이면 이미 처리됨

혼동 주의

멱등은 "부수 효과(side effect)가 없다"와 다르다. DELETE는 상태를 바꾸지만 여러 번 해도 결과가 같아 멱등이다. 응답 코드는 달라질 수 있다(첫 번째 204, 두 번째 404).

이벤트가 늦게·중복으로 도착하는 세계에서 결국 같은 상태로 모이게 하는 장치라 최종 일관성과 짝을 이룬다. 요청 횟수 자체를 제한하는 것은 요청 제한 (Throttling), 재사용 가능한 순수 함수의 성질은 명령-질의 분리과도 이어진다.

출처: RFC 9110: Idempotent Methods · IETF 초안: The Idempotency-Key HTTP Header Field · microservices.io: Idempotent Consumer

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • 데이터 무결성

    데이터 무결성(data integrity)은 저장된 데이터가 정확하고 일관되며 믿을 수 있는 상태로 유지되는 것이다. 재고가 100개로 보이는데 실제로 50개라면 무결성이 깨진 것이다. 관계형 DB는 이를 제약 조건(constraint)으로 강제한다.

  • 예외 삼키기

    예외를 잡아 놓고 아무 처리 없이 흘려보내는 안티패턴(Anti-pattern). 빈 catch뿐 아니라 debug 레벨로만 찍고 정상인 척 진행하는 것도 마찬가지다.

  • 커넥션 드레이닝과 무중단 재시작

    배포 중 서버를 재시작하는 몇 초 동안 로드밸런서가 그 서버로 요청을 보내면 502가 난다. 먼저 로드밸런서에서 빼고(드레이닝), 진행 중인 요청을 마친 뒤 재시작하고, 준비되면 다시 넣는다.

  • 디버깅 문제 정의 5단계

    문제 정의 → 올바른 동작 정의 → 최소 재현과 관찰 → 차이를 만드는 원인 탐색 → 가설 검증 순서로 버그를 좁혀 가는 틀.

  • 믹스인

    믹스인(Mixin)은 여러 클래스나 객체가 공유할 기능 묶음을 따로 정의해 두고, 상속 계층과 상관없이 섞어 넣는 재사용 방식이다. JavaScript에서는 "부모 클래스를 받아 기능을 더한 새 클래스를 돌려주는 함수"로 자주 구현한다.

보기 옵션