본문 바로가기
AI_공부

클로드코드 플러그인 완전정복 · 6편

by shaprimanAI 2026. 7. 28.
반응형
클로드코드 플러그인 완전정복 · 6편

훅이랑 MCP까지 한 봉지에 넣어버리기

설치 한 번에 환경이 완성되는 플러그인 — 여기서부터 진짜 강력해져.

여기까지 왔으면 스킬이랑 에이전트는 익숙해졌을 거야. 근데 플러그인의 진짜 힘은 지금부터야. 훅과 MCP를 같이 넣으면, 설치 한 번에 작업 환경이 통째로 세팅되거든.

훅 — 특정 순간에 자동으로 끼어드는 스크립트

훅은 "언제 무슨 일이 생기면 이걸 실행해"를 정의하는 거야. 파일을 저장할 때마다 린트를 돌린다든가, 커밋 전에 검사를 한다든가.

플러그인에서는 hooks/hooks.json에 넣어. 형식은 settings.json에 쓰던 hooks 객체랑 똑같아.

my-plugin/hooks/hooks.json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '.tool_input.file_path' | xargs npm run lint:fix"
          }
        ]
      }
    ]
  }
}

읽어보면 이런 뜻이야. 도구를 쓴 직후(PostToolUse)에, 그게 Write나 Edit이면(matcher), 해당 파일에 린트를 돌려라.

💡 jq가 왜 나와? — 훅 명령어는 표준입력으로 JSON을 받아. 어떤 파일이 수정됐는지도 그 JSON 안에 들어있고. 그래서 jqfile_path만 뽑아서 다음 명령에 넘기는 거야.

플러그인 안의 스크립트를 부르고 싶다면

훅에서 플러그인에 동봉한 셸 스크립트를 실행하고 싶을 때가 있어. 근데 여기 함정이 하나 있어.

⚠️ 플러그인은 설치되면 캐시로 복사돼
내 개발 폴더 경로를 하드코딩하면 남의 컴퓨터에선 100% 깨져. 그래서 ${CLAUDE_PLUGIN_ROOT} 변수를 써야 해. 이건 플러그인이 실제로 설치된 위치를 가리켜.
{
  "type": "command",
  "command": "${CLAUDE_PLUGIN_ROOT}/scripts/validate.sh"
}

같은 이유로 ../shared-utils처럼 플러그인 폴더 바깥을 참조하는 경로도 안 돼. 캐시에 복사될 때 그 파일들은 안 따라오거든.

MCP 서버 — 이게 진짜 킬러 기능

MCP 서버를 플러그인에 넣으면 어떻게 되냐면, 플러그인 설치 한 번에 외부 서비스 연결까지 끝나. 사용자가 설정 파일 열어서 손댈 필요가 없어져.

플러그인 루트에 .mcp.json을 두면 돼.

my-plugin/.mcp.json
{
  "mcpServers": {
    "my-service": {
      "command": "${CLAUDE_PLUGIN_ROOT}/servers/my-server",
      "args": ["--config", "${CLAUDE_PLUGIN_ROOT}/config.json"]
    }
  }
}

여기서도 ${CLAUDE_PLUGIN_ROOT}가 등장하지? 이유는 훅이랑 똑같아.

✓ 이게 왜 대단하냐면 — 예를 들어 이미지 생성 파이프라인을 팀에 공유한다고 해보자. 예전엔 "MCP 설정 파일 여시고요, 여기에 이걸 넣으시고요..." 설명이 열 줄 넘었어. 이제는 /plugin install 한 줄이면 스킬 + 에이전트 + MCP 연결이 전부 딸려와.
💡 상태를 저장해야 한다면 — 캐시는 업데이트할 때 갈아엎어져. 플러그인 업데이트 후에도 남아있어야 하는 데이터는 ${CLAUDE_PLUGIN_DATA}를 쓰자.
⚠️ MCP가 들어가면 /reload-plugins가 얌전하지 않아
MCP 서버를 제공하는 플러그인은 리로드할 때 프롬프트 캐시가 통째로 무효화돼. 다음 요청에서 대화 전체를 다시 읽어야 해서 비용이 확 뛰거든. 그래서 클로드코드가 경고만 띄우고 리로드를 실제로 적용하지 않아. 그래도 지금 적용하고 싶으면 --force를 붙이면 돼.
/reload-plugins --force

개발 중엔 그냥 세션을 새로 띄우는 게 나을 때도 많아. 어차피 대화 맥락이 얼마 없는 상태니까.

LSP 서버 — 코드 지능 붙이기

LSP는 VS Code에서 "정의로 이동", "참조 찾기" 되게 해주는 그 프로토콜이야. 이걸 붙이면 클로드가 코드베이스를 훨씬 정확하게 이해해.

my-plugin/.lsp.json
{
  "go": {
    "command": "gopls",
    "args": ["serve"],
    "extensionToLanguage": {
      ".go": "go"
    }
  }
}
💡 근데 대부분은 만들 필요 없어 — TypeScript, Python, Rust, Java, Go 같은 주요 언어는 공식 마켓플레이스에 이미 LSP 플러그인이 있어. 직접 만드는 건 거기 없는 언어를 쓸 때만 하면 돼.

주의할 점 하나. LSP 플러그인을 쓰려면 사용자 컴퓨터에 해당 언어 서버 바이너리가 설치돼 있어야 해. 없으면 안 뜨니까 README에 꼭 적어두자.

백그라운드 모니터 — 로그 지켜보게 하기

이건 상대적으로 덜 알려진 기능인데 은근 재밌어. 로그 파일이나 외부 상태를 백그라운드에서 계속 지켜보다가, 뭔가 생기면 클로드한테 알려주는 거야.

my-plugin/monitors/monitors.json
[
  {
    "name": "error-log",
    "command": "tail -F ./logs/error.log",
    "description": "애플리케이션 에러 로그"
  }
]

command가 뱉는 표준출력 한 줄 한 줄이 알림으로 전달돼. 플러그인이 활성화되면 클로드코드가 알아서 모니터를 시작하니까, "로그 좀 봐줘"라고 시킬 필요도 없어.

개발 서버 돌려놓고 에러 나면 바로 클로드가 인지하게 만드는 용도로 괜찮아.

bin/ — 실행 파일 딸려 보내기

플러그인 루트에 bin/ 폴더를 두면, 플러그인이 켜져 있는 동안 그 안의 실행 파일들이 Bash 도구의 PATH에 자동으로 추가돼. 사용자가 별도로 설치할 필요 없이 전용 CLI 도구를 딸려 보낼 수 있는 거지.

다 합치면 이런 모양

my-workflow-plugin/
├── .claude-plugin/
│   └── plugin.json
├── skills/
│   └── generate/SKILL.md
├── agents/
│   └── planner.md
├── hooks/
│   └── hooks.json          # 저장할 때마다 린트
├── monitors/
│   └── monitors.json       # 에러 로그 감시
├── scripts/
│   └── validate.sh         # 훅이 부르는 스크립트
├── bin/
│   └── mytool              # PATH에 자동 등록
└── .mcp.json               # 외부 서비스 연결
6편의 핵심

플러그인 안에서 경로를 쓸 땐 무조건 ${CLAUDE_PLUGIN_ROOT}.
설치되면 캐시로 복사된다는 걸 잊지 말자.

⚠️ 훅 넣은 뒤엔 꼭 검증hooks/hooks.json의 JSON이 깨지면 플러그인 전체가 로드에 실패해. 스킬도 에이전트도 다 안 떠. 수정할 때마다 claude plugin validate ./my-plugin 한 번씩 돌리자.
반응형