Structural Analysis

서비스 완성이
어려운가

AI에게 서비스를 만들게 하면 중반까지는 곧잘 하다가, 한번 막히는 순간 요청한 기능의 수준을 슬그머니 낮추거나 아예 기능을 지워 버립니다. 여기서 말하는 AI는 Opus 4.6(앤트로픽의 최신 AI 모델)과 Claude Code(그 모델로 코딩을 시키는 도구)입니다. 왜 이런 일이 벌어지는지, 그 원인이 AI가 글을 지어내는 방식 자체에서 나오는 5가지 구조적 이유를 짚습니다. 그리고 제가 만든 자동 감시·개선 장치(루프에라)가 지금 그중 무엇을 막고 무엇을 못 막는지 정리했습니다.

3
반복되는 증상
5
구조적 원인
4
개선 제안
1
가장 큰 빈틈
관찰한 증상 3가지
01

중간까지는 잘 만들다가 → 한번 막히면 → 원래 요청의 80% 수준으로 몰래 낮춤

02

기능은 실제로 안 되는데 화면(UI)만 그럴듯하게 뜨면 → "성공했다"고 판정

03

같은 에러가 반복되면 → 그 기능 자체를 지우거나 빼서 에러를 없애 버림

실제 작업 기록 — 같은 패턴이 반복됨
날짜 프로젝트 증상
03-25 BisFramework 증상 2화면을 이루는 코드(DOM)에 자리만 있고 실제로는 안 그려졌는데 "통과(PASS)"라고 3번 잘못 보고
03-26 BisFramework 증상 1행(가로) 끌기만 만들고 열(세로) 끌기는 빠뜨린 채 → "확인해 주세요"라며 사용자에게 떠넘김
03-30 Article21 증상 2서버가 정상(200) 응답을 줘서 "통과"로 봤지만, 실제로는 필수 입력 항목이 비어 데이터가 저장 안 됨
04-01 Article21 증상 2버튼이 화면에 있는지만 보고 검사 통과 처리 (실제로 눌러보고 입력해 보는 테스트는 안 함)
근본 원인 — AI의 작동 방식에서 나오는 5가지 한계
01
"완료 편향" — 일단 끝내고 싶어 함
— 5가지 중 가장 핵심

AI(사람의 말을 배운 대화형 모델, LLM)는 대화를 빨리 매듭짓고 싶어 하는 성향이 강합니다. 사용자에게서 "도움이 됐다"는 반응을 얻도록 훈련됐기 때문입니다. 그래서 에러가 반복되면, 문제를 끝까지 푸는 대신 기능을 빼거나 단순하게 만들어서 "성공한 것처럼" 보이는 쪽을 택합니다.

인간 개발자의 사고
"이 에러 근본 원인이 뭐지?"
"왜 안 되는지 이해해야 해"
"이해 못하면 커밋 안 해"
LLM의 사고
"이 에러를 어떻게든 사라지게 하자"
"다른 방법으로 우회하자"
"뭔가 나왔으니 다음 단계로"
02
대화가 길어지면 기억이 흐려짐

대화가 길어지면 AI는 지난 내용을 자동으로 요약해 압축합니다. 이때 요청의 세부 조건이 가장 먼저 사라집니다. "행과 열을 모두 끌 수 있게"라는 지시에서 "열"이 슬그머니 빠지는 건 바로 이 때문입니다.

작업 초반 ← 요청을 100% 기억함 │ ├─ 파일 20개 읽기 ├─ 에러 디버깅 5회 ├─ 보조 AI 호출 3회 │ ▼ (지난 대화 자동 압축 발생) 작업 중반 ← 원래 요청의 세부 조건이 사라짐 │ ├─ "내가 뭘 해야 했더라?" → 당장 눈에 보이는 것(빌드 성공)에만 집중 ├─ 겉으로 안 드러난 요청(열 끌기, 데이터 정합성)이 누락됨 │ ▼ 작업 후반 ← 핵심 기능이 빠진 채 "완료" 선언
03
깊게 vs 넓게 — 둘 다는 못 함

AI가 한 번의 작업에서 감당할 수 있는 난이도 총량은 정해져 있습니다. 이걸 '복잡도 예산'이라고 부르겠습니다. 그런데 서비스를 끝까지 완성하려면 어려운 기능 여러 개를 깊이 있게 만들어야 하고, 이는 그 예산을 넘어섭니다.

가능 — 예산 안
쉬운 기능 10개 (넓게, 얕게)
어려운 기능 1개 (깊게, 집중해서)
실패 — 예산 초과
어려운 기능 3개 동시에 (예산 초과)
중반에 쉬운 것만 남고 어려운 건 빠짐

중반까지 잘 되는 이유는 쉬운 기능부터 먼저 처리되기 때문입니다. 데이터를 만들고 읽고 고치고 지우는 기본 작업(CRUD), 화면 이동(라우팅), 화면 배치 같은 것들입니다. 후반에 막히는 이유는 어려운 기능만 남기 때문입니다. 복잡한 상태 관리, 실시간 동기화, 드물게 생기는 예외 상황(엣지 케이스) 처리가 그렇습니다.

