← posts/b.log()

blog92@web:~$ cat posts/ai-07-context-engineering.md

AI4 min read

AI 완전 정복 7편 — 컨텍스트 엔지니어링

컨텍스트 엔지니어링은 "모델이 일하는 순간에 필요한 정보만, 필요한 만큼, 적절한 순서로" 보이게 하는 설계다. 항상 필요한 것은 규칙 파일에, 가끔 필요한 것은 검색으로, 작업 중 알게 된 것은 메모로 관리한다.

한 줄 요약: 컨텍스트 엔지니어링은 "모델이 일하는 순간에 필요한 정보만, 필요한 만큼, 적절한 순서로" 보이게 하는 설계다. 항상 필요한 것은 규칙 파일에, 가끔 필요한 것은 검색으로, 작업 중 알게 된 것은 메모로 관리한다.

프롬프트에서 컨텍스트로

6편의 프롬프트 엔지니어링이 한 번의 요청을 잘 쓰는 기술이라면, 컨텍스트 엔지니어링은 에이전트가 수십 턴을 일하는 동안 컨텍스트 윈도우 안에 무엇이 들어 있을지를 설계하는 기술입니다. 5편에서 본 것처럼 컨텍스트는 많을수록 좋은 게 아니라 한정된 자원입니다. 목표는 가장 작은 토큰으로 가장 좋은 결과를 내는 것입니다.

컨텍스트에 들어갈 정보는 얼마나 자주 필요한지에 따라 세 층으로 나눌 수 있습니다.

층무엇을어디에언제 들어가나
고정 맥락빌드·테스트 명령, 코드 규칙, 금지 사항, 아키텍처 개요규칙 파일 (CLAUDE.md, AGENTS.md, .cursor/rules)매 요청 시작에 자동
필요할 때 가져오는 맥락관련 파일, 타입 정의, 라이브러리 문서, 이슈 내용코드베이스, 문서, MCP 도구모델이 검색하거나 내가 첨부할 때
작업 중 쌓이는 맥락계획, 결정 사항, 진행 상황, 알아낸 사실PLAN.md, NOTES.md, 이슈 코멘트작업을 이어갈 때, 새 세션에서

지층 1: 규칙 파일 잘 쓰기

규칙 파일은 매 요청마다 들어가므로 짧고 자주 쓰이는 것만 담습니다. 길게 쓰면 모든 요청의 비용이 늘고 중요한 규칙이 묻힙니다. 좋은 기준은 "이 줄을 지우면 모델이 실수할까?"입니다. 아니라면 지웁니다.

markdown
# CLAUDE.md
 
## 명령어
- 개발 서버: pnpm dev
- 테스트: pnpm test -- <파일경로>  (전체 테스트는 5분 걸리므로 단일 파일로)
- 타입 체크: pnpm typecheck  (커밋 전 필수)
 
## 구조
- apps/web: Next.js 프론트, apps/api: NestJS, packages/shared: 공용 타입
- DB 스키마는 packages/db/prisma/schema.prisma가 유일한 기준
 
## 규칙
- 날짜는 dayjs만 사용 (moment 금지: 번들 크기)
- API 에러는 packages/shared/errors.ts의 AppError로만 던진다
- 테스트 파일을 수정해야 하면 이유를 먼저 설명하고 허락을 받는다
 
## 주의
- 정산 배치(apps/api/src/jobs/settlement)는 운영 DB에 직접 쓴다. 로컬에서 실행 금지

이 예시에는 모델이 스스로 알기 어려운 것만 있습니다. "깨끗한 코드를 써라" 같은 당연한 말은 없고, 코드를 읽으면 알 수 있는 사실도 최소화했습니다. 모노레포라면 하위 폴더마다 규칙 파일을 두어 그 폴더를 작업할 때만 읽히게 할 수도 있습니다.

지층 2: 필요할 때 가져오기 — 검색과 RAG

모델에게 코드베이스를 보여 주는 방법은 크게 두 가지입니다.

에이전트형 검색 (agentic search): 모델이 grep, glob, 파일 읽기 도구로 직접 찾아갑니다. 사람이 코드를 탐색하는 방식과 같고, 항상 최신 코드를 보며 별도 인덱스가 필요 없습니다. Claude Code 같은 코딩 에이전트가 주로 쓰는 방식입니다.

