
AI 에이전트를 밤새 작동시킬 때, 사고를 방지하기 위해 설정한 경계선
요약
AI 에이전트를 자율적으로 실행할 때 발생할 수 있는 운영 설계상의 위험과 사고 사례를 다룹니다. 에이전트가 외부로 데이터를 전송하거나 운영 환경을 건드리지 않도록 명확한 금지 사항과 경계선을 설정하는 운용 설계의 중요성을 강조합니다.
핵심 포인트
- 에이전트 운용 시 프롬프트 개선보다 경계선 설정이 더 중요함
- 운영 환경과 검증 환경의 포트 및 데이터 분리 필수
- git add -A 사용 시 인증 정보 유출 위험 주의
- 외부 전송(push, 게시 등)을 금지하는 명확한 가이드라인 필요
- 판단이 모호할 때의 기본 동작(Default Behavior)을 정의해야 함
AI 에이전트를 자는 동안 실행하게 되면서, 가장 많은 시간을 할애한 것은 프롬프트의 개선이 아니라, 경계선을 긋는 일이었다.
무엇을 맡기고, 무엇을 맡기지 않을 것인가. 어디서 멈추게 할 것인가. 멈춘 것을 어떻게 알 것인가. 이 세 가지가 결정되어 있지 않으면, 아침에 일어났을 때 '대량의 성과물' 혹은 '대량의 뒷수습' 중 하나를 마주하게 된다. 운이 좋으면 전자, 나쁘면 후자다.
실제로 발생했던 사고와 그로부터 그어낸 선에 대해 쓰고자 한다. 기술적인 연계 절차에 대한 이야기가 아니라, **운용 설계 (Operational Design)**에 관한 이야기다.
전제: 왜 밤에 실행하는가
이유는 두 가지가 있다.
하나는 이용 한도 (Quota) 소진이다. 시간당 상한이 있는 계약이라면, 자는 시간 동안 한도가 통째로 남는다. 작업이 쌓여 있는데 한도만 버리는 것은 단순하게 봐도 아까운 일이다.
또 다른 하나는 **병렬성 (Parallelism)**이다. 한쪽에는 조사를 시키고, 다른 한쪽에는 구현을 시키는 형태를 취할 수 있다. 인간이 깨어 있을 때는 아무래도 대화에 끌려가게 되어 순차적이게 된다.
단, 두 가지 이유 모두 '사고를 일으키지 않는다'가 전제다. 아침 뒷수습에 1시간이 걸린다면, 밤의 3시간은 수지타산이 맞지 않는다.
실제로 일어난 사고 3건
① 가동 중인 서버를 다운시켰다
자작 도구의 신버전을 검증하게 하고 있었더니, 그 도구가 기본 포트(Default Port)로 기동했다. 내가 매일 사용하고 있는 운영(Production) 인스턴스와 동일한 포트였다.
에이전트는 복구한 뒤 솔직하게 보고해 왔다. 데이터 피해는 없었다. 다만 보고에는 이렇게 적혀 있었다.
기동 시점에 운영 프로세스는 이미 종료되어 있었습니다.
언제 종료되었는지, 제 조작이 원인인지는 특정할 수 없습니다.
이 부분이 중요하다. 원인을 특정할 수 없는 사고가 발생할 수 있다는 것이다. 검증은 운영과 별도의 포트 및 별도의 데이터로 진행해야 한다는 당연한 이야기를 에이전트에게 명시하지 않은 나의 설계 미스였다.
② 인증 정보가 포함된 디렉터리를 커밋할 뻔했다
git add -A를 사용한 결과, CDN 관리용 디렉터리(계정 ID가 포함되어 있음)가 스테이징(Staging)에 들어갔다. push 하기 전에 알아차리고 제거했으며, .gitignore에 추가했다고 보고가 왔다.
이것은 알아차렸기 때문에 보고된 케이스다. 알아차리지 못했다면 보고조차 되지 않았을 것이다. 같은 일이 몇 번이나 일어났는지는 알 수 없다.
③ 백업 폴더를 공개 리포지터리에 push 했다
이것은 실제로 push까지 이루어졌다. 추적을 해제하고 다시 push 했지만, 이력(History)에는 남는다. 내용을 확인하니 HTML 백업뿐이라 실질적인 피해는 없었다. 운이 좋았을 뿐이다.
원인은 ②와 같은 git add -A였다. 에이전트 스스로가 "앞으로는 git status를 반드시 읽겠다"라고 대책을 작성했다.
그어낸 경계선
사고들을 나열하며 깨달은 것은, **위험한 것은 '만드는 것'이 아니라 '내보내는 것'**이라는 사실이었다. 코드를 쓰게 해도 망가지는 것은 로컬뿐이지만, push·게시·전송은 되돌릴 수 없다.
그래서 야간에 전달하는 지시에는 매번 이것을 쓰도록 했다.
## 금지 사항 (오늘 밤의 안전 경계)
- ❌ push / 외부 공개 / SNS 게시 / DM 전송은 일절 하지 말 것
- ❌ 운영 가동 환경에는 건드리지 말 것 (검증은 별도 포트·별도 데이터로)
...
마지막 한 줄이 효과가 있었다. 판단이 망설여질 때의 기본 동작(Default Behavior)을 정해두면, 에이전트는 무리하게 앞으로 나아가려 하지 않는다.
그리고 성과물은 "복사 붙여넣기 한 번으로 낼 수 있는 상태"에서 멈춘다. 게시글이라면 문안을 작성하는 단계까지, 릴리스라면 빌드(Build)까지. 마지막 버튼만 인간이 누른다. 이렇게 하면 아침의 나는 5분 만에 판단할 수 있고, 밤의 에이전트는 멈추지 않고 작업을 이어갈 수 있다.
"멈췄다"는 것이 가장 가치 있는 보고였다
경계선을 긋는 목적은 에이전트를 구속하는 것이 아니다. 멈춰야 할 곳에서 멈추게 하는 것이다.
실례가 있다. SNS 프로필 수정을 부탁했을 때, 다음과 같은 답변이 돌아왔다.
현황을 확인한 결과, 지시에 있었던 "수정해야 할 기재 사항"이
애초에 존재하지 않았습니다.
이 계정은 영업용으로서 완결되어 있으며, 지시대로 고치면 영업용 간판을 덮어쓰게 됩니다.
이는 사실의 정정이 아니라 포지셔닝의 변경이므로, 제 판단으로 결정해서는 안 된다고 생각했습니다. 판단을 부탁드립니다.
나의 지시가 잘못되었다. 현황을 보지 않은 채 "이렇게 고쳐줘"라고 쓴 탓에, 하마터면 영업용 정보를 지워버릴 뻔했다.
지시대로 움직이지 않는 것이 옳은 상황이 있다. 이를 위해 필요한 것은 세세한 금지 사항보다 "이것은 내가 결정해도 되는 일인가?"를 다시 묻게 할 여지였다. 반대로 말하면, 모든 것을 세세하게 지시하면 이 여지가 사라진다.
완료 감지(Completion Detection)를 장치하지 않으면, 사령탑이 멈춘다
이것은 내가 지적을 받고 나서야 깨달은 점이다.
여러 에이전트(Agent)를 실행할 때, 한쪽을 사령탑으로 삼아 업무를 할당하는 방식을 사용했다. 그런데 다음 날 아침이 되어 인간과 대화를 시작하면, 사령탑이 실행 측의 감시를 중단해 버린다. 상대의 작업이 끝났음에도 다음 지시가 전달되지 않는다. 인간이 "끝났어"라고 말할 때까지 양쪽 모두 멈춰 있는 것이다.
지적은 다음과 같았다.
왜 일일이 멈춰 있어? 끝난 것을 감지해서 다음 것을 던져야 하잖아.
맞는 말이었다. 지시를 던지면 즉시 완료 대기(Completion Wait) 상태로 들어간다를 기계적으로 수행하는 것만으로 해결되었다.
# 던지기
<send-task> --to worker --text "..."
# 그 자리에서 완료 대기를 백그라운드에 배치
...
"끝나면 알려준다"는 메커니즘을 처음부터 적용해 두지 않으면, 눈치챈 인간이 말을 걸 때까지 모든 것이 멈춘다. 병렬로 실행하는 의미가 없어지는 순간이 바로 여기다.
이용 한도(Quota) 배분은 능력이 아니라 "대체 불가능성"으로 결정한다
한도에는 제한이 있으므로 누구에게 무엇을 시킬지 결정해야 한다. 처음에는 "어려운 일은 똑똑한 쪽에"라고 생각했지만, 실제로 효과가 있었던 것은 다른 기준이었다.
그 에이전트만이 할 수 있는 일에 사용한다.
나의 환경에서는 한쪽만 브라우저를 조작할 수 있었다. 그래서 남은 한도가 적어졌을 때 다음과 같이 나누었다.
| 할당 | |
|---|---|
| 브라우저를 사용할 수 있는 쪽 (남은 한도 얼마 없음) | 브라우저 조작만 수행. 게시·화면 확인·실물 체크 |
| 다른 한쪽 (한도 여유 있음) | 조사·구현·검증·문장·코드 리뷰 |
똑똑함으로 나누면 "어려운 일"의 정의를 두고 갈등이 생기지만, 할 수 있다/없다로 나누면 망설임이 없다. 결과적으로 적은 한도로 마지막까지 버틸 수 있었다.
아울러, 한쪽이 한도 초과로 멈췄을 때를 대비한 인수인계 파일을 미리 두는 것도 중요하다. 내용은 "현재 무엇이 일어나고 있는가", "당신이 움직일 조건", "이어받길 원하는 태스크", "금지 사항" 이 4가지만 있으면 된다. 움직일 가능성이 낮더라도 이를 준비해 두는 비용은 5분이면 충분하다.
요약
밤새 작동시키기 위해 필요했던 것은 똑똑한 프롬프트가 아니라 다음의 5가지였다.
위험한 것은 "만드는 것"이 아니라 "내보내는 것"이다. push·게시·전송을 금지하면 대부분의 사고는 사라진다. 결과물은 "마지막 버튼만 인간이 누르는" 상태에서 멈추게 한다.
망설여질 때의 기본 동작(Default Behavior)을 정해둔다. "수행하지 않고 보고서에 작성한다" 등.
판단할 여지를 남겨둔다. 모든 것을 세세하게 지시하면 판단을 구할 여지까지 사라진다.
지시를 던지면 즉시 완료 대기를 건다. 이를 잊으면 멈추는 쪽은 사령탑이다.
그리고 사고가 발생했을 때 정직하게 보고해 오는가가 가장 중요하다. "원인은 특정하지 못했습니다"라고 적어 오는 상대는 신뢰할 수 있다. 깔끔한 보고만 올라오는 쪽을 나는 의심하기 시작했다.
Discussion

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기