앱이 계속 재시도하면 한도는 얼마나 빨리 줄까?

이 글의 한도는 보충되지 않는 가상의 요청 단위 24개다. 토큰·돈·실제 계정 사용량이나 요금제의 사용 가능 기간이 아니다. 미리 정한 오류를 포함한 20개 행동을 로컬 가짜 처리 함수와 두 비교 정책으로 재생했다. 측정 중 실제 서비스나 AI 모델은 호출하지 않았다. 한 번 누른 작업이 여러 요청으로 늘어날 때, 어디서 멈추고 무엇을 알려야 할까?

왼쪽에서는 버튼 하나에서 수많은 봉투가 퍼져 나와 문 앞에 쌓이고, 오른쪽에서는 같은 버튼에서 봉투 몇 개만 나란히 이동해 닫힌 문과 산호색 신호등 앞에서 멈추는 개념 일러스트
Grok Imagine을 사용해 생성한 AI 이미지입니다.

개념 일러스트이며 실험 증거나 실제 요청 수를 나타낸 그림이 아니다.

이 글의 목차

출처로 보는 기준: 응답 없음은 저장 실패인가

HTTP 표준 RFC 6585 §4의 429는 일정 시간에 요청이 너무 많다는 뜻이다. 재요청까지 기다릴 시간을 안내할 수 있지만, 요청을 세는 방식은 정하지 않는다. 429 응답을 저장해 재사용해서도 안 된다. RFC 9110 §9.2.2는 반복할 때마다 효과가 더 생길 수 있는 요청을 자동으로 다시 보내려면, 실제로는 같은 의도한 효과만 낸다는 근거 또는 원래 요청이 적용되지 않았다는 근거가 필요하다고 설명한다. 저장 응답을 못 받았다는 이유만으로 다시 보내거나 임의의 키를 붙여 안전하다고 간주할 수 없다. 두 출처의 확인일은 조사 기록에 남은 2026년 10월 16일이다.

이 글은 행동 → 요청 → 효과 → 앱이 받은 확인을 나눠 센다. 효과는 저장 같은 실제 변화를 뜻한다. 저장됐어도 확인 응답이 사라질 수 있기 때문이다.

기록된 관찰: 20번의 행동, 서로 다른 장부

2026년 10월 17일, 작성자가 정한 합성 시나리오 하나를 macOS 27.0·Python 3.9.6에서 실행했다. 가짜 처리 함수가 서버 역할을 했으며 실제 서버나 통신망을 거치지 않았다. 아래 관찰의 ‘서버’는 이 가짜 함수를 뜻한다. AI 코딩 도구 Codex가 코드 제작을 보조했지만 재생에는 모델이 참여하지 않았다.

A는 모든 오류에 즉시 재시도하도록 일부러 만든 비교 조건이다. 앱 자체 중단 기능이 없어 바깥에서 실행을 제한하는 시험 장치가 최초 요청 포함 행동당 최대 8회까지만 허용했다. 가상 시간은 실제 기다린 시간이 아니라 시험 장부에서 진행시킨 시간이다. B의 설정은 다음과 같다.

  • 행동별: 최초 포함 최대 3회, 20가상초.
  • 전체: 요청 40회, 그중 재시도 12회, 300가상초.

재시도 예산을 다 써도 다른 제한에 걸리지 않는 한 각 행동의 첫 요청은 보낼 수 있도록 설계했다. 그러나 이번 측정에서는 이 예산이나 전체 요청·시간·잔량 중단이 작동할 지점까지 가지 않았다. 모두 실험 설정이며 권장 횟수가 아니다.

B에는 서버 대기 안내 준수, 성공한 읽기 결과 재사용, 진행 중인 같은 읽기 공유, 가짜 서버가 같은 저장 작업을 알아보도록 구현한 저장 작업 키도 넣었다. 여러 조건을 한꺼번에 바꿨으므로 기능별 효과는 분리할 수 없다.

가짜 함수는 받아들인 요청이 오류나 시간 초과로 끝나도 1단위를 차감한다. 같은 키로 기존 저장 결과를 돌려받는 요청도 차감한다. 잔량이 0이면 이후 요청을 거절하되 차감하지 않는다. 실제 제공자의 과금·한도 규칙으로 옮겨 읽을 수 없는 설정이다.

표 1 · 기록된 관찰: 20번의 행동, 서로 다른 장부
한 시나리오의 결과 — 단위는 모두 가상 A B
요청 / 입력 행동 20건
119회 / 20건
22회 / 20건
요청의 구성
최초 20회 + 재시도 99회
최초 14회 + 재시도 8회
사용 / 시작 단위
24 / 24
22 / 24
잔량 / 시작 단위
0 / 24
2 / 24
차감 없는 잔량 소진 거절 / 전체 요청
95 / 119회
0 / 22회
의도보다 더 생긴 저장
1건
0건
완료 확인 / 입력 행동
6 / 20건
15 / 20건
사전에 정한 문구·근거 규칙에 맞는 최종 문구 / 최종 문구
6 / 20건
20 / 20건

