
Claude Code를 모든 권한으로 실행했다가 사고를 친 이야기와 권한을 5단계로 제한하기까지
요약
Claude Code의 모든 권한을 허용했다가 중요한 디렉터리가 삭제되는 사고를 경험한 후, 권한을 5단계로 세분화하여 관리하는 과정을 다룹니다. 자율성을 무조건 높이는 것보다 적절한 확인 절차를 두는 것이 결과적으로 작업 속도와 안정성을 높인다는 교훈을 전달합니다.
핵심 포인트
- 모든 권한 허용 시 자율성은 높아지나 복구 비용이 급증함
- 확인 프롬프트는 작업 흐름을 끊지만, 사고 복구는 시간을 더 많이 뺏음
- Claude Code의 권한은 권한 모드와 룰 리스트로 구성됨
- 적절한 권한 제한이 결과적으로 더 빠른 개발을 가능하게 함
금요일 밤, 나는 기분 좋게 작업을 진행하고 있었습니다.
그날은 --dangerously-skip-permissions를 붙여서, Claude Code에 모든 권한을 부여하고 있었습니다. 확인 프롬프트가 일절 나오지 않습니다. 리팩터링 (Refactoring) 제안이 그대로 실행되고, 테스트가 돌아가며, 커밋 (Commit)까지 진행됩니다. "이것이 자율 에이전트 (Autonomous Agent)인가"라며 나는 약간 감동하기까지 했습니다.
그런데 다음 날 아침, 리포지토리 (Repository)를 열어보고 피가 식는 것을 느꼈습니다. git log에 본 적 없는 커밋이 5개나 나열되어 있었기 때문입니다. 내용을 추적해 보니, 지웠을 리 없는 검증용 디렉터리가 통째로 사라져 있었습니다. Claude가 "불필요한 임시 파일"이라고 판단하여 rm -rf를 실행했고, 그대로 git commit까지 통과시킨 것입니다.
다행히 별도의 브랜치 (Branch)에 대피시켜 두었기에 복구는 할 수 있었습니다. 하지만 나는 그날 아침 확신했습니다. 문제는 Claude가 아니라, 확인 과정을 전부 스킵한 나의 권한 설계였다는 것을.
사고 경위를 조금 더 구체적으로 적겠습니다. 나는 그날 밤, TypeScript의 모듈 구성을 정리하도록 시키고 있었습니다. 도중에 "검증용으로 만든 샘플들이 어지럽게 널려 있네"라고 내가 혼잣말을 했습니다. Claude는 이를 정리 지시로 받아들여, tmp-verify/ 하위 디렉터리를 정리 대상으로 판단했습니다. 여기까지는 흔히 있는 일입니다. 문제는 그다음이었습니다. bypassPermissions 상태였기에 확인이 뜨지 않았고, rm -rf tmp-verify/가 즉시 실행되었으며, 심지어 그 직후에 "불필요한 파일을 정리"한다는 메시지와 함께 git add -A부터 git commit까지 한 번에 통과되었습니다. 나는 다른 작업에 집중하느라 화면의 흐름을 쫓고 있지 않았습니다.
나중에 돌이켜보니 내가 멈출 수 있는 타이밍은 여러 번 있었습니다. 삭제 전, 커밋 전, 푸시 (Push) 전. 그중 어느 한 곳에서라도 확인이 떴다면 나는 "잠깐, 그건 지우지 마"라고 말할 수 있었을 것입니다. 모든 권한은 그 "잠깐"이라고 말할 틈을 구조적으로 없애버렸습니다.
이 글에서는 모든 권한이라는 대략적인 설정을 버리고, 권한을 5단계로 좁혀나간 과정을 적겠습니다.
역설: 자율도를 높일수록 빠르다, 는 아니었다
모든 권한을 주었을 때 나의 전제는 단순했습니다. 확인 프롬프트가 줄어들수록 대기 시간이 사라지니, 따라서 빠르다는 것이었습니다.
실제로 그날 밤의 체감 속도는 확실히 빨랐습니다. 문제는 다음 날 아침이었습니다. 사고 조사, 복구, 재발 방지 검토에 오전 시간을 다 써버렸습니다. 따져보면 모든 권한으로 벌어들인 시간을, 작업 되돌리기 (Rollback)가 몇 배로 더 크게 빼앗아 간 셈입니다.
여기에 역설이 있습니다. 자율도를 높일수록 빠른 것은 아닙니다. 권한을 좁히는 것이 결과적으로 더 빨랐습니다.
이유는 간단합니다. 확인 프롬프트는 작업을 멈추게 하지만, 작업 되돌리기는 훨씬 더 길게 작업을 멈추게 합니다. 전자는 몇 초, 후자는 몇 시간입니다. 좁힌 권한 설계는 일어나서는 안 될 조작이 일어나지 않게 함으로써, 이 몇 시간을 통째로 아껴주었습니다.
이 감각은 이전에 정리했던 자율성과 품질의 트레이드오프 (Trade-off)의 연장선에 있습니다. 자율도는 단조롭게 작용하는 파라미터가 아니라, 좁히는 것이 더 효과적인 영역이 있다는 이야기입니다.
우선 사양을 정확히 파악하기
감각만으로 이야기하면 재현성이 없으므로, 2026년 시점의 Claude Code 권한 사양을 확인했습니다. 내가 사고를 친 원인도 이곳을 정확히 이해하지 못했던 점에 있습니다.
Claude Code의 권한은 크게 두 가지 축으로 구성됩니다. **권한 모드 (Permission Mode)**와 **룰 리스트 (Rule List)**입니다.
권한 모드(defaultMode)는 settings.json에서 설정할 수 있으며, 유효한 값은 default / acceptEdits / plan / dontAsk / bypassPermissions의 5종류입니다 (Choose a permission mode - Claude Code Docs). 본 기사의 제목에 있는 "5단계"는 이 5가지 모드를 가리킵니다.
plan: 읽기와 조사만 수행. 변경은 일절 하지 않음.default: 모든 도구 실행 시 승인을 요구함.acceptEdits: 파일 편집은 자동 승인, 그 외에는 평소처럼 확인을 요구함.dontAsk: 사전 허가가 없는 것은 확인 없이 자동으로 거부함.bypassPermissions: 모든 확인을 스킵함 (--dangerously-skip-permissions로 진입하는 모드).
또 다른 축은 룰 리스트입니다. settings.json의 permissions에 allow...
/ ask
/ deny
의 3가지 리스트를 작성할 수 있습니다.
{
"permissions": {
"defaultMode": "default",
...
여기서 중요한 것은 평가 순서입니다. 규칙은 deny → ask → allow 순으로 평가되며, 가장 먼저 일치하는 규칙이 적용됩니다 (Configure permissions - Claude Code Docs). deny에 일치하면, allow에 동일한 대상이 있더라도 예외 없이 차단됩니다. 규칙의 구체성(specificity)은 순서에 영향을 주지 않습니다.
제 사고가 발생한 이유는 이것으로 설명이 됩니다. bypassPermissions로 실행하면서, 심지어 deny에 rm -rf를 단 한 줄도 적지 않았습니다. 안전장치가 어디에도 없는 상태였습니다.
참고로 공식 문서에서는 bypassPermissions를 컨테이너나 VM 등의 격리 환경에서만 사용할 것을 권장하고 있습니다. 또한 --dangerously-skip-permissions를 활성화하더라도, 보호 대상 경로에 대한 쓰기는 승인 프롬프트가 나타난다고 명시되어 있습니다 (Choose a permission mode). 즉, 모든 권한을 가졌다고 해도 완전히 무제한은 아니지만, 제가 삭제한 것은 보호 대상에 포함되지 않은 일반 작업 디렉토리였습니다. 그물망 밖에 있었던 셈입니다.
조작 카테고리 × 권한 모드 구배표
사양을 이해한 후, 저는 자신의 작업을 "조작 카테고리"와 "권한 모드"의 매트릭스로 정리했습니다. 어떤 조작을, 어떤 모드에서, 어떻게 다룰 것인가. 이를 한 장의 표로 만든 것이 아래와 같습니다.

이 표의 포인트는 조작 카테고리별로 취급을 달리했다는 점입니다. 읽기는 어떤 모드에서도 기본적으로 허용합니다. 반면 삭제와 외부 통신은 자율도를 아무리 높여도 확인(ask)이나 거부(deny)를 남겨둡니다.
제가 사고를 친 것은 이 표에서 말하는 "삭제"를 모든 모드에서 그대로 통과시켰기 때문입니다. 반대로 말하면, 삭제와 외부 통신만 deny나 ask로 쥐고 있었다면 그날 아침의 비극은 일어나지 않았을 것입니다.
색의 농도는 확인의 강도를 나타냅니다. 색이 짙을수록 인간이 개입하고, 옅을수록 Claude에게 맡깁니다. 의미의 차이는 농담(gradation)이라는 한 축으로만 표현했으며, 조작 카테고리 자체에는 우열의 색을 붙이지 않았습니다.
내가 정착한 설정
최종적으로 제가 채택한 settings.json의 골격은 다음과 같습니다. 모드는 acceptEdits를 상용으로 사용했습니다. 편집은 자동으로 통과시키고, 그 외에는 제어한다는 중간 지점입니다.
{
"permissions": {
"defaultMode": "acceptEdits",
...
의도는 각각 명확합니다.
allow에는 읽기와 상태 확인을 위한 명령어를 두었습니다. git status나 git diff는 몇 번을 실행해도 파괴적이지 않습니다. 테스트 실행도 여기에 포함하여 검증의 왕복을 빠르게 만들었습니다.
ask에는 커밋(commit)과 푸시(push)를 두었습니다. 여기가 제 사고의 핵심 부분입니다. Claude가 멋대로 커밋을 5개나 쌓아버렸던 그날 밤의 재림을 ask가 막아줍니다. 커밋은 한 박자 늦춥니다. 그것만으로도 히스토리가 망가지는 것을 방지할 수 있습니다.
deny에는 파괴적인 조작과 비밀 정보의 읽기를 두었습니다. rm -rf와 git reset --hard는 실수했을 때 복구가 무거운 대표적인 조작입니다. .env나 키 파일의 읽기도 외부 통신과 결합되면 정보 유출로 이어지기 때문에 차단했습니다.
도구(tool) 지정 방식에는 한 가지 주의할 점이 있습니다. Bash와 같이 날것의 도구 이름을 쓰면 해당 도구 자체가 Claude의 컨텍스트에서 사라집니다. 반면 Bash(rm -rf:*)와 같이 스코프(scope)를 지정하면, 도구는 사용할 수 있는 상태로 유지하면서 일치하는 호출만 차단됩니다 (Configure permissions - Claude Code Docs). 제가 원하는 것은 후자입니다. Bash 자체는 사용하게 두되, 위험한 일부만 막고 싶기 때문입니다.
갑자기 전부 제한하지 말고, 단계적으로 이행하기
설정을 다시 작성할 때, 저는 처음부터 완벽한 deny 리스트를 만들려고 했습니다. 이것은 실패였습니다. 무엇을 금지해야 할지 책상 앞에 앉아 전부 찾아낼 수는 없습니다.
그래서 방침을 바꿨습니다. 우선 acceptEdits를 상용으로 사용하고, deny에는 명백히 위험한 몇 줄만 둡니다. rm -rf, git reset --hard...
비밀 파일 읽기. 이 3가지 계통뿐입니다. 나머지는 작업을 진행하면서 Claude가 확인을 요청하는 조작을 관찰하고, 빈도가 높은 것은 allow에, 위험한 것은 ask나 deny로 분류해 나갔습니다.
이러한 육성 방식에는 근거가 있습니다. Claude Code의 규칙은 사용자 전체의 ~/.claude/settings.json, 팀 공유용 .claude/settings.json, 개인 재정의용 .claude/settings.local.json이라는 계층 구조로 읽힙니다 (Configure permissions - Claude Code Docs). 저는 위험 계열의 deny를 팀 공유 설정에 두고, 제 작업 효율을 위한 allow는 settings.local.json에 두었습니다. 팀의 안전장치는 모두가 공유하고, 개인의 최적화는 개인이 갖도록 한 것입니다. 이 분리를 통해 설정을 변경하더라도 타인의 안전을 해치지 않게 되었습니다.
일주일 정도 운용해 보니, ask에 두는 조작은 거의 커밋(commit), 푸시(push), 패키지 추가의 3가지 계통으로 수렴했습니다. 처음부터 의도해서 설계하는 것보다, 실행하면서 범위를 좁혀 나가는 것이 현실에 부합하는 경사(gradient)를 만들어냈습니다.
「허가/확인/거부」의 3층 구조로 생각하기
설정을 다시 작성하며 깨달은 점은, 권한 설계가 「허용할 것인가」 아니면 「금지할 것인가」의 이지선다가 아니라는 것입니다. 그 중간에 「확인(ask)」이라는 제3의 층이 있습니다. 이것이 핵심입니다.
두 가지 선택지로만 생각하면 판단이 항상 극단적이 됩니다. 허용하면 사고가 날지도 모르고, 금지하면 작업이 멈춥니다. 어느 쪽으로 기울어도 손해입니다. 그래서 저는 '전권한'이라는 대충 뭉뚱그린 쪽으로 도망치고 있었던 것입니다.
3층 구조로 생각하면 그레이 존(gray zone)을 ask로 넘길 수 있습니다. 커밋이나 푸시처럼 대부분은 옳지만 가끔 문제가 될 수 있는 조작. 이것을 허가도 거부도 아닌 '확인'에 둡니다. Claude에게 작업은 시키되, 방아쇠만 인간이 당기는 것입니다. 이 설계 덕분에 저의 재작업(rework)은 거의 사라졌습니다.
책의 장을 쓰면서 제가 깊이 체감한 것은 「Yes를 누르기 전의 1초」라는 습관의 가치였습니다. 796개의 패키지를 오염시킨 Shai-Hulud 같은 공급망 공격(supply chain attack)에 대해서도, 마지막 방어선은 바로 이 1초입니다. 전권한은 이 1초를 구조적으로 빼앗아 갑니다. ask는 그 1초를 필요한 곳에만 남겨두는 메커니즘입니다.
여기서 스스로에 대한 경계의 말을 하나 적어둡니다. ask를 너무 늘리면 이번에는 확인 피로(confirmation fatigue)가 발생합니다. 인간은 같은 프롬프트를 반복해서 보면 내용을 읽지 않고 Yes를 누르게 됩니다. 이렇게 되면 3층으로 나눈 의미가 없습니다. 그래서 저는 ask에 두는 조작을 3가지 계통까지로 제한했습니다. 확인은 빈도가 낮기 때문에 오히려 진지하게 읽힙니다. 확인의 가치는 확인의 적은 횟수에서 결정됩니다. 이 얼핏 모순되어 보이는 감각이 권한 설계의 핵심이었습니다.
세션을 끊는 방식도 효과적이었습니다. 태스크가 일단락되면 /clear로 컨텍스트(context)를 리셋합니다. 긴 세션에서 컨텍스트가 비대해지면 Claude가 무엇을 하고 있는지 아무도 파악할 수 없게 되고, 확인 프롬프트도 관성적으로 넘기게 됩니다. 권한 설계와 세션 운용은 별개의 이야기처럼 보이지만, 「인간이 판단력을 유지할 수 있는 상태를 지킨다」는 하나의 지점으로 연결되어 있었습니다.
hooks와의 차이점, 확장 기능 축소와의 맥락적 연결
여기서 오해를 피하고 싶은 점은, 본 기사가 안전장치를 구현하는 방법에 대한 이야기가 아니라는 점입니다. Claude Code에는 Hooks라는 별도의 메커니즘이 있습니다. 그것은 도구 실행 전후에 스크립트를 삽입하여 능동적으로 검사나 기록을 실행하는 안전장치입니다.
본 기사에서 다루는 권한 모드 설계는 그보다 더 앞선 단계의 이야기입니다. 애초에 어떤 조작에 어떤 모드를 적용할 것인가 하는 정적인 층의 설계입니다. hooks가 동적인 검문소라면, 권한 규칙은 입구에 세워둔 표지판에 가깝습니다. 둘 다 있으면 강력하지만 역할이 다릅니다.
그리고 이번의 범위 축소는 제가 계속 유지해 온 방침의 일부이기도 합니다. 확장 기능(extensions)을 47개에서 5개로 줄였을 때와 발상이 같습니다. 수를 늘린다고 좋아지는 것이 아니라, 좁히는 것이 더 효과적입니다. 권한도 마찬가지였습니다. 전부 허용하는 최대화 전략을 버리고, 5가지 모드와 3층 리스트로 의미 있는 경사를 만드는 것. 이것이 결과적으로 가장 빠른 구성이었습니다.
좁히는 것이 결국 더 빠르다
그 금요일 밤 이후로, 저의 작업 속도는 오히려 올라갔습니다.
확인 프롬프트는 뜹니다. 커밋 전에 한 박자 멈춥니다. 그럼에도 불구하고 다음 날 아침의 조사와 복구라는 거대한 재작업이 사라진 만큼, 토탈(total)로는 더 빠릅니다. ask가 멈춰 세우는 몇 초는 사고가 앗아가는 몇 시간에 비하면 오차 범위에 불과합니다.
전권한은 속도의 최대화처럼 보이지만, 사실은 분산의 최대화였습니다. 잘 풀리면 최속, 사고가 나면 최저속. 제가 원했던 것은 최속의 순간이 아니라, 안정적으로 빠른 것이었습니다.
권한을 5단계의 모드와 3층의 규칙으로 압축했습니다. 읽기(Read)는 허용하되, 삭제(Delete)와 외부 통신(External Communication)은 통제합니다. 모호한(Gray) 영역은 확인(Confirmation) 단계로 넘깁니다. 수수한 설계이지만, 이것이 에이전트(Agent)를 안심하고 실행할 수 있는 토대가 되었습니다.
모든 권한을 부여하여 실행했다가 사고를 쳤던 그 밤은, 지금 생각하면 저렴한 수업료였습니다.
Discussion

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