ClOr

ClOr

백엔드 실무 트러블슈팅과 AI 에이전트 구조 분석을 기록합니다.

Claude Code 해부학 (완결)

51만 줄 소스코드를 19편에 걸쳐 분석한 완결 시리즈

전체 시리즈 보기 →

백엔드 트러블슈팅

실무에서 겪은 장애와 해결 과정 기록

전체 시리즈 보기 →

최신 글

article thumbnail

시리즈 이전 편: [Part 10] 권한 시스템 분석 — rm -rf를 못 치게 막는 법

결론부터 말하면, 클로드 코드(Claude Code)의 MCP 구현은 6가지 전송 방식을 지원하는 플러그 앤 플레이 도구 연결 시스템입니다. 소스코드를 분석해보니 client.ts 하나가 117KB — 이 파일 하나에 서버 연결, 도구 등록, OAuth 인증, 세션 관리가 전부 들어있었습니다. MCP(Model Context Protocol)는 AI가 외부 도구를 쓸 수 있게 해주는 표준 프로토콜인데, Claude Code가 이걸 어떻게 구현했는지 직접 까봤습니다.


목차

  • MCP가 뭔가요? USB 비유로 설명하면
  • Claude Code는 MCP 서버를 어떻게 찾나?
  • 6가지 전송 방식 — 왜 이렇게 많을까?
  • 도구 이름은 어떻게 충돌을 막나?
  • 연결이 끊기면 어떻게 되나?
  • 서브프로세스 정리 — 600ms 안에 끝내는 3단계
  • 그래서 뭐가 달라지나
  • 요약

MCP가 뭔가요? USB 비유로 설명하면

컴퓨터에 USB 포트가 있으면 키보드든 마우스든 외장하드든 꽂기만 하면 됩니다. MCP는 AI 모델의 USB 포트입니다. GitHub 서버를 꽂으면 이슈를 만들 수 있고, DB 서버를 꽂으면 쿼리를 날릴 수 있습니다.

핵심은 표준화입니다. 도구마다 연결 방식이 다르면 매번 코드를 새로 짜야 하지만, MCP라는 규격이 있으면 아무 도구나 꽂을 수 있습니다.

Claude Code는 MCP 서버를 어떻게 찾나?

설정 파일 .mcp.json을 읽습니다. 4개 스코프에서 순서대로 로드하고, 뒤에 오는 설정이 앞을 덮어씁니다.

// src/services/mcp/types.ts
// 주요 설정 스코프 (실제로는 dynamic, managed 포함 6개)
type ConfigScope = 'local' | 'user' | 'project' | 'enterprise' | 'dynamic' | 'managed'

프로젝트 루트의 .mcp.json에 서버를 등록하면 Claude Code가 시작할 때 자동으로 연결합니다. 가장 많이 쓰는 건 local(개인)과 project(프로젝트 공유) 스코프입니다. 환경변수도 ${VAR_NAME} 문법으로 확장됩니다.

6가지 전송 방식 — 왜 이렇게 많을까?

여기가 인상적인 부분입니다. Claude Code는 MCP 서버와 통신하는 전송 계층을 6가지나 지원합니다.

// src/services/mcp/types.ts
type Transport = 'stdio' | 'sse' | 'sse-ide' | 'http' | 'ws' | 'sdk'
전송 방식 사용 상황 특징
stdio 로컬 CLI 도구 서브프로세스 생성, 가장 흔함
SSE 원격 서버 HTTP 스트리밍, 장시간 연결
HTTP 클라우드 API 요청/응답 + SSE 혼합
WebSocket 양방향 실시간 TLS, 프록시 지원
SDK 인프로세스 서브프로세스 없이 직접 실행
IDE VS Code 등 IDE 확장 브릿지

USB로 치면, USB-A, USB-C, Thunderbolt, 블루투스를 전부 지원하는 셈입니다. 어떤 서버든 하나는 맞습니다.

도구 이름은 어떻게 충돌을 막나?

MCP 서버마다 create_issue라는 도구를 만들 수 있습니다. 이름이 겹치면 어떡할까요?

// src/services/mcp/mcpStringUtils.ts
// 도구 이름 형식: mcp__서버명__도구명
// 예: mcp__github__create_issue, mcp__jira__create_issue

mcp__ 접두사 + 서버 이름으로 네임스페이스를 만듭니다. 단순하지만 확실한 방법입니다. 내장 도구(BashTool, FileReadTool 등)와도 절대 충돌하지 않습니다.

연결이 끊기면 어떻게 되나?

MCP 서버 연결은 5가지 상태를 가집니다.

// src/services/mcp/types.ts
type MCPServerConnection =
  | ConnectedMCPServer    // 연결됨, 정상
  | FailedMCPServer       // 연결 실패
  | NeedsAuthMCPServer    // 인증 필요 (401)
  | PendingMCPServer      // 연결 중, 재시도 가능
  | DisabledMCPServer     // 사용자가 비활성화

네트워크 오류가 3번 연속 발생하면 트랜스포트를 닫고, 지수 백오프(1초→2초→4초→...→최대 30초)로 재연결을 시도합니다. 최대 5번까지.

쉽게 말하면, 서버가 잠깐 죽어도 자동으로 다시 붙습니다. 사용자는 아무것도 안 해도 됩니다.

서브프로세스 정리 — 600ms 안에 끝내는 3단계

stdio 방식으로 띄운 MCP 서버 프로세스는 종료할 때 깔끔하게 정리해야 합니다. Claude Code의 방식이 영리합니다.

SIGINT (100ms 대기) → SIGTERM (400ms 대기) → SIGKILL (즉시)
총 최대 600ms

"정중하게 부탁 → 강하게 요청 → 강제 종료" 3단계입니다. CLI가 종료될 때 MCP 서버 프로세스가 좀비로 남지 않으면서도, 600ms 안에 모든 정리가 끝납니다.

그래서 뭐가 달라지나

MCP 구현을 뜯어보면 AI 도구 연결 시스템 설계의 교훈이 보입니다.

  • 전송 계층을 추상화하라 — 연결 방식을 플러그인처럼 교체 가능하게
  • 네임스페이스로 충돌을 원천 차단하라mcp__서버__도구 패턴
  • 상태 머신으로 연결을 관리하라 — 5가지 상태로 모든 장애 시나리오 대응
  • 프로세스 정리에 타임아웃을 두라 — SIGINT→SIGTERM→SIGKILL 600ms 패턴

요약

  • MCP는 AI의 USB 포트 — 표준 프로토콜로 아무 도구나 꽂을 수 있다
  • 6가지 전송 방식(stdio, SSE, HTTP, WebSocket, SDK, IDE)으로 어떤 서버든 연결 가능
  • mcp__서버__도구 네임스페이스로 도구 이름 충돌을 원천 차단
  • 5가지 연결 상태 + 지수 백오프 재연결로 안정성 확보
  • 서브프로세스는 SIGINT→SIGTERM→SIGKILL 3단계로 600ms 안에 정리

다음 편 예고: [Part 12] 메모리 시스템 분석 — Claude Code가 어제 대화를 기억하는 방법, 소스를 까봤습니다.

[Claude Code 해부학] 시리즈

관련글:

profile

ClOr

@ClOr

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

ClOr · 백엔드 트러블슈팅과 AI 에이전트 구조 분석을 기록합니다.