바이브코딩이 production에서 무너지는 8가지 이유 — Flask 로그인 한 개로 따라가는 체크리스트
핵심 요약 (TL;DR)
엔지니어 Jh Evans가 5월 30일 'Vibe Coding Is Not Engineering' 에세이로 HN 43점·72~73개 댓글의 토론을 일으켰습니다. 핵심 주장은 '바이브코딩은 코드를 만들고 엔지니어링은 시스템을 만든다, 그 사이에 production failure가 산다'입니다. Flask/SQLite 로그인 1개로 캐스케이드 실패 시나리오를 끝까지 따라가며 LLM이 건너뛰는 8가지 엔지니어링 결정을 정리했어요.
작동하는 로그인 ≠ 살아남는 로그인
Jh Evans의 글이 다른 비판들과 결정적으로 다른 지점이 하나 있습니다. 'LLM이 별로다'가 아니라 'LLM은 작동하는 로그인을 잘 만든다. 그런데 살아남는 로그인은 못 만든다'고 말한다는 점이에요.
HN 토론 페이지에서 가장 많이 인용된 시나리오를 그대로 따라가볼게요. Flask + SQLite로 흔한 로그인을 만든다고 칩시다. LLM은 30초 만에 SignUp / SignIn / Password Reset 엔드포인트와 사용자 테이블을 뽑아줘요. 잘 굴러갑니다.
그런데 5가지 결정이 빠져 있어요.
- 이메일 unique 제약을 안 걸었습니다. '그건 폼 단에서 막으면 되지' 하고 넘어가요.
- 그래서 같은 이메일로 두 번 가입한 사용자가 생깁니다(폼 우회·다른 디바이스·재가입 등).
- 그 사용자가 비밀번호를 잊고 reset을 누릅니다.
- password reset은 이메일로 매칭됩니다. 그러니 그 이메일의 모든 계정에 새 비밀번호가 적용돼요.
- 그 사용자가 계정 하나를 삭제합니다. 삭제도 이메일 기준이라 모든 계정이 같이 사라집니다.
작동하던 로그인이 production에서 두 달 뒤에 한 번에 무너지는 캐스케이드 시나리오 한 줄. 무서운 건 LLM이 만든 코드 자체엔 버그가 없다는 점이에요. 하나하나는 잘 작동합니다. 결합 지점에서 시스템 결정이 빠졌을 뿐이죠.
LLM이 건너뛰는 8가지 엔지니어링 결정
Jh Evans가 추출한 8개 항목입니다. 바이브코더가 자기 코드를 검수할 때 체크리스트로 활용하기 좋아요.
- Invariants (불변식) — 이 시스템에서 절대 깨지면 안 되는 사실이 뭔가요? '이메일은 사용자 ID 안에서 유일하다' 같은 것.
- Identity & Uniqueness (정체성과 유일성) — 무엇이 한 사람·한 객체를 식별하나요? 이메일? user_id? 둘이 다를 때 어떻게 됩니까?
- Constraints (제약) — DB 레벨에서 강제할 것 vs 애플리케이션 레벨에서 강제할 것의 경계가 잡혀 있나요?
- Failure Modes (실패 모드) — 이 호출이 실패하면 무엇이 깨지나요? 부분 실패 시 어떤 상태에 멈춰 있나요?
- Coupling & Sequencing (결합과 순서) — A가 B 다음에 일어나야만 하는 순서가 있나요? 비동기로 뒤집히면요?
- State & Transitions (상태와 전이) — 이 객체의 상태 머신이 그려져 있나요? 어떤 전이가 허용되나요?
- Interfaces & Contracts (인터페이스와 계약) — 이 함수의 호출 측이 약속하는 사전조건과 함수가 보장하는 사후조건은 뭔가요?
- Boundaries (경계) — 신뢰 경계는 어디인가요? 사용자 입력은 어디서 검증되나요?
이 8개는 새로운 개념이 아닙니다. Hoare logic(invariants), 시스템 설계 교과서(coupling), 도메인 주도 설계(boundaries)에 다 있던 이야기예요. Jh Evans의 기여는 이걸 LLM 워크플로의 검수 항목으로 재배열했다는 점이죠.
그래서 바이브코더는 무엇을 해야 하나
Jh Evans 본인의 약력은 phroneses.com에 자세히 공개되어 있지 않습니다(본인 표기는 엔지니어/작가 수준). 그래서 '권위 있는 사람이 한 말이니까'가 아니라, 체크리스트 자체의 효용으로 받아들이는 게 맞습니다.
가장 실용적인 활용은 이렇습니다. LLM이 코드를 뱉을 때마다 위 8개 항목을 헤더로 하는 짧은 점검 메모를 같이 만드세요. '이 PR에서 invariants는? identity는? failure mode는?' 채우다 보면 LLM이 건너뛴 자리가 보입니다. 5분이면 됩니다. 그 5분이 두 달 뒤의 캐스케이드 사고를 막아주는 거죠.
HN 댓글 중 인상 깊은 한 쪽 — 'AI 통합이 잘 되면 spec과 review로 8개가 다 잡힌다'는 반론이 있었습니다. 다른 쪽은 '비즈니스가 작동만 요구하면 그 선이 모호해진다'고 답했고요. 양쪽 다 맞아요. 문제는 도구가 아니라 우리가 8개를 의식하고 있느냐입니다.
자주 묻는 질문
Q. 이 8가지가 새로운 개념인가요?
아닙니다. Hoare logic의 invariants, 도메인 주도 설계의 boundaries, 시스템 설계의 coupling 등 기존 소프트웨어 엔지니어링 문헌에 다 있는 개념입니다. Jh Evans의 기여는 이를 LLM 워크플로 검수용 체크리스트로 정리한 점입니다.
Q. 캐스케이드 실패 시나리오는 실제 사고 사례인가요?
글에는 구체적 production incident 출처가 명시되어 있지 않습니다. Flask/SQLite로 자주 재현되는 패턴을 이론적으로 정리한 시나리오로 보는 게 맞습니다. 다만 패턴 자체는 현업에서 흔히 마주치는 결합 실패 유형이라 시나리오의 현실성은 높습니다.
Q. LLM이 8가지를 알아서 챙기게 만드는 방법은 없나요?
프롬프트 단에서 '이 코드에 invariants·identity·failure mode를 명시해줘'라고 강제하면 어느 정도 챙기긴 합니다. 다만 LLM이 자발적으로 의식하긴 어렵고, 사람이 8개 항목을 PR 템플릿 같은 형태로 외부에서 강제하는 쪽이 안정적입니다.
댓글 0
아직 댓글이 없습니다