AI는 코딩을 너무 잘한다 - 그래서 나는 '이유(Why)'를 유지하고 확장할 수 있는 무언가를 만들었다
요약
AI 코딩 에이전트의 빠른 개발 속도 속에서 발생하는 의사결정 및 추론 과정의 유실 문제를 해결하기 위한 도구인 Persist OS를 소개합니다. 이 도구는 결정 사항과 엔지니어링 표준을 저장소 파일로 기록하여 에이전트가 일관된 맥락을 유지하도록 돕습니다.
핵심 포인트
- AI 에이전트는 코딩은 잘하지만, 결정 과정의 추론(reasoning)은 휘발되기 쉬움
- Persist OS는 결정 사항과 컨벤션을 저장소 메모리로 관리하여 에이전트에게 제공
- 채팅 기록 대신 저장소 내 ADR과 표준을 진실의 원천(Source of Truth)으로 활용
- 로컬 CLI 기반으로 네트워크 연결이나 AI 호출 없이 동작하는 경량 도구
지난 몇 달 동안 저는 Cursor, Claude Code, 그리고 Codex를 사용하여 무언가를 만들어 왔습니다. 현재 많은 빌더(builders)들이 사용하고 있는 바로 그 도구들입니다. 그 속도는 진심으로 경이로운 수준입니다. 저는 친구들을 위해 거친 PRD(제품 요구 사항 문서)에서 단 하루 만에 작동하는 데모로 넘어가는 MVP(최소 기능 제품)를 출시해 보았습니다. 인증(auth)이 연결되고, 데이터베이스(database)가 배치되었으며, 배포된 후 자정이 되기 전에 링크가 전송되었습니다. 어떤 것은 완전히 바이브 코딩(vibe-coded)이었고, 어떤 것은 구조화되었습니다. 그 모든 것이 빨랐습니다.
이제 여러분은 어디에서나 이런 모습을 보고 계실 겁니다. 빌더들이 주말 동안, 때로는 단 몇 시간 만에 전체 제품을 만들어내고 있습니다. 도구들이 마침내 머릿속에 있는 아이디어를 따라잡을 수 있게 되었기 때문입니다.
그리고 사람들이 과소평가하는 사실이 하나 있습니다. AI 코딩 에이전트(AI coding agents)는 실제로 엔지니어링 원칙을 따르는 데 꽤 능숙합니다. 따를 수 있는 무언가가 있을 때 말이죠. PRD를 건네주고, 여러분의 컨벤션(conventions)을 가리켜 주며, 몇 가지 타협할 수 없는 규칙을 설정해 주면, 에이전트들은 대부분 이를 고수합니다. 새로운 것을 발명하는 대신 여러분의 컴포넌트(components)를 재사용할 것입니다. 테스트가 표준의 일부라면 테스트를 작성할 것입니다. 지루하고 당연한 일들이 매 세션마다 로드되는 어딘가에 기록되어 있다면, 그들은 그 일들을 건너뛰지 않을 것입니다.
제가 계속해서 마주했던 격차는 코딩 자체가 아니었습니다. 그것은 그 과정에서 내려진 결정들에 어떤 일이 일어나는가였습니다.
이렇게 빠르게 움직이다 보면, 채팅 속에서 수십 가지의 작은 결정들을 내리게 됩니다. 어떤 인증 흐름(auth flow)을 사용할지, 어떤 데이터베이스를 사용할지, 이 기능의 "완료"가 무엇을 의미하는지, 이 모듈이 저 경계(boundary)를 소유할지 등등 말입니다. 코드는 저장소(repo)에 커밋됩니다. 하지만 그 추론(reasoning)은 대개 그렇지 않습니다. 추론은 압축되어 버리는 스레드(thread) 속에 남거나, 종료되는 세션 속에 남거나, 혹은 여러분의 머릿속에 남습니다. 세 개의 빌드를 동시에 다루고 있을 때 머릿속은 아키텍처(architecture)를 저장하기에 매우 불안정한 장소입니다.
저는 속도를 늦추고 싶지 않았습니다. 저는 속도와 더불어, 에이전트가 매 세션마다 다시 불러올 수 있는 내구성 있는 레이어(durable layer)를 원했습니다. 즉, 수용된 결정들, 컨벤션(conventions), 품질 게이트(quality gates), 그리고 작업이 실제로 완료되었다는 증거 말입니다.
그래서 저는 Persist OS를 만들었습니다. 이는 해당 계층을 일반적인 저장소(repo) 파일로 기록하고, 결정론적인 persist doctor 게이트(gate)를 통해 이를 강제하는 로컬 CLI(Command Line Interface)입니다. 네트워크 연결 없음. 텔레메트리(telemetry) 없음. AI 호출 없음.
npx persist-os@latest init
실제 실패 모드 (The actual failure mode)
대부분의 에이전트(agent) 설정은 채팅 기록(chat history)을 진실의 원천(source of truth)처럼 취급합니다. 하지만 그렇지 않습니다. 채팅 기록은 가장 먼저 증발해 버리는 것입니다.
Persist OS는 우선순위 순서를 뒤집습니다. 저장소 메모리(Repository memory)가 MCP 컨텍스트(context), 외부 노트, 그리고 채팅 기록보다 우선합니다. 승인된 ADR(Architecture Decision Records)과 엔지니어링 표준은 모델이 마지막 메시지에서 추측한 그 무엇보다 우선순위가 높습니다. 만약 이들이 충돌할 경우, 에이전트는 조용히 한쪽 편을 드는 것이 아니라 중단하고 보고하도록 지시받습니다.
이것이 바로 이 도구가 해결하는 문제입니다. "기억하도록 도와줘"가 아니라, 다음 세션이 제로(zero) 상태에서 시작하지 않도록 저장소를 권위 있는(authoritative) 상태로 만드는 것입니다.
persist init이 저장소에 생성하는 것
단 한 번의 명령으로 docs/ 디렉토리 아래의 전체 메모리 구조와 .persist/config.json을 스캐폴딩(scaffolding)합니다:
docs/
00-product/ PRD, 비전, 로드맵
10-architecture/ 스택, 경계, 결정 사항
...
또한 에이전트가 실제로 로드하는 파일들도 생성합니다:
AGENTS.md- 라우팅 규칙(routing rules) + 에이전트가 직접 실행하는 Persist 명령CLAUDE.md- Claude Code를 위한 짧은 포인터 ("AGENTS.md를 읽으세요, 채팅을 믿지 마세요").cursor/rules/persist-memory.mdc- Cursor에서 항상 적용되는 규칙.persist/hooks/pre-commit- 커밋이 반영되기 전persist doctor를 실행
실제 포크(fork)를 위한 제안된 ADR을 원한다면 스택 프리셋(stack preset)을 선택하세요 (nextjs, python-fastapi, laravel-react 등). 모든 프리셋 결정은 사용자가 명시적으로 수락할 때까지 제안됨 (Proposed) 상태로 유지됩니다. 스키마(schema) 구조상 프리셋이 조용히 진실(truth)이 되는 것은 허용되지 않습니다.
persist init --preset nextjs --ai-tools cursor,claude
git config core.hooksPath .persist/hooks # 클론(clone)당 한 번씩 doctor 훅을 활성화
이것으로 하루 만에 MVP를 실행하는 방법
예를 들어, 친구의 상점을 위한 결제 흐름(checkout flow)을 만들고 있다고 가정해 봅시다. 빠르게 빌드하면서도, 결정 사항들은 그대로 유지하고 싶습니다.
1. 에이전트가 코드를 건드리기 전에 스캐폴딩(Scaffold) 메모리 구축하기
persist feature create checkout
이 명령은 docs/40-features/F-###-checkout/ 디렉토리에 PRD.md, ACCEPTANCE.md, TEST_PLAN.md, TASKS.md 등을 생성합니다. 이는 단순히 비어 있는 철학적인 문서가 아니라, 프로젝트의 인도(delivery) 워크플로우가 요구하는 정확한 체크리스트입니다. 에이전트는 곧바로 src/ 디렉토리로 뛰어들어서는 안 됩니다. 모듈 작업도 동일한 패턴을 따릅니다. 기능 문서(feature docs)를 먼저 작성하고, docs/30-modules/ 아래에 모듈 메모리를 구축하며, 수락 기준(acceptance criteria)과 테스트 계획(test plan)이 존재한 후에 작업을 수행합니다.
2. 의사결정을 제안(proposals)으로 기록하고, 내가 의도한 것을 수락하기
persist adr create payment-provider # docs/adrs/proposed/ADR-PROPOSED-payment-provider.md 작성
persist adr accept payment-provider # docs/adrs/ADR-####-payment-provider.md로 승격
어떠한 것도 우연히 수락된 메모리가 되지 않습니다. 기존 저장소에서 persist adopt를 실행하거나 persist mcp add figma를 실행하는 것도 동일한 방식으로 작동합니다. 즉, 검토(inspect)하고, 제안(propose)하며, 사람이 수락(accept)하는 것입니다. 에이전트는 MCP 컨텍스트를 오프라인 상태에서 docs/ai/mcp/<server>.md에 캡처할 수 있지만, Persist가 직접 MCP 서버를 호출하지는 않습니다.
3. 에이전트가 매 세션마다 규칙을 로드하도록 하기
생성된 AGENTS.md는 에이전트에게 무엇을 읽고 무엇을 실행해야 하는지 알려줍니다:
저장소 규칙(Repository rules)은 모델의 선호도(model preferences)보다 우선합니다. 지침이 충돌할 경우, 중단하고 충돌을 보고하십시오.
- `persist doctor` - 저장소 메모리를 검증합니다. 작업이 완료되었다고 주장하기 전에 실행하십시오.
...
Claude Code에서는 SessionStart 훅(hook)이 수락된 ADR 및 모듈의 라이브 맵(live map)을 그 위에 주입합니다. Cursor는 항상 적용되는 규칙(always-apply rule)을 가져갑니다. Codex는 AGENTS.md를 직접 읽습니다. 메커니즘은 다르지만 목적은 같습니다. 에이전트는 지도를 읽고 세부 사항으로 향하는 포인터를 따르며, 사용자가 매번 아키텍처를 다시 붙여넣을 필요가 없습니다.
4. 느낌(vibes)이 아닌 증거로 "완료"를 검증하기
에이전트가 기능이 완료되었다고 솔직하게 말하기 전에, 완료 루프(completion loop)는 다음과 같습니다:
pnpm test:run && pnpm typecheck && persist doctor
persist doctor는 결정론적 (deterministic)입니다. 즉, 당신의 아키텍처를 판단하는 모델이 없습니다. 종료 코드(Exit codes): 0은 정상, 1은 경고, 2는 에러를 의미합니다. 동일한 저장소 상태라면 매번 동일한 결과가 나옵니다.
채팅(chat)으로는 절대 잡아낼 수 없는 구체적인 항목들은 다음과 같습니다:
| 체크 항목 | 실패 사례 |
|---|---|
| 완료 증거 (Completion evidence) | 기능은 완료로 표시되었으나 REVIEW.md가 여전히 보류 중이거나 테스트 결과가 기록되지 않은 경우 |
| ... |
따라서 빠르게 작업할 때, "완료"란 "에이전트가 괜찮다고 말했다"가 아니라 persist doctor가 0으로 종료되었음을 의미합니다. 또한 persist guard --source src를 추가하여, 테스트 파일이 스테이징(staged)되지 않은 채 소스 코드만 변경된 커밋은 실패하도록 설정할 수 있습니다.
결정이 변경될 때 일어나는 변화
빠르게 빌드되는 시스템은 마음을 바꿉니다. 이때 발생하는 실패 모드는 "조용한 모순"입니다. 코드는 MySQL을 사용하고 있는데 ADR(Architecture Decision Record)은 여전히 PostgreSQL이라고 말하며, 모든 것이 "통과"되는 상황입니다.
Persist는 persist adr supersede <old> <new-title> 명령어로 이를 처리합니다. 기존 ADR은 대체(superseded)됨으로 표시되고, 새 ADR은 기존 것을 참조하며, Doctor는 여전히 이전 결정을 인용하고 있는 모든 항목에 플래그를 표시합니다. 생성된 에이전트 규칙에는 supersede 명령어가 인라인(inline)으로 포함되어 있어, 모델이 히스토리를 직접 수정하는 대신 이 명령어를 사용하게 됩니다.
Persist가 하지 않는 것: 승인된 ADR과 현재 코드가 조용히 불일치한다는 사실을 자동으로 감지하는 것은 하지 않습니다. 그것은 grep이 아니라 읽기가 필요한 영역입니다. 이를 위해 architecture-drift-review라는 생성된 스킬이 존재합니다. 게이트(gate)는 단순하게 유지하고, 해석은 에이전트가 수행합니다.
벡터 메모리 엔진이 아님 (의도된 설계)
supermemory나 mem0와 같은 도구들은 검색(retrieval) 문제를 해결합니다. 예를 들어 "Auth0에 대해 우리가 말했던 내용을 찾아줘"와 같은 요청입니다. 이는 유용하지만 다른 종류의 문제입니다.
저는 검토 흔적이 포함된 승인된 결정 사항들을 계속 놓치고 있었습니다. 즉, 어디서 결정되었는지, 사람이 승인했는지, 여전히 유효한 결정인지에 대한 정보입니다. 이것은 파일과 PR(Pull Request) 검토의 문제입니다. 순수한 마크다운(markdown) ADR, 명시적인 승인/대체(accept/supersede), 그리고 git diff가 해결책입니다. 벡터 저장소(Vector stores)는 나중에 이 파일들을 인덱싱할 수 있지만, 이 파일들을 대체할 수는 없습니다.
오버헤드를 감수할 가치가 있는 경우
동료, 미래의 당신, 혹은 다음 주에 투입될 새로운 에이전트처럼 누군가가 이 저장소를 물려받게 될 때 사용하십시오. 그때가 바로 '이유(why)'를 잃어버리는 것이 실제 시간 비용으로 직결되는 시점입니다.
금요일에 삭제할 일회성 스파이크 (spike)를 위해 그냥 건너뛰십시오. 두 번째 세션도 없고, 보상도 없습니다.
이름이 곧 테스트입니다: _지속되어야 할 것_을 지속시키십시오. 프로토타입 (Prototype)이 제품 (product)으로 변한다면 → persist init을 실행하십시오. 비례 관계를 유지하십시오 - 작은 수정이라면 그냥 배포(ship)하고, 실제 기능(feature)이나 아키텍처 분기(architectural fork)라면 기록하십시오.
사용해보기
MIT 라이선스입니다. 완전히 사용자의 로컬 머신에서 실행됩니다.
npx persist-os@latest init
- Repo: github.com/Karthick-Ramachandran/persist-os
- 제작 이유: PHILOSOPHY.md
- 프리셋별 예시 출력: 리포지토리 내
examples/generated-nextjs/,examples/generated-python-fastapi/등
만약 당신이 하루 만에 MVP (Minimum Viable Product)를 배포하고 있으며, 에이전트 (agent)가 7일째 되는 날에도 동일한 규칙을 계속 따르기를 원한다면 - 이것이 바로 제가 존재하기를 바랐던 것입니다. 실행했을 때 무엇이 깨지는지 저에게 알려주세요.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기