본문으로 건너뛰기
Kreath Archive
TechProjectsBooksAbout
TechProjectsBooksAbout

내비게이션

  • Tech
  • Projects
  • Books
  • About
  • Tags

카테고리

  • AI / ML
  • 웹 개발
  • 프로그래밍
  • 개발 도구

연결

  • GitHub
  • Email
  • RSS
© 2026 Kreath Archive. All rights reserved.Built with Next.js + MDX
홈TechProjectsBooksAbout
//
  1. 홈
  2. 테크
  3. 10장: 실전 프로젝트 -- 컨텍스트 엔지니어링 시스템 구축
2026년 3월 26일·AI / ML·

10장: 실전 프로젝트 -- 컨텍스트 엔지니어링 시스템 구축

시리즈 전체를 종합하여 실전 컨텍스트 엔지니어링 시스템을 구축합니다. CLAUDE.md 작성, MCP 서버 구현, 멀티에이전트 파이프라인, 측정 대시보드를 실습합니다.

20분1,115자10개 섹션
aiai-agentclaude-codellm
공유
context-engineering10 / 10
12345678910
이전9장: 컨텍스트 품질 측정과 개선

이 장에서 배우는 것

  • 프로젝트 컨텍스트 아키텍처 설계
  • 효과적인 CLAUDE.md 작성 실습
  • 컨텍스트 확장 MCP 서버 구축
  • 멀티에이전트 컨텍스트 파이프라인 설계
  • 측정 대시보드 구현
  • 도입 체크리스트

프로젝트 개요

이번 장에서는 이 시리즈에서 다룬 모든 개념을 종합하여, 실제 프로젝트에 적용할 수 있는 컨텍스트 엔지니어링 시스템을 단계별로 구축합니다. 대상 프로젝트는 TypeScript 기반 웹 애플리케이션을 가정합니다.

시스템 전체 아키텍처

Step 1: CLAUDE.md 작성

설계 원칙 적용

3장에서 배운 원칙을 적용하여 CLAUDE.md를 작성합니다.

CLAUDE.md
markdown
# My Project
 
## Commands
npm run dev       # dev server (port 3000)
npm run build     # production build (MUST pass before commit)
npm run test      # run tests
npm run lint      # ESLint + Prettier
 
## Critical Rules
1. TypeScript strict mode, NO 'any' or 'as any'
2. All components: named function declarations
3. Styling: Tailwind CSS only, use cn() for merging
4. Error handling: always use AppError class hierarchy
5. API responses: use ApiResponse<T> wrapper type
6. Database: all queries through repository pattern
 
## Architecture
src/
  app/           - Next.js App Router pages
  components/
    ui/          - Reusable UI primitives (Button, Input, Modal)
    features/    - Feature-specific components
  lib/
    db/          - Database client, repositories
    auth/        - Authentication utilities
    api/         - API client, types
  types/         - Shared TypeScript types
 
## Patterns (follow existing code)
- API route: src/app/api/users/route.ts (reference)
- Component: src/components/ui/Button.tsx (reference)
- Repository: src/lib/db/user-repository.ts (reference)
- Test: src/lib/db/__tests__/user-repository.test.ts (reference)
 
## Detailed Docs
- docs/architecture.md - Full architecture, data flow
- docs/api-guide.md    - API conventions, error codes
- docs/testing.md      - Test patterns, fixtures

체크리스트로 검증

작성한 CLAUDE.md를 다음 기준으로 검증합니다.

항목확인근거
300줄 미만인가약 40줄모든 대화에 로드되므로 간결해야 함
빌드 명령어가 정확한가npm run build에이전트가 검증에 사용
모든 규칙이 프로젝트 특화인가확인"좋은 코드를 작성하라" 같은 일반 규칙 없음
참조 패턴이 실제 파일을 가리키는가확인구체적 파일 경로 제공
상세 문서 경로가 명시되어 있는가확인필요 시 추가 읽기 가능
Tip

CLAUDE.md의 "Patterns" 섹션이 특히 중요합니다. 에이전트에게 "이 파일처럼 작성하라"고 참조 파일을 지정하면, 장황한 규칙 설명 없이도 일관된 코드가 생성됩니다. 하나의 좋은 예시가 열 줄의 규칙보다 효과적입니다.

Step 2: 계층적 컨텍스트 파일

프로젝트 루트의 CLAUDE.md 외에, 하위 디렉토리에 특화된 컨텍스트를 추가합니다.

