본문 바로가기

컨텍스트 엔지니어링 실전 사례

지금까지 본 시스템 프롬프트, RAG, 동적 컨텍스트, 프로젝트 규칙 파일을 실제 업무에 어떻게 조합하는지, 자주 마주치는 세 가지 시나리오로 살펴봅니다. 사례마다 "컨텍스트 없는 버전 → 컨텍스트를 깔아둔 버전"을 비교해서, 답의 실용성 차이가 어디서 나오는지 직접 느껴볼 수 있게 정리했습니다.

1. 코드 리뷰, 같은 코드 다른 결과

1.1 컨텍스트 없이 리뷰 요청

이 코드를 리뷰해줘.

function getUser(id) {
  return fetch('/api/users/' + id).then(r => r.json())
}

이 정도 입력에 대해 모델은 거의 일반론을 돌려줍니다.

  • "TypeScript로 타입을 명시하세요"
  • "에러 처리를 추가하세요"
  • "fetch보다 axios나 ky 같은 라이브러리를 고려해보세요"

조언 자체는 다 합리적인데, 우리 팀이 실제로 어떤 도구를 쓰는지 모르니까 답이 일반적입니다. 5명한테 같은 질문을 받아도 거의 같은 답을 줄 만한 수준입니다.

1.2 프로젝트 컨텍스트를 깔아둔 리뷰 요청

[프로젝트 정보]
- TypeScript + Next.js 프로젝트
- API 호출은 utils/api.ts에 만들어둔 axios 래퍼를 사용
- 에러는 utils/errors.ts의 AppError 클래스로 일관 처리

[참조: utils/api.ts]
import axios from 'axios';
import { AppError } from './errors';

export const apiClient = axios.create({
  baseURL: process.env.NEXT_PUBLIC_API_URL,
  timeout: 5000,
});

[참조: types/user.ts]
export interface User {
  id: string;
  name: string;
  email: string;
  role: 'admin' | 'member';
}

[리뷰 대상: services/user.ts]
function getUser(id) {
  return fetch('/api/users/' + id).then(r => r.json())
}

[요청]
위 코드를 우리 프로젝트 컨벤션에 맞춰 리뷰하고 개선안을 보여줘.

