[opencode 시즌 2 심화 — 나만의 도메인 특화 에이전트 만들기] 7/12화: opencode 컨텍스트 엔지니어링 5가지 실전 패턴 2026
이 글은 「opencode 시즌 2 심화 — 나만의 도메인 특화 에이전트 만들기」 7일차입니다. Phase C(오케스트레이션·컨텍스트)의 마지막 회차로, 에이전트에게 ‘내 프로젝트의 맥락’을 주입하는 기술을 다룹니다.
시즌 1 4일차에서 opencode의 컨텍스트 윈도우와 대화 흐름을 다뤘던 것을 기억하시나요? 그때는 컨텍스트를 ‘소비’하는 관점이었습니다. 오늘은 그 컨텍스트를 ‘설계’하는 관점으로 전환합니다. opencode 컨텍스트 엔지니어링이란, 에이전트가 내 코드베이스의 관습·구조·도메인 지식을 처음부터 알고 있는 것처럼 행동하게 만드는 기술입니다.
어제 6일차에서 Reviewer·Tester·Refactor·SecurityAuditor 네 명의 서브에이전트 전문가 팀을 구성했습니다. 팀은 갖추어졌는데, 한 가지 문제가 남아 있습니다. 이 전문가들이 우리 프로젝트를 모릅니다. Spring Boot인지 FastAPI인지, 테이블명이 snake_case인지 camelCase인지, 예외 처리에 커스텀 ErrorCode를 쓰는지 — 이 모든 것을 매번 설명해야 한다면 에이전트를 쓰는 의미가 반감됩니다.
오늘의 핵심 3가지:
- MVI(Minimum Viable Info) 원칙 — 에이전트에게 줘야 할 ‘최소 유효 정보’의 경계를 잡는 법
- AGENTS.md 심화 — 프로젝트 루트와 디렉토리별 컨텍스트 파일의 구조·배치 전략
- 실전 컨텍스트 주입 5가지 패턴 — 리팩토링 없이 바로 쓰는 코드를 만드는 구체적 방법
컨텍스트 엔지니어링, 왜 지금 중요한가
3일차에서 시스템 프롬프트로 에이전트의 ‘정체성’을 설계했습니다. “너는 시니어 백엔드 리뷰어야, 이런 기준으로 코드를 봐” 같은 지시입니다. 그런데 정체성만으로는 부족합니다. 시니어 리뷰어가 우리 프로젝트에 첫 출근한 신입이라면, 아무리 실력이 좋아도 첫 주는 헤맬 수밖에 없습니다.
opencode 컨텍스트 엔지니어링은 이 ‘첫 출근 문제’를 해결합니다. 에이전트의 정체성이 “누구인가”를 정의한다면, 컨텍스트는 “무엇을 알고 있는가”를 정의합니다. 두 축이 만나야 비로소 에이전트가 ‘우리 팀의 3년차 개발자’처럼 행동합니다.
이 차이가 실무에서 만들어내는 격차는 놀라울 정도입니다. 같은 에이전트에게 “결제 모듈의 환불 로직을 구현해줘”라고 요청했을 때, 컨텍스트 없이는 제네릭한 CRUD 코드가 나옵니다. 하지만 “우리 프로젝트는 CQRS 패턴을 쓰고, 환불은 RefundCommand → RefundEventHandler → RefundProjection 흐름을 따르며, 금액 계산은 반드시 BigDecimal로 한다”는 컨텍스트가 있으면 — 복사해서 바로 머지할 수 있는 코드가 나옵니다.
이것이 오늘 글의 목표입니다. 에이전트가 생성하는 코드를 리팩토링 없이 바로 쓸 수 있게 만드는 컨텍스트 설계.

