"중복은 요청 하나 낭비하고 마는 게 아냐. 진실이어야 할 로그에 박혀버린, 있으면 안 되는 두 번째 턴이야."
'그냥 다시 보내지 뭐' 가 왜 공짜처럼 느껴지나 (근데 아냐)
무심한 재시도가 그렇게 흔한 이유는, 더블 전송이 데모에선 보통 무해해 보이기 때문이야. 답은 뜨고, 사용자는 만족하고, 중복은 아무도 눈치 못 채. 비용은 진짜 발생하는데 나중에 오고 눈에 안 보여. 아무 견제 없이 쌓이기 딱 좋은 종류지. 늘어놓고 보면 '그냥 다시 보내기' 가 공짜로는 안 보여.
- 중복된 대화 턴. 같은 질문이 canonical 로그에 두 번 들어가. 대화 기록에 유령 같은 반복이 생기고, 앞으로 컨텍스트를 리플레이할 때마다 그게 따라붙어.
- 모델 비용 두 배. 모델까지 닿은 중복 하나하나가 온전한 추론 한 번을 더 돌리는 거야. 진짜 컴퓨트, 진짜 돈. 사용자가 이미 갖고 있는 답을 얻자고.
- 헷갈리는 UX. 질문 하나에 답이 둘. 게다가 미묘하게 다르기까지 하면 사용자는 어느 게 진짜인지 고민하게 돼. 클라이언트가 할 일은 의심을 줄이는 거였지 만드는 게 아니었잖아.
- 망가진 ground truth. canonical 로그가 진실의 출처인 마당에 중복 턴은 겉으로 드러나는 흠집 정도가 아냐. 진실 자체가 틀려버린 거고, 거기서 파생된 뷰가 전부 그 에러를 물려받아.
로그는 성역이야, 중복은 그걸 더럽히고
append-only 로그가 ground truth 인 시스템에선 그 로그의 무결성이 전부야. 아래에 있는 DB 도, 검색 인덱스도, UI 도 전부 거기서 다시 만들어지니까, 한 번 쓰인 중복은 사방으로 퍼지고 되돌리기도 아파. 두 번 적힌 질문을 이제 와서 깔끔하게 '안 물어본 걸로' 만들 수는 없거든. 그래서 멱등 재시도는 있으면 좋은 최적화가 아냐. 로그 무결성을 지키는 파수꾼이야. dedupe 키랑 호출 전 확인이 있는 이유는, 불안한 네트워크가 만들어낸 찌꺼기가 기록에 영구적인 거짓으로 남지 못하게 하려는 거고.
비싼 손상에 대한 싼 보험
양쪽을 저울에 올려 봐. 멱등성이 드는 비용은 UUID 하나에 상태 확인 하나야. 몇 줄, 턴당 한 번. 안 하고 넘어갔을 때 드는 비용은 중복된 역사, 날린 추론, 헷갈리는 사용자, 그리고 고치는 데 돈 많이 드는 망가진 진실의 출처고. 이렇게 한쪽으로 확 기운 거래니까, canonical 기록에 뭔가 쓰는 클라이언트라면 이 규율은 협상 대상이 아닌 거야. 요청을 최적화하자는 얘기가 아냐. 불안한 링크가 진실을 망치도록 두기를 거부하는 거지.