src/lib/db/CLAUDE.md
markdown
# Database Layer
 
## Repository Pattern
- All database access through repository classes
- Each repository implements IRepository<T> interface
- Use Drizzle ORM query builder, NOT raw SQL
- All queries must have proper error handling with DBError
 
## Naming
- File: {entity}-repository.ts
- Class: {Entity}Repository
- Method: findById, findMany, create, update, delete
 
## Testing
- Use test fixtures from src/lib/db/__fixtures__/
- Mock database with in-memory SQLite
- Every repository method needs a test
src/components/CLAUDE.md
markdown
# Components
 
## Structure
- UI primitives in ui/ (no business logic)
- Feature components in features/ (can use hooks, API calls)
- Each component: one file, named export
 
## Styling
- Use cn() for className merging (import from "@/lib/utils")
- Follow design tokens in globals.css
- Dark mode: use CSS custom properties, NOT conditional classes
- Responsive: mobile-first approach
 
## Accessibility
- All interactive elements: keyboard navigable
- Images: always include alt text
- Form inputs: always include label

Step 3: MCP 서버 구축

8장에서 다룬 MCP 서버를 실제로 구현합니다. 이 서버는 코드베이스 바깥의 정보를 에이전트에게 동적으로 제공합니다.

mcp-servers/project-context/index.ts
typescript
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
import { execSync } from "child_process";
import { readFileSync, existsSync } from "fs";
import { join } from "path";
 
const server = new McpServer({
  name: "project-context-server",
  version: "1.0.0",
});
 
// 도구 1: 모듈 아키텍처 정보
server.tool(
  "get-module-info",
  "특정 모듈의 아키텍처, 의존성, 주요 파일 정보를 반환합니다",
  {
    modulePath: z.string().describe("모듈 경로 (예: src/lib/auth)"),
  },
  async ({ modulePath }) => {
    const info = analyzeModule(modulePath);
    return {
      content: [{
        type: "text",
        text: JSON.stringify(info, null, 2),
      }],
    };
  }
);
 
// 도구 2: 최근 변경 영향 분석
server.tool(
  "analyze-recent-changes",
  "최근 N개 커밋의 변경 파일과 영향 범위를 분석합니다",
  {
    count: z.number().default(5).describe("분석할 커밋 수"),
    path: z.string().optional().describe("특정 경로로 필터링"),
  },
  async ({ count, path }) => {
    const gitLog = execSync(
      `git log --oneline --name-only -${count} ${path ? `-- ${path}` : ""}`,
      { encoding: "utf-8" }
    );
    
    return {
      content: [{
        type: "text",
        text: `최근 ${count}개 커밋의 변경 파일:\n\n${gitLog}`,
      }],
    };
  }
);
 
// 도구 3: 의존성 그래프
server.tool(
  "get-dependency-graph",
  "파일의 import/export 의존성 그래프를 반환합니다",
  {
    filePath: z.string().describe("분석할 파일 경로"),
    depth: z.number().default(2).describe("추적 깊이"),
  },
  async ({ filePath, depth }) => {
    const graph = buildDependencyGraph(filePath, depth);
    return {
      content: [{
        type: "text",
        text: formatDependencyGraph(graph),
      }],
    };
  }
);
 
// 도구 4: 테스트 커버리지 정보
server.tool(
  "get-test-coverage",
  "특정 파일이나 모듈의 테스트 커버리지 정보를 반환합니다",
  {
    path: z.string().describe("파일 또는 모듈 경로"),
  },
  async ({ path }) => {
    const coverage = getTestCoverage(path);
    return {
      content: [{
        type: "text",
        text: formatCoverage(coverage),
      }],
    };
  }
);
 
// 헬퍼 함수들
function analyzeModule(modulePath: string) {
  const fullPath = join(process.cwd(), modulePath);
  
  if (!existsSync(fullPath)) {
    return { error: `경로를 찾을 수 없습니다: ${modulePath}` };
  }
  
  const files = execSync(`find ${fullPath} -name "*.ts" -o -name "*.tsx"`, {
    encoding: "utf-8",
  }).trim().split("\n");
  
  const exports = files.flatMap(file => {
    const content = readFileSync(file, "utf-8");
    const matches = content.match(/export\s+(function|class|const|interface|type)\s+(\w+)/g);
    return (matches ?? []).map(m => ({
      file: file.replace(process.cwd() + "/", ""),
      export: m,
    }));
  });
  
  return {
    path: modulePath,
    fileCount: files.length,
    exports,
    hasTests: existsSync(join(fullPath, "__tests__")),
    hasCLAUDEmd: existsSync(join(fullPath, "CLAUDE.md")),
  };
}
 