이때 받는 답은 우리 회사의 실제 코드에 들어맞는 구체적 개선안이 됩니다.

  • fetch 대신 apiClient.get<User>(\/users/${id}`)`
  • 타입 명시: getUser(id: string): Promise<User>
  • 에러는 try/catch 후 AppError로 감싸기
  • process.env.NEXT_PUBLIC_API_URL이 이미 base에 있으니 URL 하드코딩 제거

같은 모델, 같은 코드인데, 결과가 곧바로 PR 코멘트로 붙일 수 있는 수준이 됩니다. 그리고 이걸 매번 적기 싫다면? 위 [프로젝트 정보] [참조] 같은 내용을 CLAUDE.md에 한 번 적어두면 끝입니다. 4-2에서 본 그 방식입니다.

2. 기술 문서, 우리 톤으로 쓰게 만들기

새 API 엔드포인트가 생길 때마다 문서를 적는 일은 시간이 꽤 듭니다. 그런데 문서 톤이 작성자마다 다르면 외부에서 보는 사람이 헷갈립니다. 컨텍스트 엔지니어링으로 이 둘을 같이 해결할 수 있습니다.

2.1 스타일 가이드 + 좋은 예시 함께 주기

[시스템 프롬프트]
너는 위니브 팀의 기술 문서 작성자야. 우리 팀의 문서 톤을 따라줘.

[참조: 문서 스타일 가이드]
- 제목은 한국어, 코드와 함수명은 영문 원어 그대로
- 각 섹션 첫 문단은 "왜 필요한가"를 한두 문장으로 설명한 뒤 본론으로
- 코드 예시는 실행 가능한 완성 코드 (스니펫 조각 금지)
- 주의사항은 callout 박스로 표시

[참조: 잘 작성된 기존 문서 발췌]
(우리 팀이 좋아하는 기존 문서 한두 페이지 분량)

[작업]
다음 API 엔드포인트 문서를 작성해줘.

POST /api/auth/login
- Body: { email: string, password: string }
- Response: { token: string, user: User }
- Errors: 401(잘못된 자격), 422(검증 실패), 429(과도한 시도)

핵심은 "잘 작성된 기존 문서 발췌" 입니다. 모델에게 "우리 톤으로 써줘"라고 말로 설명하는 것보다, 실제 예시 한두 개를 보여주는 쪽이 훨씬 빠릅니다. 3장에서 다룬 Few-Shot 패턴의 활용입니다.

2.2 기술 제안서 작성

조직 안에서 "우리 시스템을 어떻게 바꿀까"를 정리하는 글을 쓸 때도 컨텍스트가 결정적입니다.

[배경]
- 현재 인증: 세션 기반 (express-session)
- 문제: 서버를 늘리면 세션 동기화에 시간이 듦
- 월간 활성 사용자: 50,000명
- 인프라: AWS ECS, 최대 10개 인스턴스

[기술 요구사항]
- 마이크로서비스 아키텍처와 호환
- 모바일 앱 지원
- 6개월 안에 SSO 연동 예정

[제약]
- 마이그레이션 기간 최대 2개월
- 기존 사용자 강제 재로그인 최소화
- 하위 호환성 한 분기 유지

[요청]
JWT 기반 인증으로 옮겨가는 기술 제안서를 작성해줘.
배경 → 검토한 대안 → 추천안 → 마이그레이션 단계 → 리스크 순으로.

이렇게 깔아두지 않고 "JWT 마이그레이션 제안서 써줘"만 던지면, 모델은 인터넷에서 본 평균적인 제안서 양식을 돌려줍니다. 우리 회사의 50,000 MAU나 2개월 데드라인 같은 정보가 빠진 채로요. 위 컨텍스트가 깔리는 순간 결과는 "우리 회사에서 검토 가능한 문서"가 됩니다.

3. 고객 응대, 네 개의 컨텍스트 레이어

고객 지원에서 AI를 쓸 때는 컨텍스트가 한두 개로 끝나지 않습니다. 여러 출처의 정보를 한 번에 깔아두는 패턴이 필요합니다. 챗봇 한 명이 답을 하기 위해 알아야 하는 정보를 층으로 나눠보면 보통 네 단계가 나옵니다.

각 층은 출처가 다릅니다. 1층은 손으로 적은 규칙, 2층은 RAG로 가져온 FAQ, 3층은 우리 회사 DB에서 끌어온 고객 레코드, 4층은 실시간 시스템 상태입니다. 이걸 한 자리에 잘 깔아주는 것이 사용자의 만족도를 좌우합니다.

3.1 한 번의 응대에 들어가는 컨텍스트

[Layer 1: 응대 규칙]
- 항상 존칭을 사용
- 기술 용어 대신 쉬운 표현
- 해결할 수 없는 문제는 "담당자에게 연결해 드리겠습니다"
- 신용카드 번호, 비밀번호 같은 민감 정보는 절대 요청하지 마

[Layer 2: 관련 FAQ (벡터 DB에서 검색)]
- Q: 요금제 변경 방법은? A: 설정 > 결제 관리에서 가능합니다. ...
- Q: 변경 시 차액 처리는? A: 일할 계산 후 다음 결제일에 반영됩니다. ...

[Layer 3: 고객 정보]
- 이름: 김위니
- 구독: 프로 플랜 (2025-01-15 시작)
- 최근 문의: 2026-03-28 "결제 수단 변경 방법"
- 그때 해결 상태: 해결됨

[Layer 4: 실시간 정보]
- 현재 서비스 상태: 정상
- 진행 중 프로모션: 연간 구독 20% 할인 (4월 한정)

[고객 메시지]
"요금제를 바꾸고 싶어요."

이 컨텍스트가 깔린 상태라면 모델은 "설정에서 변경하세요"에 그치지 않고, "김위니님, 프로 플랜에서 변경하시려는 건가요? 마침 4월 한정으로 연간 결제 시 20% 할인 프로모션이 진행 중인데, 함께 안내드릴까요?" 같은 답을 만들어낼 수 있게 됩니다. 3장에서 봤던 Air Canada 사례를 떠올리면, 실시간 정보를 잘못 깔아두는 일이 어떤 비용을 부르는지 같이 보입니다. 컨텍스트 설계의 품질이 곧 책임의 크기와 맞닿아 있는 영역입니다.

4. 정리, 잘 설계된 컨텍스트의 공통점

세 사례를 관통하는 공통점이 몇 가지 보입니다. 컨텍스트 엔지니어링을 직접 해볼 때 점검하면 좋은 항목들로 정리합니다.

4.1 양보다 질

회사 자료 100개를 다 깔아두는 것보다, 지금 질문과 직접 연결된 5개를 깔아두는 쪽이 결과가 좋습니다. 3-3에서 본 Lost in the Middle과 같은 줄기입니다.

4.2 출처별로 레이블 붙이기

[시스템 프롬프트] [참조 문서] [고객 정보] [실시간 정보] 같은 명시적 레이블이 모델의 정확도를 눈에 띄게 올립니다. 모델에게 "이 정보가 어떤 종류인지" 신호를 주기 때문입니다.

4.3 점검 체크리스트

[ ] 지금 질문과 직접 관련된 정보만 깔았는가
[ ] 정보가 최신 상태인가 (특히 가격, 정책, 재고)
[ ] 같은 내용이 두 번 들어가 있지 않은가
[ ] 가장 중요한 정보가 컨텍스트의 앞 또는 뒤에 있는가
[ ] 정보마다 어떤 출처인지 레이블이 붙어 있는가
[ ] 컨텍스트 윈도우 한계 안에 들어왔는가
[ ] 답변 생성에 쓸 토큰이 충분히 남아 있는가

4.4 반복해서 다듬기

처음 만든 컨텍스트가 한 번에 잘 통하는 일은 드뭅니다. 다음 흐름을 한두 번 돌리면 빠르게 안정됩니다.

  1. 첫 컨텍스트 작성. 필요할 것 같은 정보를 모아 깔아봅니다.
  2. 답 확인. 결과가 기대만큼인지 봅니다.
  3. 조정. 안 쓰이는 정보는 빼고, 부족했던 정보는 더합니다.
  4. 다양한 케이스로 테스트. 한 케이스가 아니라 5~10개로 검증합니다.
  5. CLAUDE.md, 시스템 프롬프트, RAG 검색 쿼리에 반영. 일회용으로 두지 말고 자산화합니다.

여기까지가 프롬프트와 컨텍스트의 영역입니다. 다음 5장부터는 한 발 더 나아가, AI가 도구를 직접 호출하면서 자율적으로 일하는 환경 전체를 설계하는 하네스 엔지니어링으로 넘어갑니다. Claude Code가 어떻게 글롭과 그렙으로 코드를 뒤지면서 일을 풀어가는지, 그 뒤에 있는 설계 원리들을 직접 살펴봅니다.

컨텍스트 엔지니어링 실전 사례 - 프롬프트, 컨텍스트, 하네스 엔지니어링 에센셜 | 위니버시티