모든 세션에 전체 지침 시스템을 로드하는 것을 중단하세요
요약
모든 세션에 거대한 시스템 지침을 로드하는 모놀리식 방식의 비효율성을 지적합니다. 지침을 엔트리 포인트와 특화된 모듈로 분리하여 토큰 비용, 지연 시간, 신호 대 잡음비를 최적화하는 아키텍처를 제안합니다.
핵심 포인트
- 거대한 지침 파일은 토큰 비용과 지연 시간을 증가시킴
- 과도한 컨텍스트는 신호 대 잡음비(SNR)를 낮춰 성능 저하 유발
- 핵심 페르소나와 세부 모듈을 분리하는 모듈형 구조 권장
- 필요한 시점에만 특정 지침을 로드하여 컨텍스트 효율성 극대화
대부분의 사람들은 더 나은 프롬프트 (Prompt)에 대해 이야기합니다. 하지만 모든 프롬프트 이전에 일어나는 일, 즉 실제 작업이 시작되기 전 어시스턴트 (Assistant)가 컨텍스트 (Context)에 로드하는 지침 (Instructions)에 대해서는 거의 아무도 이야기하지 않습니다.
시스템에 따라 여러분은 이를 다양한 방식으로 지불하게 됩니다: 입력 토큰 (Input tokens), 지연 시간 (Latency), 가용 컨텍스트 (Available context)의 감소, 또는 단순히 어시스턴트의 활성 지침 내의 노이즈 (Noise) 증가입니다. 프롬프트 캐싱 (Prompt caching)을 통해 비용적 측면이 부분적으로 줄어든다 하더라도, 인지적 비용은 여전히 남아 있습니다: 어시스턴트는 여전히 더 큰 지침 환경 내에서 작동해야 하기 때문입니다.
어느 시점에 이르러, 저의 설정은 끊임없이 성장하는 단 하나의 거대한 지침 파일이 되어버렸습니다. 시스템 구조, 어시스턴트의 페르소나 (Personality), 워크플로우 (Workflows), 세션 규칙 (Session rules), 특수 사례 (Special cases): 모든 것이 하나의 파일에 들어 있었습니다. 그리고 제가 복잡한 과제를 해결하든 단순히 간단한 질문을 하든 상관없이, 모든 상호작용 시마다 모든 내용이 컨텍스트에 로드되었습니다.
이는 마치 실제 주제로 들어가기 전에 모든 전화 통화마다 직원 핸드북 전체를 읽으며 시작하는 것과 비슷합니다.
실제 문제
모놀리식 (Monolithic) 지침 파일은 결합되었을 때 불쾌해지는 두 가지 비용을 발생시킵니다:
- 기본 비용이 비싸집니다.
파일의 대부분은 구체적인 작업과 무관합니다. 그럼에도 불구하고 그것은 활성 컨텍스트에 자리 잡고 있습니다. 시스템에 따라 이는 토큰 비용, 지연 시간, 실제 작업을 위한 공간 부족, 또는 이 모든 것이 동시에 발생함을 의미합니다.
- 신호 대 잡음비 (Signal-to-noise ratio)가 떨어집니다.
더 많은 규칙과 특수 사례를 추가할수록, 현재 관련 있는 부분이 더 희석됩니다. 더 많은 컨텍스트가 자동으로 더 높은 역량을 의미하는 것은 아닙니다.
두 가지 모두 잘못된 방향으로 확장됩니다: 모든 것이 하나의 파일에 머물러 있는 한, 여러분의 설정이 성숙해질수록 그것은 더 무거워지고 정밀도는 떨어지게 됩니다.
통찰
모든 지침이 항상 필요한 것은 아닙니다.
저는 어시스턴트의 페르소나 (Persona)와 기본 운영 원칙은 항상 필요합니다. 하지만 프로젝트 시스템의 정확한 구조는 실제로 이를 탐색할 때만 필요합니다. 세션 종료 규칙은 세션이 끝날 때만 필요하며, 그 전에는 전혀 필요하지 않습니다.
글쓰기 작업에는 파일 시스템 탐색 규칙이 필요하지 않습니다.
빠른 추론 (Reasoning) 작업에는 세션 종료 워크플로우 (Workflow)가 필요하지 않습니다.
디버깅 (Debugging) 세션에는 게시 가이드라인이 필요하지 않습니다.
이것이 사실이라면, 모든 것을 영구적으로 로드된 상태로 유지하는 것은 의미가 없습니다.
아키텍처 (Architecture)
저는 하나의 커다란 파일을 가벼운 엔트리 포인트 (Entry point)와 특화된 모듈 (Modules)로 분리했습니다:
.config/
├── instructions.md -> 컴팩트한 엔트리 포인트, 항상 로드됨
├── persona.md -> 페르소나, 톤, 행동 양식
...
이제 메인 지침 파일은 의도적으로 작게 유지됩니다. 여기에는 모든 세션에 반드시 존재해야 하는 최소한의 내용과 함께, 어떤 모듈이 무엇을 담당하는지, 그리고 언제 로드되어야 하는지에 대한 명확한 참조 (Reference)가 포함됩니다.
상세 모듈들은 기본적으로 활성화되어 있지 않습니다. 접근은 가능하지만, 작업이 요구할 때만 컨텍스트 (Context)의 일부가 됩니다.
이러한 구분은 매우 중요합니다. 전체 지침 세트가 마법처럼 공짜로 존재하는 것이 아닙니다. 어시스턴트가 특정 모듈이 존재한다는 것을 알고, 그것이 관련이 있음을 인식하며, 적절한 순간에 로드할 때만 사용할 수 있습니다.
따라서 모듈화 (Modularization)가 '동일한 컨텍스트, 더 낮은 비용'을 의미하는 것은 아닙니다.
그것은 '더 작은 베이스라인 (Baseline), 그리고 라우팅 (Routing)과 로딩 (Loading)에 더 많은 책임 부여'를 의미합니다.
로딩 방식
제 설정에서 엔트리 포인트는 라우터 (Router) 역할을 합니다. 모든 상세 규칙을 포함하지 않습니다. 대신 다음과 같은 짧은 로딩 규칙을 포함합니다:
만약 작업이 프로젝트 시스템 탐색을 포함한다면,
답변하기 전에 structure.md를 로드할 것.
...
이 방식은 간단하지만, 시스템에서 가장 취약한 부분이기도 합니다. 만약 엔트리 포인트가 모호하면 어시스턴트가 올바른 모듈을 로드하는 데 실패할 수 있습니다. 반대로 너무 광범위하면 다시 너무 많은 양을 로드하게 되어 이점이 사라지게 됩니다.
진입점(entry point)의 품질이 전체 아키텍처의 품질을 결정합니다.
결과
제 설정에서 세션당 기본 토큰 로드량(baseline token load)이 약 60-80% 감소했습니다.
저는 이전에는 세션 시작 시 무조건적으로 로드되었던 파일들과, 현재 무조건적으로 로드되는 파일들을 비교하여 이를 측정했습니다. 중요한 수치는 사용 가능한 모든 지침(instruction)의 총 크기가 아닙니다. 항상 로드되는 기본값(baseline)의 크기입니다.
모듈화 전:
항상 로드됨:
...
전체 지침 세트는 여전히 존재하지만, 더 이상 기본적으로 활성화되어 있지 않습니다. 지침은 필요할 때만 활성화됩니다.
작동 원리
핵심은 개별 지침을 압축하는 것이 아닙니다. 핵심은 **기본 로드 (baseline load)**와 **온디맨드 로드 (on-demand load)**를 분리하는 것입니다.
- 기본 로드 (Baseline load): 모든 세션에서 로드되는 항목입니다. 이 비용은 반복적으로 지불되기 때문에 여기서 절감 효과가 가장 큽니다.
- 온디맨드 로드 (On-demand load): 특정 상황에서만 관련이 있는 항목입니다. 실제로 필요할 때만 로드된다면, 그 내용이 방대하고 상세해도 상관없습니다.
따라서 여러분은 지침의 전체 크기를 최적화하는 것이 아닙니다. 지침 중 어떤 부분이 항상 존재해야 하는지를 최적화하는 것입니다. 그리고 그 부분은 놀라울 정도로 적습니다.
프롬프트 캐싱 (Prompt caching)은 일부 시스템에서 반복되는 기본 지침의 금전적 비용을 줄여줄 수 있습니다. 하지만 컨텍스트 예산 (context-budget) 비용, 모든 환경에서의 지연 시간 (latency) 영향, 또는 신호 대 잡음비 (signal-to-noise) 문제를 제거하지는 못합니다. 캐싱된 무관한 지침은 활성 지침 세트 내에서 여전히 무관한 지침일 뿐입니다.
비용
이것은 공짜 점심이 아닙니다.
-
간접 참조 (Indirection):
어시스턴트가 올바른 모듈을 로드하기 위해 때때로 추가적인 단계를 거쳐야 합니다. 이는 속도를 약간 저하시키며, 올바른 모듈이 로드되지 않을 위험을 초래합니다. -
라우팅 오류 (Routing errors):
만약 어시스턴트가 특정 작업에 모듈이 필요하다는 것을 인식하지 못하면, 불완전한 지침으로 답변할 수 있습니다. 이것이 주요한 운영상의 리스크입니다. -
유지보수 (Maintenance):
파일이 많아진다는 것은 서로 어긋날 수 있는 지점이 많아짐을 의미합니다. 만약 엔트리 포인트 (entry point)가 모듈에 더 이상 존재하지 않는 무언가를 약속한다면, 당신은 소리 없는 일관성 문제 (consistency problem)를 겪게 됩니다. -
규칙 충돌 (Rule conflicts):
모듈들은 서로 모순되거나 엔트리 포인트와 충돌할 수 있습니다. 우선순위 규칙 (precedence rule)이 필요합니다: 일반 지침이 기본값을 정의하고, 특화된 모듈은 해당 도메인 내에서만 이를 재정의(override)하며, 명시적인 사용자 지침은 여전히 시스템의 계층 구조에 따라 처리되어야 합니다. -
온보딩 (Onboarding):
외부인은 시스템을 읽을 수 있게 되기 전에 먼저 로딩 로직을 이해해야 합니다. 단일 파일은 이해하기가 매우 쉽습니다.
실질적인 트레이드오프 (trade-off)는 다음과 같습니다:
기본 비용 (baseline cost)은 줄이지만, 영구적인 가용성 (availability)을 포기하게 됩니다. 복잡성을 런타임 컨텍스트 (runtime context)에서 구조, 라우팅, 그리고 유지보수로 옮기는 것입니다.
가치가 있는 경우
다음과 같은 경우라면 가치가 있습니다:
- 지침 세트가 방대하고 시간이 지남에 따라 계속 커진 경우
- 세션을 빈번하게 시작하며 기본 비용이 눈에 띄게 발생하는 경우
- 내비게이션, 세션 종료 처리, 퍼블리싱, 코딩 또는 특수 워크플로우와 같이 명확하게 분리 가능한 상황이 존재하는 경우
- 환경이 어시스턴트로 하여금 추가 지침 파일을 안정적으로 로드할 수 있도록 허용하는 경우
만약 전체 설정이 어차피 몇 백 토큰 내에 들어간다면 가치가 없습니다. 그런 경우 모듈화는 조기 최적화 (premature optimization)입니다. 즉, 상상 속의 효율성을 위해 실제적인 단순함을 맞바꾸는 것입니다.
또한 어시스턴트가 필요할 때 모듈에 안정적으로 접근할 수 없다면 가치가 없습니다. 항상 로드되는 작은 파일 하나와 접근 불가능한 세부 파일들의 조합은 아키텍처가 아닙니다. 그것은 추가적인 단계만 더해진, 컨텍스트가 누락된 상태일 뿐입니다.
결론
지침 비용 (instruction cost)을 줄이기 위한 가장 큰 지렛대는 더 나은 프롬프트 (prompt)를 만드는 것이 아닙니다. 그것은 어시스턴트 (assistant)가 모든 상호작용에 강제로 들고 다니게 할 것이 무엇인지, 그리고 언제 필요할 때만 로드 (load)해야 할 것이 무엇인지에 대한 문제입니다.
기본 로드 (baseline load)와 온디맨드 로드 (on-demand load)를 분리하세요. 진입점 (entry point)을 작게 유지하고 이를 정밀한 라우터 (router)로 만드세요. 세부 사항들은 실제로 필요할 때만 비용을 발생시키도록 그 자리에 두십시오.
저의 경우, 이는 기본 로드 (baseline load)를 60-80% 줄이는 것을 의미했습니다. 하지만 중요한 부분은 단순히 비용 절감만이 아닙니다. 그것은 트레이드오프 (trade-off)입니다: 더 적은 영구적 컨텍스트 (permanent context), 그리고 더 의도적인 로딩 (deliberate loading).
그것이 제가 실제로 원하는 아키텍처 (architecture)입니다. 지침 (instruction) 자체를 줄이는 것이 아니라, 잘못된 시점에 방 안에 불필요한 지침이 머물지 않게 하는 것입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기