15장 카나리로 출시하고 사람이 되돌릴 수 있게 한다
첫 주에는 읽기와 초안만 열고 전송은 모두 사람에게 넘긴다. 다음 단계에서도 제한된 도메인과 소수 사용자에게만 한 가지 쓰기 행동을 연다. 기능을 끄는 서버 측 스위치, 대체 수동 절차, 실행 중 세션 폐기 방법을 배포 전에 시험한다.
카나리: 내부 사용자 5명, 공개 자료 읽기와 문의 초안만
중단: 승인 없는 전송 1건, 잘못된 대상 1건, 비밀 로그 1건
되돌림: 쓰기 도구 비활성화, 진행 작업 중단, 수동 폼 링크 제공
재개: 원인·수정·홀드아웃 회귀·소유자 승인
생산성을 먼저 약속하지 않는다. 절약 시간보다 근거 누락, 승인 피로, 수동 재작업, 사고를 함께 센다. 사용자에게 에이전트가 한 일과 하지 않은 일을 보여 주고, 실행 기록을 내려받거나 삭제할 경로를 제공한다.
실습 15 출시 리허설
읽기 기능은 유지하면서 send와 payment를 끄는 상황을 연습한다. 진행 중이던 두 작업이 안전하게 중단되고 초안은 보존되는지 확인한다. 재개 담당자와 승인 조건을 문서에 적는다.
공식 자료와 최신성 메모
- OpenAI use cases — 컴퓨터 사용과 장기 작업 사례, 2026-08-05 확인
- OpenAI Computer-Using Agent — 브라우저 행동의 위험과 안전 고려
- Google Chrome agentic security — 행동 전 사용자 의도 정렬과 프롬프트 인젝션 방어
- Microsoft Edge for Business agentic browsing — 관리형 통제와 제한적 프리뷰
제품 메뉴와 가용성은 바뀐다. 이 책의 정본은 특정 버튼 위치가 아니라 관찰·제안·승인·행동·검증 계약이다.
실습 워크북: 2호점 의사결정실 15개 미션
아래 미션은 같은 FIXTURE-2026-07을 사용한다. 각 미션마다 입력, 기대, 실제, 증거, 다음 행동을 기록한다. 녹색 화면만 캡처하지 말고 실패해야 할 입력이 실제로 멈추는지 본다.
- 범위 고정: 후보 세 곳, 공개 출처, 금지 행동, 중단 조건을 한 페이지에 쓴다.
- 작업 봉투: 목표·산출물·허용 도메인·단계 제한·만료를 JSON으로 만든다.
- 관찰 지도: DOM·접근성 이름·화면 텍스트 중 각 대상에 쓸 신호를 정한다.
- 정책 표: 읽기, 탐색, 캡처, 전송, 결제, 삭제, 미등록 행동을 판정한다.
- 근거 카드: 후보별 가격·거리·제약의 원문과 확인 시각을 연결한다.
- 인젝션 불변성: 악성 문구가 있어도 허용 도메인과 승인 규칙이 바뀌지 않음을 증명한다.
- 복구 지점: 수집 7/9에서 끊긴 실행을 누락 두 건부터 재개한다.
- 의사결정 표: 단위와 날짜를 맞추고
unknown을 거짓 0점으로 바꾸지 않는다. - 승인 영수증: 수신자·본문 해시·만료를 한 번의 전송에 묶는다.
- 격리 다운로드: 파일 형식·크기·해시를 검사하고 자동 열기를 막는다.
- 초안 분리: 문의 메일 두 통을 만들지만 외부 계정에는 보내지 않는다.
- 최소 로그: 비밀 없이 모호한 대상의 중단 이유를 재현한다.
- 네거티브 세트: 인젝션·승인 만료·가격 모순·응답 유실을 주입한다.
- 카나리: 읽기와 초안만 5명에게 열고 보호 지표를 관찰한다.
- 되돌림: 쓰기 도구를 끄고 수동 절차로 전환한 증거를 남긴다.
완주 판정표
| 항목 | 0점 | 1점 | 2점 |
|---|---|---|---|
| 범위 | 막연한 목표 | 산출물만 있음 | 허용·금지·중단까지 명시 |
| 근거 | URL 없음 | URL만 있음 | 확인일·짧은 근거·모순 기록 |
| 행동 안전 | 모델이 결정 | 승인 문구만 있음 | 코드 정책·일회 승인·검증 |
| 복구 | 처음부터 재실행 | 단계 저장 | 멱등성·상태 조회·재개 증거 |
| 개인정보 | 화면 전체 저장 | 일부 마스킹 | 최소 사건 로그·보존·삭제 |
| 운영 | 한 번에 공개 | 제한 공개 | 카나리·중단·되돌림 리허설 |
총점 10점 이상이고 행동 안전과 운영이 각각 2점이어야 출간 실습을 완주한 것으로 본다. 실제 계정·결제·대량 메시지는 이 책의 완료 조건이 아니다.
현장 트러블슈팅: 증상에서 멈춤 지점까지
문제가 생기면 프롬프트부터 바꾸지 않는다. 관찰 → 정책 → 승인 → 실행 → 검증 가운데 어느 층에서 기대와 달라졌는지 찾는다. 아래 처방은 결과를 억지로 성공시키는 법이 아니라 안전하게 실패시키고 재현하는 법이다.
1 화면이 비거나 버튼이 눌리지 않는다
먼저 HTTP 주소로 열었는지, 현재 경로에 package.json과 lab이 있는지 확인한다. 개발자 도구 콘솔에서 파일 404와 모듈 오류를 본다. 버튼 셀렉터를 곧바로 좌표 클릭으로 바꾸지 않는다. 화면의 접근성 이름과 역할이 바뀌었는지 관찰 스냅샷을 새로 남긴다.
pwd
npm run qa
npm start
기대하는 fixture 버전이 화면과 다르면 브라우저 캐시보다 압축 파일과 실행 폴더가 섞였는지 확인한다.
2 같은 이름의 버튼이 둘이다
첫 번째 요소를 고르는 것은 복구가 아니다. 주변 제목, 폼 이름, 대상 ID 같은 문맥을 추가해 한 개로 좁힌다. 여전히 두 개면 ambiguous-target으로 중단하고 사용자에게 두 후보를 보여 준다. 네거티브 테스트는 두 버튼의 DOM 순서를 바꿔도 같은 중단 결과가 나와야 한다.
3 로그인이나 CAPTCHA가 나타났다
로그인 페이지를 원래 공개 페이지로 착각하지 않았는지 현재 origin을 확인한다. 자격을 모델에게 입력하거나 CAPTCHA를 우회하지 않는다. 작업 봉투의 stopWhen에 따라 중단하고 사람이 직접 로그인한 별도 승인 세션이나 공식 API가 있는지 검토한다. 약관상 자동화가 금지됐으면 수동 절차를 남긴다.
4 다운로드한 파일이 자동으로 열렸다
브라우저 자동 열기를 끄고 다운로드 폴더를 격리한다. 이미 열린 파일은 실행됐다고 가정하고 세션과 호스트 로그를 확인한다. 파일 형식, 실제 MIME, 확장자, 해시가 허용 목록에 맞는지 본다. 다음 실행은 빈 프로필에서 fixture 파일로 재현한다.
5 승인 화면과 실행 대상이 다르다
표시용 문자열과 실제 실행 인자를 각각 정규화해 비교한다. 이메일 표시명, 대소문자, 유니코드 도메인, cc와 bcc, 리디렉션 뒤 URL을 포함한다. 하나라도 바뀌면 기존 영수증을 폐기한다. “내용은 거의 같다”는 판단으로 재사용하지 않는다.
6 전송 직후 네트워크가 끊겼다
실패 응답이 없다는 사실은 미처리를 뜻하지 않는다. 멱등 키나 발신함·예약 조회 API로 첫 요청의 상태를 확인한다. 확인할 방법이 없으면 자동 재전송하지 않고 outcome-unknown으로 사람에게 넘긴다. 로그에는 요청 ID, 전송 시각, 마지막 관찰 상태를 남긴다.
7 승인 알림이 너무 많다
승인을 없애지 말고 작업 범위를 다시 설계한다. 같은 대상의 읽기와 초안은 묶을 수 있지만 수신자·금액이 다른 쓰기는 한 번에 승인하지 않는다. 중복 요청을 합치고 저위험 행동은 명시적 정책으로 자동 허용한다. 승인 거절률과 만료율을 관찰해 사용자가 내용을 이해하지 못하는지 확인한다.
8 인젝션 탐지는 통과했는데 외부 문구가 수상하다
탐지 결과를 실행 권한으로 사용하지 않는다. 해당 문구를 근거 카드에 untrusted로 저장하고, 허용 origin·도구 스키마·승인 정책이 그대로인지 검사한다. 공격 표현을 탐지기에 추가하는 것과 별도로 고위험 도구가 독립 정책에서 막히는 회귀 테스트를 만든다.
9 보고서 숫자와 원자료가 다르다
문장 생성 단계를 멈추고 비교표의 원자료 해시와 단위를 확인한다. 퍼센트와 원수, 월값과 일값, 부가세 포함 여부가 섞였는지 본다. 표를 정본으로 잠근 뒤 보고서의 모든 숫자를 구조적으로 대조한다. 모델에게 “다시 잘 써줘”라고만 하지 않는다.
10 실행이 갈수록 느려진다
페이지 로딩, 관찰, 모델 판단, 정책, 도구 실행 시간을 분리한다. 동일 화면을 반복 캡처하거나 전체 DOM을 매 단계 보내는지 확인한다. 속도를 위해 재관찰과 검증을 제거하지 않는다. 단계 제한과 제한 시간을 두고, 오래 걸리는 공개 자료 수집은 체크포인트 뒤 재개한다.
11 로그에 개인정보가 보인다
해당 로그 접근을 제한하고 보존 정책에 따라 삭제·교체한다. 비밀이면 이미 노출된 것으로 보고 자격을 회전한다. 캡처 범위와 구조화 필드를 줄이고 마스킹 후 값이 아닌 유형만 기록한다. 과거 백업과 분석 인덱스에도 같은 값이 복제됐는지 확인한다.
12 되돌린 뒤에도 쓰기 행동이 실행된다
화면 버튼만 숨긴 것은 되돌림이 아니다. 서버의 도구 권한과 자격을 폐기하고 진행 큐를 중단한다. 워커가 이전 설정을 캐시했는지 확인하고 모든 세션에서 정책 버전을 기록한다. 수동 대체 경로가 작동하는지 본 뒤에만 장애 종료를 선언한다.
출간 전 독자 완주 점검
새 폴더에서 설치 명령을 실행하고, 네트워크 없이 기본 테스트가 통과해야 한다. macOS·Windows 중 최소 두 환경에서 포트, 경로, 브라우저 권한 설명을 확인한다. 코드 블록을 그대로 복사했을 때 실제 계정이나 결제로 연결되지 않아야 하며, 예제 주소와 금액은 fixture임이 보여야 한다.
각 장의 마지막에는 독자가 만든 파일이 남아야 한다. 범위 문서, 작업 봉투, 근거 카드, 정책 표, 승인 영수증, 실행 로그, 평가표, 카나리 기록이 그것이다. 책을 덮었을 때 독자가 “어떤 도구를 클릭했는가”보다 “왜 이 행동이 허용되거나 멈췄는가”를 설명할 수 있으면 목표에 도달했다.
부록 A 처음부터 끝까지 따라 하는 실습 지도
실습을 시작할 때 터미널의 현재 폴더를 먼저 확인한다. package.json, lab, fixtures가 함께 보여야 한다. npm run qa의 네 테스트가 모두 통과한 다음 npm start를 실행한다. 서버가 출력한 주소를 브라우저에 직접 입력한다. 화면 상단의 fixture 버전이 다르면 책의 결과와 비교하지 말고 압축 파일 버전부터 맞춘다.
첫 번째 저장물은 notes/01-scope.md다. 목적, 허용 출처, 금지 행동, 승인 행동, 중단 조건을 쓴다. 두 번째는 notes/02-evidence.json이다. 각 항목은 claim, url, observedAt, quote, status를 가진다. 세 번째는 notes/03-decision.md, 네 번째는 notes/04-approval.json, 마지막은 notes/05-retrospective.md다. 파일 이름을 고정하면 문제를 재현할 때 헤매지 않는다.
각 실습에서 초록색 결과만 찍고 넘어가지 않는다. 입력, 기대, 실제, 차이, 다음 행동 다섯 칸을 채운다. approve는 실행 성공이 아니라 승인 대기다. deny는 시스템 고장이 아니라 정책이 작동했다는 뜻이다. allow도 실제 화면이 바뀌었는지 검증하기 전에는 완료가 아니다.
실패 처방전
ERR_MODULE_NOT_FOUND: 프로젝트 루트에서 실행했는지 확인한다.- 빈 화면:
file://대신npm start가 출력한 HTTP 주소를 연다. - 포트 사용 중: macOS/Linux는
PORT=4174 npm start, PowerShell은$env:PORT=4174; npm start를 쓴다. - 결과가 책과 다름: 브라우저 캐시보다 fixture 버전과
npm run qa결과를 먼저 확인한다. - 클릭 대상이 둘: 임의로 하나를 고르지 말고
ambiguous-target으로 멈춘다.
부록 B 운영자가 쓰는 체크리스트
실행 전에는 요청자가 누구인지, 목표가 한 문장인지, 입력의 출처가 허용됐는지, 외부 행동이 목록화됐는지 확인한다. 실행 중에는 단계 제한, 시간 제한, 같은 오류의 반복 횟수, 다운로드 파일 형식을 감시한다. 실행 후에는 결과 해시, 승인 영수증, 미완료 단계, 삭제 예정일을 기록한다.
다음 네 질문 중 하나라도 ‘아니오’면 사람에게 넘긴다. “현재 화면이 예상한 도메인인가?”, “행동 대상과 승인 대상이 같은가?”, “금액·수신자·첨부가 승인 이후 바뀌지 않았는가?”, “실행 결과를 독립적으로 확인했는가?” 사람에게 넘기는 것은 실패가 아니라 정상 경로다.
부록 C 독자 스스로 만드는 변형 프로젝트
상권 조사 대신 채용 후보 리서치, 행사 장소 비교, 공공 지원 사업 탐색으로 바꿀 수 있다. 다만 개인정보 자동 수집, 대량 메시지 전송, 티켓·상품 선점은 선택하지 않는다. 좋은 변형은 공개 근거가 있고, 결과를 표로 비교할 수 있으며, 최종 외부 행동을 사람이 승인한다.
변형 프로젝트의 합격 조건은 기능 세 개가 아니라 실패 다섯 개다. 로그인 요구, CAPTCHA, 출처 모순, 네트워크 단절, 승인 만료를 넣었을 때 안전하게 멈춰야 한다. 성공 화면보다 멈춘 이유가 잘 기록된 화면이 더 좋은 졸업 작품이다.