function buildDependencyGraph(filePath: string, depth: number) {
  // 간략화된 구현 - 실제로는 TypeScript Compiler API 사용
  const content = readFileSync(filePath, "utf-8");
  const imports = [...content.matchAll(/from\s+["']([^"']+)["']/g)]
    .map(m => m[1])
    .filter(imp => imp.startsWith(".") || imp.startsWith("@/"));
  
  return { file: filePath, imports, depth };
}
 
function formatDependencyGraph(graph: { file: string; imports: string[] }) {
  let result = `${graph.file}\n`;
  for (const imp of graph.imports) {
    result += `  -> ${imp}\n`;
  }
  return result;
}
 
function getTestCoverage(path: string) {
  // 실제 구현에서는 coverage report 파싱
  return { path, coverage: "N/A - run npm run test:coverage first" };
}
 
function formatCoverage(coverage: { path: string; coverage: string }) {
  return `${coverage.path}: ${coverage.coverage}`;
}
 
// 서버 시작
async function main() {
  const transport = new StdioServerTransport();
  await server.connect(transport);
}
 
main().catch(console.error);

MCP 서버 등록

.claude/settings.json
json
{
  "mcpServers": {
    "project-context": {
      "command": "npx",
      "args": ["tsx", "mcp-servers/project-context/index.ts"]
    }
  }
}

Step 4: 멀티에이전트 컨텍스트 파이프라인

7장의 격리 전략을 적용한 멀티에이전트 파이프라인을 설계합니다.

파이프라인 설계

에이전트별 컨텍스트 정의

agent-contexts.ts
typescript
const agentContexts = {
  coder: {
    shared: ["CLAUDE.md", "프로젝트 구조"],
    dedicated: {
      files: ["대상 모듈 코드", "관련 타입 정의", "참조 패턴 파일"],
      tools: ["read", "write", "edit", "grep", "glob", "terminal"],
      instructions: "코드를 작성/수정합니다. 기존 패턴을 따르세요.",
    },
  },
  
  tester: {
    shared: ["CLAUDE.md", "테스트 컨벤션"],
    dedicated: {
      files: ["테스트 대상 코드(인터페이스)", "기존 테스트 패턴", "테스트 픽스처"],
      tools: ["read", "write", "terminal"],
      instructions: "단위 테스트를 작성합니다. 기존 테스트 패턴을 따르세요.",
    },
  },
  
  reviewer: {
    shared: ["CLAUDE.md", "코딩 컨벤션"],
    dedicated: {
      files: ["변경된 코드 diff", "아키텍처 문서", "관련 모듈 인터페이스"],
      tools: ["read", "grep"],
      instructions: "코드를 리뷰하고 개선사항을 제안합니다.",
    },
  },
  
  analyzer: {
    shared: ["CLAUDE.md", "프로젝트 구조"],
    dedicated: {
      files: ["대상 모듈 전체", "의존성 그래프"],
      tools: ["read", "grep", "glob", "get-dependency-graph", "analyze-recent-changes"],
      instructions: "변경 영향을 분석하고 리팩토링 계획을 수립합니다.",
    },
  },
};

Step 5: 측정 대시보드

9장의 메트릭을 수집하고 시각화하는 시스템입니다.

메트릭 수집기

metrics/collector.ts
typescript
interface ContextMetric {
  timestamp: Date;
  taskId: string;
  taskType: string;
  
  // 컨텍스트 메트릭
  contextTokens: number;
  contextFiles: number;
  compressionRatio: number;
  
  // 결과 메트릭
  success: boolean;
  firstAttempt: boolean;
  iterationCount: number;
  buildPassed: boolean;
  testsPassed: boolean;
  
  // 효율성 메트릭
  totalCost: number;
  responseTimeMs: number;
}
 
class MetricsCollector {
  private metrics: ContextMetric[] = [];
  private storagePath: string;
  
  constructor(storagePath: string = ".claude/metrics.jsonl") {
    this.storagePath = storagePath;
  }
  
