재시작 뒤에도 기다리는 승인: Chat SDK의 승인자 제한과 타임아웃을 먼저 정하기
봇이 배포 승인을 기다리는 동안 서버를 재시작해야 한다면 무엇부터 확인해야 할까. 대기가 사라지지 않는 것도 중요하지만, 채팅방에 들어온 누구나 배포를 승인할 수 있다면 더 큰 문제가 남는다. 운영자가 먼저 정할 것은 “얼마나 오래 기다릴 수 있나”만이 아니다. “누가 결정할 수 있나”, “언제 기다림을 끝내나”, “승인 뒤 무엇을 별도로 확인하나”를 함께 정해야 한다.
Chat SDK의 requestApproval은 이 중 사람의 결정을 기다리는 절차를 다룬다. 공식 문서는 배포·재시작 뒤에도 대기가 유지된다고 설명한다. 반면 승인자 제한과 대기 종료 조건에는 개발자가 명시해야 할 중요한 기본값이 있다. 이 글의 핵심 판단은 다음과 같다. 승인을 기다릴 수 있다는 사실과 그 사람이 승인할 권한이 있다는 사실, 실제 배포가 성공했다는 사실은 서로 다르다.
자료의 시간을 먼저 구분한다. Vercel 발표의 표시 날짜는 2026년 8월 6일이고, 보존한 승인 문서의 갱신일은 10월 17일이다. 10월 22일 수집한 자료를 바탕으로 10월 23일 공개를 계획한 해설이지, 그날 새 기능이 출시됐다는 속보가 아니다. AI를 활용해 자료 정리와 원고·도식 제작을 보조했으며, 아래 내용은 제품 실행 후기가 아닌 공식 본문 기반 분석이다.
1. Durable이 유지하는 것은 한 건의 결정 대기다
chat/workflow의 requestApproval은 Approve와 Deny 버튼이 있는 카드를 게시하고, Workflow SDK 워크플로를 사람의 결정까지 중단한다. 공식 설명상 초 단위부터 며칠까지 기다릴 수 있고 배포와 재시작을 견딘다. 이 승인 대기를 위해 별도의 승인 테이블, onAction 핸들러, 폴링 루프를 직접 만들 필요가 없다는 것이 래퍼의 설명이다. 이는 서비스 전체에 데이터 저장이나 운영 기록이 불필요하다는 뜻은 아니다. 공식 발표
공식 문서의 지속 대기 계약을 도식화했다. 실제 재시작 시험이나 외부 배포 성공의 증거가 아니다. 출처: chat-sdk.dev/docs/approvals.md.
여기서 durable approval을 “한 번 허용한 사람은 앞으로 계속 신뢰한다”로 읽으면 안 된다. 지속되는 것은 지금 요청한 결정의 대기다. 특정 사람에게 이후 모든 배포를 허용하는 영구 권한이나, 외부 배포 API가 정확히 한 번만 호출된다는 보장은 이 자료에 없다. 승인 후 실제 작업은 별도 단계로 다뤄야 한다.
예를 들어 늦은 오후에 특정 릴리스의 승인을 요청한 뒤 봇을 재배포하는 상황을 생각할 수 있다. 공식 계약은 그 기다림을 이어 가는 데 의미가 있다. 그러나 기다리는 동안 릴리스가 바뀌었는데도 같은 카드로 승인받아도 되는지까지 자동으로 해결했다고 볼 수는 없다. 대상 변경 처리와 재승인 정책은 아래에서 별도 설계 문제로 구분한다.
2. 서명을 확인해도 승인자는 따로 제한해야 한다
공식 문서의 기본 동작은 단순하다. 카드를 볼 수 있는 사람은 누구나 승인 또는 거부를 결정할 수 있다. 중요한 작업에는 approvers에 허용할 사용자 ID를 넣으라고 명시한다. 목록 밖 사람이 클릭하면 스레드에 안내를 남기고 워크플로는 계속 기다린다. 채팅방에 참여했다는 사실이 곧 배포 승인권이라는 운영 규칙을 원하지 않는다면, 이 목록을 생략해서는 안 된다. Who can approve
인증된 클릭과 허용된 승인자는 다르다. 기본값은 카드 열람자 누구나 결정 가능하며 허용 목록 밖 클릭은 대기를 끝내지 않는다. 출처: chat-sdk.dev/docs/approvals.md.
Chat SDK는 수신 클릭의 플랫폼 서명을 확인하고 버튼의 콜백 URL을 클라이언트에 노출하지 않는다고 설명한다. 결과의 user.id로 클릭한 사람을 식별할 수 있다는 문서상 근거다. 다만 신원 확인과 권한 부여는 다른 질문이다. “정말 이 사람이 클릭했는가”가 참이어도 “이번 배포를 결정할 사람인가”는 approvers와 팀의 정책으로 정해야 한다.
따라서 서명 검증을 승인자 제한 대신 쓰지 않는다. 이 설명은 계정 탈취 방어, 배포 대상 버전의 무결성, 모든 어댑터 구성의 안전성까지 검증했다는 의미도 아니다. 이 글은 실제 플랫폼 이벤트나 잘못 구성한 어댑터를 시험하지 않았다. 공식 문서의 동작 계약과 그 계약으로부터 필요한 운영 판단을 구분한다.
3. 타임아웃은 실패한 승인이 아니라 별도의 결과다
timeout을 생략하면 무기한 기다린다. 문서 예제의 timeout: "24h"는 설정 예시이며 기본값이나 권장 응답 시간은 아니다. 운영자가 기다릴 수 있는 시간은 작업의 영향과 대응 체계에 따라 정해야 한다. 문자열 단위는 ms, s, m, h, d를 받을 수 있다. 숫자도 허용되지만 보존한 옵션 표는 단위 없는 숫자의 시간 단위를 명시하지 않으므로 여기서 임의로 환산하지 않는다. Options
결과는 approved, timedOut, user를 나눠 읽는다. approved는 승인 버튼을 눌렀는지, timedOut은 결정 없이 기한이 지났는지, user는 누가 결정했는지를 나타낸다. 타임아웃에는 user가 없다. 승인되지 않았다는 사실만으로 거부와 만료를 같은 원인으로 기록하면 사람의 판단과 무응답을 구분하기 어렵다.
만료는 승인이나 사람의 거부와 구분한다. timeout 생략은 무기한이며 24h는 문서의 설정 예시다. 출처: chat-sdk.dev/docs/approvals.md.
권한 목록 밖의 클릭은 곧바로 거부 결과가 되는 것이 아니라 계속 기다리는 동작이다. 따라서 알림이 생겼다는 사실과 요청이 해결됐다는 사실도 다르다. 승인·거부가 결정되거나 타임아웃이 지나면 카드는 제자리에서 갱신되고 버튼 대신 결과 줄이 남는다. 공식 문서는 이를 감사 흔적과 오래된 클릭 방지로 설명한다. 카드의 결과가 보인다는 이유만으로 후속 배포도 완료됐다고 기록해서는 안 된다. Result와 Audit trail
4. 도입 전에 채우는 승인 정책 판단표
다음 표는 공식 옵션을 운영 질문으로 재배열한 편집자 제안이다. 별도의 재현 시험이나 SDK가 자동 강제하는 전체 정책 목록이 아니다. 특히 마지막 두 행은 공식 보장과 별도로 구현·검토할 책임을 표시한다.
| 먼저 정할 질문 | 보존 문서에서 확인한 동작 | 팀이 정할 운영 판단 |
|---|---|---|
| 누구의 결정을 받을까 | 기본은 카드 열람자 누구나 결정 가능; approvers로 사용자 ID 제한 |
중요한 작업에는 실제 승인권자의 ID 목록을 명시하고 변경 책임자를 정한다 |
| 언제 기다림을 끝낼까 | timeout 생략 시 무기한; 예제의 24h는 예시 |
작업별 대기 기한과 만료 후 알림·재요청 절차를 정한다 |
| 거부와 무응답을 어떻게 나눌까 | approved, timedOut, user가 분리됨; 만료에는 user 없음 |
거부한 사람의 결정과 기한 초과를 다른 사유로 기록한다 |
| 무엇을 승인받을까 | 예제는 카드 필드와 후속 작업에 opts.version 사용 |
고정된 대상 식별자를 연결하고 대상 변경 시 재승인 여부를 별도 설계한다 |
| 실제 작업의 완료는 무엇으로 확인할까 | 카드에는 결정 또는 만료 결과가 남음 | 배포 서비스의 실제 작업 ID·결과를 별도 확인하고 재시도 중복 방지를 설계한다 |
이 판단표는 공식 문서에 근거한 편집자 분석이며, Chat SDK를 배포하거나 재시작 장애를 재현한 실험 결과가 아니다.
가령 “릴리스 후보를 승인받고 나서 최신 릴리스를 배포한다”는 가상 절차는 대기는 잘 유지해도 검토 대상과 실행 대상이 달라질 수 있다. 사람이 본 식별자와 실제 실행에 넘길 식별자를 연결해 비교하는 것은 이 글의 설계 제안이다. fields에 버전을 표시했다는 사실만으로 SDK가 버전 해시를 검증하거나 변경 시 자동으로 재승인을 요구한다고 주장하지 않는다.
고정된 대상 대조와 외부 결과 확인은 편집자 운영 제안이다. SDK가 자동 재승인이나 외부 중복 방지를 제공한다는 뜻이 아니다. 출처: chat-sdk.dev/docs/approvals.md.
배포 요청을 보낸 뒤 응답을 잃은 상황도 같은 경계에 있다. 승인 카드가 이미 결정됐는지와 외부 서비스에 작업이 만들어졌는지를 나눠 확인해야 한다는 운영상 가상 반례다. 이 글이 실제 장애를 관측했다는 뜻이 아니다. SDK의 승인 대기 기능을 외부 부작용의 정확히 한 번 실행 보장으로 확대하지 않는 것이 목적이다.
5. 시작 설정과 운영 기록을 연결한다
문서는 선택적 workflow 피어 의존성을 설치하고 사용 프레임워크에 Workflow SDK를 구성하라고 안내한다. 시작 시에는 chat.registerSingleton()을 호출해 워크플로 경계 반대편에서 스레드를 복원할 수 있게 해야 한다. Thread 인스턴스가 워크플로 경계를 넘어 직렬화된다는 설명도 함께 제공한다. 함수 한 번을 추가하면 프레임워크 설정 없이 모든 기존 봇이 자동으로 내구성을 얻는다고 이해하면 안 된다. Setup과 Start the workflow
처음 검토할 때는 실제 중대한 배포 대신 영향이 작은 확인용 작업으로 카드 게시, 허용된 승인자의 결정, 목록 밖 클릭, 만료, 결과 카드 갱신을 구분해 점검하는 계획을 세울 수 있다. 이어 재배포 전후 대기 유지와 후속 작업 결과 기록을 검증한다. 이것은 앞으로 수행할 시험 계획이며 이 글에서 이미 실행한 통과 목록이 아니다.
운영 기록도 같은 분리를 따르는 편이 좋다. 카드 게시 기록, 결정한 사람과 승인·거부 결과, 타임아웃 여부, 요청 대상 식별자, 실제 외부 작업 결과를 별개로 남기자는 제안이다. 각 이벤트가 기록되는 장소나 SDK의 추가 로깅 API는 이번 자료만으로 확정하지 않는다. 카드 감사 흔적이 외부 시스템의 성공 기록까지 대신한다고 가정하지 않는 데 의미가 있다.
함께 읽기: 지속 상태와 권한의 다른 경계
- Copilot Dynamic Workflows: 재개는 새 예산도, 권한 승인도 아니다는 저장된 결과와 실행 성공·도구 권한을 나눈다. Chat SDK 사용법은 아니지만, 재개 가능한 상태를 후속 작업의 성공으로 읽지 않는 관점을 비교할 수 있다.
- Copilot 데스크톱 조작: 영구 허용을 지워도 현재 세션 권한은 남는다는 저장 승인과 현재 세션 접근을 구분한다. 여기서 말하는 한 건의 지속적 승인 대기를 영구 허용과 혼동하지 않도록 대비해 읽을 수 있다.
결론: 대기의 지속성과 실행의 정당성을 분리한다
사람의 결정을 오래 기다려야 하고 그 사이 배포·재시작이 일어나는 봇이라면 requestApproval은 검토할 만한 추상화다. 다만 도입의 출발점은 durable이라는 이름이 아니라 승인자 목록과 종료 조건이다. 누가 결정하는지, 기한을 넘겼을 때 무엇을 하는지, 어느 대상을 승인한 것인지, 실제 작업 완료는 어디서 확인하는지가 분리돼야 대기 유지 기능의 역할도 정확해진다.
이번 근거에는 신뢰성·지연·비용 절감의 실측치가 없다. 최소 패키지 버전, 요금제별 자격, 모든 플랫폼의 제공 범위도 확정하지 않는다. 재시작을 견딘다는 공식 설명은 소개하되 직접 검증한 보안·장애 복구 결과로 표현하지 않았다. 본문 그림은 공식 문서를 바탕으로 직접 구성한 개념 도해와 명시된 운영 제안이며, 실제 제품 화면이나 성능 그래프가 아니다.
출처와 검토 범위
- Vercel 공식 발표: Pause workflows for approval with Chat SDK — 표시 날짜 2026년 8월 6일. 지속 대기, 승인자 범위, 클릭 신원 확인, 카드 감사 흔적을 확인했다.
- Chat SDK 공식 Approvals 문서 — 보존본
lastUpdated: 2026-10-17. Setup, Options, Result, Who can approve를 대조했다. 선정 단계에서 확보한 본문을 재사용했으며, 이 글의 판단표와 가상 반례는 문서의 제품 보장과 별개인 편집자 분석이다.




댓글
댓글 쓰기