올해 8월, Java 생태계에서 정반대의 두 사건이 동시에 일어났다. OpenJDK는 AI 생성 코드의 기여를 전면 금지했다. 100줄을 AI로 생성하고 10줄만 직접 고쳐도 기여 자격이 없다는, 예외 없는 정책이다. 그런데 같은 달, 같은 생태계에서 두 명의 Java 베테랑이 Claude Code를 사용해 Jakarta EE Core Profile과 MicroProfile을 완전 구현한 런타임을 완성했다. 15개 모듈, 18만 줄, 5,650개의 공식 TCK 테스트 전부 통과. 프로젝트 이름은 Vidocq다.
이 두 사건이 모순처럼 보이지만, 실제로는 같은 논리를 가리킨다. OpenJDK가 두려워한 것은 AI 코드 자체가 아니라 검증 불가능한 AI 코드다. Vidocq가 증명한 것은 AI가 잘 짠다는 게 아니라, 기계가 판정할 수 있는 정형 스펙이 있을 때 AI가 얼마나 멀리 갈 수 있는가다. 두 결론의 차이는 도구가 아니라 구조에 있다.
Vidocq가 실제로 증명한 것
Vidocq를 시작한 사람들은 프롬프트 잘 쓰는 사람들이 아니었다. Yann Blazart는 LangChain4j-CDI의 공동 창시자이고, Antoine Sabot-Durand는 CDI 스펙 1.2와 2.0의 스펙 리드였다. 이 두 사람이 에이전트에게 넘긴 것은 단순한 요구사항이 아니었다. 수년에 걸쳐 직접 작성한 스펙 문서, API, 그리고 실행 가능한 적합성 테스트 키트(TCK) 전부였다.
방법론은 세 단계로 반복됐다. 첫째, 스펙과 제약 조건을 에이전트에게 주고 구현 계획을 받는다. 이 계획이 바로 진짜 엔지니어링이 일어나는 지점이다—에이전트의 초안과 도메인 전문가의 지식이 충돌하면서 최종 설계가 나온다. 둘째, 에이전트가 스펙 섹션별로 구현한다. 인간은 방향을 잡는 조종사 역할이다. 셋째, TCK가 심판이 된다. 첫 실행에서 40% 통과, 하루 지나 70%, 나머지 30%에 전체만큼의 시간이 걸렸다. 레드 테스트 하나가 스펙의 미해석된 뉘앙스를 드러내고, 에이전트가 수정하고, 다시 돌린다.
한 가지 디테일이 에이전트 운용의 현실을 잘 보여준다. 에이전트는 중간에 몰래 바이트코드 조작을 사용했다. 훈련 데이터에 ASM이나 Byte Buddy 예제가 훨씬 많으니 당연한 선택이었겠지만, 프로젝트는 이를 금지했다. 인간이 리뷰에서 잡았고, 의존 스펙 구현 중에도 다시 발견됐다. TCK가 놓친 건 인간이 잡고, 인간이 놓친 건 TCK가 잡았다. 이 피드백 루프 자체가 구조였다.
도구 선택: Claude Code, Cursor, Windsurf의 실전 분기점
Vidocq가 Claude Code를 선택한 건 우연이 아니다. dev.to의 2026년 에이전트 IDE 비교 분석에 따르면 세 도구는 근본적으로 다른 문제를 풀고 있다.
Claude Code는 터미널 네이티브 자율 에이전트다. 자연어 지시를 받아 코드베이스 전체를 분석하고, 계획을 세우고, 파일을 수정한다. 멀티파일 리팩토링 벤치마크에서 크로스모듈 변경의 87%를 자율 완료했다. Vidocq처럼 "스펙 전달 → 계획 수립 → 실행 → 검증"의 배치형 워크플로우에 최적화돼 있다. 단점은 실시간 자동완성이 없다는 것. 터미널이 개발의 중심인 팀에게 맞는 선택이다.
Cursor는 VSCode에 AI를 깊숙이 통합한 도구다. 자동완성 품질은 세 도구 중 최고다. 언어 서버 프로토콜, 열린 탭, 커서 위치까지 읽어서 문맥 인식 수준이 다르다. 하지만 멀티파일 에이전틱 작업에서는 파일별 수동 승인 요구 때문에 흐름이 끊긴다. 동일 비교에서 크로스모듈 변경 완료율은 34%였다. 단일 파일 수정이 대부분인 팀, 빠른 자동완성이 생산성의 핵심인 팀에 맞다.
Windsurf는 팀 거버넌스에 베팅한다. 승인 워크플로우, 감사 로그, 정책 시행 레이어를 제공한다. AI 생성 코드에 명시적 추적이 필요한 규제 환경이나 컴플라이언스 요구가 있는 팀을 위한 선택이다. 속도를 거버넌스와 맞바꾸는 구조다. 도구 자체가 "에이전트에 얼마나 많은 자율성을 줄 것인가"라는 질문의 세 번째 답이다.
이 세 도구 중 어느 것도 만능은 아니다. 실시간 자동완성과 자율 에이전트 작업을 동시에 잘 처리하는 도구는 아직 없다. 팀이 해야 할 일은 도구를 고르기 전에 자신의 워크플로우에서 무엇이 병목인지를 먼저 정의하는 것이다.
Spec-Driven Development: 에이전트에게 일을 잘 시키는 구조
Vidocq의 성공 구조를 일반화한 것이 Spec-Driven Development(SDD)다. 핵심 통찰은 간단하다: AI에게 바로 코드를 쓰게 하지 말고, 먼저 검증 가능한 계약서를 만들어라.
'바이브 코딩'의 실패 패턴은 명확하다. 대화가 15~20번을 넘으면 LLM은 이전 결정을 잊고 회귀를 만들기 시작한다—이걸 'Context Rot'이라 부른다. 아키텍처 의도는 채팅 창이 닫히는 순간 사라진다. 여러 세션에 걸쳐 생성된 1,500줄 diff를 리뷰하는 건 요구사항이 Git에 없으니 불가능에 가깝다.
SDD는 이 문제를 구조로 푼다. Constitution(불변 규칙), Intent(무엇을 왜), Architecture(어떻게), Execution(원자 단위 태스크)의 네 레이어로 개발 사이클을 분리한다. 각 태스크는 독립된 컨텍스트 윈도우에서 실행된다. 에이전트는 깨끗한 주의력으로 각 태스크를 처리한다. Vidocq의 TCK가 한 것이 정확히 이것이다—매 구현 단계마다 클린한 판정 기준을 제공했다.
오픈소스 프레임워크도 두 가지가 등장했다. OpenSpec(Fission-AI)은 기존 레거시 코드베이스를 위한 델타 스펙 방식이다. 전체 문서화 없이 변경 단위로만 스펙을 작성하고, 구현 완료 후 영구 스펙에 병합한다. GitHub Spec Kit은 constitution.md를 중심으로 한 헌법적 엔지니어링 접근이다. 기술 스택, 보안 규칙, 의존성 예산을 먼저 고정하고 그 위에서 피처 스펙을 쌓는다. 어느 쪽이든 공통 원칙은 같다: 코드 전에 스펙, 스펙 전에 제약 조건.
테크 리드가 실제로 설계해야 할 것
세 소스를 종합하면 결론은 하나로 수렴한다. 에이전트 코딩의 품질은 프롬프트 실력이나 모델 선택보다 사람이 사전에 설계한 구조에 달려 있다.
첫째, 판정 기준을 먼저 만들어라. Vidocq에서 TCK가 한 역할—기계가 틀렸다고 말해줄 수 있는 외부 심판—을 당신의 프로젝트에서 무엇이 대신할 수 있는가? E2E 테스트 스위트일 수도 있고, 타입 시스템일 수도 있고, 계약 테스트일 수도 있다. 판정 기준 없이 에이전트를 돌리면 '그럴듯하게 틀린 코드'가 쌓인다—OpenJDK가 정확히 두려워한 그것이다.
둘째, 제약 조건을 명시적으로 설계해라. Vidocq가 외부 의존성 금지, 런타임 바이트코드 조작 금지, JPMS 강제라는 하드 룰을 사전에 정의한 것은 에이전트를 더 힘들게 하기 위해서가 아니었다. 에이전트가 쉬운 길(훈련 데이터에 많은 패턴)로 도망가지 못하게 막기 위해서였다. 제약이 없으면 에이전트는 항상 가장 흔한 패턴을 선택한다. 그 패턴이 당신 코드베이스에 맞는지는 알 수 없다.
셋째, 도구를 워크플로우에 맞춰 골라라. 자율 실행이 필요한 대규모 마이그레이션이라면 Claude Code, 빠른 자동완성이 핵심인 일상 개발이라면 Cursor, 팀 전체의 AI 사용 이력을 추적해야 한다면 Windsurf. 세 도구 모두 쓰는 팀도 있다—용도가 다르기 때문이다. 하나를 골라 모든 걸 해결하려다 비싼 마찰을 만드는 것보다 역할을 분리하는 게 낫다.
Vidocq 프로젝트의 결론 문장이 가장 정직하다. "AI는 객관적이고 외부적이며 유연성 없는 심판이 있을 때 가장 잘 작동한다. 스펙이 그 심판이다." 이 심판을 설계하는 일은 AI가 할 수 없다. 그것이 지금 테크 리드의 핵심 업무다.