AI 코딩 도구를 처음 팀에 도입했을 때 느끼는 흥분은 오래가지 않는다. Copilot은 존재하지 않는 함수 시그니처를 자신 있게 제안하고, Claude는 claude.md 지시를 조용히 무시하며, 에이전트가 생성한 코드는 어느 순간부터 내가 감당할 수 없을 만큼 빠르게 쌓인다. 문제는 도구가 아니다. 도구를 둘러싼 설계가 없다는 것이다.
컨텍스트 없는 AI는 절반짜리 도구다
dev.to에 소개된 CIPHER-Local 프로젝트는 이 문제를 정면으로 짚는다. 16개 마이크로서비스로 구성된 TypeScript 플랫폼을 개발하던 중, GitHub Copilot이 코드베이스가 커질수록 점점 엉뚱한 제안을 내놓기 시작했다. 원인은 단순하다. AI는 현재 열린 파일은 볼 수 있지만, 함수가 어디서 정의되고, 어떤 모듈이 어떻게 연결되는지—구조를 이해하지 못한다.
해법은 MCP(Model Context Protocol)를 통해 AI에게 '구조화된 코드 컨텍스트'를 직접 주입하는 것이었다. Tree-sitter로 워크스페이스를 파싱하고 심볼·참조·의존성을 SQLite에 저장한 뒤, 로컬 MCP 서버가 search_symbols, find_references, get_dependencies 같은 도구를 AI에 노출한다. AI가 파일을 맹목적으로 grep하는 대신, 정제된 구조 데이터를 호출하는 방식이다. 모든 인덱스는 로컬에 머물고 클라우드로 나가지 않는다. 이건 단순한 생산성 팁이 아니다. AI가 얼마나 정확한 답을 낼 수 있는가는 입력되는 컨텍스트의 품질에 직결된다는 근본 원칙의 실천이다.
명세를 먼저 쓰면 AI가 달라진다
같은 맥락에서 'Specification-First Agentic Development' 방법론은 AI 협업의 구조적 취약점을 다른 각도로 해결한다. 저자가 지적하는 핵심 문제는 '왜'의 부재다. 코드는 있는데 결정 이유가 없고, 세션이 끊기면 AI는 매번 처음부터 컨텍스트를 요구한다. 토큰이 낭비되고, 히스토리가 사라지며, 6개월 뒤엔 아무도 이 코드가 왜 이렇게 생겼는지 기억하지 못한다.
이 방법론의 해법은 명쾌하다. 구현 전에 명세 문서를 먼저 작성하고, .agentsmith/phases/ 폴더 구조(done / active / planned)로 AI의 작업 상태를 명시적으로 관리한다. 매 페이즈가 끝나면 Claude가 decisions.md에 결정 사항과 트레이드오프를 남기는 것이 필수다. context.yaml은 전체 프로젝트의 스택·상태·완료된 페이즈 요약을 압축해 보관한다. 결과적으로 AI는 매번 처음부터 설명을 듣는 대신, 이 파일 하나로 현재 위치를 파악한다.
흥미로운 건 이 문서들이 '사후에 작성하는 기술 문서'가 아니라는 점이다. 개발 프로세스의 부산물로 자동 생성된다. Andrej Karpathy가 외부 지식을 LLM으로 정리하는 방식과 구조적으로 닮았지만, 방향이 반대다. 외부 지식이 아니라 내가 만들어가는 제품 내부의 결정 맥락을 실시간으로 쌓는 것이다.
프로덕트 사고 없는 마이그레이션은 없다
세 번째 현장은 코드 레벨이 아니라 아키텍처 결정의 레벨이다. 149개 라우트를 가진 AngularJS 1.5 엔터프라이즈 플랫폼을 React 19로 마이그레이션하면서, 팀이 선택한 전략은 '빅뱅 컷오버'가 아닌 카나리 배포였다. 핵심 고민은 기술이 아니라 사용자 경험의 연속성이었다. 배포 직후 지원 티켓이 쏟아지는 상황을 막으려면, 전환이 사용자에게 보이지 않아야 했다.
구현은 영리했다. 구 포털(Spring MVC + AngularJS)과 신 포털(nginx + React SPA)을 동일 도메인에서 병렬 운영하고, Traefik IngressRoute의 가중치로 로그인 라우트에서만 트래픽을 분기했다. 세션 쿠키를 공유해 재인증 없이 두 포털 사이를 오갈 수 있게 했고, URL prefix는 미들웨어로 스트리핑해 사용자에겐 동일한 주소가 보이도록 했다. 10% → 25% → 50% → 100%로 트래픽을 점진적으로 이전하는 동안, 기능은 하나씩 검증됐다.
이 전략이 흥미로운 건 기술 선택 자체보다 그 의사결정 방식 때문이다. '빠르게 전부 바꾸자'는 충동을 억누르고, 사용자에게 어떤 경험이 보장되어야 하는지를 먼저 정의한 뒤, 인프라를 그 요구사항에 맞게 설계했다. 이게 바로 프로덕트 사고가 프론트엔드 아키텍처 결정에 개입해야 하는 순간이다.
설계가 먼저라는 것의 진짜 의미
세 사례를 관통하는 공통점은 하나다. AI든, 마이그레이션이든, 빠르게 실행하기 전에 구조를 먼저 정의한 팀이 더 나은 결과를 얻었다. CIPHER-Local은 AI에게 넘기는 컨텍스트를 구조화했고, Specification-First는 AI와의 협업 상태를 명세로 관리했으며, 카나리 마이그레이션은 사용자 경험 연속성을 아키텍처 제약 조건으로 먼저 정의했다.
AI 코딩 도구의 품질은 결국 AI에게 무엇을 어떻게 주느냐에 달려 있다. 더 나은 프롬프트를 쓰는 것도 중요하지만, 그보다 앞서 AI가 작동하는 환경—컨텍스트, 상태, 경계—을 설계하는 것이 훨씬 더 큰 레버리지를 만든다. '일단 시켜보자'는 접근에서 '작동 조건을 먼저 설계하자'는 접근으로의 전환. 이것이 AI 에이전트를 진짜 팀 자산으로 만드는 첫 번째 스텝이다.
앞으로의 방향도 이 흐름에서 벗어나지 않을 것이다. React Server Components나 Next.js의 Partial Prerendering처럼 렌더링 경계를 명시적으로 선언하는 트렌드, 디자인 시스템의 토큰 기반 구조화, MCP 표준의 확산—모두 '암묵적 맥락'을 '명시적 구조'로 바꾸려는 같은 방향의 움직임이다. AI를 잘 쓰는 팀과 그렇지 않은 팀의 차이는 결국 이 구조를 얼마나 의도적으로 설계하느냐에서 갈릴 것이다.