MVI 원칙 — 최소 유효 정보의 기술
MVI(Minimum Viable Info)는 Anthropic의 에이전트 구축 가이드에서도 강조하는 원칙입니다. 에이전트에게 제공하는 컨텍스트는 ‘최소한이되 충분한’ 수준이어야 합니다. 너무 적으면 부정확하고, 너무 많으면 핵심이 묻힙니다.
왜 “많이 주면 좋은 것 아닌가”가 틀린가
LLM의 컨텍스트 윈도우가 128K, 200K 토큰으로 넓어졌지만, ‘넓은 윈도우 = 무한한 이해’가 아닙니다. 연구에 따르면 컨텍스트가 길어질수록 중간 부분의 정보를 놓치는 ‘Lost in the Middle’ 현상이 발생합니다. 에이전트에게 프로젝트의 모든 파일을 읽히는 것은 마치 신입에게 첫날 3,000 페이지짜리 문서를 던지는 것과 같습니다.
MVI 원칙은 이렇게 정의됩니다:
“에이전트가 현재 작업을 올바르게 수행하기 위해 반드시 알아야 하는 정보의 최소 집합.”
핵심은 ‘현재 작업’에 있습니다. 에이전트가 결제 모듈을 작업할 때 인증 모듈의 세부 구현까지 알 필요는 없습니다. 다만 결제 모듈이 인증 모듈과 어떤 인터페이스로 통신하는지는 알아야 합니다.
MVI 3단계 프레임워크
실전에서 MVI를 적용할 때 저는 3단계로 나눕니다:
Level 1 — 프로젝트 전역 (Always-On Context)
- 기술 스택과 버전 (예: Java 21 + Spring Boot 3.3 + Gradle)
- 아키텍처 패턴 (예: Hexagonal Architecture, CQRS)
- 코딩 컨벤션 핵심 규칙 5~10개
- 디렉토리 구조 개요 (트리 1레벨)
- 네이밍 규칙 (클래스, 메서드, 테이블, API 엔드포인트)
이 정보는 에이전트가 어떤 작업을 하든 항상 필요합니다. 프로젝트 루트의 AGENTS.md에 넣습니다. 분량은 200~400줄이 적정합니다.
Level 2 — 모듈/도메인 (On-Demand Context)
- 해당 모듈의 도메인 용어집
- 모듈 내부 의존 관계
- 비즈니스 규칙 (예: 환불은 결제 후 7일 이내만 가능)
- 해당 모듈에서만 쓰는 유틸리티/헬퍼 설명
- 관련 테이블 스키마 요약
에이전트가 해당 디렉토리의 파일을 작업할 때만 읽히면 되는 정보입니다. 각 모듈 디렉토리의 AGENTS.md에 넣습니다. 분량은 50~150줄.
Level 3 — 작업 특화 (Task-Specific Context)
- 현재 작업의 요구사항이나 티켓 내용
- 관련 코드 스니펫 또는 인터페이스 정의
- 이전 PR의 리뷰 피드백
이것은 프롬프트에 직접 포함하거나 {file:} 참조로 주입합니다. 고정 파일이 아니라 작업마다 달라지는 동적 컨텍스트입니다.
MVI 체크리스트 — 컨텍스트 추가 전 자문
새로운 정보를 에이전트 컨텍스트에 추가하기 전에 이 질문들을 던져보세요:
- 이 정보가 없으면 에이전트가 잘못된 코드를 생성하는가? (없으면 삭제)
- 이 정보는 모든 작업에 필요한가, 특정 모듈에만 필요한가? (레벨 분류)
- 이 정보를 에이전트가 코드를 읽어서 스스로 파악할 수 있는가? (있으면 삭제)
- 이 정보의 길이가 3줄 이내로 줄일 수 있는가? (있으면 압축)
세 번째 질문이 특히 중요합니다. opencode의 Explore 서브에이전트는 코드를 탐색하는 데 특화되어 있습니다. 타입 정의, 함수 시그니처, import 구조 같은 것은 에이전트가 코드에서 직접 읽을 수 있습니다. AGENTS.md에 넣을 것은 코드에서 읽어낼 수 없는 것 — 의도, 이유, 관습, 비즈니스 규칙입니다.
AGENTS.md 심화 — 프로젝트의 두뇌를 설계하다
AGENTS.md는 opencode 에이전트가 프로젝트 컨텍스트를 읽는 일차적 진입점입니다. opencode는 작업을 시작할 때 현재 디렉토리에서 루트까지 거슬러 올라가며 AGENTS.md 파일을 찾아 읽습니다. 이 파일이 에이전트의 ‘프로젝트 온보딩 문서’ 역할을 합니다.
루트 AGENTS.md — 프로젝트의 헌법
프로젝트 루트에 놓는 AGENTS.md는 프로젝트 전체에 적용되는 ‘헌법’입니다. 모든 에이전트가 모든 작업에서 참조하므로, MVI Level 1에 해당하는 정보만 담아야 합니다.
필수 포함 섹션:
1. 프로젝트 개요 (3~5줄)
프로젝트가 무엇이고, 핵심 기술 스택이 뭔지. 에이전트가 “이 프로젝트는 무엇인가”라는 질문에 즉답할 수 있어야 합니다.
2. 아키텍처 규칙 (10~20줄)
계층 구조, 의존 방향, 사용하는 패턴. “Controller → Service → Repository” 같은 것을 명시합니다. 이것을 모르면 에이전트가 계층을 무시한 코드를 생성합니다.
3. 네이밍 컨벤션 (10~15줄)
클래스명, 메서드명, 테이블명, REST 엔드포인트, 패키지 구조의 명명 규칙. 이것이 없으면 에이전트는 자기 마음대로 이름을 짓고, 코드 리뷰에서 “네이밍 고쳐주세요”가 반복됩니다.
4. 금지 사항 (5~10줄)
“이것만은 하지 마라” 목록. 예: “Lombok @Data 사용 금지, 대신 @Getter + @Builder 사용”, “System.out.println 금지, SLF4J 사용” 같은 것. 에이전트는 ‘하라’보다 ‘하지 마라’를 더 잘 따릅니다.
5. 디렉토리 구조 (10~20줄)
1~2 레벨 깊이의 디렉토리 트리와 각 디렉토리의 역할 한 줄 설명. 에이전트가 새 파일을 만들 때 올바른 위치에 놓게 합니다.
6. 테스트 규칙 (5~10줄)
테스트 프레임워크, 네이밍 패턴, 커버리지 기준, 목킹 전략. “JUnit 5 + Mockito, 테스트 클래스명은 대상클래스Test, given-when-then 패턴” 같은 것.
위 6개 섹션을 합치면 대략 50~80줄입니다. 추가 설명과 예시를 넣어도 200줄을 넘기지 않는 것이 좋습니다. 루트 AGENTS.md는 모든 작업에 로드되므로 토큰 예산을 의식해야 합니다.
디렉토리별 AGENTS.md — 전문 지식 레이어
opencode가 특정 디렉토리 안의 파일을 작업할 때, 그 디렉토리와 상위 디렉토리의 AGENTS.md를 함께 읽습니다. 이것을 이용하면 MVI Level 2를 자연스럽게 구현할 수 있습니다.
예를 들어 이런 구조를 생각해보세요:
project-root/
├── AGENTS.md ← 프로젝트 전역 (Level 1)
├── src/
│ ├── payment/
│ │ ├── AGENTS.md ← 결제 도메인 (Level 2)
│ │ ├── command/
│ │ ├── query/
│ │ └── event/
│ ├── account/
│ │ ├── AGENTS.md ← 계좌 도메인 (Level 2)
│ │ └── ...
│ └── common/
│ ├── AGENTS.md ← 공통 유틸 (Level 2)
│ └── ...
└── tests/
└── AGENTS.md ← 테스트 전용 규칙 (Level 2)
에이전트가 src/payment/command/RefundCommand.java를 작업할 때 읽는 컨텍스트는:
project-root/AGENTS.md— 전역 규칙src/payment/AGENTS.md— 결제 도메인 규칙
이렇게 하면 결제 도메인의 에이전트는 “BigDecimal 필수, 원 단위 절사, 환불 한도 7일”을 알지만, 계좌 도메인의 에이전트는 그런 규칙에 방해받지 않습니다. 필요한 곳에 필요한 정보만. 이것이 MVI의 실천입니다.
디렉토리 AGENTS.md에 넣어야 할 것
디렉토리별 AGENTS.md는 루트보다 더 구체적이고 도메인 밀착적이어야 합니다.
- 도메인 용어집: 해당 모듈에서만 쓰는 용어와 정의. “정산(Settlement): 가맹점에 매출 대금을 지급하는 행위. 일정산/주정산/월정산 세 가지.”
- 비즈니스 규칙: 코드에 하드코딩된 매직 넘버의 의미. “REFUND_LIMIT_DAYS = 7 → 전자상거래법 제17조 근거.”
- 내부 인터페이스: 이 모듈이 다른 모듈과 통신하는 계약. “PaymentGateway 인터페이스의 charge()는 항상 PaymentResult를 반환, 예외 아님.”
- 자주 발생하는 실수: “이 모듈에서 float/double로 금액 계산하면 절대 안 됨. 과거 장애 이력 있음.”
- 관련 테이블 스키마: ERD 전체가 아니라, 이 모듈이 직접 조회/수정하는 테이블 2~3개의 핵심 컬럼만.
분량은 50~150줄. 이보다 길어지면 별도의 컨텍스트 파일로 분리하고 {file:} 참조를 씁니다.

