버전 관리 및 검색 가능한 규칙을 통해 세션 간 AI 에이전트 드리프트(Drift) 방지하기
요약
AI 에이전트의 세션 간 답변 불일치 문제인 '드리프트(Drift)'를 해결하기 위해 '재사용 가능한 결정 단위(RDU)' 개념을 제안합니다. 결정을 버전 관리되는 마크다운 파일로 인코딩하여 트리거 기반으로 실행함으로써 확장성과 일관성을 확보하는 방법론을 다룹니다.
핵심 포인트
- 에이전트 드리프트는 단순 프롬프트 수정이나 긴 문서화로 해결하기 어려움
- RDU는 검색 가능한 트리거와 확정된 판단을 포함한 버전 관리된 아티팩트임
- 결정을 코드처럼 취급하여 버전 관리와 명시적 진화 조건을 갖춰야 함
- YAML 프론트매터를 활용해 규칙의 실행 조건과 ID를 구조화함
원문은 hexisteme notes에 게시되었습니다.
AI 에이전트를 매일 사용한다면 이런 경험을 해보셨을 것입니다. 월요일에는 에이전트가 질문에 대해 정확하고 논리적인 답변을 내놓았는데, 금요일에 새로운 세션에서 동일한 질문을 던지니 다른 답변을 내놓는 경우 말입니다. 틀린 것은 아니지만, 처음에 어떤 컨텍스트가 먼저 나타났느냐에 따라 답변이 달라진 것입니다.
이것이 바로 드리프트(Drift)입니다. 이는 더 나은 프롬프트(Prompt)를 사용하거나 CLAUDE.md 파일에 더 많은 예시를 쌓아 넣는다고 해서 해결되지 않습니다. 그러한 방식은 확장성(Scale)이 떨어지며 버전 관리(Version)도 되지 않기 때문입니다. 실제로 효과가 있는 방법은 반복 가능한 각 결정을 제가 **재사용 가능한 결정 단위 (Reusable Decision Unit, RDU)**라고 부르는 작고 버전 관리되는 아티팩트(Artifact)로 취급하는 것입니다.
한 문장으로 요약하자면: 반복 가능한 각 결정을 검색 가능한 트리거(Trigger)와 확정된 판단(Judgment)을 포함한 버전 관리되는 마크다운(Markdown) 파일로 인코딩하고, 에이전트가 세션 시작 시 이를 로드하는 곳에 저장하며, 모델의 메모리에 의존하는 대신 트리거 발생 시 규칙이 자동으로 실행되도록 하는 것입니다. 저는 iOS 배포, 트레이딩, AI 에이전트 설계, 게임 개발 및 부동산 분야에 걸쳐 140개 이상의 이러한 라이브러리를 운영하고 있습니다. 이것이 RDU가 구축되는 방식이며, 왜 효과를 유지하는지에 대한 이유입니다.
"그냥 적어두기"의 문제점
드리프트에 대한 순진한 해결책은 결정을 문서화하는 것입니다. 즉, "X가 발생하면 Y를 하라"고 적힌 CLAUDE.md 또는 AGENTS.md 항목을 작성하는 것이죠. 하지만 이는 두 가지 이유로 실패합니다.
- 문서화는 읽기가 필요합니다. 긴 마크다운 파일 속에 파묻힌 규칙은 파일 내의 다른 모든 내용과 주의력을 다투게 됩니다. 규칙은 한 번 읽힌 뒤, 파일이 커짐에 따라 점차 드리프트(Drift)됩니다.
- 판단 자체에 대한 버전 관리(Version Control)가 없습니다. 더 나은 접근 방식을 발견했을 때, 기존 규칙을 조용히 덮어쓰게 됩니다. 판단이 왜 바뀌었는지에 대한 이력이 남지 않기 때문에, 다음에 그 판단에 의문을 갖게 될 때 처음부터 다시 유도해야 합니다.
해결책은 결정을 코드(Code)를 다루는 방식과 같이 취급하는 것입니다. 즉, 버전 관리되고, 트리거에 의해 구동되며, 명시적인 진화 조건(Evolution conditions)을 갖추어야 합니다.
RDU의 모습
각 RDU는 YAML 프론트매터 (YAML frontmatter)를 포함하는 마크다운 (markdown) 파일입니다. 다음은 iOS 배포 (iOS-deployment) 도메인의 실제 사례입니다:
---
id: RDU-047
title: "App Store Connect in-flight limits — 1 version / 2+5 reviewSubmissions"
...
```bash
# 진행 중인 버전 확인
GET /v1/appStoreVersions?filter[appStoreState]=PREPARE_FOR_SUBMISSION,WAITING_FOR_REVIEW,IN_REVIEW
# reviewSubmission 슬롯 확인
GET /v1/reviewSubmissions?filter[state]=READY_FOR_REVIEW,WAITING_FOR_REVIEW,IN_REVIEW
```
각 구조적 요소는 특정 실패를 방지하기 위해 존재합니다:
| 섹션 | 목적 | 방지하는 안티 패턴 (Anti-pattern) |
|---|---|---|
Trigger | 규칙을 실행하는 검색 가능한 (Grep-able) 조건 | 에이전트가 확인해야 할 사항을 "기억"해야 하는 규칙 |
| ... |
4가지 핵심 원칙
1. 절대적인 것은 없다 (No absolutes)
모든 RDU는 _작성 시점_에서의 최선의 판단입니다. 메타 규칙(meta-rule)인 RDU-000은 이를 명확히 명시합니다. 즉, 절대적인 것은 전혀 없다는 것입니다. 모든 규칙은 암묵적인 진화 조건 (evolution conditions)을 수반하므로, 더 나은 접근 방식이 나타나면 버전 업그레이드 (version bump) 또는 대체 (supersession)를 제안해야 합니다. 절대로 몰래 재작성해서는 안 됩니다. 정직하게 수정될 수 없는 규칙은 조용히 틀린 규칙이 되어버릴 것입니다.
2. 트리거의 구체성 (Trigger specificity)
트리거는 모호한 설명이 아니라 검색 가능한 (grep-able) 토큰이어야 합니다. "iOS 작업을 할 때"는 트리거가 아닙니다. "app_versions_create가 409를 반환할 때"가 트리거입니다. 만약 트리거가 정규 표현식 (regex)으로 매칭될 수 없다면, 규칙은 안정적으로 실행되지 않을 것입니다. 그리고 불안정하게 실행되는 규칙은 규칙이 없는 것보다 더 나쁩니다. 시스템 전체를 신뢰하지 않게 되기 때문입니다.
3. 선제적 등록 (Proactive registration)
에이전트가 이전에 내렸던 판단을 다시 도출하고 있음을 감지하거나, 사용자가 "이것은 유용하니 저장해 두세요"라고 신호를 보낼 때, 에이전트는 기다리지 말고 즉시 RDU 초안을 제안해야 합니다. 패턴은 항상 제안 → 사용자 승인 → 파일 작성 순서입니다. 몰래 생성해서는 안 됩니다. 동의하지 않은 규칙은 신뢰할 수 없는 규칙이 되기 때문입니다.
3. 도메인 불가지론 (Domain-agnostic)
트리거-상황-판단 (trigger–situation–judgment) 구조는 모든 도메인에서 작동합니다. 140개 이상의 RDU 라이브러리는 다음을 아우릅니다:
- iOS 배포 (iOS deployment) — ASC API 제한, fastlane 패턴, Swift 6 동시성 (concurrency)
- 트레이딩 (Trading) — LLM 확률 생성 금지 (RDU-021), 워크포워드 검증 (walkforward validation) 필수 (RDU-022)
- AI 에이전트 설계 (AI-agent design) — 의회 오케스트레이션 패턴 (council orchestration patterns), 스톱 훅 아키텍처 (stop-hook architectures)
- 게임 개발 (Game development) — Godot 플랫폼 게임 느낌 수치 (코요테 타임 (coyote time) 100 ms, 점프 버퍼 (jump buffer) 150 ms)
- 부동산 (Real estate) — LTV 계산, 대출 여력 (loan-headroom) 계산
동일한 5개 섹션 구조는 형태의 변화 없이 Swift 동시성 규칙과 점프 버퍼 타이밍을 모두 담아냅니다.
실제 작동 방식
세션이 시작될 때, 에이전트는 규칙당 한 줄로 구성된 단일 인덱스 파일을 로드합니다. 대화 중에 트리거 조건이 나타나면, 에이전트는 전체 RDU 파일을 읽습니다. 인덱스는 짧게 유지되며, 전체 규칙은 관련이 있을 때만 로드됩니다. 이것이 모든 내용을 CLAUDE.md에 쏟아붓는 방식에 반대하는 효율성 논거의 핵심입니다. 전역적으로 항상 로드되는 파일은 매 턴마다 모든 규칙에 대한 비용을 지불하게 만들지만, 인덱스 및 트리거 기반 설계는 규칙이 실행될 때만 비용을 지불하기 때문입니다.
진화는 명시적입니다. 더 새로운 접근 방식이 발견되면, 에이전트는 제자리에서 수정하는 대신 차이점(diff)을 제안합니다:
# RDU 진화 예시
- version: 2 → version: 3
- 판단 (Judgment) 업데이트: fastlane은 이제 READY_FOR_SALE 상태에서 작동함 (ASC MCP는 불가)
...
가치는 140개의 규칙을 보유하는 데 있는 것이 아니라, *트리거 메커니즘 (trigger mechanism)*에 있습니다. 자동으로 실행되는 규칙은 에이전트가 확인해야 함을 기억해야 하는 규칙보다 10배의 가치가 있습니다.
RDU가 해결하지 못하는 것
RDU는 *반복 가능한 판단 (repeatable judgments)*을 인코딩합니다. RDU는 새로운 상황, 가치 질문 (사용자 선호도, 위험 감수 성향), 또는 실행 시점의 컨텍스트 (runtime context)에 진정으로 의존하는 결정은 처리하지 않습니다. 그러한 경우에는 에이전트가 질문해야 합니다. 하지만 RDU로 옮기는 판단이 많아질수록 실제로 질문해야 하는 영역은 줄어듭니다. 이는 에이전트가 던지는 질문이 진정으로 인간의 도움이 필요한 질문이 된다는 것을 의미합니다.
시작하기
최소한의 실행 가능한 설정(minimal viable setup)은 세 가지입니다: 규칙 파일들을 위한 단일 디렉토리, 인덱스 파일, 그리고 템플릿입니다. 시작하기 위해 140개의 규칙이 필요한 것은 아닙니다. 단 하나만 있으면 되며, 다음 규칙을 추가할 규율이 필요할 뿐입니다. 규칙을 작성해야 한다는 신호는 구체적입니다. 동일한 판단을 두 번 반복해서 설명하고 있는 자신을 발견하거나, 에이전트가 이전의 결정을 잊어버려 발생한 버그를 수정하고 있을 때, 그것이 바로 작성되기를 기다리는 RDU(Rule-Driven Unit)입니다.
템플릿은 다음과 같습니다:
---
id: RDU-XXX
title: [한 줄 설명]
...
이 중 어느 것도 생소한 것이 아닙니다. 이는 매번 동작을 수동으로 재확인하는 대신 테스트를 작성하게 만드는 것과 동일한 본능입니다. 판단을 한 번만 인코딩(encode)하여 스스로 실행되는 형태로 만들고, 기억해야 하는 비용을 지불하는 것을 멈추십시오. 규칙은 더 이상 누군가의 기억 속에 있는 것이 아니라 디스크에 저장되어 버전 관리(versioned)되고 트리거(trigger)를 기다리고 있기 때문에, 드리프트(drift)는 다시 발생하지 않습니다.
추가 노트는 hexisteme.github.io/notes에서 확인할 수 있습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기