  record(metric: ContextMetric): void {
    this.metrics.push(metric);
    // JSONL 형식으로 추가 기록
    appendFileSync(
      this.storagePath,
      JSON.stringify(metric) + "\n"
    );
  }
  
  generateReport(period: "day" | "week" | "month"): Report {
    const filtered = this.filterByPeriod(period);
    
    return {
      period,
      totalTasks: filtered.length,
      successRate: this.calcRate(filtered, m => m.success),
      firstAttemptRate: this.calcRate(filtered, m => m.firstAttempt),
      avgCost: this.calcAvg(filtered, m => m.totalCost),
      avgTokens: this.calcAvg(filtered, m => m.contextTokens),
      avgIterations: this.calcAvg(filtered, m => m.iterationCount),
      costPerSuccess: this.calcCostPerSuccess(filtered),
      
      // 작업 유형별 분석
      byTaskType: this.groupBy(filtered, m => m.taskType),
      
      // 트렌드
      trend: this.calculateTrend(filtered),
    };
  }
  
  private calcRate(metrics: ContextMetric[], predicate: (m: ContextMetric) => boolean): number {
    if (metrics.length === 0) return 0;
    return metrics.filter(predicate).length / metrics.length;
  }
  
  private calcAvg(metrics: ContextMetric[], selector: (m: ContextMetric) => number): number {
    if (metrics.length === 0) return 0;
    return metrics.reduce((sum, m) => sum + selector(m), 0) / metrics.length;
  }
  
  private calcCostPerSuccess(metrics: ContextMetric[]): number {
    const successful = metrics.filter(m => m.success);
    if (successful.length === 0) return 0;
    return successful.reduce((sum, m) => sum + m.totalCost, 0) / successful.length;
  }
  
  private filterByPeriod(period: string): ContextMetric[] {
    // 기간별 필터링 구현
    return this.metrics;
  }
  
  private groupBy(metrics: ContextMetric[], key: (m: ContextMetric) => string) {
    const groups = new Map<string, ContextMetric[]>();
    for (const m of metrics) {
      const k = key(m);
      if (!groups.has(k)) groups.set(k, []);
      groups.get(k)?.push(m);
    }
    return Object.fromEntries(groups);
  }
  
  private calculateTrend(metrics: ContextMetric[]) {
    // 시간에 따른 성공률 변화 추적
    return { direction: "stable" as const };
  }
}

리포트 출력 예시

weekly-report.txt
text
=== 컨텍스트 엔지니어링 주간 리포트 ===
기간: 2026-03-29 ~ 2026-04-05
 
총 태스크: 47건
성공률: 87.2% (41/47)
첫 시도 성공률: 72.3% (34/47)
 
평균 컨텍스트 토큰: 28,450
평균 비용: $0.12/태스크
성공 건당 비용: $0.14
 
작업 유형별:
  create: 93.3% (14/15)
  modify: 85.0% (17/20)
  fix:    83.3% (10/12)
 
전주 대비:
  성공률: +3.2%p
  비용: -8.5%
  첫 시도 성공률: +5.1%p
 
개선 제안:
  - fix 유형 성공률이 낮음 -> 에러 컨텍스트 강화 권장
  - modify 유형에서 테스트 관련 실패 빈발 -> 테스트 컨텍스트 추가 권장

Step 6: 도입 체크리스트

프로젝트에 컨텍스트 엔지니어링을 도입할 때 참고할 체크리스트입니다.

Phase 1: 기초 (1-2일)

  • CLAUDE.md 작성 (300줄 미만, 핵심만)
  • 빌드/테스트 명령어 정확히 기록
  • 절대 규칙 3-5개 정의
  • 참조 패턴 파일 지정

Phase 2: 확장 (3-5일)

  • 하위 디렉토리 CLAUDE.md 추가
  • AGENTS.md 작성 (범용 규칙)
  • MCP 서버 구축 (DB 스키마, 이슈 트래커 등)
  • 후크 설정 (린트 자동 실행 등)

Phase 3: 최적화 (1-2주)

  • 메트릭 수집 시작
  • A/B 테스트로 전략 비교
  • 컨텍스트 파일 드리프트 감지 자동화
  • 작업 유형별 동적 컨텍스트 조립

Phase 4: 고도화 (지속)

  • 멀티에이전트 파이프라인 적용
  • 주간 리포트 기반 지속 개선
  • 팀 전체 도입 및 교육
  • 컨텍스트 파일 코드 리뷰 프로세스 추가
