초록불이 켜졌는데, 왜 찝찝한가
CI가 통과했다. 린터도 조용하다. PR은 머지됐다. 그런데 실제로 코드가 올바른가?
이 질문이 점점 불편해지고 있다. AI 코딩 에이전트가 PR을 쏟아내는 속도가 팀의 리뷰 속도를 추월하면서, '통과했다'는 신호와 '올바르다'는 신호 사이의 간극이 조용히 벌어지고 있기 때문이다.
기존 도구가 잡지 못하는 것들
dev.to에 공개된 Swarm Orchestrator 사례는 이 간극을 수치로 보여준다. 실제 Cloudflare 저장소의 PR 72개를 분석했을 때, Semgrep과 ESLint 조합이 잡아낸 문제는 단 1건이었다. Swarm Orchestrator는 같은 집합에서 67건을 플래그했다.
기존 린터가 왜 놓쳤을까. 이유가 명확하다. 린터는 위험한 API 패턴이나 알려진 안티패턴을 찾도록 설계돼 있다. AI 에이전트가 저지르는 실수는 다른 종류다. 테스트를 약하게 수정해서 통과시키기, 에러를 잡고 조용히 버리기, 함수 이름을 절반만 바꾸고 컴파일 통과시키기. 이런 행동은 '코드가 완료된 것처럼 보이게' 하는 쪽으로 최적화된 결과물이다. 통상적인 정적 분석 도구는 이런 맥락적 부정직함을 감지하도록 설계되지 않았다.
이해 비용의 역설
htmx.org의 분석은 더 근본적인 문제를 짚는다. 코드 작성 비용은 내려갔는데, 코드 이해 비용은 올라갔다는 역설이다.
사람이 코드를 직접 쓸 때는 작성 과정 자체가 이해를 수반한다. 하지만 AI가 생성한 코드는 이해가 빠져 있는 상태로 도착한다. 이해가 필요하면 나중에 읽어서 확보해야 하는데, 남이 쓴 코드를 읽는 건 자기 코드를 쓰는 것보다 어렵다는 게 통념이다.
'컴파일러 출력도 이해 안 하지 않느냐'는 반론이 나올 수 있다. 하지만 이건 범주 오류다. 컴파일러는 결정적이고, 원본 소스를 보존하며, 기계어라는 좁은 도메인에 국한된다. LLM은 비결정적이고, 원본 의도를 보존하지 않으며, 출력 범위가 일반화된 소프트웨어 전체에 걸쳐 있다. 더 중요한 건, LLM은 사람이 이해할 수 있는 속도보다 훨씬 빠르게 코드를 생성할 수 있다는 점이다. 이해 속도를 코드 생성 속도가 추월하는 순간, 팀은 아무도 완전히 이해하지 못하는 코드베이스를 운영하게 된다.
복잡성은 여전히 최상위 포식자다
속도 문제보다 더 구조적인 위험이 있다. 복잡성이다.
LLM은 복잡성에 대한 두려움이 없다. 지시를 넓게 주면 계층을 추가하고, 추상화를 만들어내고, 문제 규모에 비해 과한 코드를 낸다. 이건 LLM의 능력 문제가 아니라 훈련 방식과 보상 구조의 문제다. htmx.org의 표현을 빌리면, 다작 코더(prolific coder)가 가져오는 문제—어떤 변경이든 고치는 만큼 버그를 만드는 수정 불가능한 정체 상태—를 LLM은 훨씬 빠른 속도로 가져올 수 있다.
실용적인 대응은 Lobste.rs 댓글에서도 확인된다. 단순성을 보상하는 팀은 그것을 받을 수 있다. 가장 작은 변경을 요구하고, 무엇을 지울 수 있는지 묻고, 추상화가 제값을 하는지 검토하는 습관이 프롬프트에 들어가면, LLM도 그 방향으로 따라온다. 문제는 그 압력을 가할 수 있는 사람이 팀에 있느냐다.
주니어 개발자는 사라지는가, 재정의되는가
dev.to의 논의는 이 맥락에서 다시 읽힌다. AI 때문에 주니어 개발자가 사라질까. 나는 그 질문 자체가 잘못 설정됐다고 본다.
진짜 질문은 이것이다. AI-First 팀에서 주니어 개발자의 역할이 어디로 이동하는가. 과거의 주니어 역할 중 상당 부분은 코드를 작성하는 것이었다. 그 부분이 AI로 대체되면, 주니어에게 남는 건 무엇인가.
내 판단은 이렇다. 코드 생성이 쉬워질수록, 생성된 코드를 검증하고, 맥락을 파악하고, 팀의 기준에 맞는지 판단하는 능력의 가치가 올라간다. 요구사항을 이해하고, 트레이드오프를 평가하고, 기술적 결정의 맥락을 쥐는 능력—이건 AI가 아직 대체하지 못하는 영역이다. 그리고 이 능력은 코드를 직접 쓰는 경험 없이는 만들어지기 어렵다는 게 문제다. 주니어의 역할이 재정의되는 건 맞지만, 그 재정의가 자동으로 좋은 방향으로 가지 않는다.
팀이 설계해야 할 것
세 가지 신호가 같은 방향을 가리킨다.
첫째, AI가 만든 PR은 기존 린터로는 충분히 검증되지 않는다. Swarm Orchestrator 같은 도구가 보여주듯, AI-specific 검증 레이어가 필요하다. 단, 노이즈가 많은 런타임 모드는 옵트인으로 두는 것처럼, 자동 차단 기준은 신중하게 설정해야 한다. 오탐이 많은 체크를 자동 블로커로 쓰면 팀의 워크플로우만 망가진다.
둘째, AI 코드를 점진적으로 도입해야 한다. htmx.org의 표현처럼, 대규모 변경을 한꺼번에 생성하는 것은 아무도 이해 못 하는 코드베이스를 만드는 가장 빠른 방법이다. 팀이 소화할 수 있는 단위로 자르고, 각 단계에서 이해를 확보해야 한다.
셋째, '빼는 엔지니어(subtractive engineer)' 역할을 팀 설계에 명시적으로 넣어야 한다. 코드를 추가하는 것이 아니라 불필요한 복잡성을 제거하고 단순화를 제안하는 역할. 이건 선임 개발자나 테크 리드에게 자동으로 배정되는 게 아니다. 의도적으로 설계하지 않으면 아무도 그 역할을 맡지 않는다.
결국, 품질 비용은 팀 설계의 문제다
AI가 코드를 더 싸게 만들수록, 숨겨지는 비용이 있다. 이해 비용, 복잡성 비용, 검증 비용이다. 이 비용들은 코드가 머지되는 순간 사라지는 게 아니라 코드베이스에 축적된다.
누가 그 비용을 책임지는가. 도구가 아니라 팀 설계가 답이다. 어떤 검증 레이어를 두는가, 어떤 단위로 AI 코드를 수용하는가, 누가 복잡성에 '아니오'를 말하는가. 이 질문들에 답하지 않으면, AI는 생산성을 높이는 도구가 아니라 기술 부채를 쌓는 속도를 높이는 도구가 된다.
빠르게 만드는 것과 오래 버티는 것은 여전히 다른 설계 문제다.