코드 전체를 프롬프트에 넣을수록 AI가 바보가 되는 이유
코드베이스 전체를 쏟아붓는 컨텍스트 덤프가 어떻게 어텐션 감쇠와 환각을 부르는지 메커니즘을 규명하고, 실무 컨텍스트 격리 엔지니어링 5대 원칙을 제시합니다.
새벽 3시 15분, 온콜(On-Call) 엔지니어의 스마트폰에 페이저듀티(PagerDuty) 경보음이 날카롭게 울려 퍼졌다. 결제 게이트웨이 서비스의 결제 승인 성공률이 순식간에 0%로 곤두박질치고 있었다. 장애를 유발한 원인은 방금 프로덕션 브랜치에 자동 병합된 풀 리퀘스트(PR #1428)였다.
터미널을 열고 문제가 된 커밋의 git diff를 확인한 시니어 엔지니어는 아연실색했다.
- import { StripeClient } from "@stripe/stripe-node";
+ // AI Agent Refactoring: Optimized for lightning payment flow
+ import { FastStripeStream } from "@stripe/lightning-stream-v3";
+ const client = new FastStripeStream({ ultraFast: true });
@stripe/lightning-stream-v3라는 패키지는 npm 공식 레지스트리에 존재하지도 않는 가짜 모듈이었다. 코딩 에이전트 도구에게 “결제 지연 시간을 줄이도록 코드를 최적화해 줘”라고 무심하게 던진 단 한 줄의 자연어 프롬프트가, 언어 모델의 잠재 공간(Latent Space)에서 그럴듯하게 날조된 유령 라이브러리를 합성해 냈고, 주변의 필수 결제 검증 로직을 조용히 지워버린 채 전체 시스템을 마비시킨 것이다.
유명 오픈소스 개발자이자 테크 인플루언서인 테오(Theo - t3.gg)는 최근 공개한 기술 비평 영상에서 이 참사의 본질을 정확하게 관통했다. 대부분의 개발자가 겪는 코딩 에이전트의 치명적 결함은 인공지능 모델의 지능 부족 때문이 아니라, 개발자가 모델에게 컨텍스트를 주입하는 방식이 근본적으로 잘못되었기 때문이라는 진단이다.
우리가 흔히 말하는 ’프롬프트 엔지니어링’이라는 마법 주문의 시대는 끝났다. 이제 실무 엔지니어에게 요구되는 것은 정교한 시스템 공학적 접근법인 **컨텍스트 엔지니어링(Context Engineering)**이다. 수만 줄의 소스코드를 무지성으로 프롬프트 창에 복사해 붙여넣는 ’컨텍스트 덤프’가 왜 필연적으로 모델의 주의력 붕괴를 초래하는지, 그리고 프로덕션 레벨의 소프트웨어를 안전하게 생성하기 위해 어떤 결정론적 하네스를 구축해야 하는지 그 구체적 메커니즘을 파헤쳐 본다.
컨텍스트 덤프와 어텐션 감쇠 메커니즘
많은 개발자가 에이전트 코딩 도구(Claude Code, Cursor, Windsurf 등)를 처음 다룰 때 범하는 가장 흔한 실수는 “모델에게 최대한 많은 정보를 주면 더 똑똑하게 판단할 것”이라는 순진한 가정이다. 리포지토리 전체의 트리 구조, 모든 타입스크립트 인터페이스, 과거 커밋 로그, 심지어 2만 줄에 달하는 데이터베이스 마이그레이션 스크립트까지 모조리 컨텍스트 윈도우에 쏟아붓는다.
그러나 트랜스포머 아키텍처의 셀프 어텐션(Self-Attention) 메커니즘은 무한한 집중력을 보장하지 않는다. 컨텍스트 길이가 32K, 64K, 128K를 넘어서는 순간, 모델 내부의 소프트맥스(Softmax) 가중치는 수천 개의 토큰 사이로 극도로 희석된다. 이를 학계에서는 ‘어텐션 감쇠(Attention Dilution)’ 또는 ’건초더미 속 바늘 찾기(Needle in a Haystack) 현상의 역효과’라고 부른다.

위 아키텍처 다이어그램이 명확히 보여주듯, 모놀리식 컨텍스트 덤프 파이프라인에서는 관련 없는 유틸리티 함수와 레거시 인터페이스가 핵심 비즈니스 로직과 동일한 어텐션 비중으로 경쟁한다. 그 결과 모델은 다음과 같은 세 가지 치명적 인지 왜곡을 일으킨다.
-
최신성 편향과 중간 정보 망각 (Lost in the Middle)
프롬프트의 맨 앞이나 맨 뒤에 위치한 토큰은 상대적으로 높은 어텐션을 받지만, 중간에 삽입된 핵심 제약 조건(예: “트랜잭션 격리 수준은 반드시 SERIALIZABLE이어야 함”)은 완전히 무시된다. -
유령 의존성 합성 (Phantom Import Hallucination)
방대한 소스코드 덤프 속에 흩어져 있는 오래된 버전의 라이브러리 명세와 신규 API 명세가 모델 내부 잠재 공간에서 뒤섞이면서, 프로젝트에 설치되지도 않은 서드파티 패키지의 메서드를 능숙하게 호출하는 코드를 생성한다. -
기존 방어 로직의 임의 삭제 (Destructive Refactoring)
컨텍스트 토큰이 가득 차서 토큰 생성 예산(Max Generation Budget)이 부족해지면, 모델은 요청받은 새 기능을 추가하는 과정에서 주변의 복잡한 예외 처리기, 뮤텍스 락, 널 체크 코드를 임의로 축약하거나 삭제해 버린다.

실제 프로덕션 리팩토링 벤치마크 데이터를 살펴보면 컨텍스트 크기와 생성 품질의 상관관계는 명확하다. 컨텍스트가 8K 수준으로 정밀하게 제한된 환경에서는 지시 준수율이 98.5%에 달하고 가짜 임포트 발생률은 1.2%에 불과하다.
반면 128K 이상의 전체 코드베이스 덤프 환경에서는 가짜 임포트 발생률이 41.5%로 폭증하며, 지시 준수율은 48.0%로 추락한다. 더 많은 토큰을 밀어 넣을수록 모델은 영리해지는 것이 아니라 지적으로 마비되는 것이다.
T3 Code의 도구 호출 격리 아키텍처
테오는 이 문제를 해결하기 위해 자신이 개발 중인 실험적 도구(T3 Code)의 내부 설계 원리를 공유했다. 핵심은 에이전트에게 전체 파일 시스템을 무제한으로 열어주는 것이 아니라, 각 도구 호출(Tool Call)의 반환 페이로드를 극단적으로 다이어트시키는 데 있다.
과거의 단순한 AI 어시스턴트는 사용자가 “로그인 버그 고쳐줘”라고 말하면 프로젝트의 모든 관련 파일을 통째로 읽어 들였다. 하지만 차세대 에이전트 아키텍처는 다음과 같은 3단계 컨텍스트 가상화(Virtualization) 방식을 채택한다.
- 정밀한 AST 심볼 탐색: 파일 전체를 텍스트로 읽지 않고, 언어 서버(LSP)를 통해 특정 함수 시그니처와 인터페이스 타입 정의만 발췌하여 주입한다.
- 슬라이딩 에디트 윈도우: 수정이 필요한 블록 전후 20줄 이내의 범위만 격리하여 모델에게 제공하고, 원본 파일의 나머지 부분은 메모리 해시값으로 보호한다.
- 세션 컨텍스트 휘발화: 하나의 서브태스크(예: 데이터베이스 마이그레이션)가 완료되면 해당 작업 로그를 마스터 세션에서 즉시 폐기하고, 오직 결과 아티팩트의 인터페이스만 상위 에이전트에게 반환한다.
이 접근법은 인간 수석 엔지니어가 신입 개발자에게 업무를 위임하는 방식과 정확히 일치한다. 수석 엔지니어는 신입에게 회사의 전체 코드베이스 100만 줄을 읽고 오라고 요구하지 않는다. 오직 이번 스프린트에서 구현해야 할 API 입출력 스펙과, 통과해야 할 유닛 테스트 명세서 딱 두 페이지만 전달한다. 컨텍스트 엔지니어링의 본질은 모델의 거대한 지능을 믿는 것이 아니라, 모델의 인지적 과부하를 시스템적으로 통제하는 데 있다.
컨텍스트 엔지니어링 5대 구현 원칙
일선 엔지니어링 조직이 코딩 에이전트를 프로덕션 워크플로에 안전하게 안착시키기 위해 반드시 준수해야 할 5가지 구체적 실무 원칙은 다음과 같다.
원칙 1. 자연어 명령 대신 실행 가능한 사양서 우선 작성
“사용자 탈퇴 기능을 깔끔하게 구현해 줘”라는 모호한 자연어 프롬프트는 100% 확률로 예외 상황 누락과 데이터 무결성 파괴를 낳는다. 실무에서는 코드 작성을 지시하기 전에 반드시 마크다운 기반의 정형화된 사양(Spec) 파일을 먼저 생성하도록 에이전트를 유도해야 한다.
사양 파일에는 엔드포인트 경로, 필수 헤더, 입력 JSON 스키마, 발생 가능한 HTTP 에러 코드(400, 401, 403, 409, 500), 그리고 데이터베이스 캐스케이드 삭제 정책이 명시되어야 한다. 이 사양 파일 자체가 다음 단계 에이전트의 단일 진실 공급원(Single Source of Truth)이자 컨텍스트 앵커가 된다.
원칙 2. TDD 기반의 실패하는 테스트 하네스 선행 주입
코드를 생성하기 전에 실패하는 단위 테스트(Red Stage)를 먼저 작성하고 실행 환경에 마운트해야 한다. 에이전트에게 주입되어야 할 최우선 컨텍스트는 수백 줄의 비즈니스 코드가 아니라, 테스트 프레임워크가 뱉어내는 명확한 오류 스택 트레이스다.
에이전트는 추상적인 상상력으로 코드를 짜는 것이 아니라, 실패한 어설션(Assertion)을 성공(Green Stage)으로 바꾸기 위한 최소한의 코드 변경(Minimal Diff)만을 계산하게 된다. 이는 불필요한 코드 오버엔지니어링을 원천적으로 차단한다.
원칙 3. 컨텍스트 윈도우 스코프의 외과적 최소화
단일 에이전트 세션에 10개 이상의 파일 경로를 넘겨주지 마라. 디렉터리 단위의 와일드카드(src/**/*.ts) 조회를 금지하고, 반드시 수정 대상이 되는 파일과 해당 파일이 직접 의존하는 선언부 타입 정의 파일(.d.ts)만을 화이트리스트로 지정하여 공급해야 한다.
원칙 4. 결정론적 정적 분석기 및 린트 피드백 루프 결합
모델이 생성한 패치는 인간의 눈으로 검토하기 전에 반드시 기계적인 정적 분석 관문을 통과해야 한다. 타입스크립트 컴파일러(tsc --noEmit), 린터(eslint), 보안 스캐너(semgrep)의 실행 결과를 에이전트에게 즉각 피드백으로 반환하여, 문법 오류와 타입 불일치를 모델 스스로 1차 수정하도록 강제한다.
원칙 5. 장기 기억 오염 방지를 위한 점진적 커밋과 세션 리셋
하나의 프롬프트 세션 안에서 기능 기획부터 데이터베이스 설계, API 개발, 프론트엔드 UI 바인딩까지 한 번에 끝내려 하지 마라. 각 논리적 단위가 완료되고 단위 테스트를 통과할 때마다 즉시 git commit을 수행하고 대화 세션을 완전히 초기화(Reset)해야 한다. 누적된 대화 기록이야말로 모델을 환각의 늪으로 빠뜨리는 가장 위험한 독극물이다.
격리 검증 하네스 구현 예제
아래 코드는 에이전트에게 전체 파일 시스템을 노출하지 않고, 타입 정의와 단위 테스트만을 격리하여 공급한 뒤 컴파일러 피드백을 통해 안전하게 패치를 수렴시키는 타입스크립트 기반의 미니 컨텍스트 하네스 구현체다.
// context-harness.ts: 결정론적 격리 환경에서 에이전트 코드 생성을 검증하는 하네스 모듈
import { execSync } from "node:child_process";
import { readFileSync, writeFileSync } from "node:fs";
export interface SpecContract {
featureName: string;
targetFile: string;
typeDefinitionFile: string;
unitTestFile: string;
maxTokenBudget: number;
}
export class ContextEngineeringHarness {
private spec: SpecContract;
constructor(spec: SpecContract) {
this.spec = spec;
}
// 전체 코드 대신 컴파일러 검증에 필요한 최소 인터페이스 컨텍스트만 추출
public buildMinimalContext(): string {
const typeDef = readFileSync(this.spec.typeDefinitionFile, "utf-8");
const testCases = readFileSync(this.spec.unitTestFile, "utf-8");
return [
`### FEATURE SPEC: ${this.spec.featureName}`,
"Strict Rule: Do NOT import any external module not present in the type contract.",
"Strict Rule: Your output MUST satisfy 100% of the assertions in the test suite.",
"",
"--- [ALLOWED TYPE CONTRACT] ---",
typeDef,
"",
"--- [TARGET TEST SUITE (RED)] ---",
testCases,
].join("\n");
}
// 에이전트가 제안한 패치를 격리 샌드박스 파일에 기록하고 결정론적 검증 게이트 통과 여부 판정
public verifyPatch(candidateCode: string): { success: boolean; errorLog?: string } {
try {
// 1단계: 격리된 대상 파일에만 최소 변경분 기록
writeFileSync(this.spec.targetFile, candidateCode, "utf-8");
// 2단계: 타입스크립트 컴파일러 엄격 모드 정적 검증
execSync("npx tsc --noEmit --strict", { stdio: "pipe" });
// 3단계: 격리된 단위 테스트 실행
execSync(`npx vitest run ${this.spec.unitTestFile}`, { stdio: "pipe" });
return { success: true };
} catch (error: any) {
// 실패 시 시스템 로그에서 핵심 오류 메시지만 슬라이싱하여 에이전트 수정 컨텍스트로 반환
const stderr = error.stderr ? error.stderr.toString("utf-8") : error.message;
return {
success: false,
errorLog: stderr.slice(0, 1500), // 어텐션 희석 방지를 위한 에러 로그 1500자 제한
};
}
}
}
위 하네스를 적용하면 에이전트에게 전달되는 컨텍스트의 양은 기존 전체 코드베이스 덤프(수십만 자) 대비 95% 이상 감소한 5,000자 내외로 압축된다. 또한 테스트 실패 시 전체 스택 트레이스를 무분별하게 쏟아내는 대신, 컴파일러가 지적한 구체적 타입 미스매치 라인만을 1,500자 이내로 잘라 에이전트에게 재입력함으로써 정확한 1차 수정 루프를 완성한다.

위 실측 지표가 증명하듯, 단순 바이브 프롬프팅 방식에서는 깨진 단위 테스트 비율이 62.1%, 타입 체크 오류율이 58.4%에 달하지만, 정밀한 컨텍스트 엔지니어링 하네스를 통과한 작업물은 깨진 테스트 4.0%, 타입 오류 3.2%로 급감하며 환각 패키지 임포트 발생률은 사실상 0에 수렴한다.
에이전트 규칙 파일 3계층 구성 전략
컨텍스트 엔지니어링의 핵심 중 하나는 에이전트가 프로젝트에 진입할 때 읽어 들이는 메타 설정 파일을 극도로 슬림하고 명확하게 유지하는 것입니다. 많은 개발자가 실수로 수백 줄의 사내 코딩 컨벤션이나 장황한 비즈니스 철학을 이 파일에 적어 두지만, 이는 에이전트의 첫 번째 컨텍스트 슬롯을 무의미하게 소모시키는 주범입니다.
실무에서 검증된 최적의 에이전트 규칙 파일은 다음과 같이 3개 레이어로 분리되어야 합니다.
# [Workspace Agent Core Contract]
# 1. Scope Boundary
- Never scan or index files outside of the explicitly requested directory.
- For all refactoring tasks, you must preserve existing public API signatures exactly.
# 2. Strict Compiler Verification
- After modifying any TypeScript file, run: `npx tsc --noEmit`
- After updating API routes, run: `npm run test:contracts`
- If any check fails, do NOT proceed. Immediately fix the offending lines.
# 3. Code Generation Restraints
- Never generate mock or placeholder implementations (e.g., "// TODO: implement later").
- Never introduce new third-party npm dependencies without explicit user confirmation.
- Output concise git-friendly diffs instead of re-printing entire files.
위와 같이 명확하고 측정 가능한 제약 조건(Constraints)만을 규칙 파일에 남겨 둘 때, 모델은 작업 도중 엉뚱한 길로 빠지지 않고 엄격한 궤도 안에서 작동합니다.
규칙이 길어질수록 모델은 규칙을 지키지 않습니다. 규칙이 짧고 컴파일러 명령과 직결될수록 모델은 인간 시니어 개발자가 작성한 것과 다름없는 무결점 코드를 생산합니다.
컨텍스트 엔지니어링 4대 체크리스트
코딩 에이전트를 실무 파이프라인에 도입하려는 테크 리드와 아키텍트는 다음 4가지 질문을 엔지니어링 표준으로 확립해야 합니다.
| 점검 영역 | 핵심 검증 항목 | 미충족 시 발생하는 결함 유형 | 권장 프로덕션 해결책 |
|---|---|---|---|
| 컨텍스트 크기 | 단일 프롬프트 페이로드가 10KB(약 3,000토큰) 이하인가 | 어텐션 희석으로 인한 기존 방어 로직 임의 누락 | AST 기반 타입 인터페이스만 추출하여 공급 |
| 사양 선행성 | 자연어 요청 이전에 마크다운 사양서가 정의되었는가 | API 입출력 규격 불일치 및 엣지 케이스 미처리 | 입출력 스키마와 HTTP 상태 코드를 포함한 Spec 선작성 |
| 테스트 하네스 | 코드를 생성하기 전에 실패하는 단위 테스트가 존재하는가 | 작동하는 것처럼 보이지만 실제로는 실패하는 가짜 코드 | Vitest / Jest 실패 픽스처를 컨텍스트 최상단에 주입 |
| 세션 불변성 | 작업 단위 완료 후 대화 기록을 초기화(Reset)하는가 | 이전 대화의 오래된 가정들이 신규 작업에 누적 간섭 | 단위 커밋 완료 즉시 신규 에이전트 세션 강제 스폰 |
또한 에이전트의 출력 신뢰도를 높이기 위해 CI/CD 파이프라인 상에서 ’컨텍스트 린터(Context Linter)’를 구동하는 것을 권장합니다. 에이전트에게 전송되는 프롬프트의 토큰 크기가 임계치(예: 8,000 토큰)를 초과하거나, 참조되지 않는 미사용 파일 목록이 페이로드에 포함되어 있을 경우 자동으로 컴파일러 에러를 발생시켜 전송을 중단시키는 메커니즘입니다. 이러한 사전 필터링 계층이 갖추어질 때 에이전트는 환각이나 탈선 없이 항상 가장 맑고 정돈된 상태의 인터페이스만을 학습하게 됩니다.
인공지능 코딩 도구가 발전할수록 역설적으로 개발자에게 가장 중요해지는 능력은 화려한 자연어 프롬프트 작성 요령이 아닙니다. 소프트웨어의 경계를 나누는 모듈화 역량, 외부 결합도를 낮추는 엄격한 인터페이스 설계 능력, 그리고 인공지능의 확률적 출력을 단단하게 가두는 결정론적 엔지니어링 기본기입니다. 불필요한 노이즈를 걷어내고 컴파일러와 테스트 하네스라는 차가운 안전장치를 구축하는 것, 그것이 바로 2026년 시니어 소프트웨어 엔지니어가 갖추어야 할 컨텍스트 엔지니어링의 본질입니다.