내가 걱정을 멈추고 --dangerously-skip-permissions를 사랑하게 된 방법
요약
Claude Code의 `--dangerously-skip-permissions` 플래그를 활용하여 개발 워크플로우의 병목 현상인 '인간의 승인 단계'를 자동화하는 방법을 다룹니다. 단순한 명령 승인을 넘어, 훅(hooks)과 에이전트 기반의 작업 관리로 전환하여 생산성을 극대화하는 실전 경험을 공유합니다.
핵심 포인트
- Claude Code의 권한 건너뛰기 플래그로 작업 지연 시간 제거
- 인간의 승인 게이트를 자동화된 코드 체크(hooks)로 대체
- 에이전트를 서버 관리자로 활용하여 원격 진단 및 수정 자동화
- 명확한 문맥과 수락 기준을 포함한 이슈 기반의 에이전트 워크플로우 구축
그 플래그의 이름은 --dangerously-skip-permissions입니다. 1년 전, 당시 새로 나왔던 Claude Code를 배운 지 몇 주 되었을 때, 저는 모든 셸 명령(shell command)을 승인하는 것에 지쳐 이 기능을 켰습니다. 그것도 컨테이너나 VM(가상 머신)도 없는 제 메인 머신에서 말이죠. 디스크를 통째로 날려버릴 수 있는 명령을 포함하여 모든 명령이 자동으로 승인되었습니다.
하지만 디스크가 날아간 적은 한 번도 없었습니다. 며칠 만에 저의 처리량(throughput)은 눈에 띄게 급증했습니다. 그리고 이는 제가 이름을 붙일 수 있을 정도로 자주 반복하게 된 하나의 패턴을 만들기 시작했습니다: 더 이상 아무것도 잡아내지 못하는 인간의 승인 게이트(human approval gate)를 찾아내어, 그것을 제거하고 자동화된 체크(automated check)로 대체하는 것입니다.
이 글은 그러한 게이트 중 4개에 대한 이야기입니다. 3개는 제거되었고, 하나는 현재 결정 중입니다.
문맥 (Context)
저는 슬로바키아에서 활동하는 1인 AI 컨설턴트이자 풀스택 개발자(full-stack developer)입니다. 저는 Claude Code를 주요 구현 엔진으로 사용하여 제 개인 제품과 클라이언트 프로젝트 등 여러 리포지토리(repos)를 병렬로 운영하고 있습니다. 아래의 모든 내용은 사고 실험이 아닌 저의 실제 작업 환경입니다.
게이트 1: 명령당 승인 (per-command approval)
모든 Bash 명령을 승인하는 것은 통제권을 갖고 있다는 느낌을 줍니다. 하지만 실제로는 대부분 지연 시간(latency)일 뿐입니다. 며칠 지나고 나면 명령의 형태를 보고 패턴 매칭(pattern-matching)을 하며 '예'를 누르게 됩니다.
그래서 저는 YOLO 결정을 내리고 몇 주 동안 --dangerously-skip-permissions를 실행했습니다. 작업 순서에 대해 솔직하게 말씀드리자면, 신뢰는 도약을 하기 '전'이 아니라 도약을 한 '후'에 생겨났습니다. 사후적으로 이를 정당화해 준 것은 단순한 관찰이었습니다. 수 주 동안 명령을 자동 승인하는 동안, 제거된 게이트가 저를 구해냈을 횟수는 0번이었습니다.
그 후 저는 지치지 않는 무언가인 훅(hooks)으로 저의 주의력을 대체했습니다. 실행 전 훅(pre-execution hook)이 파괴적인 명령(재귀적 삭제 및 유사 명령들)을 패턴 매칭하여 실행 전에 차단합니다. 게이트가 사라진 것이 아니라, 인간에서 코드로 격하된 것입니다.
게이트 2: 나만의 서버
그 경험을 바탕으로 저는 Claude를 제 VPS에 설치하고 서버 관리자로 만들었습니다. 오늘날 저는 로컬 세션에서 SSH를 통해 동일한 작업을 수행합니다. 에이전트(agent)가 접속하여 진단하고 수정하면, 저는 나중에 보고서를 읽습니다.
동일한 패턴, 더 넓은 폭발 반경(blast radius), 그리고 동일한 결과: 서버의 모든 명령어를 일일이 감시하며 머무르는 것은 그럴 만한 가치가 없었습니다.
Gate 3: 구현 그 자체
이번 여름의 파이프라인은 다음과 같습니다. 저는 과제(assignment)를 작성합니다. 더 큰 작업의 경우 비전 문서(vision document)를 작성합니다. 에이전트(agent)는 불분명한 부분에 대해 저와 인터뷰를 진행한 후, GitHub 이슈(issue)를 작성하거나 명시적인 의존성 그래프(dependency graph)가 포함된 일련의 이슈들을 작성합니다. 각 이슈는 그 자체로 완결성을 갖도록 작성됩니다. 즉, 문맥(context)과 '이유(why)'를 먼저 제시하고, 기각된 대안들과 함께 결정된 사항들을 명시하며, 범위(scope)와 범위 외 사항(out-of-scope), 그리고 검증 가능한 수락 기준(acceptance criteria)을 포함합니다. 이 이슈는 원래의 대화 내용에 대해 아무런 문맥이 없는 초심자도 이해할 수 있어야 합니다. 왜냐하면 작업 에이전트(worker agent)가 바로 그런 존재가 될 것이기 때문입니다.
그다음 저는 /orchestrate-task queue 57 55(커스텀 슬래시 명령어)를 입력하고 자리를 떠납니다. 각 이슈별로, 자신의 git 워크트리(worktree) 내에서 새로운 문맥을 가진 워커(worker)가 다음을 수행합니다:
- 이슈를 구현합니다.
- 테스트를 작성하며, 파이프라인은 이를 변이 검증(mutation-validates) 합니다. 즉, 구현 코드를 변형(mutate)했을 때 테스트 스위트가 실패(red)하도록 요구합니다. 자신이 커버한다고 주장하는 코드가 변형되었음에도 살아남는 테스트는 다시 작성하거나 폐기합니다.
- 셀프 리뷰(self-review)를 수행한 후, 별도의 새로운 문맥에서 적대적 비평가 리뷰(hostile critic review)를 수행합니다.
- **교차 벤더 리뷰(cross-vendor review)**를 수행합니다. 구현자의 사각지대를 공유하지 않는다는 점을 정확히 활용하기 위해, diff(차이점)를 다른 벤더의 모델(
codex exec review)로 보냅니다. - **블라인드 할당 리뷰(blind assignment review)**를 수행합니다. 새로운 리뷰어는 구현자의 설명 없이 오직 원래의 이슈 텍스트와 최종 diff만 전달받으며, 단 하나의 질문에 답합니다:
교차 벤더 (cross-vendor) 단계는 데이터로 그 가치를 증명했습니다. 한 프로덕션 리포지토리(production repo)에서 교차 벤더 패스는 동일 모델 리뷰 단계가 놓쳤던 7개의 탐지 결과(findings)를 찾아냈으며, 여기에는 2개의 동시성 데이터 손실(concurrency data-loss) 버그가 포함되어 있었습니다. 이는 벤더의 주장이 아닌, 제가 작업하며 얻은 설명입니다: 구현자와 동일한 베이스 모델(base model)에서 실행되는 리뷰어들은 동일한 추론의 흐름을 따라가는 경향이 있습니다. 반면 다른 모델 패밀리(model family)는 다르게 이견을 제시합니다. 그 이후로 교차 벤더 리뷰는 보안이나 데이터 무결성(data integrity)에 영향을 미치는 모든 작업에 대해 상시 단계로 유지되고 있습니다.
나를 괴롭혔던 두 번의 사례
게이트(gate)를 제거하는 것은 공짜가 아니며, 저에게는 그 증거인 흉터가 있습니다.
한 번은 git 워크트리(worktree)에서 실행 중이던 워커(worker)가 명시적으로 리포지토리의 메인 체크아웃(main checkout) 디렉토리로 cd 하여 그곳에서 git reset --hard를 실행했습니다. 이는 격리된 복사본이 아닌 메인 리포지토리의 실제 브랜치를 이동시킨 것이었습니다. reflog를 통해 복구했습니다. 이 사건을 통해 도출된 규칙은 현재 모든 워커 브리프(worker brief)에 포함되어 있습니다: 절대 워크트리 밖으로 cd 하지 말 것, 그리고 파괴적인 git 명령을 실행하기 전에 pwd -P를 실행할 것.
또 다른 때는 PR 머지(merge)와 머지 후 정리(post-merge cleanup)를 하나의 명령어로 체이닝(chaining)하도록 허용했습니다. 머지는 실패했지만, 정리는 어쨌든 절반이 실행되어 브랜치를 삭제하고 PR을 닫아버렸습니다. 이번에도 reflog 덕분에 살았습니다. 규칙은 다음과 같습니다: 정리는 새로운 메인 SHA가 실제로 관찰된 후에만 실행되어야 합니다. 검증 게이트(verification gate)를 그것이 보호해야 할 동작과 절대 체이닝하지 마십시오.
두 사건 모두 인간 게이트를 다시 도입하게 만들지는 않았습니다. 대신 각 사건은 향후 모든 실행이 준수해야 할 규칙이 되었습니다. 신뢰는 더 엄격하게 감독함으로써 회복되는 것이 아니라, 실패를 인코딩(encoding)함으로써 회복됩니다.
게이트 4: auto-merge — 현재 내가 고민 중인 단계
오늘날에도 모든 PR은 여전히 저의 확인을 거쳐 종료됩니다. 그리고 솔직한 관찰 결과는 1년 전과 동일합니다: 저의 최종 리뷰에서 발견되는 것들은 파이프라인이 이미 찾아낸 것 외에는 점점 더 없어지고 있습니다. 그것이 바로 신호입니다. 이는 이전 게이트들이 통과했던 것과 동일한 임계값(threshold)입니다.
이러한 제거가 전역적인 전환(global flip)으로 일어나지는 않을 것입니다. 설계는 저장소(repo)별로 이루어집니다. 각 저장소는 자신의 검증(verification)이 실제로 얼마나 신뢰할 수 있는지 분류하는 명시적인 병합 정책(merge policy)을 갖게 됩니다. 실제 테스트 스위트(test suite)인가요? CI인가요? 배포 스모크 체크(deploy smoke checks)인가요? 기본값은 이유를 명시한 상태로 자동 병합(auto-merge)이 OFF로 설정되며, 저장소는 변경 사항의 클래스(class)별로 플래그를 획득하게 되며, 결코 첫날부터 획득할 수는 없습니다. 배포, 비용 지출, 되돌릴 수 없는 모든 것 — 이러한 것들은 인간의 영역으로 남습니다.
왜 굳이 이런 일을 하는가: 모든 PR(Pull Request)을 인간이 읽는 방식은 전체 플릿(fleet)의 규모를 한 명의 인간이 읽을 수 있는 수준으로 제한합니다. 몇 개의 병렬 에이전트(agents)는 그 게이트를 통과할 수 있지만, 수십 개는 불가능합니다.
지표 (The metric)
저는 "AI에 대한 신뢰"가 스스로를 설득해서 얻어지는 감정이라고 생각하지 않습니다. 그것은 자신의 장부(ledger)에서 읽어내는 숫자입니다: 이 게이트가 자동화된 체크(automated checks)가 놓친 무언가를 마지막으로 잡아낸 것이 언제인가? 만약 답이 "몇 달 전"이라면, 그 게이트는 더 이상 통제 수단(control)이 아니라 대기열(queue)일 뿐입니다. 그것을 제거하고, 게이트가 수행하던 체크를 자동화한 뒤, 확보된 주의력(attention)을 그 다음 단계의 게이트에 투자하십시오.
YOLO라는 단어는 처음 한 번만 정확했습니다. 그 이후의 모든 도약은 장부를 읽어가는 과정이었습니다.
에이전트의 출력물에 더 이상 인간의 개입(human in the loop)이 필요하지 않은 시점을 어떻게 결정하시겠습니까?
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기