AI 코딩 도구를 본격적으로 팀에 붙이고 나서 가장 먼저 실감한 건 '빠르다'는 것이었다. 그 다음으로 실감한 건 '뭔가 이상하다'는 것이었다. PR은 쌓이는데 리뷰가 따라가질 못하고, 코드는 늘어나는데 시스템에 대한 이해는 오히려 얕아지는 느낌. 이게 단순한 기분 문제가 아니라 구조적 문제라는 걸 이제는 확신한다.
병목은 사라지지 않았다, 이동했을 뿐이다
Dev.to에 올라온 'Code Is Cheap, Understanding Is Expensive'는 이 현상을 정확하게 짚는다. 수십 년간 소프트웨어 개발의 병목은 코드를 쓰는 것이었다. 그런데 AI 어시스턴트가 그 병목을 사실상 제거해버렸다. 이제 수백 줄은 몇 초면 된다. 문제는 병목이 없어진 게 아니라 옮겨갔다는 것이다. 새 병목의 이름은 이해(Understanding)다.
"이 코드가 맞나요?", "이게 안전한가요?", "어딘가를 조용히 깨뜨리지 않나요?" 이 질문들은 AI가 10배 빨라져도 10배 빨리 답할 수 없다. 왜냐하면 이건 코드에 관한 질문이 아니라, 코드 뒤에 쌓인 과거 장애·운영 제약·도메인 규칙에 관한 질문이기 때문이다. 시니어 엔지니어가 결제 시스템의 'retry 3회' 같은 단순한 변경에 몇 시간을 쓰는 이유가 여기 있다. 코드가 길어서가 아니라, 맥락이 불투명하기 때문이다.
AI는 자신감 있게 틀린다
병목이 이동했다는 사실을 더 위험하게 만드는 건 AI의 오류 패턴이다. 같은 Dev.to의 'Why your AI coding agent ships confident, slightly-wrong code'는 이 문제를 구체적으로 파고든다. AI 코딩 에이전트는 user.getProfileById() 같이 코드베이스에 존재하지 않는 메서드를 아무렇지도 않게 생성한다. 명백히 망가진 코드가 아니라, 조용히 잘못된 코드다. 이게 훨씬 위험하다.
팀이 흔히 저지르는 실수는 프롬프트를 더 정교하게 다듬는 것이다. "존재하지 않는 함수를 만들지 마라"는 규칙을 추가하고, 또 추가하고, 열다섯 줄짜리 규칙 목록을 만든다. 그래도 뚫린다. 이 글이 핵심을 정확하게 짚는다: 프롬프트 수정은 어휘 문제로 구조 문제를 해결하려는 시도다. 모델은 작업이 복잡해질수록 규칙을 하나씩 드롭한다. 열여섯 번째 규칙은 드롭할 것이 하나 더 늘 뿐이다.
해법은 규칙을 금지하는 게 아니라 검증을 필수 단계로 구조화하는 것이다. 코드를 쓰기 전에 사용할 모든 메서드를 열거하고, 각각이 코드베이스 어디에 정의되었는지 찾도록 강제한다. 찾지 못하면 코드를 쓰지 않고 멈추게 한다. 같은 모델, 추가 규칙 없이, 구조만 바꿔도 할루시네이션의 발생 공간 자체가 사라진다.
보안 취약점은 '패턴 경쟁'에서 진 결과다
속도 문제와 이해 문제에 보안 문제까지 겹친다. 'Why LLMs Write Insecure WordPress Code'는 LLM이 왜 구조적으로 취약한 코드를 생성하는지를 냉정하게 설명한다. LLM은 다음 토큰을 예측하는 통계 엔진이다. 훈련 데이터엔 훌륭한 코드와 끔찍한 코드가 공존한다. 특히 2014년식 StackOverflow 스니펫처럼 입력 검증도, 권한 체크도 없는 코드가 대거 포함돼 있다. 보안은 생성 과정의 제약 조건이 아니라, 수천 개의 패턴 중 하나일 뿐이다.
이 글이 제안하는 해법은 단순히 "더 좋은 프롬프트"가 아니다. 확률적 생성기를 결정론적 시스템으로 감싸는 아키텍처다. 세 단계로 구성된다: ① Intent Analysis—코드를 쓰기 전에 필요한 권한·훅·nonce를 JSON 매니페스트로 선언한다. ② Context-Aware Generation—선언된 계약에 따라 모듈별로 코드를 생성한다. ③ Deterministic Audit Loop—생성된 코드가 입력 검증·출력 이스케이핑·권한 체크 등 불변 조건을 만족하는지 자동 검사하고, 실패하면 재생성 루프로 돌린다. 이 구조에서 보안 체크는 선택적 스타일 가이드가 아니라 컴파일 요구 조건이 된다.
팀이 지금 당장 설계해야 할 것
세 기사가 동시에 가리키는 결론은 하나다. AI가 빠를수록 검증 구조가 먼저 있어야 한다. 속도가 올라간 만큼 이해 비용과 오류 비용도 함께 올라간다. 이 비용을 개인의 주의력과 리뷰어의 경험에 의존하는 건 한계가 있다. 직관은 이전 가능하지 않고, 감사 추적이 안 되며, 재현도 불가능하다.
실용적으로 정리하면 세 가지다.
첫째, 의사결정을 코드 밖에 선언하라. 코드는 '무엇을 했는지'는 보여주지만 '왜 그렇게 했는지'는 보여주지 않는다. 재시도 로직 하나에도 '어떤 실패 유형인지', '멱등성은 보장되는지', '마지막으로 맹목적 재시도를 했을 때 무슨 일이 있었는지'가 기록되어야 한다. CLAUDE.md든 ADR이든 형식은 상관없다. 의도가 추적 가능해야 AI가 같은 컨텍스트를 다음에도 올바르게 다룰 수 있다.
둘째, 생성 전 그라운딩을 필수 단계로 박아라. 코드 작성 전 사용할 API·메서드·권한을 먼저 열거하고 검증하는 단계를 프롬프트 구조에 내장한다. 이건 LLM의 할루시네이션 발생 공간을 줄이는 가장 직접적인 방법이다.
셋째, 보안 검증은 CI에서 결정론적으로 실행하라. LLM에게 "안전하게 짜줘"라고 부탁하는 건 확률적 설득이다. 생성 이후 불변 조건을 자동 검사하고 실패 시 통과를 막는 파이프라인이 확률을 구조로 대체한다.
속도는 자산이다, 단 검증 구조가 있을 때
AI 코딩 도구의 속도를 포기하자는 게 아니다. 속도는 분명한 자산이다. 그런데 그 자산을 팀이 소화할 수 있는 구조 없이 쌓으면, 이해할 수 없는 코드 더미만 늘어난다. '우리가 쓴 것보다 빠르게 짜여지는 코드'가 아니라 '우리가 검증할 수 있는 속도로 짜여지는 코드'가 목표여야 한다.
진짜 위험은 코드를 못 쓰는 게 아니다. 이해할 수 있는 속도보다 빠르게 쌓이는 코드다. 검증 구조는 속도를 제한하는 장치가 아니라, 속도를 지속 가능하게 만드는 인프라다.