opencode 컨텍스트 엔지니어링의 폴백 체인
opencode가 컨텍스트를 해석하는 순서를 이해하면 전략적으로 정보를 배치할 수 있습니다. 폴백 체인은 가장 구체적인 것에서 가장 일반적인 것 순서입니다:
해석 순서 (높은 우선순위 → 낮은 우선순위)
- 프롬프트 직접 입력 — 사용자가 대화에서 직접 전달한 지시 (Level 3, 최우선)
- 디렉토리 AGENTS.md — 현재 작업 디렉토리의 AGENTS.md (Level 2)
- 상위 디렉토리 AGENTS.md — 루트까지 거슬러 올라가며 발견되는 AGENTS.md들 (Level 2~1)
- 프로젝트 루트 AGENTS.md — 프로젝트 최상위의 AGENTS.md (Level 1)
- 프로젝트 로컬 에이전트 정의 —
.opencode/agents/*.md의 시스템 프롬프트 (3일차 내용) - 프로젝트 로컬 설정 —
.opencode/디렉토리의 opencode.json (Level 1) - 글로벌 에이전트 정의 —
~/.config/opencode/agents/*.md(글로벌 기본값) - 글로벌 설정 —
~/.config/opencode/opencode.json(글로벌 기본값)
중요한 것은 이 체인에서 같은 키가 충돌하면 더 구체적인(상위 우선순위) 것이 이긴다는 점입니다. 글로벌 설정에서 기본 모델을 지정해도 프로젝트 로컬 설정에서 덮어쓸 수 있고, AGENTS.md에서 “이 프로젝트는 camelCase를 쓴다”라고 해도 특정 디렉토리의 AGENTS.md에서 “이 레거시 모듈은 snake_case를 쓴다”로 예외를 둘 수 있습니다.
전략적 배치 — 어디에 무엇을 놓을까
폴백 체인을 이해했으니 전략적 배치를 설계해봅시다.
글로벌 (모든 프로젝트 공통)
# ~/.config/opencode/agents/reviewer.md
---
name: Reviewer
description: 코드 리뷰 전문가
model: anthropic/claude-sonnet-4
---
당신은 시니어 코드 리뷰어입니다.
모든 리뷰에서 다음을 확인합니다:
- 보안 취약점 (SQL Injection, XSS, CSRF)
- 에러 핸들링 누락
- 성능 안티패턴
이것은 프로젝트를 불문하고 적용되는 ‘개인의 기본 설정’입니다. 글로벌에는 개인 취향과 범용 원칙만 넣습니다.
프로젝트 로컬 (이 프로젝트만)
# .opencode/agents/reviewer.md
---
name: Reviewer
description: 이 프로젝트의 코드 리뷰 전문가
model: anthropic/claude-sonnet-4
---
{file:./AGENTS.md}
추가 리뷰 기준:
- 모든 금액 계산은 BigDecimal인지 확인
- @Transactional 범위가 최소화되어 있는지 확인
- 도메인 이벤트 발행이 누락되지 않았는지 확인
같은 이름의 에이전트가 프로젝트 로컬에도 있으면 로컬이 글로벌을 덮어씁니다. 글로벌의 범용 리뷰 기준 위에 프로젝트 특화 기준을 얹는 패턴입니다. 여기서 {file:./AGENTS.md}로 프로젝트 루트의 AGENTS.md 전체를 시스템 프롬프트에 주입하는 점에 주목하세요. 3일차에서 다룬 외부화 패턴의 실전 응용입니다.
글로벌 vs 로컬 판단 기준:
- “이 설정이 다른 프로젝트에서도 유효한가?” → Yes면 글로벌
- “이 설정이 이 프로젝트의 특수한 사정 때문인가?” → Yes면 로컬
- “팀원도 같은 설정을 쓰면 좋겠는가?” → Yes면 로컬 (Git에 커밋 가능)
- “나만의 개인 취향인가?” → Yes면 글로벌 (Git에 커밋하지 않음)
실전 opencode 컨텍스트 엔지니어링 5가지 주입 패턴
이론은 충분합니다. 이제 실전입니다. 아래 5가지 패턴은 에이전트가 생성하는 코드의 품질을 극적으로 올리는, 검증된 컨텍스트 주입 방법입니다.

패턴 1: 프로젝트 구조 맵 (Structural Map)
에이전트에게 프로젝트의 디렉토리 구조와 각 부분의 역할을 알려줍니다. 새 파일을 만들 때 올바른 위치에 놓고, 기존 유틸리티를 재발명하지 않게 합니다.
# AGENTS.md — 프로젝트 구조 맵 섹션
## 디렉토리 구조
```
src/main/java/com/example/trade/
├── api/ # REST Controller (외부 진입점)
│ ├── dto/ # 요청/응답 DTO (record 사용)
│ └── advice/ # @ControllerAdvice 예외 핸들러
├── application/ # UseCase (비즈니스 유스케이스, 1 class = 1 use case)
│ ├── command/ # 쓰기 유스케이스
│ └── query/ # 읽기 유스케이스
├── domain/ # Entity, VO, Domain Event, Domain Service
│ ├── model/ # JPA Entity
│ ├── vo/ # Value Object (불변)
│ ├── event/ # 도메인 이벤트
│ └── repository/ # Repository 인터페이스 (구현체는 infra)
├── infrastructure/ # 외부 시스템 연동
│ ├── persistence/ # JPA Repository 구현
│ ├── messaging/ # Kafka Producer/Consumer
│ └── external/ # 외부 API 클라이언트
└── config/ # Spring @Configuration
```
## 의존 방향 (절대 규칙)
api → application → domain ← infrastructure
- domain은 어떤 외부 계층도 import하지 않는다
- application은 domain의 인터페이스만 의존한다
- infrastructure가 domain 인터페이스를 구현한다
이 구조 맵이 있으면 에이전트에게 “주문 취소 기능을 만들어줘”라고만 해도:
- Controller를
api/에 만들고 - UseCase를
application/command/에 만들고 - 도메인 이벤트를
domain/event/에 만들고 - 의존 방향을 지켜서 import합니다
구조 맵이 없으면? 모든 로직이 Controller에 몰리는 ‘Fat Controller’ 코드가 나올 확률이 높습니다.
패턴 2: 코딩 컨벤션 체크리스트 (Convention Checklist)
에이전트에게 ‘우리 팀의 코딩 스타일’을 구체적으로 알려줍니다. 추상적인 원칙이 아니라 바로 판단할 수 있는 체크리스트 형태가 효과적입니다.
# AGENTS.md — 코딩 컨벤션 섹션
## 코딩 컨벤션
### 네이밍
- 클래스명: PascalCase. UseCase는 동사+명사 (예: CancelOrderUseCase)
- 메서드명: camelCase. boolean 반환은 is/has/can 접두사
- 상수: UPPER_SNAKE_CASE
- 테이블명: lower_snake_case. 복수형 (orders, trade_items)
- REST 엔드포인트: kebab-case (POST /api/v1/trade-orders)
### Java 스타일
- record 적극 사용: DTO, VO, Event는 모두 record
- Optional: 반환 타입에만 사용. 파라미터, 필드에 사용 금지
- null 반환 금지: Optional 또는 빈 컬렉션 반환
- 접근 제한자: 최소 권한 원칙. public 남발 금지
- final 로컬 변수: 선언 후 재할당 없으면 final
- Lombok: @Getter, @Builder, @RequiredArgsConstructor만 허용
- @Data, @Setter, @ToString 사용 금지
### 예외 처리
- 비즈니스 예외: BusinessException(ErrorCode) 패턴
- ErrorCode: enum으로 정의. HTTP 상태코드 + 메시지 포함
- catch(Exception e) 금지: 구체적 예외만 catch
- 예외 로깅: catch 블록에서 반드시 log.error() 후 rethrow 또는 변환
### 테스트
- 프레임워크: JUnit 5 + Mockito + AssertJ
- 클래스명: {대상클래스}Test
- 메서드명: should_{결과}_when_{조건} (예: should_throw_when_amount_negative)
- 패턴: given-when-then 주석으로 구분
- 커버리지: 신규 코드 80% 이상
이 체크리스트가 있으면 에이전트가 생성하는 코드의 스타일이 팀원이 작성한 것과 구분할 수 없을 정도로 일관됩니다. 특히 금지 사항을 명확히 적는 것이 효과가 큽니다. 에이전트는 “~하라”보다 “~하지 마라”에 더 정확하게 반응합니다.
패턴 3: 도메인 용어집 (Domain Glossary)
도메인 주도 설계(DDD)에서 유비쿼터스 언어가 중요하듯, 에이전트에게도 도메인 용어를 정확히 알려줘야 합니다. 특히 같은 단어가 일반적 의미와 도메인 의미가 다를 때 필수입니다.
# src/payment/AGENTS.md — 결제 도메인 용어집
## 도메인 용어집
| 용어 | 정의 | 코드 표현 |
|------|------|-----------|
| 결제(Payment) | 고객이 상품 대금을 지불하는 행위 | Payment entity |
| 승인(Approval) | PG사가 카드사에 결제를 요청하여 승인받는 행위 | ApprovalResult VO |
| 매입(Capture) | 승인된 거래를 실제 정산 대상으로 확정하는 행위 | CaptureCommand |
| 취소(Cancel) | 매입 전 승인을 무효화하는 행위 | CancelCommand |
| 환불(Refund) | 매입 후 금액을 고객에게 반환하는 행위 | RefundCommand |
| 부분환불(Partial Refund) | 결제 금액의 일부만 환불 | refundAmount < originalAmount |
| 정산(Settlement) | 가맹점에 매출 대금을 지급하는 행위 | SettlementBatch |
| PG사 | Payment Gateway 사업자 (토스, KG이니시스 등) | PaymentGateway interface |
## 비즈니스 규칙
- 환불 가능 기간: 결제 승인일로부터 7일 (REFUND_LIMIT_DAYS = 7)
- 부분환불 횟수 제한: 동일 결제 건당 최대 3회
- 최소 결제 금액: 100원 (MIN_PAYMENT_AMOUNT = 100)
- 금액 계산: 반드시 BigDecimal, RoundingMode.HALF_UP, scale=0 (원 단위 절사)
- 금액 필드 타입: DB는 DECIMAL(15,0), Java는 BigDecimal
용어집이 있으면 에이전트는 “취소”와 “환불”을 정확히 구분합니다. 없으면 두 개념을 혼용하거나, Cancel 로직에 Refund를 쓰는 버그를 만들 수 있습니다. 업무 도메인이 복잡할수록 용어집의 가치는 커집니다.
이 패턴은 금융IT뿐 아니라 의료(진료·처방·조제의 구분), 물류(입고·출고·반품의 차이), 교육(수강·이수·평가의 관계) 등 전문 용어가 많은 도메인에서 특히 강력합니다.
패턴 4: 에러 패턴 사전 (Error Pattern Dictionary)
에이전트가 자주 실수하는 패턴을 사전에 등록해두면 같은 실수를 반복하지 않습니다. 이것은 팀의 코드 리뷰 히스토리에서 추출하는 것이 가장 효과적입니다.
# AGENTS.md — 에러 패턴 사전 섹션
## ⚠️ 자주 발생하는 실수 — 이것만은 피하세요
### 금액 계산 실수
❌ 잘못된 코드:
```java
double total = price * quantity * (1 - discountRate);
```
✅ 올바른 코드:
```java
BigDecimal total = price.multiply(BigDecimal.valueOf(quantity))
.multiply(BigDecimal.ONE.subtract(discountRate))
.setScale(0, RoundingMode.HALF_UP);
```
이유: 부동소수점 오차로 1원 차이가 발생하면 정산 불일치.
### 트랜잭션 범위 실수
❌ 잘못된 코드:
```java
@Transactional
public void processOrder(OrderCommand cmd) {
Order order = orderRepository.save(cmd.toEntity());
paymentGateway.charge(order); // 외부 API 호출이 트랜잭션 안에!
eventPublisher.publish(new OrderCreated(order));
}
```
✅ 올바른 코드:
```java
@Transactional
public Order createOrder(OrderCommand cmd) {
Order order = orderRepository.save(cmd.toEntity());
eventPublisher.publish(new OrderCreated(order));
return order;
}
// 외부 API 호출은 이벤트 핸들러에서 트랜잭션 밖에서 수행
```
이유: 외부 API 호출이 트랜잭션 안에 있으면 타임아웃 시 DB 커넥션 고갈.
### N+1 쿼리 실수
❌: 연관 엔티티를 반복 조회하는 LAZY 로딩 방치
✅: @EntityGraph 또는 fetch join 사용
확인법: 테스트에서 쿼리 카운트 검증 (hibernate.session_metrics 활용)
이 패턴이 강력한 이유는 부정 예시(❌)와 긍정 예시(✅)를 함께 보여주기 때문입니다. LLM은 “이렇게 하지 마라”만 보면 가끔 무시하지만, 구체적인 잘못된 코드와 올바른 코드를 함께 보면 구분을 정확히 합니다. 코드 리뷰에서 반복적으로 지적되는 패턴 3~5개만 등록해도 에이전트의 코드 품질이 눈에 띄게 올라갑니다.
패턴 5: 예시 기반 원샷 러닝 (One-Shot Learning by Example)
가장 강력하면서도 가장 과소평가된 패턴입니다. 에이전트에게 “이 프로젝트에서 비슷한 기능을 어떻게 구현했는지” 참조 파일을 보여주는 것입니다.
# src/payment/AGENTS.md — 참조 구현 섹션
## 참조 구현 (새 기능 구현 시 이 파일들을 패턴으로 삼으세요)
### 새 결제 수단 추가 시
1. 인터페이스: src/payment/domain/PaymentGateway.java (포트)
2. 구현체: src/payment/infrastructure/external/TossPaymentGateway.java
3. UseCase: src/payment/application/command/ChargePaymentUseCase.java
4. 테스트: tests/payment/application/command/ChargePaymentUseCaseTest.java
→ 새 결제 수단(예: 네이버페이)을 추가할 때는 위 4개 파일의 구조를
동일하게 따르되, PaymentGateway 구현체만 새로 작성하세요.
### 새 도메인 이벤트 추가 시
참조: src/payment/domain/event/PaymentApproved.java
→ record로 선언, 타임스탬프 + aggregate ID + 변경 데이터만 포함
→ 이벤트 핸들러는 infrastructure/messaging/ 아래에 작성
“이것처럼 만들어줘”는 백 마디 규칙보다 강력합니다. 에이전트가 참조 파일을 읽고 동일한 구조·네이밍·패턴으로 새 코드를 생성합니다. 이 방식으로 만든 코드는 정말로 리팩토링 없이 바로 머지 가능합니다.
다만 주의할 점이 있습니다. 참조 파일 자체를 AGENTS.md에 인라인하지 마세요. 파일 경로만 알려주면 에이전트의 Explore 서브에이전트가 필요할 때 읽습니다. 인라인하면 AGENTS.md가 비대해지고 MVI 원칙에 어긋납니다.
동작하는 설정 한 벌 — 복사해서 바로 쓰기
지금까지 다룬 5가지 패턴을 모두 통합한, 실제로 동작하는 설정 파일을 제공합니다. Spring Boot 기반 거래 시스템을 예로 들지만, 프레임워크와 도메인을 바꾸면 어떤 프로젝트에든 적용할 수 있습니다.
파일 1: 프로젝트 루트 AGENTS.md (완전한 형태)
# Trade Platform — 에이전트 컨텍스트
## 프로젝트 개요
Java 21 + Spring Boot 3.3 + Gradle 기반의 실시간 거래 플랫폼.
Hexagonal Architecture(포트-어댑터) + CQRS 패턴 사용.
PostgreSQL(쓰기) + Redis(읽기 캐시) + Kafka(이벤트 버스) 구성.
## 아키텍처 규칙
### 계층 구조와 의존 방향
```
api → application → domain ← infrastructure
```
- domain 계층은 외부 의존성 없음 (순수 Java)
- application 계층은 domain의 인터페이스(포트)만 의존
- infrastructure가 domain 인터페이스를 구현 (어댑터)
- api 계층은 application의 UseCase만 호출
### 디렉토리 구조
```
src/main/java/com/example/trade/
├── api/ # REST Controller + DTO + 예외 핸들러
├── application/ # UseCase (command/ + query/)
├── domain/ # Entity, VO, Event, Repository 인터페이스
├── infrastructure/ # JPA, Kafka, 외부 API 구현
└── config/ # Spring 설정
```
## 코딩 컨벤션
### 네이밍
- 클래스: PascalCase. UseCase는 동사+명사 (CancelOrderUseCase)
- 메서드: camelCase. boolean → is/has/can 접두사
- 상수: UPPER_SNAKE_CASE
- 테이블: lower_snake_case, 복수형 (trade_orders)
- 엔드포인트: kebab-case (POST /api/v1/trade-orders)
- 패키지: 도메인별 모듈 분리 (com.example.trade.payment)
### Java 스타일
- DTO, VO, Event: Java record 사용
- Optional: 반환 타입에만 허용. 파라미터/필드 금지
- null 반환 금지 → Optional 또는 빈 컬렉션
- Lombok: @Getter, @Builder, @RequiredArgsConstructor만 허용
- @Data, @Setter, @ToString → 사용 금지
- 접근 제한자 최소 권한 원칙. public 남발 금지
- final 로컬 변수: 재할당 없으면 final
### 예외 처리
- 비즈니스 예외: throw new BusinessException(ErrorCode.XXX)
- ErrorCode: enum, HTTP 상태 코드 + 메시지 포함
- catch(Exception e) 금지 → 구체적 예외만 catch
- 로깅: catch에서 log.error(msg, e) 후 rethrow/변환
### 금액 계산 (절대 규칙)
- 타입: Java BigDecimal / DB DECIMAL(15,0)
- 반올림: RoundingMode.HALF_UP, scale=0
- float/double로 금액 계산 절대 금지
### 테스트
- JUnit 5 + Mockito + AssertJ
- 클래스명: {대상}Test
- 메서드명: should_{결과}_when_{조건}
- 패턴: given-when-then 주석 구분
- 신규 코드 커버리지 80% 이상
## 금지 사항
- System.out.println → SLF4J log 사용
- @Autowired 필드 주입 → 생성자 주입
- 순환 의존 → 이벤트 기반으로 분리
- domain 계층에 Spring 어노테이션 → 순수 Java만
- 하드코딩된 매직 넘버 → 상수 또는 설정으로 추출
이 파일은 약 80줄로, 에이전트가 프로젝트의 전체 맥락을 파악하기에 충분하면서도 토큰 예산을 과도하게 쓰지 않습니다.
파일 2: 결제 모듈 디렉토리 AGENTS.md
# Payment Module — 에이전트 컨텍스트
## 도메인 용어
| 용어 | 정의 | 코드 표현 |
|------|------|-----------|
| 승인(Approval) | PG사가 카드사에 결제 승인 | ApprovalResult |
| 매입(Capture) | 승인 → 정산 대상 확정 | CaptureCommand |
| 취소(Cancel) | 매입 전 승인 무효화 | CancelCommand |
| 환불(Refund) | 매입 후 금액 반환 | RefundCommand |
## 비즈니스 규칙
- 환불 기한: 승인일 +7일 (REFUND_LIMIT_DAYS = 7)
- 부분환불: 동일 건 최대 3회 (MAX_PARTIAL_REFUND_COUNT = 3)
- 최소 결제: 100원 (MIN_PAYMENT_AMOUNT = 100)
## 참조 구현 (새 기능은 이 파일들의 패턴을 따르세요)
- 포트 인터페이스: domain/PaymentGateway.java
- 어댑터 구현: infrastructure/external/TossPaymentGateway.java
- 커맨드 UseCase: application/command/ChargePaymentUseCase.java
- UseCase 테스트: tests/payment/ChargePaymentUseCaseTest.java
## ⚠️ 이 모듈에서 자주 발생하는 실수
1. float/double 금액 계산 → BigDecimal 필수
2. 외부 PG API 호출을 @Transactional 안에 넣기 → 이벤트 핸들러로 분리
3. 취소와 환불 혼동 → 매입 전=취소, 매입 후=환불
파일 3: 컨텍스트를 활용하는 에이전트 정의
# .opencode/agents/impl-agent.md
---
name: Implementor
description: "프로젝트 컨벤션을 준수하는 구현 전문가. 새 기능 구현, 버그 수정, 리팩토링 요청 시 위임."
model: anthropic/claude-sonnet-4
---
{file:./AGENTS.md}
당신은 이 프로젝트의 구현 전문가입니다.
## 작업 절차
1. 요청받은 작업의 관련 디렉토리 AGENTS.md를 먼저 읽으세요
2. 참조 구현 파일이 명시되어 있으면 해당 파일의 패턴을 따르세요
3. 루트 AGENTS.md의 코딩 컨벤션과 금지 사항을 반드시 준수하세요
4. 새 파일의 위치는 디렉토리 구조 규칙을 따르세요
5. 테스트를 반드시 함께 작성하세요
## 코드 생성 원칙
- 기존 코드베이스와 동일한 스타일을 유지합니다
- 새 유틸리티를 만들기 전에 common/ 디렉토리의 기존 유틸리티를 확인합니다
- 금액 관련 코드는 BigDecimal 외에는 사용하지 않습니다
- 불확실한 비즈니스 규칙은 구현 전에 반드시 확인을 요청합니다
이 세 파일이 조합되면 에이전트는:
- 루트 AGENTS.md에서 전역 규칙을 읽고
- 작업 디렉토리의 AGENTS.md에서 도메인 지식을 읽고
- 참조 구현 파일에서 코드 패턴을 학습하고
- 에이전트 정의의 시스템 프롬프트에서 작업 절차를 따릅니다
이 4단계 파이프라인이 갖추어지면, “환불 기능을 구현해줘”라는 한 마디에 프로젝트 컨벤션을 완벽히 따르는 코드가 나옵니다.
고급 기법: opencode 컨텍스트 엔지니어링의 경계를 넓히다
조건부 컨텍스트 — 작업 유형에 따라 다른 정보 주입
6일차에서 만든 서브에이전트들을 떠올려보세요. Reviewer, Tester, Refactor, SecurityAuditor — 각각 필요한 컨텍스트가 다릅니다. Reviewer에게는 코딩 컨벤션이 중요하고, SecurityAuditor에게는 보안 체크리스트가 중요합니다.
에이전트별로 다른 컨텍스트를 주입하는 방법:
# .opencode/agents/security-auditor.md
---
name: SecurityAuditor
description: "보안 취약점 전문 감사. 새 API 엔드포인트, 인증/인가 변경, 외부 연동 시 위임."
model: anthropic/claude-sonnet-4
---
{file:./AGENTS.md}
{file:./.opencode/context/security-checklist.md}
당신은 이 프로젝트의 보안 감사 전문가입니다.
OWASP Top 10과 프로젝트 보안 체크리스트를 기준으로 코드를 검토합니다.
# .opencode/context/security-checklist.md
## 프로젝트 보안 체크리스트
### 인증/인가
- 모든 API에 @PreAuthorize 또는 SecurityConfig 설정 확인
- 관리자 API는 ROLE_ADMIN 권한 필수
- 토큰 만료 시간: Access 30분, Refresh 7일
### 입력 검증
- @Valid + DTO 단위 검증 (Controller 레벨)
- SQL 파라미터: PreparedStatement만 사용 (문자열 결합 금지)
- 파일 업로드: 확장자 화이트리스트 + MIME 타입 검증
### 데이터 보호
- 개인정보(이름, 전화, 이메일): 로그 출력 시 마스킹 필수
- 카드 번호: 앞 6자리 + 뒤 4자리만 표시 (PCI-DSS)
- 비밀번호: BCrypt 해싱, 평문 저장/로깅 절대 금지
### 외부 통신
- HTTPS만 허용 (HTTP 직접 호출 금지)
- API 키/시크릿: 환경변수로만 주입, 코드/설정 파일에 평문 금지
- 타임아웃: connect 3초, read 10초 설정 필수
SecurityAuditor는 루트 AGENTS.md(전역 규칙) + security-checklist.md(보안 전용 체크리스트) 두 가지를 읽습니다. Implementor 에이전트에게는 보안 체크리스트 대신 코딩 컨벤션이 더 중요하므로, 서로 다른 {file:} 조합을 사용합니다.
이렇게 하면 각 에이전트가 자기 역할에 필요한 정보만 가지고 작업합니다. MVI 원칙의 에이전트 레벨 적용입니다.
컨텍스트 파일 구조화 — .opencode/context/ 패턴
컨텍스트 파일이 여러 개로 늘어나면 관리가 필요합니다. 저는 .opencode/context/ 디렉토리를 만들어 용도별로 분류합니다:
.opencode/
├── agents/
│ ├── impl-agent.md
│ ├── reviewer.md
│ └── security-auditor.md
└── context/
├── architecture-rules.md # 아키텍처 규칙 상세
├── coding-conventions.md # 코딩 컨벤션 확장
├── security-checklist.md # 보안 체크리스트
├── domain-glossary.md # 전체 도메인 용어집
└── error-patterns.md # 에러 패턴 사전
AGENTS.md가 너무 길어지면 핵심만 남기고 상세 내용은 context/ 파일로 분리합니다. 에이전트 정의에서 {file:./.opencode/context/xxx.md}로 필요한 것만 선택적으로 가져옵니다.
이 구조의 장점은 재사용성입니다. coding-conventions.md는 Implementor와 Reviewer 에이전트 모두에서 참조할 수 있고, security-checklist.md는 SecurityAuditor만 참조합니다. 에이전트마다 필요한 컨텍스트 파일을 조합하는 ‘장바구니’ 패턴입니다.
컨텍스트 버전 관리 — Git에 커밋하는 이유
AGENTS.md와 .opencode/ 디렉토리의 컨텍스트 파일은 반드시 Git에 커밋해야 합니다. 이유가 세 가지입니다:
- 팀 공유: 나만 에이전트를 잘 쓰는 게 아니라, 팀 전체가 같은 컨텍스트로 에이전트를 씁니다. 코드 리뷰 품질이 팀원에 관계없이 일정해집니다.
- 변경 이력: 컨벤션이 바뀔 때 AGENTS.md도 같은 PR에서 업데이트합니다. “왜 에이전트가 갑자기 다른 스타일로 코드를 만들지?”라는 혼란을 방지합니다.
- 코드-컨텍스트 동기화: AGENTS.md가 코드와 같은 저장소에 있으면, 코드가 바뀔 때 컨텍스트도 함께 바뀝니다. 별도 위키나 노션에 두면 어느 순간 코드와 동기가 어긋납니다.
개인 취향에 해당하는 설정(기본 모델 선호, 개인 단축키 등)만 글로벌(~/.config/opencode/)에 두고, 프로젝트 규칙은 모두 프로젝트 로컬에 커밋합니다.
실전 적용 사례 — 컨텍스트 전후 비교
시나리오: “주문 취소 API를 만들어줘”
컨텍스트 없이 생성된 코드 (Before):
@RestController
@RequestMapping("/orders")
public class OrderController {
@Autowired
private OrderRepository orderRepository;
@PostMapping("/{id}/cancel")
public ResponseEntity<String> cancelOrder(@PathVariable Long id) {
Order order = orderRepository.findById(id)
.orElseThrow(() -> new RuntimeException("Order not found"));
order.setStatus("CANCELLED");
order.setCancelledAt(new Date());
double refundAmount = order.getTotalAmount() * 0.95; // 5% 수수료
orderRepository.save(order);
return ResponseEntity.ok("Order cancelled. Refund: " + refundAmount);
}
}
이 코드의 문제점을 세어볼까요?
- ❌ @Autowired 필드 주입 (컨벤션 위반)
- ❌ RuntimeException 사용 (BusinessException 패턴 위반)
- ❌ setter 사용 (record/불변 원칙 위반)
- ❌ 문자열 상태값 (enum 미사용)
- ❌ double 금액 계산 (BigDecimal 필수 규칙 위반)
- ❌ 매직 넘버 0.95 (상수 미추출)
- ❌ 계층 분리 없음 (UseCase 패턴 위반)
- ❌ 도메인 이벤트 미발행
- ❌ 테스트 없음
9가지 리팩토링 포인트. 에이전트에게 코드를 받고도 결국 직접 다시 쓰는 수준입니다.
컨텍스트가 있을 때 생성된 코드 (After):
// api/dto/CancelOrderRequest.java
public record CancelOrderRequest(
@NotBlank String cancelReason
) {}
// api/OrderController.java
@RestController
@RequestMapping("/api/v1/orders")
@RequiredArgsConstructor
public class OrderController {
private final CancelOrderUseCase cancelOrderUseCase;
@PostMapping("/{orderId}/cancel")
public ResponseEntity<CancelOrderResponse> cancelOrder(
@PathVariable final Long orderId,
@RequestBody @Valid final CancelOrderRequest request) {
final CancelOrderResult result = cancelOrderUseCase.execute(
new CancelOrderCommand(orderId, request.cancelReason())
);
return ResponseEntity.ok(CancelOrderResponse.from(result));
}
}
// application/command/CancelOrderUseCase.java
@Service
@RequiredArgsConstructor
public class CancelOrderUseCase {
private final OrderRepository orderRepository;
private final ApplicationEventPublisher eventPublisher;
@Transactional
public CancelOrderResult execute(final CancelOrderCommand command) {
final Order order = orderRepository.findById(command.orderId())
.orElseThrow(() -> new BusinessException(ErrorCode.ORDER_NOT_FOUND));
order.cancel(command.cancelReason());
eventPublisher.publishEvent(new OrderCancelled(
order.getId(),
order.getCancelledAt(),
command.cancelReason()
));
return CancelOrderResult.from(order);
}
}
// domain/model/Order.java (cancel 메서드)
public void cancel(final String reason) {
if (this.status != OrderStatus.CONFIRMED) {
throw new BusinessException(ErrorCode.ORDER_CANNOT_CANCEL);
}
this.status = OrderStatus.CANCELLED;
this.cancelReason = reason;
this.cancelledAt = LocalDateTime.now();
}
같은 요청, 완전히 다른 결과입니다. 두 번째 코드는:
- ✅ 생성자 주입 (@RequiredArgsConstructor)
- ✅ UseCase 패턴으로 계층 분리
- ✅ record DTO
- ✅ BusinessException + ErrorCode
- ✅ 도메인 모델의 상태 변경 메서드
- ✅ 도메인 이벤트 발행
- ✅ final 로컬 변수
- ✅ @Valid 입력 검증
리팩토링 포인트가 0입니다. 이것이 opencode 컨텍스트 엔지니어링의 실질적 가치입니다.
컨텍스트 유지보수 — 살아있는 문서로 만들기
AGENTS.md와 컨텍스트 파일은 한 번 작성하고 끝이 아닙니다. 코드베이스가 진화하면 컨텍스트도 함께 진화해야 합니다.
컨텍스트 업데이트 트리거
- 새 컨벤션 도입 시: 팀에서 “앞으로 DTO는 record로 한다”고 결정하면 AGENTS.md에 즉시 반영
- 아키텍처 변경 시: 새 모듈 추가, 의존 구조 변경 시 디렉토리 구조 맵 업데이트
- 코드 리뷰에서 반복 지적 시: 같은 피드백이 3번 나오면 에러 패턴 사전에 추가
- 신규 팀원 온보딩 시: 신규 팀원이 자주 묻는 질문은 AGENTS.md에 추가할 후보
컨텍스트 리뷰 주기
월 1회 AGENTS.md를 리뷰하는 것을 권합니다. 체크할 것:
- 코드와 동기가 맞는가? (더 이상 쓰지 않는 패턴이 남아있지 않은가)
- MVI를 지키고 있는가? (불필요하게 비대해지지 않았는가)
- 에이전트가 여전히 컨텍스트를 잘 따르는가? (실제 생성 코드로 검증)
팀 차원의 컨텍스트 거버넌스
AGENTS.md 변경도 일반 코드 변경과 같은 PR 프로세스를 따르게 합니다. “에이전트 컨텍스트 변경”이라고 대충 머지하면 안 됩니다. 컨벤션 변경은 팀 전체에 영향을 미치는 결정이기 때문입니다.
opencode 공식 저장소에서도 AGENTS.md 관련 기능이 지속적으로 개선되고 있으니, 릴리즈 노트를 주기적으로 확인하는 것을 추천합니다.
opencode.json과 AGENTS.md의 역할 분담
2일차에서 opencode.json과 .opencode/agents/*.md 두 가지 에이전트 정의 방식을 비교했습니다. 컨텍스트 엔지니어링 관점에서 역할을 명확히 구분하면:
- opencode.json: 구조적 설정 (모델, 권한, MCP 서버 등). “에이전트가 무엇을 할 수 있는가.”
- .opencode/agents/*.md: 행동 정의 + 컨텍스트 주입. “에이전트가 어떻게 행동하고, 무엇을 아는가.”
- AGENTS.md: 프로젝트/도메인 지식. “이 프로젝트는 무엇이고, 어떤 규칙을 따르는가.”
세 파일의 관계:
opencode.json
└── agent 키: 에이전트 등록 (이름, 모델, 권한)
│
▼
.opencode/agents/*.md
└── 시스템 프롬프트: 에이전트 정체성 + {file:} 컨텍스트 참조
│
▼
AGENTS.md + .opencode/context/*.md
└── 프로젝트 지식: 아키텍처, 컨벤션, 도메인, 에러 패턴
opencode.json에서 에이전트를 등록하고, agents/*.md에서 행동을 정의하고, AGENTS.md에서 지식을 주입합니다. 이 삼각 구조가 opencode 컨텍스트 엔지니어링의 완전한 그림입니다.
컨텍스트 크기 관리 — 토큰 예산 감각 기르기
AGENTS.md가 효과적이려면 토큰 예산을 의식해야 합니다. 에이전트의 컨텍스트 윈도우는 유한하고, AGENTS.md가 차지하는 비율이 높을수록 실제 작업에 쓸 수 있는 공간이 줄어듭니다.
경험적 가이드라인
- 루트 AGENTS.md: 200줄 이내 (약 2,000~3,000 토큰). 모든 작업에 로드되므로 가장 엄격하게 관리.
- 디렉토리 AGENTS.md: 100줄 이내 (약 1,000~1,500 토큰). 해당 모듈 작업 시에만 로드.
- context/ 참조 파일: 파일당 150줄 이내. 에이전트 정의에서 선택적으로 로드.
- 전체 고정 컨텍스트 합계: 5,000~8,000 토큰이 적정. 전체 윈도우의 5% 이내를 목표.
줄 수로 관리하는 이유는 토큰 수가 직관적이지 않기 때문입니다. 한국어 기준으로 1줄 ≈ 15~25 토큰 정도입니다. 영어 코드 블록은 1줄 ≈ 8~15 토큰입니다. 혼합 문서라면 1줄 ≈ 12~20 토큰으로 대략 잡으면 됩니다.
비대해진 AGENTS.md 다이어트 기법
AGENTS.md가 300줄을 넘어가면 다이어트가 필요합니다:
- 에이전트가 코드에서 읽을 수 있는 것 삭제: 타입 정의, import 구조, 디렉토리 리스팅 등은 Explore 에이전트가 직접 파악 가능
- 중복 제거: 루트와 디렉토리 AGENTS.md에서 같은 내용이 반복되면 루트에만 남김
- 상세 내용 분리: 에러 패턴 사전 같은 긴 내용은 context/ 파일로 분리하고 필요한 에이전트만 {file:}로 참조
- 예시 코드 최소화: ❌/✅ 대조는 3~5줄로 압축. 전체 클래스를 인라인하지 않음
- 참조 경로만 제공: “이 파일을 참고하세요”라고 경로만 적으면 에이전트가 필요할 때 읽음
요점은 AGENTS.md를 ‘백과사전’이 아니라 ‘치트 시트’로 만드는 것입니다. 에이전트가 빠르게 훑고 핵심을 잡을 수 있어야 합니다.
Gotcha 미니 코너 — “컨텍스트 과적재” 함정
처음 AGENTS.md를 작성하면 흥이 나서 모든 것을 넣고 싶어집니다. 프로젝트의 역사, 모든 테이블의 스키마, 코드 리뷰 히스토리, 심지어 회의록까지. 이것을 컨텍스트 과적재(Context Overload)라고 부릅니다.
증상:
- 에이전트가 AGENTS.md에 있는 규칙을 어기기 시작한다 (중요한 규칙이 덜 중요한 정보에 묻힘)
- 응답 속도가 느려진다 (토큰 소비 증가)
- 에이전트가 관련 없는 규칙을 적용한다 (결제 모듈 작업에 인증 규칙을 적용)
- 비용이 올라간다 (입력 토큰 = 과금 대상)
해결:
- MVI 원칙을 적용하세요. “이 정보가 없으면 에이전트가 잘못된 코드를 만드는가?” 아니라면 삭제.
- 계층형 AGENTS.md를 활용하세요. 모든 정보를 루트에 넣지 말고, 디렉토리별로 분산.
- 주기적으로 AGENTS.md를 절반으로 줄여보세요. 놀랍게도 대부분의 경우 에이전트 출력 품질이 오히려 올라갑니다.
기억하세요: 좋은 AGENTS.md는 짧은 AGENTS.md입니다. 에이전트에게 100가지를 알려주는 것보다, 가장 중요한 10가지를 명확히 알려주는 것이 낫습니다.
마무리 — 오늘 만든 것, 내일 추가할 것
오늘 Phase C의 두 번째이자 마지막 퍼즐 조각을 맞추었습니다. 6일차에서 에이전트 팀을 구성했고, 오늘 그 팀에게 ‘우리 프로젝트의 지식’을 주입했습니다. MVI 원칙으로 적정량을 판단하고, 계층형 AGENTS.md로 필요한 곳에 필요한 정보만 전달하고, 5가지 주입 패턴으로 리팩토링 없이 바로 쓸 수 있는 코드를 이끌어냈습니다.
이제 에이전트 팀은 정체성(시스템 프롬프트)도, 권한(allow/ask/deny)도, 지식(컨텍스트)도 갖추었습니다. 하지만 아직 하나가 빠져있습니다 — 워크플로우를 단축키처럼 호출하는 방법입니다.
내일 8일차에서는 opencode 슬래시 커맨드를 다룹니다. /commit, /deploy, /review 같은 커스텀 명령을 만들어서, 복잡한 워크플로우를 한 줄로 실행하는 법을 익힙니다. 에이전트에게 “뭘 해줘”가 아니라 “이 프로세스를 실행해”라고 말할 수 있게 되는 거죠.
◀ 이전 6화 (다음 차수는 아직 게시되지 않았습니다)
[…] 시즌 2 심화 — 나만의 도메인 특화 에이전트 만들기 (총 12화 중 8화)◀ 이전 7화 (다음 차수는 아직 게시되지 […]