RAG (Retrieval-Augmented Generation): 문서나 코드를 미리 조각내 임베딩 벡터로 저장해 두고(2편), 질문과 의미가 가까운 조각을 찾아 넣습니다. 코드보다는 사내 위키, 설계 문서, 운영 매뉴얼처럼 키워드가 딱 맞지 않는 자연어 자료에 강합니다.

  1. 조각내기(chunking): 문서는 제목 단위, 코드는 함수·클래스 단위로 자른다. 글자 수로 기계적으로 자르면 함수가 반토막 난다.
  2. 임베딩과 저장: 각 조각을 벡터로 바꿔 pgvector, Qdrant 같은 벡터 DB에 저장한다.
  3. 검색: 질문을 임베딩해 가까운 조각 상위 N개를 가져온다. 키워드 검색(BM25)을 함께 쓰는 하이브리드 방식이 보통 더 정확하다.
  4. 주입: 찾은 조각을 출처와 함께 프롬프트에 넣고 "주어진 자료만으로 답하라"고 지시한다.

폐쇄망 환경의 사내 라이브러리처럼 모델이 학습한 적 없는 대상은, 관련 README나 타입 정의 파일을 먼저 읽게 하는 것만으로도 할루시네이션이 크게 줍니다. 외부 라이브러리는 최신 공식 문서를 가져오는 MCP 서버나 llms.txt를 제공하는 문서 사이트를 활용합니다.

지층 3: 작업 메모로 세션을 넘어 이어가기

긴 작업은 한 대화에 다 들어가지 않습니다. 그래서 에이전트에게 진행 상황을 파일에 쓰게 합니다.

markdown
# PLAN.md — 커서 페이지네이션
 
## 결정
- 커서 = base64(updatedAt|id). 이유: updatedAt 중복 가능
 
## 진행
- [x] repository 계층 수정
- [x] 경계값 테스트 3개
- [ ] 프론트 useInfiniteQuery 적용
 
## 알아낸 것
- posts 테이블에 (updated_at, id) 복합 인덱스가 없음 → 마이그레이션 필요

대화를 리셋하거나 압축되더라도 "PLAN.md를 읽고 이어서 진행해"라는 한 마디로 맥락이 복구됩니다. 진행 상황을 대화 기록이 아닌 파일에 두는 것이 핵심입니다.

순서도 설계다

같은 내용이라도 배치에 따라 비용과 품질이 달라집니다.

  • 안 바뀌는 것을 앞에: 시스템 프롬프트 → 규칙 파일 → 참고 문서 → 대화 기록 → 이번 질문. 앞부분이 고정되면 프롬프트 캐시가 적중합니다(2·4편).
  • 질문은 맨 뒤에: 긴 자료 다음에 질문을 두면 모델이 자료를 읽은 뒤 무엇을 해야 하는지 바로 알 수 있습니다.
  • 도구 결과는 다이어트: 테스트 출력 전체 대신 실패한 테스트만, 파일 전체 대신 필요한 줄 범위만 돌려주도록 도구를 설계합니다.

코딩 실습 (40분)

  1. 지금 진행 중인 프로젝트에 위 예시를 참고해 CLAUDE.md(또는 쓰는 도구의 규칙 파일)를 30줄 이내로 작성한다.
  2. 규칙 파일이 없는 상태와 있는 상태에서 같은 작업(예: 새 API 엔드포인트 추가)을 시켜 보고, 규칙 위반이 얼마나 줄었는지 확인한다.
  3. 모델이 틀린 지점마다 "이건 규칙 파일에 한 줄 추가하면 막을 수 있었나?"를 묻고, 그렇다면 추가한다. 규칙 파일은 이렇게 실수를 통해 자라야 합니다.

정리

  • 컨텍스트는 고정(규칙 파일) / 주문형(검색·RAG·MCP) / 작업 메모 세 층으로 설계한다.
  • 규칙 파일은 짧게, 모델이 스스로 알 수 없는 것만.
  • 안 바뀌는 것은 앞에, 질문은 뒤에, 도구 결과는 줄여서.

다음 편: 모델이 직접 검색하고 파일을 고치는 "에이전트"는 내부에서 어떻게 돌아갈까요?

COMMENTS (…)

댓글을 불러오는 중이에요.

NEW COMMENT0 / 1000
⌘↵ 전송

blog92@web:~$ cd ..