AI가 코드를 빠르게 생성한다는 것은 이제 전제다. 문제는 그 이후다. 금요일 오후에 머지된 PR이 월요일 아침 SQL Injection 취약점으로 돌아오는 일이 실제로 벌어지고 있다. "Copilot이 생성한 부분인데, 제가 꼼꼼히 읽지 않았어요." dev.to의 Securing AI Generated Code는 이 한 문장이 버그 자체보다 더 심각한 문제라고 단언한다. AI가 코드를 생성했다고 해서 소유권까지 위탁된 것은 아니기 때문이다.
첫 번째 층위: 책임 소재를 명확히 하는 언어 설계
"Claude가 그 엔드포인트를 추가했어요." "Copilot이 null 체크를 빠뜨렸어요." 이런 3인칭 표현이 팀 내에 퍼지는 순간, 리뷰 기준은 느슨해지고 사고 분석은 엉뚱한 방향으로 흘러간다. 모델 품질을 탓하는 동안 진짜 문제—왜 사람이 승인했는가—는 묻히게 된다. 같은 글이 제안하는 'First-Person Merge Rule'은 단순하다. 머지하면 당신이 작성한 것이다. "Copilot이 유효성 검사를 빠뜨렸다"가 아니라 "내가 유효성 검사 없는 코드를 머지했다"가 올바른 문장이다. 이건 책임 추궁이 아니다. 소유권 라인이 흐려지지 않도록 유지하는 문화 설계다.
AI가 절약해준 두 시간을 더 많은 기능 배포에 쓰는 팀은 이 거래를 잘못 이해한 것이다. AI가 제거한 것은 타이핑이지, 아키텍처 판단이나 보안 리뷰가 아니다. AI가 생성한 테스트는 해피 패스에 치우쳐 있고, AI가 제안하는 패키지는 공급망 리스크를 품고 있다. VS Code 확장이나 MCP 서버에 연결된 에이전트는 소스코드, 환경 변수, 내부 문서에 접근 권한을 갖는다. 런타임 의존성만큼 꼼꼼히 살펴야 할 공급망이 하나 더 생긴 것이다.
두 번째 층위: 검증의 정의를 바꾸는 하네스 엔지니어링
개발 생산성 전문가 Martin Fowler가 큐레이션한 agentic engineering 관련 글들은 공통된 결론으로 수렴한다. AI 시대의 차별점은 생성 속도가 아니라 검증 체계에 있다는 것이다. Chris Parsons는 "verified"의 정의 자체가 바뀌어야 한다고 말한다. 예전의 verified는 '당신이 읽었다'는 뜻이었다. 에이전트 처리량이 개인 리뷰 능력을 초과한 지금, verified는 '테스트, 타입 체커, 자동화 게이트, 혹은 판단이 필요한 지점에서의 인간 검토를 통과했다'는 뜻으로 진화해야 한다.
Birgitta Böckeler가 제안하는 하네스 엔지니어링은 이 맥락에서 핵심 개념이다. LLM은 탐색적·모호한 규칙에 강하지만, 품질 규칙이 객관적이고 결정론적으로 정의될 수 있다면 그것을 테스트나 타입 시스템으로 형식화하는 편이 인간 리뷰보다 더 높은 보증을 준다. 실용적 시사점은 명확하다. 프롬프트를 최적화하기 전에 먼저 물어야 할 것이 있다. 우리 하네스가 에이전트가 도입할 수 있는 문제를 탐지할 수 있는가? 하네스가 약하면 더 좋은 프롬프트는 그저 더 정교한 버그를 만들어낼 뿐이다. 그리고 Adam Tornhill의 연구가 더하는 한 가지: LLM은 식별자 이름, 함수 구조, 로컬 컨텍스트에 크게 의존한다. 레거시 코드베이스의 불일치한 네이밍은 에이전트 산출물 품질을 구조적으로 떨어뜨린다. 코드베이스 가독성은 단순히 사람을 위한 것이 아니라 에이전트 성능을 위한 인프라다.
세 번째 층위: 구조화 프롬프트로 산출물을 예측 가능하게 만들기
검증 체계가 작동하려면 검증할 대상의 형태가 예측 가능해야 한다. dev.to의 Structured Prompts Cut Token Waste 35-40% 실험은 이 지점에서 유용한 데이터를 제공한다. 동일한 코드 생성 태스크에 비구조적 자연어 프롬프트를 쓰면 5회 실행에서 세 가지 다른 아키텍처가 나왔다. 모두 기능적으로는 정확했지만, 원하던 형태는 아니었고 토큰은 평균 1,240개를 소비했다. XML 태그와 명시적 스키마로 구조화한 프롬프트는 5회 모두 동일한 형태를 반환했고 토큰은 847개, 32% 감소했다.
단, 이 데이터를 과잉 해석하지 않을 필요가 있다. 토큰 절감은 실재하지만, 그게 전부가 아니다. 비구조적 프롬프트가 산출한 세 가지 아키텍처 중 하나는 테스트 하네스 연결에 더 유리했을 수 있다. 구조화 프롬프트는 일관성 대신 유연성을 포기한다. 코드 생성 태스크에서는 스키마 준수가 목표이기 때문에 구조화가 명확히 이긴다. 반면 추론, 분석, 탐색이 목적인 태스크에서는 같은 실험에서도 품질 차이가 발생했다. 구조화된 프롬프트가 추론 공간을 지나치게 좁혀버리기 때문이다. "항상 프롬프트를 구조화하라"는 조언은 코드 생성 커뮤니티에서 나온 것이다. 당신의 태스크에서 직접 검증해야 한다.
세 층위를 연결하면 보이는 것
세 가지 논의는 결국 하나의 실행 질문으로 수렴한다. AI 산출물을 신뢰 가능한 수준으로 끌어올리는 검증 설계는 어디서 시작해야 하는가. 책임 언어에서 시작해 하네스로 확장하고, 구조화 프롬프트로 산출물을 예측 가능하게 만드는 순서가 논리적이다. 그런데 팀 대부분은 이 순서를 뒤집는다. 프롬프트 최적화부터 시작하고, 하네스는 나중에, 책임 소재는 사고가 나면 그때 이야기한다.
내가 테크 리드로서 팀에 설계하는 검증 레이어는 이렇다. 첫째, 리뷰 언어부터 바꾼다. PR 코멘트에서 도구를 주어로 쓰지 않는다. 둘째, 하네스를 먼저 점검한다. 프롬프트를 개선하기 전에 그 산출물이 타입 체커와 테스트를 통과하는지 확인하는 파이프라인이 있는지 묻는다. 셋째, 구조화 프롬프트는 코드 생성에만 적용한다. 설계 탐색이나 리뷰 논의에는 의도적으로 자연어를 쓴다. AI가 생성 속도를 높여준다면, 그 속도로 확보한 시간을 검증에 쓰는 것이 팀이 실제로 더 빨라지는 방법이다. 대시보드에서는 덜 화려해 보인다. 하지만 프로덕션에서는 훨씬 낫다.