클로드 코드란 무엇인가?
Claude Code는 에이전트 기반 코딩 도구이다. Claude와의 차이점은 AI 에이전트로서 동작한다는 것이다.
- 코드베이스를 이해할 수 있다.
- 파일을 편집하고 명령을 실행할 수 있다.
- 기존 개발자 도구와 통합할 수 있다.
주변 환경과 상호작용하여 목표를 달성하기 위한 소프트웨어이다. LLM이 실시간으로 반복 작동하는 것으로 동작한다. 클로드 코드를 효과적으로 사용하려면 다음 3가지를 염두해둬야 한다.
- 컨텍스트 윈도우 → 클로드의 작업 메모리이다.
- 클로드 코드는 명령을 실행하기 전에 사용자에게 권한을 얻어야한다.
- 클로드 코드는 실수를 할 수 있다.
Claude Code의 동작 방식은 다음과 같다.
- Claude Code는 컨텍스트 수집, 액션(도구 호출), 검증의 반복으로 동작한다. 이를 Agentic Loop라고 한다.
- Claude에는 대화 내용, 파일 내용, 명령 실행 결과 등을 얼마나 저장하고 참고할 수 있는지를 결정하는 컨텍스트 창(context window)이 있다. 이 한도에 도달하면 Claude Code는 대화를 압축한다. 컨텍스트 창을 다시 사용할 수 있는 수준으로 줄이기 위해 어떤 내용을 제거하거나 요약할지 자동으로 판단한다.
- Claude Code는 의미(semantic)를 이해하여 어떤 도구를 호출할지, 그리고 그 결과를 어떻게 활용할지를 결정한다.
- Claude Code는 다양한 권한 모드가 존재한다.
Claude Code 권한 모드
Claude Code에게 다른 AI 에이전트처럼 말 걸면 된다. 사용자를 보호하고 작업을 더 쉽게 만들기 위한 권한 모드를 알아야 한다. 권한 모드는 Shift + Tab을 통해 모드 전환을 할 수 있다.
- manual : 아무 안내 없이 읽기만 가능하다. 다른 모드는 먼저 사용자에게 물어본다.
- accept edits : 읽기, 파일 편집 및 일반적인 파일 시스템 bash 명령을 묻지 않고 실행한다. 검토할 코드를 반복적으로 수정하는 데 유용하다.
- plan : 읽기 전용이다. 내용을 수정하지 않고, 변경 사항을 조사하고 제안한다. 프롬프트를 기반으로 읽기 전용 도구를 사용해 코드 베이스를 분석, 제안된 구현 방식을 조사한다. 이 과정에서 몇 가지 질문을 통해 내용을 명확히한 이후, 실행 계획을 반환한다. → 복잡한 변경 사항 계획 및 코드 검토에 유용, 여러 단계에 걸친 기능 구현에 사용
- auto : 모든 것을 수용하고, 별도의 분류 모델이 각 동작을 실행 전에 검토한다.
- 분류 모델은 사용자의 의도를 파악하는 역할을 수행한다. 사용자가 실제로 요청한 범위를 넘어서는 동작이 발생하는지 감시한다. 차단하도록 설계된 유형은 다음과 같다.
- 프로덕션 배포, 마이그레이션, code force push, 다운로드 코드를 셸로 타이핑, 민감 데이터 외부 전송, 세션 존재 파일 제거 등
- 이는 프로젝트의 로컬 편집, 잠금 파일에서 종속성 설치, 읽기 전용 요청, 자체 브랜치에 푸시하는 등 일상적인 작업 전반에 걸쳐 나타난다.
- 분류기는 정확성이 아닌 의도를 확인한다. 즉, 코드가 실제로 작동하는지는 잡아내지 못한다. 그래서 자동 모드와 테스트를 실행하는 중지 훅을 함께 사용하는 것이 좋다. (훅에 대한 내용은 아래 참고)
- 자동 모드는 클로드가 작업을 수행하는 동안 무엇을 하려고 하는지 감시한다. (동작 전 의도 확인)
- 정지 훅은 클로드가 작업을 완료하면 코드가 실제로 실햄됨을 확인한다. (동작 후 정확성 확인)
- 분류 모델은 사용자의 의도를 파악하는 역할을 수행한다. 사용자가 실제로 요청한 범위를 넘어서는 동작이 발생하는지 감시한다. 차단하도록 설계된 유형은 다음과 같다.
- don’t ask : 사전에 승인된 도구만 허용한다. 이외의 도구는 자동으로 차단된다.
- 사람이 직접 승인할 수 없는 상황에서 유용하다. ex) ci 파이프라인, 예약 작업, 야간 배치 작업
- bypass permission : 모든 검사를 건너뛴다. 권한을 위험하게 건너뛰는 플래그와 동일하다. 격리된 컨테이너 및 가상 머신 내에서만 실행하는 것을 권장한다.
Workflow
탐색 → 계획 → 코딩 → 확정으로 이루어진 워크 플로우가 없으면, 무작정 클로드에게 무언가 만들어달라고 요청하게 되고, 나중에 더 많은 수정 작업을 해야한다.
- 탐색 및 계획 : 이를 처리하는 가장 빠른 방법은 플랜 모드를 사용하는 것이다. 이 과정에서 클로드는 파일을 편집할 수 없다. 코드 작성 전이기 때문에 방향을 수정하기에 가장 좋은 단계이다. 계획을 명확히하기 위해서 사용자는 개입할 수 있다.
- 코딩 : 최종 결과를 결정하기 전에 의견 클로드와 의견 교환을 통해 코딩을 수행한다. 이 단계를 수월하기 위한 팁은 다음과 같다.
- 성공 기준을 정의한다. : 클로드가 결과에 대한 확신을 가지려면 정확함이 무엇인지 명확히 해야한다. 계획단계에서 이를 명시적으로 언급하는 것이 좋다.
- 도구를 추가한다. : 클로드가 목표를 달성하기 위해 도움이 되는 도구는 불필요한 작업을 줄여준다. ex) 웹 UI를 개발한다면, Chrome 확장 프로그램을 추가해 Cladue가 브라우저를 제어하고, 테스트하도록 도울 수 있다.
- 테스트 스위트를 포함한다. : 클로드가 지속적으로 검증할 수 있는 테스트 스위트를 제공한다. 이 과정에서 클로드가 직접 테스트를 작성할 수 있다. 테스트는 false positive (실제로는 아닌데, 있다고 판단하는 경우)를 방지하기 위한 신뢰성있는 진실의 원천이어야 한다.
- Simple Tip : 클로드가 반복적으로 같은 문제에 직면한다면, 해결 방법을 CLAUDE.md 파일에 저장하도록 요청하라.
- 확정 : 변경 사항을 직접 테스트하고 코드를 푸시한다. 커밋하기 이전에 서브에이전트에게 리뷰를 요청할 수 있다. 서브 에이전트는 메인 에이전트 세션이 가질 수 있는 편견 없이 새로운 시각으로 검토한다.
- 내장 스킬 : /commit-push-pr 스킬은 커밋, 푸시, PR 생성 작업을 한 번에 처리한다. CLAUDE.md 파일에 Slack MCP 서버가 구성된 경우에 PR 알림 구성 가능 → PR이 생성되면, gh pr create 세션이 PR에 자동 연결된다. claude —from -pr <PR_NUMBER>로 돌아올 수 있음
Context 관리
컨텍스트는 클로드의 작업 메모리이고, 컨텍스트 윈도우는 그 공간의 양이다. 파일을 읽거나, 도구 호출을 실행하거나, 도구 호출의 결과를 수신할 때마다 컨텍스트 윈도우에 데이터가 추가된다. 이 공간은 한정적이다.
- 용량이 가능찬다면 : 컨텍스트 윈도우가 압축된다. 이 과정에서 중요한 세부 정보가 요약되고, 불필요한 도구 호출 결과를 제거해 공간이 확보된다. 이 과정에서 세부 정보 손실이 발생할 수 있다.
- 수동으로 실행 가능 : /compact 를 통해 수동 압축이 가능하다. 만약, 이전 세션 내용을 전부 삭제하고 재시작하려면 /clear를 사용할 수 있다.
- 특정 기능 개발 과정에서 컨텍스트 제한이 걸렸지만 작업을 계속 수행하고 싶은 경우에 사용.
- 컨텍스트 상태를 확인하려면 : /context를 사용하면 컨텍스트 크기에 대한 정보를 시각적인 그래프로 확인 가능하다.
- 새로운 기능을 시작할 때 사용. 세션 간 기억해야할 내용은 CLAUDE.md에 저장한다.
컨텍스트 공간을 절약하기 위한 팁이 존재한다.
- 구체적인 설명을 제공한다. : 모호한 지시는 Claude가 코드베이스를 더 많이 탐색하고 자체적인 추론을 하게 만든다.
- MCP 서버를 관리한다. : MCP 서버는 기본적으로 사용하지 않을 때에도 사용 가능한 모든 도구를 컨텍스트에 로드한다. 현재 프로젝트와 무관한 서버를 비활성화하는 것을 고려하라. 혹은 MCP와 유사하게 동작하지만, 모든 도구를 미리 컨텍스트에 로드하지 않는 Skill 기능을 사용할 수 있다.
- 서브에이전트를 사용한다. : 서브에이전트는 메인과 병렬로 실행되지만, 컨텍스트 윈도우가 분리되어 있다. “인증 API는 어디있어?”와 같이 답만 필요한 간단한 작업은 서브에이전트가 수행하고, 그 결과를 메인 에이전트에 요약 정보만 반환해 컨텍스트를 깔끔하게 유지할 수 있다.
Claude Code 커스터마이징
CLAUDE.md
CLAUDE.md 파일은 Claude Code에게 유용한 기능 중 하나이다. 이는 프로젝트에 대한 Claude Code 영구적인 메모리이다. (Persistent memory)
해당 파일이 없이 Claude Code를 열면 매번 처음부터 다시 시작된다. 이 과정에서 코드베이스를 다시 탐색하고, 필요한 종속성을 파악하고, 이미 구현된 기능을 이해해야 한다. Claude Code는 이 문제를 해결하며, 매 세션을 시작할 때마다 해당 파일을 자동으로 읽는다. (온보딩 스크립트)
CLAUDE.md는 사용 목적에 따라 계층적이다. (반복적인 지시가 필요한 경우, 해당 파일에 업데이트하라고 요청하라.)
- 프로젝트 수준의 CLAUDE.md는 프로젝트 루트 디렉터리에 존재하고, 팀원들과 공유한다.
- 개인 수준의 CLAUDE.md는 구성 디렉터리에 있다. 사용자 본인만을 위한 파일이며, 모든 프로젝트에 적용된다.
만약, 참조할 프로젝트 문서가 존재한다면 해당 문서를 @ symbol을 파일 경로와 함께 사용할 수 있다. Anthropic에서는 해당 파일을 최대한 간결하고, 필요한 정보만 포함시키기 위해 해당 파일 없이 시작하는 것을 권장한다. /init 으로 파일을 생성할 수 있다.
Please read if you need more info: @README.md
문제가 생기면 새로운 규칙이 생기고 이것이 반복되다보면 claude.md 파일은 점점 커진다. claude는 파일이 커지면 그 일부를 무시하기 시작한다. 이는 claude의 파일 처리 방식때문에 발생한다.
- claude.md는 강제적인 설정이 아닌 지침이다.
- 모든 line은 claude의 관심을 끌기 위해 경쟁한다. 파일이 커지면 내부 경쟁이 심해지고, claude가 어떠한 규칙도 따르지 않을 수 있다.
- 파일을 간결하게 유지하면 claude는 더 많은 규칙을 준수할 수 있다.
이에 대한 몇가지 팁이 존재한다.
- 규칙을 작성하기 전에, 해당 규칙이 claude.md에 작성하는 것이 적합한지 판단하라. 지침과 규칙은 다르다. 예를 들어, main에 push하지 말라는 규칙이지만, 이를 claude.md에 명시하면 claude가 이를 존중해달라는 뜻으로 이해한다. 이러한 규칙은 hooks에 추가하는 것이 적절하다. claude.md는 지침이라는 것을 명심하라
- claude.md는 단순히 하나의 파일이 아니다. 이는 총 4가지 장소에 저장될 수 있으며, claude는 모든 파일을 한번에 불러온다.
- 관리형 정책 : 플랫폼 팀에서 관리하는 조직 수준의 파일 (항상 적용된다.)
- 사용자 : 컴퓨터의 모든 프로젝트에서 적용되는 개인 설정(personal-global)
- 프로젝트 : 팀과 공유하고 저장소에 커밋된 파일
- 로컬 - Git에서 무시된다. 저장소 개인에 대한 메모(personal-local)
- 프로젝트 파일이 길어지면, 파일 경로 가져오기 구문을 사용해 파일을 분할하라. 하나의 긴 텍스트 대신 파일을 가리키도록 하면 된다. claude가 실행될 때, 가져온 파일은 참조한 바로 그 위치에서 자동으로 확장된다. 가져오기 기능은 파일을 깔끔하게 정리하는데 도움이 되지만, 모든 파일은 여전히 처음에 로딩된다. 파일 로드를 줄이기 위해 사용하는 것은 아니라서, 컨텍스트 양을 줄이지는 않는다.
@.claude/conventions/code-style.md
@.claude/conventions/testing.md
@.claude/conventions/workflow.md
- 규칙이 모호한 경우, 제대로 동작하지 않는다. 이를 해결하기 위해 최대한 구체적이고 검증 가능하게 작성해야 한다.
- 어떤 일을 하지 말라고 하면, 대안이 있어야 한다. 그렇지 않으면 여지를 남기게 된다. 오해의 소지를 남기지 마라.
- “중요” 혹은 “반드시”와 같은 단어는 규칙의 중요도를 높여주지만, 모든 규칙이 강조된다면 어떤 규칙도 눈에 띄지 않고 강조의 의미가 없어진다. → 강조는 예산처럼 생각해야 한다. 어겼을 때 문제가 발생하는 2-3가지 규칙에 집중하고, 나머지는 일반적인 수준으로 유지하라.
- claude.md는 완성된 파일이 아니다. 살아있는 코드처럼 다뤄라. claude가 잘못된 동작을 했을 때, 이를 수정하라.
Subagents
서브 에이전트를 사용해 위임해 작업을 세분화하고 구성 요소 작업을 병렬로 실행해 컨텍스트 관리를 개선할 수 있다. (꼭 모든 컨텍스트를 하나의 세션이 기억할 필요는 없으니)서브 에이전트는 자체 컨텍스트 윈도우를 가지고 병렬로 실행된다. 모든 탐색 작업이 끝나면, 결과를 요약해 반환한다.
서브 에이전트는 YAML Frontmatter가 포함된 Markdown 파일에 정의된다. 가장 쉽게 생성하려면, Claude를 사용해 이를 생성하는 것이다.
- /agents를 사용하고, 새 에이전트 생성을 선택한다.
- 에이전트의 범위, 목적 정의, 액세스 권한 도구 선택, 색상과 같은 안내를 받는다.
- 클로드는 서브 에이전트에 대한 이름과 설명, 프롬프트를 생성한다. (사용자가 제공하는 프롬프트에 따라 클로드가 언제 서브 에이전트를 호출해야하는지 알려준다.)
또한 맞춤 설정도 가능한데, 다음과 같은 주요 기능이 있다.
- 영구 메모리 기능 : 서브 에이전트가 대화 내용을 유지한다. 동일한 프로젝트에서 지속적으로 사용하는 경우에 유용하다.
- 스킬 사전 로딩 : 서브 에이전트에 스킬을 미리 로드하려면, skill 키를 추가해 사용할 스킬 이름을 나열한다. 메인 대화에서 사용하는 스킬과 달리, 서브 에이전트에서는 스킬 전체 내용이 컨텍스트에 모두 로드된다.
Skills
스킬은 클로드 코드(Claude Code)가 특정 작업을 자동으로 처리하도록 학습시키는 재사용 가능한 마크다운 파일이다.
클로드에게 PR 검토나 커밋 메시지 작성을 요청할 때마다 반복적인 지침을 입력하는 대신, 스킬을 한 번만 작성해 두면 해당 작업이 발생할 때마다 클로드가 자동으로 적용한다.
스킬에 대한 내용 별도로 작성 예정
MCP
Model Context Protocol(MCP)는 에이전트가 외부 도구와 데이터 소스에 연결할 수 있게 해주는 개방형 표준이다. 클로드는 해당 도구를 언제 사용해야 하는지 자동으로 파악해 사용자 쿼리를 효율적으로 처리한다.
컨텍스트 정보의 상당 부분은 코드베이스 외부(DB, 생산성 앱, 저장소)에 존재하는데, MCP는 이 간극을 매워준다. claude mcp add 명령어로 MCP 서버를 추가할 수 있다. 2가지 주요한 유형이 존재한다.
- HTTP 서버 : 원격 서비스를 위한 것이다.
- Stdio 서버 : 사용자 컴퓨터에서 실행되는 로컬 프로세스를 위한 것이다.
/mcp로 연결된 서버를 확인하고, 상태를 점검하고, 필요없는 서버를 비활성화 할 수 있다. MCP는 3가지 방식으로 범위를 지정할 수 있다.
- 로컬 : 현재 프로젝트에서만 사용 가능하다.
- 사용자 : 모든 프로젝트에서 사용 가능하다.
- 프로젝트 : .mcp.json 버전 관리 시스템에 커밋하는 파일을 사용하므로 코드 베이스의 모든 사용자가 자동으로 동일한 서버를 사용한다.
MCP 서버는 사용자가 서버를 사용하지 않아도 컨텍스트 윈도우에 도구 정의를 추가하므로, 구성 서버가 많으면 공간이 부조해질 수 있다. 사용하지 않는 서버는 비활성화하는 것을 권장한다. CLI 버전의 도구가 존재하면, 이를 사용하는 것이 컨텍스트 관리에 도움이 된다. 스킬은 이름과 설명이 컨텍스트에 로드되고, 필요할 경우에만 전체 스킬을 로드한다.
Hooks
훅을 사용하면 Claude Code 생명주기 중 특정 시점에 명령을 실행할 수 있다. CLAUDE.md에 파일 편집 후 프리티어 실행을 지정할 수 있다. 하지만, 가끔 실행이 안될때가 존재하는데, 이 경우에 예외 없이 항상 실행되도록 할 수 있다. 사용 예시는 다음과 같다.
- 파일 편집 이후, 프리티어 수행
- 규정 준수를 위해 모든 명령 기록
- 운영 파일 수정과 같은 위험 작업 차단
- 작업 완료 이후, 알림 설정
훅은 settings.json 파일에서 구성한다. (혹은 /hooks 사용)이벤트를 선택하고, 해당 이벤트가 적용될 도구를 지정하는 매처를 설정한 다음, 실행 명령을 제공하면 된다. (async 동작 가능) Claude Code는 세션 동안 약 30개의 훅 이벤트를 발생시킨다. 아래는 알아두면 좋은 이벤트 목록이다.
- PreToolUse : 도구를 호출하기 전에 실행한다. 작업이 실행되기 전에 중단할 수 있으므로, 규칙을 강제하는 핵심 수단이다.
- Claude에게 결과를 전달하려면 JSON을 출력하고 종료 코드
0으로 끝낸다. 핵심 필드는permissionDecision이며 다음 세 가지 값을 사용한다.- allow : 도구 호출 허용한다.
- deny : 도구 호출을 중단한다.
- ask : 사용자에게 결정을 넘긴다.
- defer : 기술적으로 존재, 일반적으로 사용하지는 않는다. (호출 프로세스가 도구 실행을 일시 정지한 뒤 재개하는 비대화형 실행에만 동작)
- Claude에게 결과를 전달하려면 JSON을 출력하고 종료 코드
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": "...",
// 도구 호출을 차단하는 대신, 입력값을 재작성할 수 있다.
// ex) bash 명령어에서 비밀 정보를 제거하고, 명령어 계속 실행
// 기존 입력 객체의 일부만 수정하는 것이 아닌 입력 객체 전체를 수정한다.
"updatedInput": {
"command": "..."
}
}
}
ex)
Claude: rm -rf ./data를 실행하고 싶다
→ PreToolUse 훅 실행
→ check-command.sh가 명령을 정상적으로 검사
→ 훅: 검사는 성공했지만 원래 명령은 거부한다
- PostToolUse : 도구 호출이 성공한 후 실행한다. 일반적으로 자동 포맷팅이나 자동 린트 검사를 여기에 연결한다.
- Stop : Claude가 자신의 차례를 끝내려고 할 때 실행한다. 특정 조건이 충족되지 않았다면 “아직 작업이 끝나지 않았다”며 종료를 거부할 수 있다. 서브에이전트가 작업을 마칠 때 실행하는 대응 훅으로 SubagentStop이 있다.
- PreCompact / PostCompact : 각각 컨텍스트 압축 전과 후에 실행한다.
- InstructionsLoaded :
CLAUDE.md또는 규칙 파일을 로드할 때 실행한다. 어떤 지침이 실제로 컨텍스트에 포함됐는지 감사하거나 확인할 때 유용하다. - SessionStart : 세션이 시작될 때 실행하며 작업 환경을 초기화한다. 새 세션을 처음 시작할 때만 실행하고 싶다면 시작 소스(startup source)를 사용한다.
압축 후 단순히 어떤 작업을 실행하려면
PostCompact를 사용하고, Claude에게 중요한 정보를 다시 기억시키려면SessionStart의compact매처를 사용해야 출력값을 대화에 다시 포함시킬 수 있다.PostCompact에는 출력 내용을 Claude 컨텍스트로 전달하는 공식 채널이 없고,SessionStart에는 그 채널이 명시적으로 있다.
모든 훅이 JSON으로 응답할 필요는 없다. 단순한 훅에서는 종료 코드만으로 충분하다. 중요하게 알아야 할 종료 코드는 세 가지다.
0: 성공을 의미한다. 표준 출력(stdout)이 JSON이면 Claude가 이를 해석한다. 대부분의 이벤트에서는 일반 텍스트를 무시하지만,SessionStart,UserPromptSubmit,UserPromptExpansion에서는 일반 텍스트를 컨텍스트에 추가한다. 이 동작을 이용해 상태 보존 훅을 구현한다.2: 차단 오류를 의미한다. 표준 오류(stderr)의 내용을 Claude에게 피드백으로 전달한다. 대부분의 이벤트에서 작업을 차단할 때 사용하는 종료 코드다.
그 밖의 종료 코드는 작업을 차단하지 않는다. 표준 오류를 로그에 기록하고 Claude는 작업을 계속한다. 특히 주의해야 할 것은 종료 코드 1이다. 일반적으로 오류처럼 느껴지지만 도구 실행을 차단하지 않는다. Claude는 원래 요청한 명령을 계속 실행한다. 따라서 작업을 중단하려면 1이 아니라 2로 종료해야 한다.
몇 가지 추가적인 예외도 있다. 종료 코드 2는 Stop 이벤트도 차단할 수 있다. 이를 이용해 Claude에게 아직 작업이 끝나지 않았다고 알린다. 하지만 PostToolUse는 도구가 이미 실행된 후에 발생하므로, 이 시점에서 차단해도 해당 도구 호출을 막기에는 너무 늦다. 다만 Claude에게 피드백을 전달하는 것은 가능하다.
또한 Notification과 SessionStart 같은 일부 이벤트는 차단을 완전히 무시한다. 이러한 이벤트에서는 표준 오류를 표시하지만 작업은 그대로 계속한다.
| 종료 코드 | 의미 | Claude Code의 행동 |
|---|---|---|
0 | 훅이 정상적으로 끝남 | 원래 작업을 계속한다 |
2 | 원래 작업을 막아야 함 | 실행을 차단한다 |
1 등 나머지 | 훅에서 오류가 났지만 차단은 아님 | 오류를 기록하고 원래 작업을 계속한다 |
Hook 예제 살펴보기 1 - 안전 장치로 사용
- Bash 도구에
PreToolUse안전 장치를 적용한다고 가정 - 매처는 감시할 도구를 선택하고, 선택적인 if 조건은 감시 대상을 특정 명령어로 좁힌다.
deny로 위험 호출을 중단시키는 것도 좋지만,updateInput으로 호출 내용을 수정할 수 있다. 이를 사용하면 명령어 실행을 거부하는 대신, 명령어에 포함된 비밀 정보를 제거하고, 나머지 명령은 그대로 실행할 수 있다.- claude가 실제 비밀키처럼 보이는 값이 포함된 명령어를 수행하려고 한다면, 훅이 명령어 실행 전에 이를 가로채고
sk_live_패턴을 발견한 뒤, 해당 값을 플레이스 홀더로 교체한다. (sk_live는 stripe 비밀 api키 prefix라고 함) - 명령어는 계속 실행되고, 작업도 완료되지만 비밀키는 명령어에 전달되지 않는다. (차단과 가리기의 차이)
Hook 예제 살펴보기 2 - 컨텍스트 압축 후 작업 상태 유지
- Claude가 대화 압축 시 세부 정보가 사라짐.
- compact 매처가 설정된
SessionStart훅은 압축 직후에 실행된다. - 이 훅에서 현재까지 작업한 파일들의 간단한 요약을 출력하게 한다.
- 출력된 요약은 컨텍스트에 다시 추가된다.
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/redact-secret.sh"
}
]
}
],
"SessionStart": [
{
"matcher": "compact",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/restore-context.sh"
}
]
}
]
}
}
#!/bin/bash
INPUT=$(cat)
COMMAND=$(printf '%s' "$INPUT" | jq -r '.tool_input.command')
REDACTED_COMMAND=$(
printf '%s' "$COMMAND" |
sed -E 's/sk_live_[A-Za-z0-9_-]+/[REDACTED]/g'
)
# 비밀 키가 없으면 아무 결정도 하지 않는다.
if [ "$COMMAND" = "$REDACTED_COMMAND" ]; then
exit 0
fi
# 비밀 키가 있으면 전체 tool_input에서 command만 변경하여 반환한다.
printf '%s' "$INPUT" |
jq --arg command "$REDACTED_COMMAND" '{
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "allow",
permissionDecisionReason: "명령어에서 비밀 키를 제거함",
updatedInput: (.tool_input + {command: $command})
}
}'
긴 세션 Steering(조작, 주행)
수십 개의 파일을 리팩터링하거나 새로운 기능을 구축하는 데 오랜 시간이 소요될 수 있다. claude에게 계속 지시해야할수록 작업 시간은 늘어난다. 이러한 긴 세션을 다루기 위한 도구들이 존재한다. 핵심은 작업 범위를 정하고, 작업 진행 도중에 방향을 제시하는 것이다.
- 계획 모드를 사용해 작업 범위를 결정 :
- 클로드가 코드를 작성하기 전에 계획을 세워야 한다.
- 계획 모드에서 클로드는 읽기 전용 모드로 조사를 수행한다. 코드를 읽고 변경 부분을 파악한 다음 검토할 수 있는 계획을 제공한다.
- 계획을 꼼꼼히 읽고, 계획에 오류가 있거나 누락된 부분이 있다면 추가해달라고 요청한다.
- 이를 통해 예상치 못한 문제가 발생할 가능성을 조기에 줄이면서 작업 범위를 결정할 수 있다.
- 클로드가 작업하는 동안 운전대를 잡기 :
- compact : 대화를 요약하고, 해당 요약을 새로운 컨텍스트로 사용한다. 이를 통해 컨텍스트 윈도우를 확보할 수 있다. 단, compact 과정에서 중요한 내용이 누락될 수 있다. 따라서
/compact Focus on the —version flag implementation처럼 compact에 대한 지침을 추가하면 좋다. - riwind : 클로드가 잘못된 길로 들어섰을 때, 이 기능을 사용하면 마지막 체크포인트로 이동할 수 있다. 사용자가 입력하는 모든 프롬프트는 되돌릴 수 있는 체크포인트를 생성한다. 빈 프롬프트에서 ESC키를 두번 누르면 메뉴가 열린다.
- 코드 및 대화 복원, 대화만 복원, 코드만 복원이 가능
- Summarize from here : 체크포인트 이후의 모든 내용 요약(side chat 이후, 공간 확보할때 유용)
- Summarize up to here : 체크포인트 이전의 모든 내용 요약(설정이 길어 압축하고 싶은데, 구현은 유지하고 싶은 경우 유용)
- compact : 대화를 요약하고, 해당 요약을 새로운 컨텍스트로 사용한다. 이를 통해 컨텍스트 윈도우를 확보할 수 있다. 단, compact 과정에서 중요한 내용이 누락될 수 있다. 따라서
자율적인 작동
Claude가 좀 더 자율적으로 동작하게 하려면, 목표를 설정하고 loop 기능을 사용할 수 있다.
- Goal : 완료 조건을 설정한다. 완료의 기준을 정의하면, Claude는 평가자가 해당 조건이 충족되었음을 확인할 때까지 터마다 작업을 계속 수행한다. 처음 완료되었다고 판단했다고 해서 바로 작업을 멈추지는 않는다. (취소하려면 /goal clear 수행) 평가자는 오직 transcript만 읽기 때문에, 조건은 결과물로부터 확인할 수 있어야 한다. 예를 들어, 테스트 수행 결과가 이에 해당된다.
/goal all tests in src/billing pass, and the type checker reports zero errors
- Loop : 고정된 간격 혹은 자체 속도로 턴 사이에 프롬프트를 실행한다. CI 실행이나 배포 같은 외부 데이터를 가져와서 상태가 변경될 때 동작하도록 사용할 수 있다. (종료하려면 ESC 입력)
워크트리를 사용한 병렬 실행
동일 코드베이스에 여러 에이전트를 실행할 때는 자동차 한 대에 핸들이 두 개인 것과 같다. (안전하지 않음) 두 개의 Claude 세션 각각에 독립적인 공간을 만들어 줄 수 있다. (브랜치 같은 개념인듯) 이를 워크 트리라고 하는데, 세션들은 서로 겹치는 대신, 독립적인 파일 트리를 가진다. 다음과 같은 특징이 존재한다.
- 서로의 변경 사항을 덮어쓸 수 없다.
- 세션 종료 시 워크 트리가 제거된다.
저장소 루트에 존재하는 .worktreeinclude 파일에는 각 워크트리에 복사할 git-ignored 파일이 있다. 환경 변수 파일이나 로컬 설정과 같은 모든 워크트리에는 필요하지만, vcs에 커밋하고 싶지 않은 파일에 유용하다.
습관을 만들어라
Claude Code 세션을 효율적으로 관리하려면 몇 가지 습관을 들이는 것이 중요하다.
- 작업 범위를 결정하고 방향을 설정하라
- 요약에 중요한 내용이 남도록 압축 방향을 조정하라
- 클로드가 방향을 잃으면 되감기 메뉴를 사용해 방향을 수정하라
- 목표를 세울 때는 ‘완료’된 모습을 단계별 과정보다 더 명확하게 설명할 수 있을 때 목표로 삼아라.
- 작업 트리에서 병렬 작업을 실행하라
반복 작업 자동화하기
루틴과 헤드리스
루틴은 클라우드에서 실행되는 저장된 프롬프트이며, 작업을 자동화하는 가장 직접적인 방법이다. 스크립트나 서버가 필요하지 않다. 인프라는 Anthropic의 것이며, 사용자의 장비가 밤새 켜져 있을 필요가 없다. 유지 관리해야할 파일도 없다. 작업 정의 이후, 바로 실행된다.
- 루틴은 프롬프트, 작업 대상 저장소, 커넥터를 묶어서 실행한다.
- 루틴은 몇 가지 유형의 트리거에 의해 실행될 수 있다.
- cron 스케줄
- api 엔드포인트
- github 이벤트
- 웹에서 루틴을 생성할 수 있다. (claude.ai/code/routines) 루틴 이름을 지정하고, 각 세션에서 Claude가 수행해야 할 작업을 설명하는 지침을 작성하고, 저장소를 선택하고, 트리거를 선택하면 된다.
-
혹은 claude code 내에서 /schedule 명령어를 실행해 설명하면 된다.
/schedule daily dependency audit at 9pm
루틴에 중요한 일을 맡기기 전에 다음 3가지를 명심해야 한다.
- Routines are a research preview → 실험적 기능이라는 뜻인듯
- A recurring schedule runs at most hourly. → 최대 1시간에 1번 실행 가능
- Each run starts from a fresh clone of your default branch and can only push to
claude/prefixed branches → 기본 브랜치를 새로 복제한 상태에서 시작, 저장소별 제한을 완화하지 않는 한 claude/ 접두사가 붙은 브랜치에만 푸시할 수 있음 (main 브랜치를 덮어쓰지 못하도록 하는 안전 장치)
자체 환경이 필요하다면 헤드리스 모드를 사용하면 된다. 작업을 클라우드에서 처리할 수 있으면 루틴이 유용하지만, 떄로는 작업 자체에 환경이 필요하거나 실행 전후를 감싸는 별도의 로직이 필요할 수 있다.
claude -p "summarize the changes in this diff"
- -p를 사용하면, claude code가 대화형 ui 없이 일회성 명령으로 실행된다. 표준 셸 도구처럼 파이프로 연결 가능
- -p를 사용하면 훅, 스킬, 플러그인, mcp 서버 및 claude.md 파일을 자동으로 탐색하지 않는다.
- 로컬 환경에서 우연히 로드된 다른 요소는 사용되지 않는다. (시작 속도가 빨라진다는 장점)
- 자동화 스크립트나 ci에서 claude code를 일회성 명령어처럼 사용할 때 사용한다.
- 헤드리스 모드는 파이프를 사용하기 떄문에, 일반적인 텍스트 대신 구조화된 데이터를 반환하는 것이 좋다. json 스키마와 json 출력을 함께 지정하면 claude는 해당 스키마에 맞춰 출력을 제한한다. 스키마와 일치하는 객체는 json 응답의 structured_output 필드에 담긴다. 따라서 jq 명령어로 이를 추출한 다음에 다른 DB나 스크립트로 전달할 수 있다.
claude -p "Extract the exported function names from src/core/style.js" \
--output-format json \
--json-schema '{"type":"object","properties":{"functions":{"type":"array","items":{"type":"string"}}},"required":["functions"]}' \
| jq '.structured_output.functions'
- 만약, 여러 단계에 걸쳐 진행되는 작업이라면 모든 내용을 하나의 명령어에 억지로 넣을 필요는 없다. JSON 출력에서 세션 ID를 저장해 뒀다가 나중에 해당 세션을 재개할 수 있다. 이 경우에는 한 스크립트가 작업을 시작하고, 나중에 다른 스크립트가 맥락을 유지한 채 작업을 이어서 진행할 수 있다.
claude --resume "$(jq -r .session_id /tmp/plan.json)"
- CI 에서 실행할 때마다 동일한 결과가 필요하다면 —bare 플래그를 사용할 수 있다. (결정론적 모드) 실행마다 달라질 수 있는 결과 대신, 예측 가능한 출력을 원할 때 사용한다.
자체 앱 안에서 Claude Code를 사용할 수 있다. Agent SDK는 Claude Code를 자체 TS, Python 앱에 내장할 수 있게하는 라이브러리이다. qurey 함수와 cli에서 사용하는 것과 동일한 기본 기능을 제공한다. 프롬프트와 다음 옵션을 전달할 수 있다.
- claude가 사용할 수 있는 도구 제한 (allowedTools)
- 시스템 프롬프트
- 권한 모드
Github Actions 및 Code Review
반복 작업을 맡기기 가장 좋은 곳은 PR이다. 코드 리뷰가 이루어지고 변경 사항이 반영되며, 번거로운 작업의 상당 부분이 발생하는 곳이기 때문이다. 이를 위해 Claude를 활용하는 2가지 방식이 존재한다. 팁은 관리형 방식으로 시작하고, claude가 단순히 댓글만 작성하는 것이 아닌, CI 안에서 작업을 수행해야 한다면 actions로 전환한다.
-
관리형 방식을 사용한 Code Review
- Claude Github 앱을 사용해 PR을 검토하는 Antropic 호스팅 서비스
- 기능을 활성화하면 중요한 코드 라인에 인라인 댓글로 검토 결과를 남긴다.
- 실행 시점 : PR open, PR push, @claude review (manual)
- 다음과 같은 제한 사항이 존재한다.
- PR 승인 및 차단은 하지 않음 → 결정은 사용자 몫
- 자동 수정 기능 존재하지 않음 → 수정하려면? → 로컬에서 /code-review 명령어를 통해 diff 검토하고, —fix 플래그를 추가하면 현재 작업 트리에 직접 반영한다.
- 연구 프리뷰 단계이며, 팀 및 엔터프라이즈 요금제에서 사용 가능
-
직접 Github Actions 구성하기
- /install-github-app 명령어 실행
- 사용 action은 anthropics/claude-code-action@v1이다.
- 주요 입력값은 api key, gh_token, use_bedrock / use_vertex, prompt, claude_args (claude code에 그대로 전달할 cli 인자 문자열)
- uses: anthropics/claude-code-action@v1 with: anthropic_api_key: $ github_token: $ trigger_phrase: "@claude" prompt: "여기에 작업 지시를 입력하세요" claude_args: "--max-turns 5 --model claude-sonnet-5".github/workflows/claude.yaml에 워크플로 파일을 추가하면 PR 댓글과 이슈 댓글에 작성된 @claude를 감지한다.- cron 트리거를 등록해 일정에 따라 실행되는 워크플로를 구축할 수 있다.
- claude_args를 사용하면, 실행 방식을 세부적으로 조정할 수 있다.
- —max-turns 5 : 에이전트 반복 횟수를 최대 5로 제한해서 무한 실행을 방지
- 권한 모드
- 허용 도구
검증 및 공유
Trust It: Verifying Unsupervised Runs
결과물을 배포하기 전에 직접 감독하지 않은 작업을 검증할 방법이 필요하다. 이 검증 과정이 있어야 자율적으로 실행한 Claude Code를 안전하게 신뢰할 수 있다. 핵심 원칙은 Claude에게 얼마나 많은 자율성을 주었는지에 비례해 검증한다. 짧은 세션에서 메시지 출력 과정을 검토했다면 빠르게 확인해도 좋지만, 사람이 지켜보지 않은 실행이나, 아무도 개입하지 않은 상태에서 CI로 실행된 작업에는 제대로된 검증이 필요하다. 즉, 적게 지켜봤을 수록 더 많이 검증해야한다. 이에 대한 몇가지 실행 지침은 다음과 같다.
- 무인 실행에서는 자동 모드를 유지하라.
- 업무 환경에서 claude를 사람의 감독 없이 실행할 때는 권한 검사를 우회하지 말고, 자동 모드를 유지하라.
- 자동 모드에서는 분류기가 각 작업의 위험성을 계속 검토한다.
- 하지만, 이 안전장치가 무엇을 하고, 무엇을 하지 않는지 명확히 이해해야한다. (위에 작성된 내용 참고)
- 요약이 아닌 diff부터 확인하라.
- claude가 작성한 요약부터 읽지 말고, 실제 diff부터 확인해라
- /code-review를 실행해 변경 사항을 살펴보고 문제를 찾는다.
- 그런 다음 직접 git diff를 확인한다.
- claude의 요약은 깔끔하고 문제가 없어보이지만, 실제 diff에는 예상하지 못한 파일의 변경 사항이 포함될 수 있다.
- 실제로 무엇이 변경되었는지 읽어야 한다. 먼저 계획에 포함됐던 파일을 확인하고, 그 다음 계획 범위를 벗어난 변경 사항이 있는지 확인하라. 잘 정리된 설명이 깨끗한 코드를 증명하지는 않는다.
- claude가 작성한 요약부터 읽지 말고, 실제 diff부터 확인해라
- 테스트를 약속이 아닌 통과 조건으로 만들어라.
- 감독 없이 실행된 작업의 실질적인 통과 조건은 테스트 성공 여부이다. claude가 테스트를 실제로 실행했는지, 아니면 실행했다고 말하기만 했는지도 확인해야 한다. 이를 신뢰에 맡기지 말고, claude가 테스트를 건너뛸 수 없도록 훅으로 설정해야 한다.
- 종료 훅(stop hook) : 실패하면 해당 턴이 종료되지 않도록 한다.
- 도구 사용 후 훅(post-tool-use hook) : 코드가 수정될때마다 린트와 타입 검사를 실행한다.
- 감독 없이 실행된 작업의 실질적인 통과 조건은 테스트 성공 여부이다. claude가 테스트를 실제로 실행했는지, 아니면 실행했다고 말하기만 했는지도 확인해야 한다. 이를 신뢰에 맡기지 말고, claude가 테스트를 건너뛸 수 없도록 훅으로 설정해야 한다.
- 맥락이 없는 두 번째 의견을 받아라.
- PR 생성 이전 실행하는 서브 에이전트 코드 리뷰를 감독 없이 진행된 작업에도 사용할 수 있다.
- 새로운 세션이나 서브 에이전트를 열고, 코드가 어떻게 작성되었는지에 관한 사전 정보 없이 변경된 코드를 검토하도록 하라. 새로운 검토자는 기존 접근 방식에 선입견이 없기 때문에 최초 실행이 스스로 합리화하며 지나친 문제를 발견할 수 있다.
정리하자면, 다음과 같다.
- diff를 직접 읽는다.
- 테스트를 훅으로 설정해 작업 종료의 통과 조건으로 만든다.
- 헤드리스 실행은 JSON 결과와 종료 코드로 검증한다.
- 중요한 작업에는 맥락이 없는 2번째 검토자의 의견을 받는다.
플러그인
팀 전체가 신뢰할 수 있는 동일한 설정을 사용한다면, 설정의 가치는 훨씬 커진다. 하지만, 문제는 설정을 공유하는 방법이다. 스킬, 서브에이전트, 훅으로 훌륭한 .claude 디렉터리를 만들었다면, 그 다음에는 어떻게 해야할까? 플러그인은 이 문제를 해결한다. 플러그인은 claude code 설정을 하나로 패키징해 다른 사람에게 전달하는 방법이다. 이에는 두 가지 측면이 있다.
- 다른 사람이 배포한 플러그인을 사용하는 방법
- 공유할 가치가 있는 설정을 직접 만든 후, 플러그인으로 패키징하는 방법
플러그인은 설치 가능한 하나의 단위이다. 원래라면 수동으로 공유해야 했을 다음 요소를 묶는다.
- 스킬
- 서브에이전트
- 훅
- MCP 서버 설정
- LSP 서버
- 백그라운드 모니터
- 테마
- settings.json 설정 일부
플러그인이 어디에 배포되어 있는지에 따라 설치 방식이 달라진다. 세션 안에서는 이름을 사용해 플러그인을 직접 설치할 수 있다.
/plugin install org-name@plugin-name
팀을 위해 마켓플레이스에 추가할 수 있다. 마켓플레이스는 플러그인을 검색하고 가져오는 공용 소스이다.
/plugin marketplace add your-org/claude-plugins
- 마켓플레이스 이름은 원하는 대로 정할 수 있다.
- 한 번 추가하면 이후의 모든 설치가 마켓플레이스를 통해 처리된다.
- 이를 통해서 모든 팀원의 노트북에 설정이 흩어지는 대신, 한곳에서 플러그인을 검색하고 버전을 추적하면 업데이트할 수 있다.
- Discover 탭에서 사용 가능한 플러그인을 둘러볼 수 있다. 등록한 마켓플레이스의 플러그인 목록이 표시되므로, 원하는 플러그인을 검색하고 선택 가능하다.
가장 중요한 것은 플러그인은 사용자의 권한으로 컴퓨터에서 코드를 실행한다는 것이다. 플러그인의 훅은 조건에 맞는 도구 호출이 발생할 때마다 실행된다.
어떤 플러그인을 스킬 때문에 설치했더라도, 내부 내용을 확인했는지와 관계없이 해당 플러그인의 PreToolUse 훅과 Stop 훅도 함께 적용된다. → 즉, 설치전에 꼭 상세 정보를 확인해봐야 한다. 플러그인의 출처와 관련해서 알아야할 내용은 다음과 같다.
- 앱 내부의 제출 양식으로 등록된 플러그인은 Anthropic의 자동 검토를 거친 후 커뮤니티 마켓플레이스에 게시된다.
- 공식 마켓플레이스는 별도의 절차로 선별되고 관리된다.
- 검토를 통과했다고 신뢰할 수 있다는 뜻이 아니다. 자동 검토는 모든 문제를 발견하지 못한다.
- 플러그인을 설치하거나 마켓플레이스를 추가할 때는 정말 신뢰할 수 있는 출처만 사용하고, 활성화하기 전에 플러그인이 실제로 무엇을 하는지 확인하라
플러그인 구성 요소는 기존 구성과 함께 실행된다.
- 기존 설정을 덮어쓰지 않는다. 대체로 좋은 방식이지만 알아야 할 결과가 있다.
- 훅은 누적된다. 즉, 기존 구성과 플러그인 구성 요소 훅 모두 동작한다.
- 플러그인에 settings.json 파일을 포함할 수 있지만, 사용할 수 있는 설정은 제한적이다. claude code는 해당 파일에서 에이전트와 서브 에이전트의 상태 표시줄에 관련된 두 개의 키만 적용한다.
- 여기서 agent 키는 특히 주의해서 봐야한다. 이를 설정하면, 플러그인의 서브 에이전트 하나가 메인 스레드의 에이전트로 승격된다.
- 해당 서브 에이전트의 시스템 프롬프트, 도구 제한 및 모델 설정도 함께 적용된다.
- 즉, 플러그인을 활성화하는 것만으로 claude code의 기본 동작 방식이 달라질 수 있다.
제대로 작동하는 .claude 디렉터리를 만들었다면 팀원들이 컴퓨터 사이에서 이를 복사하고 붙여 넣게 하지 말고 플러그인으로 패키징하면 된다.
기존 구조를 바꿀 필요는 없다. 플러그인은 이미 사용 중인 .claude와 동일한 구조를 사용한다.
- 스킬마다 하나의 폴더
agents디렉터리 아래에 서브 에이전트별 마크다운 파일 하나- 플러그인 루트에
hooks/hooks.json과.mcp.json
디렉터리 구조가 대부분의 역할을 수행한다. Claude Code는 정해진 규칙에 따라 각 구성 요소를 자동으로 발견한다.
추가로, 매니페스트 파일을 추가할 수 있다. 매니페스트는 .claude-plugin/plugin.json에 위치하며 이름, 버전, 설명 및 작성자 정보를 담는다.
{
"name": "svg-splitter-review",
"version": "0.1.0",
"description": "SVG Splitter 저장소를 검토합니다",
"author": {
"name": "Lewis Menelaws"
}
}
- 매니페스트는 선택 사항이다. 매니페스트가 없어도 claude code는 디렉터리 규칙에 따라 구성 요소를 발견한다. 다만 다음 사항은 알아둘 가치가 있다.
- name은 유일한 필수 필드이다. 스킬에 네임스페이스를 부여해 다른 플러그인의 스킬과 충돌하지 않도록 한다.
- 다른 의존성과 마찬가지로 버전을 지정해야 한다. 그래야 팀 전체에서 업데이트하고 버전을 추적할 수 있다.