Warning

한 번에 모든 것을 구축하려 하지 마십시오. Phase 1의 기초만으로도 상당한 개선을 경험할 수 있습니다. 이후 단계는 메트릭에 기반하여 필요한 부분부터 점진적으로 도입하는 것이 효과적입니다.

핵심 원칙 정리

이 시리즈 전체를 관통하는 핵심 원칙을 정리합니다.

  1. 컨텍스트가 결과를 결정한다: 모델의 출력 품질은 프롬프트보다 컨텍스트에 더 크게 좌우됩니다.

  2. 적을수록 좋다: 300줄 미만의 집중된 CLAUDE.md가 500줄 이상의 비대한 파일보다 낫습니다. 더 많은 규칙이 더 나은 성능을 만들지 않습니다.

  3. 측정하고 개선한다: 주관적 판단이 아닌 태스크 성공률과 토큰 효율성으로 평가합니다.

  4. 코드화한다: 컨텍스트를 일급 엔지니어링 산출물로 다룹니다. 버전 관리하고, 테스트하고, 리뷰합니다.

  5. 동적으로 조립한다: 모든 작업에 동일한 컨텍스트를 사용하지 않습니다. 작업 유형과 복잡도에 따라 맞춤형 컨텍스트를 구성합니다.


시리즈를 마치며

10개 장에 걸쳐 컨텍스트 엔지니어링의 개념, 전략, 도구, 측정, 그리고 실전 적용을 살펴보았습니다.

프롬프트 엔지니어링이 "모델에게 잘 말하는 기술"이었다면, 컨텍스트 엔지니어링은 "모델이 잘 일할 수 있는 환경을 체계적으로 구축하는 기술"입니다. 이 분야는 아직 빠르게 발전하고 있으며, 모델의 능력이 향상될수록 컨텍스트의 품질이 차별화 요소가 됩니다.

컨텍스트 엔지니어링은 특정 도구에 종속되지 않는 범용 기술입니다. 오늘 이 시리즈에서 배운 원칙들은 내일 등장할 새로운 도구와 모델에서도 유효합니다. 선택, 압축, 정렬, 격리, 포맷이라는 다섯 가지 전략을 기억하고, 측정을 통해 지속적으로 개선해 나가시기 바랍니다.

이 글이 도움이 되셨나요?

관련 주제 더 보기

#ai#ai-agent#claude-code#llm

관련 글

AI / ML

9장: 컨텍스트 품질 측정과 개선

컨텍스트 엔지니어링의 효과를 정량적으로 측정하는 방법을 다룹니다. 태스크 성공률, 토큰 효율성, A/B 테스트, 컨텍스트 드리프트 감지를 분석합니다.

2026년 3월 24일·17분
AI / ML

8장: 컨텍스트 엔지니어링 도구와 기법

Claude Code, Cursor, GitHub Copilot에서 컨텍스트를 최적화하는 구체적 방법과, MCP 서버를 통한 동적 컨텍스트 확장 기법을 다룹니다.

2026년 3월 22일·16분
AI / ML

7장: 컨텍스트 격리와 멀티에이전트 설계

멀티에이전트 시스템에서 에이전트별 컨텍스트를 격리하고, 크로스 오염을 방지하며, 공유 컨텍스트를 효과적으로 관리하는 전략을 다룹니다.

2026년 3월 20일·18분
이전 글9장: 컨텍스트 품질 측정과 개선

댓글

목차

약 20분 남음
  • 이 장에서 배우는 것
  • 프로젝트 개요
    • 시스템 전체 아키텍처
  • Step 1: CLAUDE.md 작성
    • 설계 원칙 적용
    • 체크리스트로 검증
  • Step 2: 계층적 컨텍스트 파일
  • Step 3: MCP 서버 구축
    • MCP 서버 등록
  • Step 4: 멀티에이전트 컨텍스트 파이프라인
    • 파이프라인 설계
    • 에이전트별 컨텍스트 정의
  • Step 5: 측정 대시보드
    • 메트릭 수집기
    • 리포트 출력 예시
  • Step 6: 도입 체크리스트
    • Phase 1: 기초 (1-2일)
    • Phase 2: 확장 (3-5일)
    • Phase 3: 최적화 (1-2주)
    • Phase 4: 고도화 (지속)
  • 핵심 원칙 정리
  • 시리즈를 마치며