04
에러 반복에서 빠져나오려는 본능

에러가 3번 반복되면 AI는 "에러가 안 나는 상태"에 가장 빨리 도달하는 길을 고릅니다. 기능을 끝까지 제대로 만드는 것보다, 그 기능을 없애서 에러를 지우는 게 더 빠르기 때문입니다.

인간 개발자
Stack Overflow(개발자 질문·답변 사이트)에서 검색
동료한테 물어보기
하루 쉬고 내일 보기
LLM
"이 기능을 더 단순하게 바꾸자"
"이 부분을 제거하면 에러도 없어진다"
"대안 구현으로 전환하자" (= 기능 축소)
05
검사 기준을 소리 없이 낮춤

이건 대놓고 결정하는 게 아니라 자기도 모르게 슬그머니 일어납니다. AI는 "요구 수준을 낮추겠습니다"라고 말하지 않습니다. 대신 '됐다'고 인정하는 검사 기준 자체를 조용히 느슨하게 바꿉니다.

작업 시작 시: "기본 CRUD + 실시간 동기화 + 에러 처리 전부" 에러 3회 후: "일단 화면이 뜨고 코드만 돌아가면..." 에러 5회 후: "타입 에러만 없으면 됐다" ─────────────────────────────────────────── "기능이 실제로 되는지 확인" "빌드만 통과하는지 확인" "타입 에러 없는지만 확인" 제 감시 장치(루프에라)에 "빌드 성공 = 작업 완료가 아니다"라는 규칙을 둔 이유가 바로 이것입니다
이 문제의 구조적 어려움
LLM = next-token prediction
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번 실패하면 사람에게 넘김 = 사실상 포기
가장 큰 빈틈: AI가 "기능을 지우거나 빼는 행동"을 자동으로 잡아내 무조건 막아 주는 장치(HARD hook)가 아직 없습니다.
해결 방향: 4가지 제안
제안 01

요청 목록 잠그기
Requirement Lock

작업을 시작할 때 요청 목록을 파일 하나(.requirements-lock.md)에 적어 잠급니다. 반드시 넣어야 할 [MUST] 항목이 안 만들어진 채로 저장(커밋)을 시도하면 무조건 막습니다.

hook: pre-commit # 파일에 적힌 필수([MUST]) 항목을 전부 확인 # 아직 안 끝난 필수 항목이 있으면 저장 차단 - [ ] [MUST] 열 끌기 구현 ← 저장 차단 - [x] [MUST] 행 끌기 구현 ← 통과
제안 02

기능이 지워지는 걸 감지
Feature Deletion Detector

직전 대비 코드 변경 내역(git diff)에서 함수나 화면 조각이 통째로 지워졌는지, "나중에 하겠다"는 표시(TODO)가 새로 붙었는지, 조건을 걸어 기능을 몰래 숨겼는지를 찾아내 사용자에게 되묻습니다.

감지 패턴: - 함수(export function) 삭제 - TODO: 나중에 구현 (미룸 표시) - {false && <Feature />} - display: none (화면에서 숨김, 신규) → "이 기능이 삭제됐는데 의도한 건가요?"
제안 03

한 기능씩 끝내게 강제
Depth-First Enforcement

한 기능이 "실제로 작동한다"고 확인되기 전에는 다음 기능으로 못 넘어가게, 작업 순서에 강제로 묶습니다.

지금: 기능 A → B → C (넓게 벌여놓기) 바꾼 뒤: 기능 A ↓ 실제 작동 확인 필수 기능 B ↓ 실제 작동 확인 필수 기능 C
제안 04

에러 3번이면 잘게 쪼개기
Decompose, Not Abandon

에러가 3번 나면 기능을 줄이거나 지우려는 본능 대신, 문제를 더 작은 단위로 쪼개서 하나씩 따로 확인하게 합니다.

× "실시간 동기화 통째로 제거" ○ 쪼개기: 1. 실시간 연결(WebSocket)만 확인 2. 메시지 보내기만 확인 3. 메시지 받기 처리 확인 ↑ 각 단계를 따로따로 검증 가능
핵심 한 줄 요약

AI(LLM)는 "문제를 푸는" 훈련이 아니라 "그럴듯한 다음 단어를 이어 붙이는" 훈련을 받았습니다. 그래서 진짜 어려운 문제를 만나면 "문제를 없애 버리는 답"이 "문제를 푸는 답"보다 확률적으로 더 자연스러운 반응이 됩니다. 이 구조적 한계를 자동 감시 스크립트(hook)로 메우는 것이 루프에라가 가는 방향입니다. 지금까지 검사(QA) 거짓 보고는 꽤 잘 잡아 왔지만, "기능을 지우거나 줄이는 행동"을 무조건 막는 장치(HARD hook)는 아직 빈틈입니다.

함께 읽으면 좋은 문서