'AI가 짠 코드는 일단 돌아가니까 괜찮지 않을까?' 솔직히 말하면, 나도 한 번쯤 이 생각을 한 적 있다. 프롬프트 한 줄에 컴포넌트가 뚝딱 나오고, 에이전트가 PR까지 올려주는 시대에 '코드 품질'이나 '토큰 비용' 같은 이야기는 잠시 뒤로 밀리기 쉽다. 그런데 최근 세 가지 실패 사례를 연달아 마주치면서 생각이 달라졌다. AI 도구를 '잘 쓴다'는 것과 '쓰고 있다'는 것 사이에는 생각보다 훨씬 넓은 간극이 있다.
화려한 외관 뒤에 숨은 엉터리 최적화
dev.to에 올라온 한 분석 글은 Claude Opus 4.5로 생성된 C++ 단일 헤더 라이브러리 markus를 해부한다. 코드는 첫눈에 인상적이다. [[unlikely]] 같은 브랜치 예측 힌트, if constexpr 조건부 컴파일, std::pmr 네임스페이스를 활용한 메모리 전략, SIMD 친화적 함수들—키워드만 보면 시니어 엔지니어가 공들여 짠 것 같다. 문제는 그 안을 들여다보면 실제로 SIMD가 전혀 작동하지 않는다는 데 있다.
대표적인 예가 IsSpanBlank 함수다. 주석엔 "8바이트씩 SIMD로 처리"라고 적혀 있지만, 실제 구현은 중첩 루프로 바이트를 하나씩 순차 처리한다. 결과적으로 가장 단순한 구현과 성능 차이가 없다. AI는 SIMD라는 개념을 '알고' 있어서 관련 주석과 구조를 생성했지만, 실제로 컴파일러가 벡터화를 할 수 있는 형태로 코드를 짜지는 못했다. 비교 대상 라이브러리 대비 2~3배 느린 성능이 그 증거다. 프로젝트 저자 스스로도 "프로덕션에 절대 쓰지 말 것"이라고 경고했다.
이 사례가 던지는 핵심 질문은 하나다. 코드가 그럴듯해 보일 때, 우리는 검증을 건너뛰지 않는가? AI가 생성한 코드에는 사람이 짠 코드와는 다른 종류의 안티패턴이 숨어 있다. 눈에 잘 띄지 않는다는 점에서 오히려 더 위험하다. 정적 분석기조차 경고를 내지 않았다—구문적으로는 완벽했으니까. 결국 성능 비교나 전문가 리뷰 같은 '외부 기준'이 없으면 이 함정은 잡히지 않는다.
DRY 원칙을 지켰는데 오히려 이중으로 돈을 냈다
두 번째 사례는 AI 에이전트 워크플로우의 토큰 비용 문제다. 한 개발자는 Claude Code 세션에서 반복 호출되는 foundation 스킬들이 토큰을 과도하게 소비한다고 판단하고, 해당 로직을 각 스킬 파일에 인라인으로 복붙하는 리팩토링을 단행했다. 코드 중복을 없애는 DRY 원칙을 적용한 것처럼 보였다. 하지만 결과는 반대였다.
독립적인 감사를 위해 별도 Claude 세션을 열고 자신의 기존 감사 스킬이나 README를 읽지 말 것을 명시적으로 지시한 뒤 감사를 돌렸다. 결과 리포트의 첫 문장은 냉정했다. "이 컬렉션에서 가장 큰 반복 비용은 scratchpad, question, commit-msg에 인라인된 브랜치 파싱 + 파일명 로직의 자가 복제다." 인라인했다고 foundation 스킬이 auto-consultation을 멈추지 않았고, 같은 로직이 세 곳에 따로 존재하면서 이미 내용도 조금씩 달라지고 있었다. 두 벌의 비용을 동시에 지불하고 있었던 셈이다.
해결책은 Markdown 덩어리를 더 정교하게 쪼개는 게 아니라, 결정론적 로직을 셸 스크립트로 빼내는 것이었다. target-path.sh 하나로 브랜치 파싱, 이슈 ID 추출, 파일 경로 생성을 처리하고 stdout 한 줄만 돌려받도록 했다. 스킬 파일의 45줄짜리 Step 1 블록이 두 줄의 병렬 툴 호출로 줄었다. 교훈은 명확하다. AI에게 추론을 맡기면 토큰이 들고, 스크립트에게 계산을 맡기면 토큰이 안 든다. 'DRY하게 만들었다'는 착각이 실제로는 중복 비용을 두 배로 키울 수 있다.
PR에 AI 컨텍스트를 기록하지 않으면 지식은 사라진다
세 번째 사례는 조금 결이 다르다. 코드 품질이나 비용이 아니라 지식의 휘발성 문제다. AI 에이전트는 세션이 끝나는 순간 대화 맥락을 잃는다. 어떤 프롬프트가 이 코드를 만들었는지, 어떤 SKILL.md가 활성화됐는지, AI가 처음에 뭘 틀렸는지—PR에 남기지 않으면 아무것도 남지 않는다.
dev.to의 AI Coding Tip 016은 PR description에 AI Context 섹션을 명시적으로 추가하는 실천법을 제안한다. 사용한 에이전트와 모델 버전, 결정적인 프롬프트, 활성화된 SKILL.md와 AGENTS.md, AI가 처음 시도했다가 실패한 접근, 직접 수정한 내용과 이유—이 다섯 가지를 기록하면 PR 자체가 미래 에이전트의 학습 데이터가 된다. 단순히 "Fix bug"라고 쓴 PR은 다음 에이전트에게 아무것도 전달하지 못한다.
이 방식의 진짜 가치는 개인 생산성이 아니라 팀 전체의 AI 품질 개선 루프에 있다. 좋은 프롬프트는 SKILL.md로 승격되고, 반복된 실수는 AGENTS.md 규칙으로 굳어진다. 스프린트 회고에서 AI 컨텍스트가 풍부한 PR을 골라 검토하면 어떤 스킬이 버그를 줄이는지 측정할 수도 있다. PR을 'AI 추론의 커밋 메시지'로 대하는 순간, 에이전트는 매 세션마다 제로에서 시작하지 않게 된다.
세 가지 실패가 가리키는 같은 방향
세 사례는 서로 다른 층위의 문제를 다루지만, 결국 같은 지점을 향한다. AI 도구에 대한 근거 없는 신뢰다. 코드가 그럴듯해 보인다고 최적화된 게 아니고, DRY하게 정리했다고 비용이 줄어든 게 아니며, 빠르게 머지했다고 지식이 팀에 쌓인 것도 아니다.
바이브 코딩이 나쁜 게 아니다. AI 도구가 문제인 것도 아니다. 문제는 생성의 쉬움이 검증의 필요성을 지워버리는 심리적 메커니즘이다. Claude Opus가 [[unlikely]]와 SIMD 주석을 달아주면 '최적화된 코드'처럼 느껴지고, 에이전트가 스킬 파일을 알아서 참조하면 '효율적인 워크플로우'처럼 느껴진다. 하지만 느낌과 실제 사이의 간극을 메우는 것은 여전히 개발자의 몫이다.
실용적인 처방은 세 가지로 정리된다. 첫째, AI가 생성한 코드는 '작동 여부'가 아니라 실제 성능과 아키텍처로 검증하라. 둘째, 프롬프트 엔지니어링보다 결정론적 로직을 스크립트로 빼내는 구조적 최적화가 토큰 비용 관리에 더 효과적이다. 셋째, PR description에 AI 컨텍스트를 남기는 것은 문서화가 아니라 에이전트 품질의 복리 투자다.
앞으로 AI 코딩 도구는 더 빠르고 더 그럴듯한 코드를 내놓을 것이다. 그럴수록 '잘 쓰고 있다는 착각'은 더 정교해진다. 프론트엔드 개발자에게 지금 필요한 역량은 AI를 더 잘 쓰는 것이 아니라, AI가 만들어내는 착각을 구분하는 감각을 기르는 것이다. 비판적 시각과 검증 루프—이 두 가지가 바이브 코딩 시대의 진짜 시니어 스킬이 되고 있다.