Claude Code hooks onFailure:block: 에이전트 작업을 실패 조건에서 멈추게 하는 방법
요약: Claude Code의 최근 릴리스에서 hooks에 onFailure: "block" 동작이 추가되었다. 핵심은 에이전트가 명령이나 HTTP 훅 실패를 무시하고 다음 단계로 넘어가지 못하게 하는 것이다. AI 코딩 에이전트를 개인 도구가 아니라 팀 개발 워크플로우에 붙이려면, “잘하는 일”보다 “멈춰야 할 조건”을 먼저 설계해야 한다.
왜 실패 시 차단이 중요한가
코딩 에이전트는 사람보다 훨씬 많은 작은 결정을 빠르게 내린다. 파일을 읽고, 명령을 실행하고, 테스트를 돌리고, 실패 로그를 해석하고, 다시 수정한다. 이 흐름에서 가장 위험한 순간은 실패가 발생했는데도 에이전트가 그것을 경고 정도로 보고 다음 단계로 넘어가는 경우다.
예를 들어 린트가 실패했는데 에이전트가 “나중에 고치면 된다”고 판단하고 PR 설명을 작성한다고 하자. 또는 보안 스캔 훅이 네트워크 오류로 실패했는데, 실제 취약점 없음으로 착각하고 배포 체크를 통과시킨다고 하자. 사람이라면 이상하다고 느끼는 상황도 에이전트는 목표 달성 압력 때문에 진행하려 할 수 있다. onFailure: "block"의 의미는 이 지점에서 강제로 멈추게 하는 데 있다.
훅은 자동화가 아니라 경계선이다
많은 팀이 훅을 “자동으로 무언가 실행하는 기능” 정도로 생각한다. 하지만 에이전트 환경에서 훅은 경계선 역할을 한다. 어떤 명령을 실행하기 전에 확인할 것, 실행 후 결과가 나쁘면 멈출 것, 외부 API를 부르기 전에 승인받을 것 같은 규칙을 코드 근처에 둘 수 있기 때문이다.
개발팀이 먼저 정의할 훅은 화려할 필요가 없다. 비밀값 탐지, 금지 경로 변경 감지, 테스트 실패 확인, 라이선스 검사, 패키지 잠금 파일 변경 확인 정도면 충분하다. 중요한 것은 실패를 “참고 정보”로 둘지 “차단 조건”으로 둘지 구분하는 것이다. 모든 실패를 차단하면 에이전트가 사소한 경고에도 멈춘다. 반대로 모든 실패를 경고로 두면 훅을 둔 의미가 없다.
기준은 간단하다. 되돌릴 수 있지만 불편한 것은 경고, 되돌릴 수 없거나 외부에 영향을 주는 것은 차단이다. 포맷팅 실패는 경고 또는 자동수정 대상일 수 있다. 프로덕션 환경 변수 접근, 고객 데이터 포함 로그 업로드, 비밀값 커밋 가능성은 차단이다.
실무에서 바로 쓸 수 있는 차단 조건
첫 번째 차단 조건은 비밀값이다. 에이전트가 만든 코드에는 테스트용 토큰, 임시 API 키, .env 내용이 섞일 수 있다. 커밋 전 훅에서 AWS_SECRET_ACCESS_KEY, OPENAI_API_KEY, DATABASE_URL 같은 패턴을 검사하고 발견되면 무조건 멈춰야 한다. 단순 정규식만으로 완벽하지는 않지만, 없는 것보다 훨씬 낫다.
두 번째는 위험 경로다. infra/, migrations/, auth/, billing/, security/ 같은 디렉터리는 작은 변경도 영향이 크다. 에이전트가 이 경로를 수정하면 테스트 통과 여부와 관계없이 사람 승인을 요구하는 편이 안전하다. 특히 마이그레이션 파일은 생성 자체보다 롤백 계획이 더 중요하다.
세 번째는 검증 명령 실패다. 타입체크, 린트, 유닛 테스트, 빌드 중 팀이 필수로 보는 명령이 있다면 실패 시 차단해야 한다. 여기서 주의할 점은 “실행 실패”와 “테스트 실패”를 구분하는 것이다. 패키지 설치 문제나 네트워크 장애로 명령이 실행되지 않은 경우도 통과로 처리하면 안 된다.
네 번째는 외부 호출이다. Slack, Discord, 이메일, 배포 API, 결제 API처럼 외부 상태를 바꾸는 호출은 에이전트가 임의로 실행하지 못하게 해야 한다. 훅에서 URL 도메인 또는 CLI 명령을 검사해 승인 없는 호출을 막을 수 있다.
onFailure:block을 적용할 때 생기는 흔한 문제
차단 조건을 넣으면 처음에는 작업이 자주 멈춘다. 이것은 실패가 아니라 관측 단계다. 기존에는 조용히 넘어가던 문제가 보이기 시작한 것이다. 다만 너무 많은 차단은 개발자가 기능을 꺼버리게 만든다. 따라서 차단 로그를 1~2주 모아 실제로 위험했던 것과 노이즈를 나눠야 한다.
예를 들어 문서 파일에서 API_KEY라는 문자열을 설명 목적으로 썼는데 비밀값 탐지 훅이 멈출 수 있다. 이 경우 전체 규칙을 끄는 대신 테스트용 예외 경로나 허용 패턴을 둔다. 반대로 .env.local 내용이 문서에 복사된 경우는 예외로 처리하면 안 된다. 훅 운영은 규칙을 한 번 정하고 끝내는 일이 아니라, 팀의 실패 사례를 반영해 좁혀 가는 일이다.
또 하나의 문제는 에이전트가 멈춘 이유를 사람이 이해하지 못하는 경우다. “hook failed”만 보여주면 개발자는 무엇을 해야 할지 모른다. 차단 메시지에는 실패한 규칙, 관련 파일, 다음 액션을 넣어야 한다. 예를 들어 “billing/ 경로가 수정되었습니다. 결제 담당자 리뷰가 필요합니다. 테스트 결과와 변경 의도를 PR 설명에 남기세요”처럼 써야 한다.
터미널 상태 표시도 운영에 중요하다
같은 릴리스에서 언급된 Program Status Protocol(OSC 7501) 지원은 겉으로는 작은 UI 개선처럼 보일 수 있다. 하지만 에이전트가 실제로 처리 중인지, 멈췄는지, 입력을 기다리는지 터미널이 알 수 있으면 운영 경험이 달라진다. 장시간 작업에서 사람이 가장 답답해하는 것은 실패 자체보다 상태를 모르는 것이다.
상태 표시가 명확하면 차단 조건과도 잘 맞는다. 에이전트가 테스트를 실행 중인지, 훅 실패로 멈췄는지, 승인 대기 중인지 구분되면 사용자는 불필요하게 중복 명령을 보내지 않는다. 특히 원격 세션이나 tmux 기반 작업에서는 상태 표시가 문제 파악 시간을 줄인다.
팀 도입 방법
처음부터 모든 저장소에 적용하지 말고, 변경 빈도가 높고 배포 위험이 낮은 저장소 하나에서 시작한다. 먼저 경고 모드로 1주일 운영하면서 어떤 훅이 얼마나 자주 실패하는지 기록한다. 그다음 실제 사고를 막을 수 있는 항목만 차단으로 올린다. 비밀값, 외부 호출, 프로덕션 설정 변경은 대체로 바로 차단해도 된다.
문서화도 필요하다. 훅 규칙은 개발자만 보는 내부 설정으로 남겨두면 안 된다. 에이전트에게 줄 작업 프롬프트에도 “이 저장소에서는 테스트 실패, 비밀값 감지, 결제 경로 변경 시 즉시 멈춘다”고 적어야 한다. 에이전트가 멈추는 이유를 미리 알면 불필요한 재시도가 줄어든다.
실행 체크리스트
- 훅을 자동화 기능이 아니라 에이전트 작업 경계선으로 정의한다.
- 실패 시 경고할 항목과 차단할 항목을 분리한다.
- 비밀값 탐지, 위험 경로 변경, 필수 테스트 실패, 외부 호출을 우선 차단한다.
- 차단 메시지에는 실패 규칙, 관련 파일, 사람이 할 다음 액션을 포함한다.
- 처음 1주일은 실패 로그를 모아 노이즈와 실제 위험을 구분한다.
- 예외 규칙은 넓게 열지 말고 경로·패턴 단위로 좁게 둔다.
- 터미널 상태 표시를 활용해 실행 중, 차단, 승인 대기를 구분한다.
- 에이전트 작업 프롬프트에도 훅 정책을 명시해 불필요한 재시도를 줄인다.