중복 저장의 양쪽 비교 사례는 W1이다. 세 저장 의도 모두가 같은 조건에 노출된 비율은 아니다. 아래에서 다룰 W3는 A의 잔량이 이미 없어 저장 단계에 도달하지 못했다.

행동에는 A01–A20이라는 식별자가 붙어 있지만 숫자순으로 실행하지 않았다. A01·A02는 함께 시작했고, 영구 오류 A16은 A03 뒤에 배치했다. 정책 A는 A16과 A04에 각각 8단위를 쓰고, A07까지 총 23단위를 썼다. 이어 A08의 첫 시간 초과에서 마지막 단위를 썼다. 이때 A의 가상 시각은 3,100밀리초였다. B는 A08까지 9단위, 그 뒤 13단위를 써서 끝에 2단위를 남겼다. 요청 차이 97회와 사용 단위 차이 2개는 이 순서·상한·차감 규칙에서 나온 최종 차이이며 실제 한도의 소진 속도가 아니다.

A08의 남은 요청 7회와 이후 요청 88회는 차감 없는 거절이었다. B가 추가로 확인한 9건 중 7건은 A가 잔량 부족으로 처리 내용을 실행하지 못한 행동이다. 나머지는 A04와 A08이다. A04에서 A는 기다리지 않고 8회 요청했지만 B는 기다린 뒤 2회로 확인했다. A08에서는 A의 후속 시도가 거절됐으므로, 잔량이 있는 상태에서 시간 초과를 재시도한 양쪽 비교가 아니다. 완료 총계는 유효하지만 동일하게 실행된 오류들의 성공률 비교로 읽어서는 안 된다.

B의 완료에는 성공한 읽기 결과 재사용 5건과 진행 중 읽기 공유 1건이 포함된다. 각각 입력 20건 중의 수이며 새 요청 없이 확인된 완료다. B가 실제 멈춘 장면은 영구 오류 A16, 3회 제한에 닿은 A11·A12, 저장 미확인 A13, 그리고 120초 대기를 20가상초 제한 안에 수용할 수 없었던 A17이다. 설정한 모든 상한이 실제 작동했다는 뜻은 아니다.

양쪽을 새 프로세스에서 한 번씩 더 재생했고 각 쌍의 비교 파일 9개 중 9개가 일치했다. 같은 입력의 일관성 검사이지 독립 표본 증가는 아니다. 가상 종료 시간은 A 13.600초(13,600밀리초), B 14.548초(14,548밀리초)여서 B가 더 빠르다는 결과도 아니다.

측정 전 검토 3회와 수정 2회를 거쳤다. 대기를 1밀리초 짧게 계산한 문제, 성공 응답 뒤 거짓 실패를 통과시킨 검사, 중단 기록 누락 등을 고쳤다. 실패 기록을 보존하고 코드·입력·판정 기준을 고정한 뒤 측정했으며, 결과에 맞춰 시나리오를 바꾸거나 재측정하지 않았다. 전체 20행과 수정 이력은 별도로 보관한 실험 기록(영문 기술 문서)에 남겼다.

저장됐지만 앱은 모르는 경우

세 저장 의도를 W1·W2·W3로 구별했다. 첫 의도 W1은 양쪽 모두 요청 2회였다. A는 저장 2건을 만들었다. B는 같은 저장 작업 키로 다시 요청했고 가짜 서버가 기존 저장 1건의 결과를 돌려줬다. 이 재요청도 1단위를 썼다. 내용이 같아도 별개 의도인 W2는 양쪽에서 각각 1건 저장됐다.

저장 작업 키의 보호가 없는 W3에서 B는 1건을 저장했지만 응답을 받지 못해 재전송하지 않았다. 실제 출력 전체는 다음과 같다.

응답을 받지 못해 저장 여부를 확인할 수 없습니다. 자동 재시도를 멈췄습니다. 중단 이유: UNSAFE_WRITE. 저장되었을 수 있으며 자동으로 다시 보내지 않습니다.

저장 사실은 시험 장부에 기록됐지만 앱은 모른다. A의 W3 요청 8회는 모두 잔량 부족으로 차감 없이 거절돼 저장은 0건이었다. 이 장면은 양쪽의 중복 방지 비교가 아니다. 자동 재전송을 멈춰도 사용자가 같은 저장을 다시 제출하면 중복될 가능성은 남는다. 이는 설계상 위험이며 사람의 반복 클릭을 측정한 결과가 아니다. 확인 없이 재제출을 권하거나 시험하지 않은 새로고침 경로로 확인된다고 안내할 수 없다.

