Claude Code Plugin 스코프와 Managed 스코프
이 글에서 다루는 내용
이 글에서는 Claude Code의 기본 스코프(Local/Project/User) 위에 존재하는 Plugin 스코프와 Managed 스코프를 설명합니다. 플러그인이 본질적으로 무엇인지, mcpServers에 추가되는 서버가 Plugin 스코프인지 어떻게 구분하는지, 플러그인 루트(${CLAUDE_PLUGIN_ROOT})가 무엇이며 Mac에서 실제 경로를 어떻게 확인하는지를 다룹니다. 이어서 플러그인을 잘 활용하지 못하는 것은 아닌지에 대한 관점, GitHub·Linear·Asana·Playwright 같은 도구 연결이 실제 작업을 어떻게 개선하는지, 작업별로 어떤 플러그인을 설치하는지, 설치 후 발동 시점은 언제인지, 설치된 플러그인이 많을 때의 로딩 부담과 Tool Search, 그리고 Managed 스코프의 용도와 플러그인 구성요소 중 커맨드·훅의 정의까지 정리합니다.
Plugin 스코프
플러그인은 본질적으로 여러 도구(MCP 서버 + 커맨드 + 스킬 + 훅)를 한 묶음으로 편하게 배포·설치하는 포장 방식입니다. 플러그인 자체가 새로운 기능을 주는 것이 아니라, 이미 있는 기능들을 한 번에 깔아주는 편의 장치에 가깝습니다.
동작 방식은 이렇습니다. 플러그인은 MCP 서버를 플러그인 루트의 .mcp.json에 정의하거나 plugin.json 안에 인라인으로 정의합니다. 플러그인이 활성화되면 해당 MCP 서버들이 자동으로 시작되고, 플러그인 MCP 도구는 수동 설정한 MCP 도구와 나란히 표시되며, 플러그인 서버는 /mcp 명령이 아니라 플러그인 설치를 통해 관리됩니다.
{
"mcpServers": {
"database-tools": {
"command": "${CLAUDE_PLUGIN_ROOT}/servers/db-server",
"args": ["--config", "${CLAUDE_PLUGIN_ROOT}/config.json"],
"env": { "DB_URL": "${DB_URL}" }
}
}
}
특징적인 점은 전용 환경변수를 쓴다는 것입니다. 번들된 플러그인 파일에는 ${CLAUDE_PLUGIN_ROOT}, 플러그인 업데이트 후에도 유지되는 영속 상태에는 ${CLAUDE_PLUGIN_DATA}, 안정적인 프로젝트 루트에는 ${CLAUDE_PROJECT_DIR}를 사용합니다.
mcpServers에서 Plugin 스코프 구분하기
Plugin 스코프 서버는 개인 설정 파일(~/.claude.json이나 프로젝트 .mcp.json)에 들어가지 않습니다. 같은 mcpServers 형식을 쓰지만 저장 위치가 플러그인 내부라는 점이 결정적 차이입니다.
빠른 판별 순서는 다음과 같습니다.
| 확인 | 결과 |
|---|---|
/mcp 패널에 "plugin" 출처 표시가 있나? |
있으면 Plugin |
claude mcp remove로 지워지나? |
안 지워지면 Plugin (플러그인 관리 대상) |
설정에 ${CLAUDE_PLUGIN_ROOT} 등이 있나? |
있으면 Plugin |
~/.claude.json / 프로젝트 .mcp.json에 항목이 있나? |
없는데 떠 있으면 Plugin |
세션 안에서 /mcp를 실행하면 플러그인 서버는 플러그인에서 왔음을 나타내는 표시와 함께 나타나고, claude.ai 커넥터도 claude.ai에서 왔다는 표시와 함께 나타납니다. 또한 플러그인 서버는 claude mcp remove로 지워지지 않고, 플러그인 자체를 비활성화/제거하거나 /reload-plugins로 연결을 끊어야 합니다.
플러그인 루트와 ${CLAUDE_PLUGIN_ROOT}
플러그인 루트는 하나의 플러그인이 설치되어 그 파일들이 모여 있는 최상위 디렉터리를 말합니다. 프로젝트에 "프로젝트 루트"가 있듯이, 플러그인에도 그 플러그인만의 루트 폴더가 있는 셈입니다. 여기에는 plugin.json(메타데이터, 정확히는 .claude-plugin/plugin.json), MCP 서버를 번들하는 경우 .mcp.json, 서버 실행 파일, 설정 파일 등이 함께 들어갑니다.
${CLAUDE_PLUGIN_ROOT}를 쓰는 이유는 플러그인이 사용자·머신마다 다른 절대 경로에 설치되기 때문입니다. 설정에 절대 경로를 박아두면 깨지므로, Claude Code가 실행 시점에 그 사용자의 실제 설치 경로로 자동 치환해 주는 변수를 사용합니다.
| 변수 | 가리키는 곳 |
|---|---|
${CLAUDE_PLUGIN_ROOT} |
플러그인이 설치된 폴더 (플러그인 자기 자신의 파일들) |
${CLAUDE_PROJECT_DIR} |
사용자가 작업 중인 프로젝트 루트 |
${CLAUDE_PLUGIN_DATA} |
플러그인 업데이트 후에도 유지되는 영속 상태 저장 폴더 |
Mac에서 플러그인 경로 확인하기
${CLAUDE_PLUGIN_ROOT}는 Claude Code가 실행 시점에만 치환하는 변수라, 터미널에서 echo $CLAUDE_PLUGIN_ROOT 해도 보통 빈 값이 나옵니다. Mac에서 실제 경로를 확인하려면 디렉터리를 직접 점검합니다.
# 플러그인 설치 디렉터리
ls -la ~/.claude/plugins/
# 등록된 마켓플레이스
cat ~/.claude/plugins/known_marketplaces.json
# plugin.json 위치로 각 플러그인 루트 찾기
find ~/.claude/plugins -name "plugin.json"
# MCP를 번들한 플러그인 찾기
find ~/.claude/plugins -name ".mcp.json"
# 실제 활성화된 플러그인 목록
claude plugin list
여기서 중요한 구분이 있습니다. marketplaces/ 아래에 보이는 플러그인들은 "설치 가능한 카탈로그"일 뿐이며, 마켓플레이스를 등록하면 카탈로그가 통째로 캐시됩니다. 실제로 활성화된 플러그인이 무엇인지는 claude plugin list로 확인해야 정확합니다. 만약 "No plugins installed"가 나온다면, 마켓플레이스만 등록되어 있고 개별 플러그인은 설치되지 않은 상태입니다. 이 경우 현재 보이는 mcpServers 항목은 Plugin 스코프가 아니라 Local·Project·User 스코프(또는 claude.ai 커넥터)에서 온 것입니다.
플러그인을 잘 활용하지 못하는 걸까
플러그인을 안 쓴다고 해서 Claude Code를 잘못 쓰고 있는 것이 아닙니다. 판단 기준은 "플러그인을 쓰느냐"가 아니라 "내가 반복적으로 Claude Code 밖에서 복사해 오는 작업이 있느냐"입니다. 이슈 트래커나 모니터링 대시보드에서 데이터를 채팅창에 복사해 붙여넣고 있는 자신을 발견할 때가 바로 그 도구를 연결할 타이밍입니다.
이런 반복이 없다면 굳이 미리 다 깔아둘 이유가 없습니다. 안 쓰는 MCP 서버를 많이 붙이면 컨텍스트만 차지하기 때문입니다. 플러그인을 꼭 써야 하는 경우는 팀 전체가 동일한 도구 세트를 일관되게 갖춰야 할 때입니다. 혼자 쓰는 단계라면 claude mcp add로 필요한 것만 그때그때 붙이는 것이 더 가볍고 명확합니다.
도구 연결이 작업을 어떻게 개선하나
핵심은 복사·붙여넣기·창 전환이 사라지고, Claude가 그 시스템을 직접 읽고 쓰는 에이전트가 된다는 점입니다.
GitHub를 연결하면 이슈 번호만 말해도 됩니다. "JIRA 이슈 ENG-4521에 설명된 기능을 추가하고 GitHub에 PR을 만들어줘"처럼 구현부터 PR 생성까지 한 번에 시킬 수 있고, "PR #456을 리뷰하고 개선점을 제안해줘", "나에게 할당된 열린 PR을 모두 보여줘" 같은 작업이 가능합니다.
Linear·Asana를 연결하면 읽기와 쓰기가 다 자동화됩니다. 티켓 내용을 옮겨 적고 작업 후 상태를 수동으로 바꾸던 양방향 작업이, "이번 스프린트 이슈 보여줘 → 구현 → 상태를 Done으로 변경" 같은 한 흐름으로 이어집니다. 모니터링 데이터 분석도 가능해서 여러 시스템을 엮어 물어볼 수 있습니다.
Playwright를 연결하면 자연어로 브라우저 테스트를 돌립니다. "test@example.com으로 로그인 플로우가 동작하는지 테스트해줘", "모바일에서 결제 페이지 스크린샷 찍어줘" 같은 식으로 수동 클릭 테스트가 대화 한 줄로 바뀝니다.
작업별 설치 플러그인
세 작업에 각각 필요한 플러그인은 공식 마켓플레이스(claude-plugins-official) 카탈로그에 들어 있습니다.
claude plugin install github@claude-plugins-official
claude plugin install linear@claude-plugins-official
claude plugin install asana@claude-plugins-official
claude plugin install playwright@claude-plugins-official
claude plugin list # 설치 후 확인
| 작업 | 플러그인 | 설치 후 인증 |
|---|---|---|
| GitHub 이슈/PR | github | PAT 또는 OAuth |
| Linear 티켓 | linear | /mcp로 OAuth |
| Asana 티켓 | asana | /mcp로 OAuth |
| 브라우저 테스트 | playwright | 인증 불필요 (로컬 stdio) |
설치 전에 어떤 서버를 가져오는지 미리 보려면 cat ~/.claude/plugins/marketplaces/claude-plugins-official/external_plugins/<name>/.mcp.json으로 확인할 수 있습니다. type이 http/sse면 원격 서버라 OAuth가 필요하고, command(예: npx)면 로컬 stdio라 별도 로그인이 없습니다.
설치 후 발동 시점
설치와 발동의 시점은 다릅니다. 발동에는 세 단계가 있습니다.
| 단계 | 시점 | 무슨 일 |
|---|---|---|
| 1. 연결 | 세션 시작 (또는 /reload-plugins) |
MCP 서버가 Claude Code에 붙음 |
| 2. 인증 | /mcp에서 OAuth (원격 서버만) |
도구가 실제 사용 가능해짐 |
| 3. 호출 | 내가 관련 작업을 요청할 때 | Claude가 필요한 도구를 골라 실행 |
세션 시작 시 활성화된 플러그인의 서버가 자동으로 연결됩니다. 이미 실행 중인 세션에서 방금 설치했다면 /reload-plugins로 다시 불러오거나 세션을 재시작해야 합니다. 원격 서버는 연결됐어도 /mcp에서 OAuth 인증을 통과해야 도구가 동작합니다. 인증 토큰은 안전하게 저장되고 자동 갱신됩니다. 인증까지 끝나면 이후엔 평소처럼 일을 시킬 때 Claude가 알아서 도구를 꺼내 씁니다.
플러그인이 많으면 로딩 부담은
설치된 플러그인이 많으면 세션 시작 때마다 서버를 연결하는 비용은 발생하지만, 대부분 백그라운드에서 처리되고 컨텍스트 부담은 예전만큼 크지 않습니다. 두 종류의 비용을 구분하면 명확합니다.
서버 연결 비용은 세션 시작 때마다 발생하지만, MCP 시작은 기본적으로 논블로킹이라 다른 서버들은 백그라운드에서 계속 연결됩니다. 컨텍스트 비용은 Tool Search가 기본값으로 켜져 있어 거의 사라졌습니다. Tool Search는 세션 시작 시 도구 이름과 서버 설명만 로드하고 실제 도구 정의는 미뤄두며, Claude가 실제로 쓰는 도구만 컨텍스트에 들어옵니다. 그래서 MCP 서버를 더 추가해도 컨텍스트 창에 미치는 영향이 미미합니다.
| Tool Search 이전 | 지금 (기본값) | |
|---|---|---|
| 서버 연결 | 세션마다 발생 | 세션마다 발생 (백그라운드) |
| 도구 스키마 로딩 | 전부 컨텍스트에 올라감 | 이름·설명만, 정의는 필요 시 검색 |
| 많이 붙였을 때 | 컨텍스트 크게 잠식 | 영향 미미 |
가장 깔끔한 원칙은 실제로 자주 쓰는 것만 설치해두는 것입니다. 매 턴 필요한 소수의 도구만 alwaysLoad로 컨텍스트에 올릴 수 있지만, 이 경우 그 서버가 연결될 때까지 시작이 차단되므로 남발은 금물입니다.
Managed 스코프
Managed 스코프는 조직(IT/관리자)이 위에서 강제로 내려보내는 MCP 설정입니다. Local/Project/User/Plugin이 전부 개발자 본인이 자기 환경을 구성하는 스코프였다면, Managed는 개인이 손댈 수 없는, 회사가 정하는 스코프입니다.
중앙 집중식 통제가 필요한 조직을 위해, 관리자는 managed-mcp.json으로 고정된 서버 세트를 배포하고, allowedMcpServers와 deniedMcpServers로 서버를 제한할 수 있습니다. 강제 배포와 허용/차단 목록 두 가지를 모두 수행합니다.
우선순위에서 Managed가 최상위인 이유는, 개인이 같은 이름의 서버를 Local이나 User로 추가해도 Managed가 정한 것이 이겨야 보안·거버넌스 목적이 성립하기 때문입니다. Managed 설정은 가장 높은 우선순위라서 다른 어떤 것으로도 덮어쓸 수 없습니다. 규제가 엄격한 기업의 "승인된 서버만 사용 허용", 신뢰 안 된 외부 서버 차단(프롬프트 인젝션 방지), 전사 표준 도구 일괄 배포 등에 쓰입니다. 개인 머신에서 혼자 쓰는 환경이라면 사실상 신경 쓸 일이 없습니다.
다섯 스코프 한눈에 정리
| 스코프 | 누가 설정 | 통제 방향 | 개인이 덮어쓰기 |
|---|---|---|---|
| Managed | 조직/IT 관리자 | 위에서 강제 | 불가 (최상위) |
| Local | 본인 | 프로젝트 단위 비공개 | 가능 |
| Project | 팀 (.mcp.json 커밋) | 팀 공유 | 가능 |
| User | 본인 | 전 프로젝트 개인용 | 가능 |
| Plugin | 본인/팀 (번들 설치) | 묶음 배포 | 가능 |
세 스코프(Local·Project·User)는 이름으로 중복을 판단하지만, 플러그인과 커넥터는 엔드포인트(URL·command)로 매칭합니다.
플러그인 구성요소 - 커맨드와 훅
플러그인이 묶을 수 있는 네 가지 중 커맨드와 훅의 역할은 다음과 같습니다.
커맨드는 /로 시작하는, 사용자가 직접 호출하는 명령입니다. 자주 반복하는 프롬프트나 작업 절차를 미리 정의해두고 한 단어로 부릅니다. MCP 서버가 프롬프트를 노출하면 /mcp__서버명__프롬프트명 형식의 커맨드로 나타나고 인자도 공백으로 구분해 전달할 수 있습니다. 핵심은 내가 의도적으로 부를 때만 동작한다는 점입니다.
훅은 특정 이벤트가 일어날 때 자동으로 실행되는 동작입니다. 커맨드가 "내가 부르는 것"이라면, 훅은 "조건이 맞으면 시키지 않아도 알아서 돌아가는 것"입니다. 린팅을 매 편집마다 돌리거나 테스트 통과 전까지 커밋을 막는 것처럼, 예외 없이 매번 일어나야 하는 일에 씁니다. 훅은 결정론적이고 시스템 지향적인 반면, 스킬은 맥락을 보고 Claude가 언제 적용할지 스스로 판단합니다.
| 구성요소 | 발동 방식 | 성격 |
|---|---|---|
| MCP 서버 | Claude가 작업에 필요할 때 호출 | 외부 시스템 연결(읽기·쓰기) |
| 커맨드 | 내가 /명령으로 직접 호출 |
미리 정의한 프롬프트·절차 단축키 |
| 스킬 | Claude가 맥락 보고 스스로 판단해 적용 | 상황 인지형 지식·절차 |
| 훅 | 이벤트 발생 시 자동 (결정론적) | 강제 규칙·자동화 |
플러그인 하나에 이 네 가지를 다 담을 수 있어서, 팀원은 플러그인 하나만 설치하면 관련 도구 일습이 한꺼번에 세팅됩니다.