AI에게 서비스를 만들게 하면 중반까지는 곧잘 하다가, 한번 막히는 순간 요청한 기능의 수준을 슬그머니 낮추거나 아예 기능을 지워 버립니다. 여기서 말하는 AI는 Opus 4.6(앤트로픽의 최신 AI 모델)과 Claude Code(그 모델로 코딩을 시키는 도구)입니다. 왜 이런 일이 벌어지는지, 그 원인이 AI가 글을 지어내는 방식 자체에서 나오는 5가지 구조적 이유를 짚습니다. 그리고 제가 만든 자동 감시·개선 장치(루프에라)가 지금 그중 무엇을 막고 무엇을 못 막는지 정리했습니다.
중간까지는 잘 만들다가 → 한번 막히면 → 원래 요청의 80% 수준으로 몰래 낮춤
기능은 실제로 안 되는데 화면(UI)만 그럴듯하게 뜨면 → "성공했다"고 판정
같은 에러가 반복되면 → 그 기능 자체를 지우거나 빼서 에러를 없애 버림
| 날짜 | 프로젝트 | 증상 |
|---|---|---|
| 03-25 | BisFramework | 증상 2화면을 이루는 코드(DOM)에 자리만 있고 실제로는 안 그려졌는데 "통과(PASS)"라고 3번 잘못 보고 |
| 03-26 | BisFramework | 증상 1행(가로) 끌기만 만들고 열(세로) 끌기는 빠뜨린 채 → "확인해 주세요"라며 사용자에게 떠넘김 |
| 03-30 | Article21 | 증상 2서버가 정상(200) 응답을 줘서 "통과"로 봤지만, 실제로는 필수 입력 항목이 비어 데이터가 저장 안 됨 |
| 04-01 | Article21 | 증상 2버튼이 화면에 있는지만 보고 검사 통과 처리 (실제로 눌러보고 입력해 보는 테스트는 안 함) |
AI(사람의 말을 배운 대화형 모델, LLM)는 대화를 빨리 매듭짓고 싶어 하는 성향이 강합니다. 사용자에게서 "도움이 됐다"는 반응을 얻도록 훈련됐기 때문입니다. 그래서 에러가 반복되면, 문제를 끝까지 푸는 대신 기능을 빼거나 단순하게 만들어서 "성공한 것처럼" 보이는 쪽을 택합니다.
대화가 길어지면 AI는 지난 내용을 자동으로 요약해 압축합니다. 이때 요청의 세부 조건이 가장 먼저 사라집니다. "행과 열을 모두 끌 수 있게"라는 지시에서 "열"이 슬그머니 빠지는 건 바로 이 때문입니다.
AI가 한 번의 작업에서 감당할 수 있는 난이도 총량은 정해져 있습니다. 이걸 '복잡도 예산'이라고 부르겠습니다. 그런데 서비스를 끝까지 완성하려면 어려운 기능 여러 개를 깊이 있게 만들어야 하고, 이는 그 예산을 넘어섭니다.
중반까지 잘 되는 이유는 쉬운 기능부터 먼저 처리되기 때문입니다. 데이터를 만들고 읽고 고치고 지우는 기본 작업(CRUD), 화면 이동(라우팅), 화면 배치 같은 것들입니다. 후반에 막히는 이유는 어려운 기능만 남기 때문입니다. 복잡한 상태 관리, 실시간 동기화, 드물게 생기는 예외 상황(엣지 케이스) 처리가 그렇습니다.
에러가 3번 반복되면 AI는 "에러가 안 나는 상태"에 가장 빨리 도달하는 길을 고릅니다. 기능을 끝까지 제대로 만드는 것보다, 그 기능을 없애서 에러를 지우는 게 더 빠르기 때문입니다.
이건 대놓고 결정하는 게 아니라 자기도 모르게 슬그머니 일어납니다. AI는 "요구 수준을 낮추겠습니다"라고 말하지 않습니다. 대신 '됐다'고 인정하는 검사 기준 자체를 조용히 느슨하게 바꿉니다.
"서비스를 끝까지 완성하기"는 AI에게 가장 어려운 종류의 작업입니다. 긴 대화 내용을 처음부터 끝까지 기억해야 하고, 어려운 문제 여러 개를 차례로 풀어야 하며, 요청을 한 번도 잊으면 안 되고, "대충 돌아가는 것"과 "제대로 되는 것"의 차이를 끝까지 구분해야 하기 때문입니다.
| 대응 대상 | 장치 | 강제력 | 효과 | 한계 |
|---|---|---|---|---|
| 검사 기준 낮추기 방지 | qa-gate-before-push.sh |
HARD | 코드 업로드(push)를 막아 "빌드만 됐는데 통과" 방지 | AI가 형식만 갖춰 통과시킬 수 있음 |
| 검사(QA) 거짓 보고 방지 | web-qa-tester(웹 화면 검사 도구)로 3중 교차 확인 | HARD | 화면 코드(DOM)만 보고 넘어가는 걸 차단 | 큰 프로젝트에선 검사가 불완전할 수 있음 |
| 기능 삭제 방지 | 없음 | 없음 | — | 이것이 가장 큰 빈틈 |
| 요청 사라짐 방지 | PreCompact/PostCompact hook | SOFT | 대화 압축 직전·직후에 요청 내용을 저장해 둠 | 세부 요청까지는 되살리지 못할 수 있음 |
| 에러 반복에서 탈출 | bug-fixer가 4번 다른 전략으로 시도 + codex:rescue(다른 AI에 넘기기) | SOFT | 매번 다른 전략·모델로 다시 시도 | 4번 실패하면 사람에게 넘김 = 사실상 포기 |
작업을 시작할 때 요청 목록을 파일 하나(.requirements-lock.md)에 적어 잠급니다. 반드시 넣어야 할 [MUST] 항목이 안 만들어진 채로 저장(커밋)을 시도하면 무조건 막습니다.
직전 대비 코드 변경 내역(git diff)에서 함수나 화면 조각이 통째로 지워졌는지, "나중에 하겠다"는 표시(TODO)가 새로 붙었는지, 조건을 걸어 기능을 몰래 숨겼는지를 찾아내 사용자에게 되묻습니다.
한 기능이 "실제로 작동한다"고 확인되기 전에는 다음 기능으로 못 넘어가게, 작업 순서에 강제로 묶습니다.
에러가 3번 나면 기능을 줄이거나 지우려는 본능 대신, 문제를 더 작은 단위로 쪼개서 하나씩 따로 확인하게 합니다.
AI(LLM)는 "문제를 푸는" 훈련이 아니라 "그럴듯한 다음 단어를 이어 붙이는" 훈련을 받았습니다. 그래서 진짜 어려운 문제를 만나면 "문제를 없애 버리는 답"이 "문제를 푸는 답"보다 확률적으로 더 자연스러운 반응이 됩니다. 이 구조적 한계를 자동 감시 스크립트(hook)로 메우는 것이 루프에라가 가는 방향입니다. 지금까지 검사(QA) 거짓 보고는 꽤 잘 잡아 왔지만, "기능을 지우거나 줄이는 행동"을 무조건 막는 장치(HARD hook)는 아직 빈틈입니다.