총 저장은 양쪽 모두 3건이고, 받은 확인과 연결되지 않은 저장은 각각 1건이다. 그러나 A는 W1의 첫 저장을 확인하지 못한 채 두 번째 저장의 성공을 확인했다. B는 W3의 유일한 저장을 미확인으로 남겼다. ‘완료 확인’은 ‘한 번만 저장’을 뜻하지 않으며 B의 중복 0건도 모든 저장의 확인을 뜻하지 않는다.

A는 행동 20건 중 14건을 시험 장치가 잘랐는데도 앱에 “Trying again…”(다시 시도 중)이 남았다. 이는 의도적으로 만든 비교 조건의 동작이다. B의 최종 문구 20/20은 사전에 정한 문구·근거 규칙과 기록의 일치이지 사람의 이해도 점수가 아니다.

작성자 판단: 앱을 만드는 AI에 물어볼 것

예약 에이전트 운영을 다룬 17번 글은 등록·실행 종료·보고·결과를 믿는 일을 구분했다. 여기서는 요청·효과·확인을 구분한다. 두 실험 모두 로컬 제한이 제공자의 지출 상한을 증명하지는 않는다.

다음 요청을 자신의 앱을 만드는 AI 도구에 붙여 넣고, 장담 대신 확인 근거를 요구할 수 있다. 사용성이나 절감 효과를 검증한 도구는 아니다. 이 점검표의 서버는 실제 앱이 이용하는 서버다.

이 앱의 재시도를 점검해 줘.
1. 앱과 라이브러리에서 각각 어디가 다시 요청하는가?
2. 최초 포함 행동별 횟수·시간, 전체 요청·재시도 예산은?
   그 값을 정한 이유와 실제로 재시도를 멈추는 증거를 보여 줘.
   설정만 한 제한과 실제 작동을 확인한 제한을 나눠 줘.
3. 서버가 기다리라면 지키는가? 제한 안에 못 기다리면 멈추는가?
4. 성공한 읽기 결과만 재사용하며 사용자·내용 버전·유효기간이 맞는가?
   오류와 429 응답을 저장해 재사용하지 않는가?
5. 저장 작업 키는 서버가 지원하는가? 별개 작업은 별개 키인가?
6. 완료·이전/공유 결과·읽기 실패·저장 미확인·미전송을
   구별하고, 중단 이유와 자동 재시도 종료를 알리는가?
   저장 미확인 때 재제출을 권하지 않는가?
   저장을 새로 만들지 않는 확인 경로도 검증 전에는 안내하지 말아 줘.
행동 → 요청 → 효과 → 확인을 기록하고, 미확인은 그대로 적어 줘.

확인하지 않은 것

실제 제공자 한도·소진 속도·요금·청구·사용 기간, 제작 세션 사용량·비용과 전체 노동시간은 확인하지 않았다. 측정의 제공자 호출 0회가 총비용이 없다는 뜻은 아니다. 용량 예측표도 만들지 않았다.

  • 실서비스 통신 신뢰성, 보편적인 재시도 횟수, 기능별 인과효과, AI 코드 결함 빈도, 저장이 반드시 한 번만 된다는 보장은 입증하지 않았다.
  • 여러 사용자의 재시도 분산 효과, 앱과 라이브러리의 중첩 재시도, 장애 때 요청을 차단했다가 시험적으로 재개하는 회로 차단기의 복구는 측정하지 않았다.
  • 사람의 이해·반복 클릭 감소, 새로고침으로 저장을 확인하는 경로는 시험하지 않았다.

이번 측정은 B의 전체 요청·시간·잔량 중단, 재시도 예산 소진, 성공한 읽기 결과의 유효기간 만료, 같은 키에 다른 내용 충돌, 여러 제한이 동시에 걸릴 때의 모든 우선순위를 시험하지 않았다. 이 가짜 서버는 잔량을 먼저 확인한 뒤 저장 작업 키를 조회하지만, 잔량 소진 후 키 재요청으로 저장을 확인하는 상황도 관측하지 않았다. 별도 사전 검사를 이 시나리오의 관측으로 세지 않는다. 입력 순서나 가짜 한도 규칙이 달라지면 결과도 달라질 수 있다.

이 글은 AI를 활용해 자료 조사와 초안 작성을 보조했으며, 작성자가 최종 원고를 검토하고 수정 방향을 결정했습니다.

댓글

“앱이 계속 재시도하면 한도는 얼마나 빨리 줄까?”에 대한 1개 응답

  1. […] English EXPERIMENT NOTES · 39한국어로 읽기 → […]

    좋아요

답글 남기기