컨텍스트 엔지니어링(Context engineering)은 프롬프트 작성이 아닌 엔지니어링 작업이다
요약
프롬프트 엔지니어링을 넘어 시스템 엔지니어링 관점의 '컨텍스트 엔지니어링'으로의 전환을 제안합니다. 명확한 비즈니스 규칙과 제약 조건을 포함한 정밀한 명세를 작성하면, 구현 단계에서는 더 저렴하고 빠른 모델로도 높은 정확도를 달성할 수 있습니다.
핵심 포인트
- 프롬프트 엔지니어링은 글쓰기지만, 컨텍스트 엔지니어링은 시스템 엔지니어링이다.
- 정밀한 명세(Spec)는 구현 모델의 요구 역량을 낮추고 비용을 절감한다.
- 최상위 모델로 명세를 작성하고, 저렴한 모델로 구현하는 이원화 전략이 효율적이다.
- 정확도는 모델의 성능보다 명세의 정밀함에서 결정된다.
요약(TL;DR) — 명세(spec)가 좋으면 구현에 필요한 모델의 성능은 낮아져도 됩니다. 저는 명세를 작성할 때는 최상위 모델을 사용하고, 이를 구현할 때는 더 저렴하고 빠른 모델을 사용하는 방식을 시작했습니다. 여전히 강력한 모델을 사용하고 있지만, 구현 대신 명세를 작성하는 데 사용하고 있는 것입니다. 이 이득은 어떤 마법 같은 프롬프트 문구에서 오는 것이 아닙니다. 그것은 바로 컨텍스트(context), 즉 명시적인 비즈니스 규칙, 검증된 프로젝트 제약 조건, 정의된 출력 계약(output contract)에서 옵니다. 이것이 바로 시스템 엔지니어링(systems engineering)입니다. 스택이 무엇이든 실제 소프트웨어를 유지해 온 사람이라면 누구나 갖는 규율입니다.
모든 백엔드 개발자는 이런 상황을 알고 있습니다: Swagger는 최신 상태가 아니고, 마지막 핫픽스(hotfix)는 유닛 테스트(unit test) 없이 배포되었으며, README.md에는 아무도 6개월 동안 사용하지 않은 명령어가 기록되어 있습니다. 코드는 작동합니다. 문서는 거짓을 말합니다. 그리고 그 둘 사이의 간극이 바로 AI와 우리가 잘못되기 시작하는 지점입니다.
저는 지난 몇 달 동안 튜토리얼용 그린필드(greenfield) 프로젝트가 아니라, 실제 운영 프로젝트 내부에서 AI를 사용하여 진짜로 개발해 왔습니다. 제가 얻은 결론은 어떤 모델을 사용할 것인가에 대한 것이라기보다, 이미 이름이 붙여진 변화, 즉 **프롬프트 엔지니어링 (prompt engineering)**에서 **컨텍스트 엔지니어링 (context engineering)**으로의 전환에 관한 것이었습니다.
이 차이는 단순한 의미론적 차이가 아닙니다. 프롬프트 엔지니어링은 문제를 글쓰기, 즉 마법의 문구를 찾는 것으로 취급합니다. 컨텍스트 엔지니어링은 문제를 항상 그래왔던 것처럼 시스템 엔지니어링 (systems engineering) 문제로 취급합니다. 그리고 이것이 저의 백엔드 배경 지식이 가장 직접적으로 적용된 부분입니다. 비록 실제 시스템을 유지해 온 사람이라면 누구나 같은 본능을 가지고 있겠지만 말입니다.
나를 설득한 실험
제가 이 문제를 진지하게 받아들이게 된 계기인 증거부터 시작하겠습니다.
오랫동안 저의 반사적인 행동은 모든 것에 가장 강력한 모델을 사용하는 것이었습니다. 더 비싸고, 더 똑똑하며, 오류가 적은 모델 말이죠. 이론적으로는 말이 됩니다.
실제로 저는 다른 것을 목격했습니다. 작업의 _명세(specification)_가 잘 이루어졌을 때 — 명시적인 비즈니스 규칙, 검증된 프로젝트 제약 조건, 정의된 출력 형식 등 — **구현(implementation)**에 필요한 모델의 역량 요구치가 급격히 떨어집니다. 작업을 단계별로 나눌 수 있을 정도였습니다. 저는 최상위 모델(현재는 Opus)을 사용하여 **명세를 작성(write the spec)**하고, 더 저렴하고 빠른 모델(Sonnet)을 사용하여 그것으로부터 **구현(implement)**하기 시작했습니다. 저는 강력한 모델을 포기한 것이 아니라, 역할을 옮긴 것입니다. 구현 단계에서 명세 작성 단계로 옮긴 것이죠.
실제로 중요한 비교는 '저렴한 구현자 vs 비싼 구현자'가 아닙니다. 그것은 '구조화된 명세 없이 구현하는 강력한 모델' 대 '명세를 작성하는 강력한 모델과 그것을 바탕으로 구현하는 더 저렴한 모델'의 비교이며, 후자가 더 저렴하면서도 더 정확합니다. 정확도는 저렴한 모델에서 나오는 것이 아니라, 명세가 정밀함을 전달하기 때문에 발생하는 것입니다. 예산이 무제한이라면 두 단계 모두에 강력한 모델을 사용할 수 있으며, 그것이 한계치(ceiling)입니다. 하지만 여기서 유용한 발견은 더 좁은 범위에 있습니다. 즉, 좋은 컨텍스트(context)는 가장 많은 작업량이 발생하는 단계에서 비용을 절감하면서도, 명세 없이 구현에 투입된 강력한 모델보다 더 저렴한 구현자가 더 나은 성능을 내게 만든다는 것입니다.
하지만 이것이 무엇을 보여주고 무엇을 보여주지 않는지에 대해 정확히 짚고 넘어가야 합니다. Sonnet은 약한 모델이 아닙니다. Opus보다 한 단계 아래일 뿐이며, 그 차이가 아주 미미한 것도 아닙니다. 따라서 이것은 어떤 최소한의 모델이라도 무엇이든 구현할 수 있다는 증거가 아닙니다. 좋은 명세가 작업에 요구되는 역량의 _한계치(ceiling)_를 낮춰준다는 것이며, 제 경우에는 그 한계치가 최상위 모델 아래로 떨어진 것입니다. 그 한계치가 얼마나 떨어지는지는 작업에 따라 달라집니다.
저는 이 주장의 범위에 대해 솔직해지고 싶습니다. 왜냐하면 이것이 쉽게 오해를 불러일으키는 클릭베이트(clickbait)로 변질될 수 있기 때문입니다. 이것은 보편적인 레시피가 아닙니다. 정확한 분할 방식은 작업의 복잡성, 코드베이스의 성숙도, 그리고 이미 구축된 패턴의 품질에 따라 달라집니다. 명세가 없는 엉망인 프로젝트에 이를 적용하면 저렴한 모델은 환각(hallucination)을 일으킬 것이고, 당신은 제가 틀렸다고 결론 내릴 것입니다. 하지만 실제로 누락된 것은 이 주장을 성립하게 만드는 바로 그 절반의 요소입니다.
일반화할 수 있는 것은 그 이면에 있는 원칙입니다:
컨텍스트 품질(Context quality)은 작업에 필요한 모델의 역량 요구치를 낮춘다.
Opus에서 Sonnet으로의 분리는 이 원칙이 작동한다는 구체적인 증거일 뿐입니다. 그리고 이는 보너스로, 왜 열풍이 "프롬프트 엔지니어링 (prompt engineering)"에서 "컨텍스트 엔지니어링 (context engineering)"으로 그렇게 빠르게 옮겨갔는지 설명해 줍니다. 즉, 컨텍스트에 투자하여 얻는 한계 이득(marginal gain)이 문구(phrasing)에 투자하는 것보다 더 크기 때문입니다.
무엇이 "좋은 컨텍스트"로 간주되는가
저 또한 빠졌던 함정이 하나 있습니다. 바로 더 많은 컨텍스트가 더 좋은 컨텍스트라고 생각하는 것입니다. 그렇지 않습니다. 전체 리포지토리(repo)를 컨텍스트 창에 쏟아붓는 것은 모델이 더 잘 추론하도록 돕지 않습니다. 그저 비용을 부풀리고 신호(signal)를 희석할 뿐입니다. 좋은 컨텍스트는 양이 아니라 **정밀도 (precision)**입니다. 실제로 유의미한 변화를 만들어내는 요소는 다음과 같습니다:
- 프로젝트가 무엇을 하는가 — 한 문장이면 충분합니다. 당연해 보이지만, 실제로 문서화되어 있는 경우는 거의 없습니다.
- 스택(stack), 아키텍처(architecture), 그리고 패턴(patterns) — LLM은 _복제(replicating)_에 매우 뛰어나기 때문입니다. 그것이 그들의 핵심 강점입니다. 일관되고 문서화된 패턴을 가진 프로젝트는 모델에게 복사할 틀을 제공하며, 바로 이 지점에서 환각(hallucination)이 줄어듭니다.
README.md내의 명확한 명령(commands) — 우스꽝스럽지만 실제 사례입니다. 테스트가 깨졌을 때 에이전트에게 수정을 요청했더니, 에이전트가 아무것도 건드리기 전에 에러를 확인하기 위해 테스트 명령을 직접 실행했습니다. 이는 명령이 문서화되어 있었기에 가능했던 일입니다.- 출력 계약 (output contract) — 함수와 메서드의 입력 및 출력 형식을 사전에 정의하면 모델에게 추측 대신 목표를 제공하게 됩니다. 다만, 이를 "실행 가능한 명세로서의 TDD"라고 부르기 전에 주의할 점이 있습니다. 제 워크플로우에서는 동일한 모델이 테스트와 구현을 모두 작성하므로, 테스트가 독립적인 오라클(oracle) 역할을 하지는 않습니다. 즉, 테스트는 모델이 작업에 대한 자신의 해석을 스스로 검증하는 것에 가깝습니다. 실제로 상황을 고정하는 것은 제가 직접 검토하는 명세(spec) 내의 계약이며, 테스트는 이를 실행 가능한 상태로 만들 뿐입니다. 또한 테스트의 단언(assertions)은 아래에 설명할 검증기(verifier)의 '체크 2(Check 2)' 단계를 여전히 통과해야 합니다.
이 중 어느 것도 "프롬프트 기술 (prompt technique)"이 아니라는 점에 주목하십시오. 이것은 엔지니어링 위생(engineering hygiene)입니다. AI는 단지 이러한 위생을 건너뛰었을 때 발생하는 비용을 가시적이고 즉각적으로 만들었을 뿐입니다.
시스템: 스킬의 파이프라인
방법론 없는 논문은 동기 부여 연설에 불과합니다. 그래서 그 방법을 소개합니다.
저는 제 워크플로우의 반복 가능한 모든 단계를 **스킬(skill)**로 취급합니다. 이는 세 가지 고정된 부분—지침(Instructions), 제약 조건(Constraints), 그리고 _출력 형식(Output Format)_을 가진 구조화된 프롬프트입니다. 이 스킬들은 .md 파일에 버전 관리되어 에디터와 에이전트 모두에서 접근 가능합니다. 여러 프로젝트에서 모델에게 같은 것을 세 번째로 요청하고 있다는 것을 깨달을 때마다, 저는 그것을 하나의 스킬로 공식화합니다.
기존 프로젝트에서 작업이 진행되는 흐름은 다음과 같습니다:
extract task description
→ spec-writer (비공식 티켓으로부터 명세서를 생성)
→ [명세서 검토] (인간의 개입 — 제가 위임하지 않는 단계)
...
이 스킬들 중 세 가지가 핵심적인 작업을 수행합니다. 이 세 가지를 모두 보여드리겠습니다.
1. 컨텍스트를 생성하는 스킬: spec-writer
파이프라인의 핵심입니다. 비공식 티켓(자연어, 글머리 기호, Slack 스레드)을 구현 가능한 명세서(SDD spec)로 변환합니다. 차이를 만드는 디테일은 템플릿 자체가 아니라 **제약 조건 감사(Constraints Audit)**입니다. 이 스킬은 코드가 무엇을 해야 하는지 설명하기 전에, 프로젝트가 이미 설정한 내용 중 모델의 출력을 무효화할 수 있는 것이 무엇인지 강제로 검사합니다.
# 스킬: Spec Writer
비공식 티켓 설명을 구현 가능한 SDD 명세서로 변환합니다.
...
이것이 중요한 이유: 제가 목격한 환각(hallucination)의 대부분은 모델이 아무것도 없는 것에서
아첨(Sycophancy)은 LLM이 정확성을 희생하면서 사용자의 의견에 동조하고, 아부하며, 확인해 주려는 경향을 말합니다. 즉, 모델이 중립적인 진실 탐구자(truth-seeker)로서 행동하는 대신 사용자가 듣고 싶어 하는 말을 하는 것입니다. AI가 많은 양의 코드를 생성하는 흐름 속에서, 이것은 **숨겨진 세금(hidden tax)**이 됩니다. 코드는 올바르게 보이고, (동일한 AI가 작성한) 테스트를 통과하며, 정작 그 테스트가 무엇인가를 제대로 테스트하고 있는지는 아무도 확인하지 않기 때문입니다.
이 기술은 불신을 체크리스트로 공식화합니다. 저는 체크 항목을 순서대로 실행하며, 첫 번째 적신호(red flag)가 나타나면 즉시 중단합니다:
# 기술: AI 출력 검증기 (AI Output Verifier)
AI가 생성한 출력물에 대한 레드팀(Red-team) 역할. 아첨(sycophancy), 날조(fabrication) 및 ...와 싸웁니다.
저에게 중요해지기 시작한 지표는 "하루에 코드를 얼마나 많이 짜는가"가 아닙니다. 그것은 얼마나 많은 잘못된 코드가 운영 환경(production)에 도달하는 것을 막았는가입니다. 이 기술은 바로 그것을 위한 도구입니다.
3. 판결을 내리는 것: code-reviewer
짧고 직설적입니다. 스타일(Prettier가 처리함)이 아닌, 정확성과 보안에 집중하여 시니어 백엔드 Node/TS 수준에서 비판적인 검토를 수행합니다.
# 기술: 코드 리뷰어 (Code Reviewer)
시니어 백엔드 Node/TS 수준의 비판적인 코드 리뷰. ...에 집중합니다.
세 가지 모두에서 나타나는 패턴을 주목하세요: 항상 **지시사항(Instructions) + 제약 사항(Constraints) + 출력 형식(Output Format)**의 구조를 가집니다. 그중 제약 사항(Constraints)이 가장 중요한 부분인데, 왜냐하면 바로 그곳에 "하지 마시오(do NOT)"를 인코딩하기 때문입니다. 그리고 이 "하지 마시오"가 AI를 궤도 이탈 없이 유지시켜 줍니다.
이것이 가리키는 방향
이 모든 것의 아킬레스건은 문서의 노후화입니다. 명세서(spec)는 과거의 스냅샷일 뿐이며, 코드는 계속해서 변합니다. 제가 옳다고 느끼는 방향은 **살아있는 문서(living documentation)**입니다. 즉, 영웅적인 분기별 노력으로 만드는 것이 아니라, 모든 변경 사항마다 생성되고 유지 관리되는 문서입니다. 도구들은 이미 정확히 이 지점을 목표로 하고 있으며, 도구들이 성숙해지는 동안 여러분은 이를 근사치로 구현할 수 있습니다. 프로젝트의 스냅샷을 찍고, 모델에게 코드와 README.md를 바탕으로 컨텍스트 파일(context file)을 생성하도록 요청하는 방식입니다.
제가 리포지토리(repo) 내부에서 이것이 어떻게 진화할 것으로 보는지 말씀드리자면: README.md와 함께, 팀의 구조화된 프롬프트(prompts)와 사용 가능한 기술(skills)을 나열하고 프로젝트의 CONTEXT.md를 가리키는 앵커 파일(CLAUDE.md, CODEX.md)이 포함된 _Skills/ 폴더가 공존하는 방식입니다. 모델이 리포지토리에 진입하면 무엇을 어떤 순서로 읽어야 할지 이미 알고 있게 됩니다.
그리고 이 단계를 넘어선 또 다른 레이어가 있습니다. 컨텍스트 엔지니어링(Context engineering)이 모델 호출(model call) 시 무엇을 '넣느냐'에 관한 것이라면, 이러한 호출들을 시스템 — 품질 게이트(quality gates), 재시도(retries), 독립적인 검토자(independent reviewer), 지속성 메모리(persistent memory) — 으로 감싸는 순간, 여러분은 이제 이 분야에서 _하네스 엔지니어링 (harness engineering)_이라 부르는 영역으로 넘어가게 됩니다. 즉, 모델이 아닌 모든 것을 다루는 규율입니다. 앞서 언급한 기술 파이프라인은 이미 축소된 형태의 하네스(harness)입니다. 이것이 제가 다음에 다룰 내용입니다.
이 중 어느 것도 생소한 것이 아닙니다. 이는 의사결정을 문서화하고, 패턴을 유지하며, 검증 가능한 테스트를 작성하는 기존의 엔지니어링 규율과 같습니다. 다만 무시할 수 없는 새로운 동기 부여 요소가 생겼을 뿐입니다. 이제 이러한 단계들을 건너뛰는 비용은 환각(hallucination)을 일으키는 에이전트라는 형태로 즉각 나타납니다. AI가 무엇이 좋은 개발인지에 대한 정의를 바꾼 것은 아닙니다. 단지 지름길이 공짜라는 착각을 더 이상 허용하지 않게 되었을 뿐입니다.
이것이 제가 오늘날 실행하고 있는 흐름입니다. AI가 새로운 방식으로 실패하는 것을 목격할 때마다 기술은 매주 진화합니다. 만약 여러분도 유사한 작업을 수행하며 다른 벽에 부딪히고 있다면, 어떤 것인지 알고 싶습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기