프롤로그 — 칭찬이 아니라 보정(calibration)이 필요한 시기
지난 18개월 동안의 AI 코딩 콘텐츠는 대부분 **세 가지 모드** 중 하나였다.
1. **유토피아** — "이제 개발자는 필요 없다"
2. **디스토피아** — "AI 코드는 다 쓰레기다"
3. **마케팅** — "우리 도구가 X%를 자동화합니다"
이 글은 그 중 어느 것도 아니다. 이 글은 **calibration**에 관한 글이다.
> **AI 코딩 어시스턴트는 강력하다. 그러나 강력함의 모양은 균일하지 않다.** 어떤 작업에서는 3x~10x의 multiplier이고, 어떤 작업에서는 0x이며, 어떤 작업에서는 **음수의 multiplier** — 즉, 사람이 직접 했을 때보다 더 느리고 더 잘못된 결과를 낸다.
2026년 5월 현재, SWE-bench Verified 상위권 에이전트들은 75% 안팎에 도달했다. 좋은 수치다. 그러나 그 25%가 어떤 25%인지를 모르면, 우리는 25%의 영역에서 신뢰를 1로 두고 손해를 본다.
이 글은 **AI가 잘 못하는 일 10가지**를 다룬다. 각각에 대해:
- **실제 실패 패턴** — 추상이 아니라 코드.
- **왜 그런가** — 모델 아키텍처와 하네스의 한계로 환원.
- **개발자가 계속 해야 할 일** — 인간 판단이 multiplier가 되는 지점.
마지막에 **한 매트릭스**, **체크리스트**, **안티패턴 목록**을 둔다. AI 회의론이 아니라 **AI 도구를 더 잘 쓰기 위한 보정**이다.
1장 · 깊은 버그 디버깅 — "에이전트는 코드는 쓰지만 버그는 좁히지 못한다"
패턴
상용 서비스에서 5분에 한 번씩 P99 레이턴시가 튀는 버그가 있었다. 원인은 결국 GC가 아니라 **TLS 세션 재협상 폭주**였다. 에이전트는 8시간을 GC 튜닝에 쓰고, 그 8시간 끝에 "GC 로그를 더 자세히 보고 싶으니 권한을 달라"고 했다.
왜 그런가
LLM 에이전트는 **가설 터널링(hypothesis tunneling)**에 취약하다. 한번 "이건 GC 문제 같다"고 컨텍스트에 들어가면, 그 다음 모든 도구 호출과 추론이 그 가설을 **확정하는 방향으로 편향**된다. 인간 디버거는 1시간쯤 뒤에 "이게 아닌가?"라고 멈추고 다른 가지를 본다. 에이전트는 컨텍스트가 점점 두꺼워지면서 처음의 가설을 강화한다 — **context rot**의 가장 음험한 형태다.
게다가 에이전트의 도구 호출은 **로컬한 정보**를 본다. 디버거를 띄워서 코어 덤프를 보고, 패킷 캡처를 추적하고, 커널 trace를 읽는 — 이런 작업은 부분적으로만 자동화된다. 그리고 "재현되지 않는" 버그는 에이전트의 약점 중 하나다 — 재현이 어려우면 에이전트는 **추측을 더 늘린다**.
사람이 계속 해야 할 일
- **가설을 닫지 마라.** 에이전트에게 "이건 GC가 아닐 수도 있다, 5가지 다른 가설을 나열하라"고 강제하라.
- **반증 가능한 실험을 설계하라.** 에이전트는 "내가 옳다는 증거"를 잘 찾지만, "내가 틀렸다는 증거"를 잘 찾지 못한다.
- **8시간 룰.** 같은 가설을 8시간 이상 쫓고 있다면 멈춰라. 에이전트는 멈추지 않는다 — 당신이 멈춰야 한다.
실제 다이얼로그 예시
사람: "P99이 갑자기 튀는데 GC인 것 같아. 봐줘."
에이전트: (1시간) "G1GC 파라미터를 튜닝합시다…"
사람: "어떤 가설을 더 가질 수 있을까? 5개 나열해."
에이전트: "1) GC, 2) 디스크 IO 폭주, 3) 네트워크 재전송, 4) TLS 재협상, 5) 컴팩션 작업"
사람: "GC 외의 4개를 5분씩 봐. 증거가 있는지."
이 강제 분기가 없으면 에이전트는 1번에서 빠져나오지 못한다. **메타 지시(meta-instruction)** — "다른 가설도 봐라" — 가 multiplier다.
2장 · 대규모 코드베이스의 아키텍처 — "에이전트는 단면을 보고, 전체를 못 본다"
패턴
100만 라인 모노레포에서 새 기능을 추가하라고 한다. 에이전트는 그 기능을 **`new-feature/`** 디렉터리에 깔끔하게 만든다. 코드는 작동한다. 그러나 같은 팀의 시니어가 보면 "어… 이거 이미 `platform/shared/orchestration`에 비슷한 게 있는데?"라고 한다. 에이전트는 그걸 못 본다 — **그 디렉터리를 한 번도 읽지 않았기 때문**이다.
왜 그런가
LLM은 컨텍스트 윈도우 안에서만 추론한다. 1M 토큰 모델도 100만 라인 모노레포 전체를 한 번에 못 본다. 에이전트는 **이름 기반 검색**과 **언급된 경로**로 코드베이스를 탐색하는데, 이는 **암묵적 지식**을 못 잡는다.
특히 위험한 것은 **abstraction conflict**다. 에이전트는 "깔끔한 추상화"를 만든다. 그러나 그 추상이 기존 추상과 **모양만 다르고 의도는 겹친다**면, 코드베이스는 **두 개의 비슷한 abstraction layer**를 갖게 된다. 6개월 뒤 어떤 신입은 어느 쪽을 써야 하는지 모르고, 양쪽 다 쓰고, 결국 third one을 만든다.
사람이 계속 해야 할 일
- **에이전트에게 "비슷한 게 이미 있는지 먼저 검색하라"는 명시 단계를 강제하라.** AGENTS.md 또는 prompt에.
- **PR 단계의 "abstraction review"** — 시니어가 "이게 기존 X와 어떻게 다르냐"를 묻는 단계. AI는 이 질문을 자기 자신에게 잘 던지지 못한다.
- **아키텍처 문서**를 텍스트가 아니라 **에이전트가 읽을 수 있는 형태**로 두라. 결정 기록(ADR), 모듈 책임 매트릭스. 에이전트는 못 읽는 것을 못 본다.
한 발 더 — "기존 코드를 두 번 읽게 하라"
대규모 코드베이스에서 효과가 좋았던 트릭 하나. 에이전트에게 task를 주기 전에 명시적으로 두 단계를 시킨다.
1) "이 task와 관련될 수 있는 기존 모듈을 5분간 검색해서 나열하라."
2) "그 모듈들의 책임이 task와 어떻게 겹치는지, 새 코드를 어디에 두는 것이 옳은지 후보를 3개 제시하라."
3) "사람의 확인 받은 뒤에 코딩을 시작하라."
3단계 게이트는 추상화 충돌을 30~50% 줄인다는 게 우리 팀의 경험이다. 에이전트는 "코드 쓰기 시작"이 디폴트라서, **쓰기 전에 멈추도록 명시**해야 한다.
3장 · 미묘한 성능 회귀 — "보기엔 같은데 10배 느리다"
패턴
에이전트가 N+1 쿼리를 "리팩터링"한다. 코드는 더 깔끔해 보인다. 테스트는 전부 통과한다. 운영에 배포한다. P95 레이턴시가 10배가 된다. 보니까, 깔끔해 보이는 그 코드가 **인덱스가 안 타는 쿼리 패턴**으로 바뀌었다. 또는 lazy load이던 게 eager load이 됐다.
왜 그런가
LLM은 코드의 **모양**을 본다. 코드의 **런타임 비용**은 직접 보지 않는다 — 추론할 뿐이다. 그리고 그 추론은 종종 **데이터 분포에 의존**한다. 100건의 row에서는 안 보이는 N+1이 100만 건에서는 P95를 죽인다. 에이전트는 100만 건의 분포를 **모른다**.
또한 에이전트는 **micro-benchmark**를 잘 짜지 못한다. JIT 워밍업, 캐시 효과, 측정 노이즈 — 모두 인간 직관이 필요한 영역이다.
사람이 계속 해야 할 일
- **성능 회귀 테스트**를 CI에 박아라. 에이전트는 회귀를 안 본다 — CI가 봐줘야 한다.
- **프로파일러 결과를 에이전트에게 직접 먹여라.** "이 PR이 어떤지 봐"가 아니라 "이 flamegraph를 보고 회귀를 찾아라". 도구가 다르면 능력이 다르다.
- **데이터 분포에 대한 책임은 인간이 진다.** 에이전트는 "1000건에서 잘 돌아간다"는 알지만, "1억 건일 때 어떨까"는 모른다.
작은 사례 — 알고리즘 복잡도의 hidden upgrade
에이전트가 `Set` 기반 dedup을 `Array.filter + includes`로 "단순화"하는 PR을 자주 본다. 코드는 더 짧다. 100건일 때는 더 빠르다(상수 작은). 10만 건일 때는 O(n²)이라 30배 느리다. 단위 테스트는 10건짜리라 못 잡는다. 운영에서 잡힌다.
이런 패턴이 위험한 이유는 **"리팩터처럼 보이는 회귀"**이기 때문이다. PR 리뷰어도 "더 깔끔하네"하고 넘긴다. 자동 성능 회귀 테스트만이 객관적인 안전망이다.
4장 · 동시성 정확성 — "패턴매칭으로 race-free 흉내를 낸다"
패턴
에이전트가 멀티 스레드 큐 구현을 짠다. 코드는 `Mutex`와 `Condvar`를 정석대로 쓴다. 리뷰하면 "어, 잘 했네"라고 한다. 6개월 뒤, 부하 상황에서 deadlock이 발생한다. 보니까 두 락의 획득 순서가 두 곳에서 **반대**였다 — 경합이 거의 일어나지 않는 경로에서.
왜 그런가
동시성 코드는 **사례 학습**으로 잘 안 잡힌다. 모델은 "흔한 race-free 패턴"을 매우 잘 흉내낸다 — producer/consumer, reader/writer lock, channel 기반 메시지 패싱. 그러나 **두 락의 순서 일관성**, **메모리 모델**(`Acquire`/`Release`/`SeqCst`), **재진입 조건** 같은 것들은 **전역 추론**이 필요하다. 모델은 슬라이스를 본다.
또한 **테스트로 잡히지 않는다**. race condition은 본질적으로 비결정적이고, 단위 테스트는 대부분 결정적인 케이스만 친다. ThreadSanitizer, loom, jepsen 같은 도구가 필요한데, 에이전트는 이런 도구를 능숙하게 다루지 못한다.
사람이 계속 해야 할 일
- **동시성 코드는 항상 사람의 두 번째 눈으로.** PR에 "concurrency: review needed" 라벨을 박아라.
- **모델 체커를 써라.** TLA+, loom, Coq — 동시성 정확성에 대한 진짜 보장은 여전히 형식 검증.
- **에이전트에게는 "interleaving을 따져봐라"고 명시.** 에이전트는 묻지 않으면 안 한다.
한 줄 코멘트로 lock order 강제
// LOCK_ORDER: always (config -> session) — see SECURITY.md L42
let _c = config.lock();
let _s = session.lock();
이런 명시 코멘트가 두 곳에서 같은 순서를 강제하는 도구가 된다. 에이전트는 "맥락 표시 코멘트"를 잘 따른다. 단, 코멘트를 쓰는 것은 사람의 몫이다.
5장 · 모호함 속의 판단 — "팀이 어떤 트레이드오프를 선호하나"
패턴
"이 API의 에러 처리를 추가하라." 에이전트는 깔끔한 `Result` 기반 에러 처리를 추가한다. 그런데 이 팀은 **panic-on-invariant-violation**이 컨벤션이었다. 또 다른 팀은 **OpenTelemetry**로 에러를 보내는 게 컨벤션이었다. 에이전트는 "옳은" 답을 모른다 — **답은 팀의 선택에 달려 있기 때문**이다.
왜 그런가
소프트웨어 엔지니어링의 큰 부분은 **취향과 트레이드오프**다. "어떤 패러다임을 쓸까", "여기까지가 적절한 추상화 수준일까", "이 latency 50ms를 코드 가독성 30% 향상과 바꿀 가치가 있을까". 이 질문들에는 **컨텍스트 외부의 정보**가 필요하다 — 팀의 가치관, 회사의 우선순위, 사용자의 통증점.
에이전트는 이걸 **추측한다**. 좋은 추측을 한다. 그러나 추측은 추측이다.
사람이 계속 해야 할 일
- **"선호도" 문서를 만들어라.** AGENTS.md에 "에러 처리는 panic이 아니라 Result", "로깅은 structured", "비동기는 채널 기반" 같은 것을 박아라.
- **에이전트에게 "어떤 트레이드오프가 있냐"고 묻게 하라.** 모호하면 묻게 해라. 에이전트는 묻지 않으면 추측한다.
- **PR 단계에서 "팀 컨벤션 일치"를 명시적으로 본다.** 자동화에 맡기지 마라.
6장 · 진짜 새로운 기술 — "훈련 컷오프 편향, 새 문서를 줘도 옛 패턴으로 회귀한다"
패턴
2026년 초에 나온 라이브러리(가령 `Effect-TS` 3.x, `React 19.5`의 new concurrent features, `Next.js 16`의 PPR 안정화)에 대해 새 문서를 컨텍스트에 통째로 넣어준다. 에이전트는 처음엔 새 API를 잘 쓴다. 그러다 200 토큰쯤 지나면 **2024년 패턴**으로 회귀한다 — `useEffect` 패턴을 새 동시성 hook 위에 얹는다든가, 새 API의 시그니처가 기억나지 않아 옛 시그니처로 호출한다든가.
왜 그런가
LLM은 **훈련 데이터에서 본 빈도**에 강하게 영향받는다. 새 라이브러리의 문서는 토큰 수십 K에 불과한 반면, 옛 라이브러리는 모델 가중치에 깊이 박혀 있다. **컨텍스트의 정보는 가중치의 prior를 완전히 덮지 못한다.**
이건 RAG로도 잘 안 풀린다. 검색해서 새 문서를 줘도, 모델은 일관성 있게 새 패턴을 따르는 게 아니라 — 새 시그니처 + 옛 패턴이라는 **혼합 hallucination**을 만든다.
사람이 계속 해야 할 일
- **새 라이브러리는 직접 손으로 한 번 짜라.** 에이전트에게 넘기기 전에 본인이 패턴을 익혀라. 그러면 에이전트의 회귀를 알아챌 수 있다.
- **에이전트 코드에 "버전 강제" 어설션을 박아라.** lint 룰, 타입 검사. "옛 API 호출은 컴파일 에러"가 되도록.
- **에이전트가 옛 패턴으로 회귀할 때마다 명시적으로 정정하라.** 한 세션 안에서 반복 정정은 효과가 있다.
검증된 회귀 신호
새 라이브러리 작업 중 다음을 보면 회귀를 의심해라:
- import 경로가 옛 path로 슬며시 돌아간다 (`react/jsx-runtime`이 아니라 `react`).
- 새 hook 안에서 옛 hook의 mental model이 보인다.
- 에러 메시지가 옛 버전의 시그니처와 일치하지 않는다 (이건 옛 API를 가정한 try/catch라는 뜻).
이 셋 중 하나라도 보이면 새 세션을 시작하고 새 docs를 더 강한 어조로 주입.
7장 · 멀티 레포 cross-cutting 변경 — "여전히 어렵다"
패턴
40개의 마이크로서비스에서 같은 변경(예: deprecated SDK 1.x → 2.x)을 해야 한다. 에이전트는 한 레포는 잘 한다. 두 번째 레포도 잘 한다. 다섯 번째 레포에서 **각 레포가 가진 미묘한 차이**(테스트 러너 차이, 빌드 시스템 차이, 의존성 버전 차이)를 못 잡는다. PR을 40개 열지만, 그 중 12개가 빌드 깨진 채로 올라간다.
왜 그런가
각 레포는 자체의 **숨겨진 컨텍스트**가 있다. 멀티 레포 변경은 본질적으로 **N개의 컨텍스트**를 다루는 것인데, LLM의 컨텍스트 윈도우는 하나다. 에이전트는 한 레포의 결정을 다른 레포에 일반화하려 한다 — 그게 안 되는 부분에서 실패한다.
또한 멀티 레포는 **의존성 그래프**다. A를 바꾸려면 B를 먼저 배포해야 하고, 그러려면 C가 호환되어야 한다. 이 그래프 추론은 단일 컨텍스트에서 잘 안 된다.
사람이 계속 해야 할 일
- **한 레포에서 패턴을 정착시킨 다음 다른 레포로 확장하라.** 첫 5개는 사람이 직접, 나머지는 에이전트 + 인간 검토.
- **공통 변경은 codemod로 만들어라.** AST 변환 + AI 검토가 순수 AI보다 안정적이다.
- **배포 순서**는 사람이 진다. 에이전트는 의존성 그래프 추론에 약하다.
8장 · 보안 크리티컬 코드 — "맞아 보이는데, 미묘한 결함이 있다"
패턴
에이전트가 비밀번호 해싱 함수를 짠다. `bcrypt`를 쓰고, salt는 random에서 가져온다. 보기엔 정석이다. 그런데 **타이밍 공격에 취약한 비교** (`==` 대신 `constant_time_eq`을 써야 함), **salt rounds가 cost factor 8** (2026 기준 10~12 권장), **에러 메시지가 username을 echo한다** (timing leak). 모두 미묘하고, 코드 리뷰에서 못 잡을 수 있다.
왜 그런가
보안은 **negative space**의 학문이다 — "있어야 할 것이 없으면 보안 결함". LLM은 "있는 것"을 보고 추론한다. "없는 것"을 잡으려면 보안 mental model이 필요하다. 에이전트의 mental model은 평균이지, 전문가 수준이 아니다.
또한 보안 vulnerability는 **느린 발견**이다. 6개월 뒤 침해 사고가 나서야 보인다. 그 시점엔 에이전트는 다른 일을 하고 있다.
사람이 계속 해야 할 일
- **보안 크리티컬 코드는 보안 전문가 리뷰가 필수.** AI 리뷰는 보조.
- **자동화 도구**(`semgrep`, `bandit`, `gosec`, `cargo-audit`)를 강제하라. AI보다 결정적이다.
- **AGENTS.md에 "보안 위험" 섹션**을 명시. "이 디렉터리의 코드는 항상 인간 보안 리뷰"라고 박아라.
자주 놓치는 negative space 목록
에이전트 코드 보안 리뷰에서 우리가 체크하는 항목:
- timing-safe 비교가 쓰였는가
- 비밀 키가 로그에 들어갈 수 있는가
- 에러 응답이 timing oracle을 만드는가
- rate limit이 모든 path에 걸렸는가
- input validation이 sanitization 직전이 아니라 직후에 있는가
- CSRF/CORS가 명시적으로 설정됐는가 (defaults 의존이 아니라)
이 6가지를 PR 템플릿에 박으면 보안 회귀의 80%는 잡힌다. 나머지 20%가 전문가 리뷰의 영역이다.
9장 · 레거시 코드 — "코드가 '아는' 것을 코드가 '말하지' 않는다"
패턴
15년 된 모놀리스의 한 함수가 이상하게 생겼다. 변수 이름은 `magic_offset_42`다. 에이전트는 "이건 정리해야 한다"고 판단하고 리팩터링한다. 배포한다. 한 달 뒤, 오래된 데이터 마이그레이션 파이프라인이 죽는다. 보니까 `magic_offset_42`는 2012년의 데이터베이스 마이그레이션 사고에서 생긴 **off-by-one 보정**이었다. 코드는 그걸 안 적었다. 그러나 **코드는 그걸 알았다**.
왜 그런가
레거시 코드는 **암묵적 지식의 압축**이다. 코드가 그런 모양인 이유는 종종 코드 자체에 안 적혀 있다 — 슬랙 채널의 어딘가, 떠난 엔지니어의 머릿속, 5년 전의 사고 보고서에 적혀 있다. LLM은 **코드만 본다**.
이건 RAG로도 해결 안 된다. 사고 보고서가 검색되어도, 그게 이 코드 라인과 연결되어야 한다는 걸 모델이 알아내야 하는데 — 그 연결이 종종 안 일어난다.
사람이 계속 해야 할 일
- **레거시 코드에는 "리팩터링 금지" 마커를 박아라.** 주석으로, 또는 별도 파일로.
- **`git blame` + 변경 히스토리**를 에이전트에게 강제 주입. "이 줄을 왜 이렇게 짰는지 알려면 커밋 history를 봐라".
- **레거시 코드 변경은 항상 사람이 한 번 본다.** 자동 리팩터링은 위험.
10장 · 긴 세션의 prompt drift — "에이전트가 천천히 줄을 놓는다"
패턴
8시간짜리 에이전트 세션. 처음 1시간은 흠 잡을 데 없다. 4시간쯤 지나면 코드 스타일이 **이상해진다** — 변수 이름 컨벤션이 조금 바뀌고, 에러 처리 패턴이 살짝 다르고, 주석이 점점 줄어든다. 7시간쯤에는 처음의 지시사항을 **잊은 것처럼** 행동한다.
왜 그런가
컨텍스트가 길어질수록 모델은 **초반의 instructions**보다 **최근의 도구 결과**에 더 가중치를 둔다. 이게 본질적인 **attention dilution**이다. 또한 자동 컨텍스트 압축(summarization)을 쓰면, 압축 과정에서 미묘한 정보가 사라진다. 결과적으로 모델은 **자신이 누구인지** 천천히 잊는다.
이건 모델 크기로 완전히 안 풀린다. 200K, 1M, 10M 컨텍스트가 와도 — **상대적 attention**은 그대로다.
사람이 계속 해야 할 일
- **세션을 짧게 유지하라.** 큰 작업은 여러 세션으로 쪼개라. 각 세션은 명확한 input과 output을 갖게.
- **AGENTS.md를 매번 다시 주입.** 시스템 프롬프트가 있더라도, 중요한 컨벤션은 명시적으로 다시 말해라.
- **drift를 보면 새 세션을 시작하라.** 미련 갖지 마라. 컨텍스트 리셋이 가장 강력한 도구다.
drift를 측정하는 한 줄 휴리스틱
세션 시작 시점에 "이 작업의 3가지 핵심 규칙을 한 줄로 말하라"고 묻고 답을 메모해 둔다. 4시간 뒤 같은 질문을 다시 던진다. 답이 달라지면 drift다. 답이 같아도 코드 스타일이 달라지면 부분 drift다. 어떤 경우든 새 세션을 시작.
11장 · 그래서 AI는 무엇을 잘 하는가 (대조군)
이 글은 AI 부정이 아니다. AI가 **분명히 multiplier**인 영역을 명시해야 공정하다.
AI가 빛나는 작업
- **부트스트랩** — 새 프로젝트 scaffold, 보일러플레이트, 익숙한 패턴의 첫 100줄.
- **잘 정의된 단일 작업** — "이 함수를 TypeScript로 변환", "이 SQL을 ORM 코드로", "이 테스트의 빠진 케이스 추가".
- **읽기·요약·설명** — 1000줄 파일을 200줄로 요약, 빌드 로그에서 진짜 에러 찾기, PR 변경의 의도 설명.
- **반복적인 마이그레이션 (잘 정의된)** — 일관된 codemod로 표현 가능한 변경.
- **테스트 작성** — 특히 input/output 형태가 명확한 unit test.
- **문서 생성** — 코드에서 docstring, README 초안, API 명세.
- **익숙한 디버깅** — null pointer, off-by-one, 흔한 트랜잭션 누락 같은 패턴 인지.
이 영역들에서 AI는 **3x~10x** multiplier다. 부정할 이유 없다.
AI가 인간보다 빠른 영역
- **타이핑 자체** — 키보드 입력은 무조건 더 빠르다.
- **API surface 외우기** — 인간이 매뉴얼을 뒤지는 시간을 0으로.
- **포맷 변환** — JSON ↔ YAML, schema ↔ TypeScript, REST ↔ GraphQL.
- **번역** — 자연어, 코드 언어 간 모두.
12장 · "AI가 빛나는 영역" vs "인간이 곱하는 영역" 매트릭스
| 작업 유형 | AI 단독 | AI + 인간 (인간 multiplier) |
|----|----|----|
| 보일러플레이트, scaffold | 강력 | 인간 검토 마지막 5분 |
| 잘 정의된 함수 작성 | 강력 | 인간이 함수 시그니처 정의 |
| 단위 테스트 | 강력 | 인간이 edge case 후보 제시 |
| 코드 요약·설명 | 강력 | 인간 없어도 OK |
| 익숙한 디버깅 | 양호 | 인간이 가설 다양화 강제 |
| 깊은 버그 디버깅 | 약함 | **인간이 가설 터널링 깨야 함** |
| 작은 리팩터링 | 양호 | 인간이 범위 한정 |
| 대규모 아키텍처 | 약함 | **인간이 큰 그림 소유** |
| 성능 회귀 잡기 | 약함 | **인간이 프로파일링 결과 해석** |
| 동시성 코드 | 위험 | **인간 + 형식 검증** |
| 보안 코드 | 위험 | **인간 보안 전문가 + 자동 도구** |
| 레거시 변경 | 위험 | **인간이 암묵 가정 알려줘야** |
| 새 라이브러리 | 회귀 위험 | **인간이 패턴 직접 짜본 뒤 위임** |
| 멀티 레포 변경 | 일관성 깨짐 | **인간이 codemod 작성 + 검토** |
| 모호한 트레이드오프 | 추측 | **인간이 팀 선호 알려줘야** |
| 긴 세션 작업 | drift | **세션 쪼개기 (인간 결정)** |
이 매트릭스가 메시지다. **"AI를 쓸까 말까"**가 아니라 **"이 작업의 어디서 인간이 multiplier인가"**를 묻는 것.
13장 · 안티패턴 — 자주 보는 잘못
안티패턴 1: "에이전트가 8시간 째 한 가설을 쫓고 있는데 그냥 둔다"
→ 멈추고 가설을 의심하라. 인간 디버거의 첫 룰.
안티패턴 2: "AI가 짠 보안 코드를 사람이 보지 않는다"
→ 보안은 negative space. 자동 도구 + 전문가 리뷰가 비협상.
안티패턴 3: "큰 코드베이스에서 'feature X를 추가하라'고 한 줄 지시한다"
→ 에이전트는 단면을 본다. 비슷한 게 있는지 먼저 검색하라고 강제.
안티패턴 4: "에이전트 성능 회귀를 CI 없이 믿는다"
→ 회귀는 결정적 측정으로 잡아야 한다. AI 측정은 보조.
안티패턴 5: "긴 세션을 그냥 둔다"
→ 4시간 넘으면 drift를 가정. 세션을 쪼개라.
안티패턴 6: "새 라이브러리에 대해 RAG만 믿는다"
→ RAG는 weight prior를 덮지 못한다. 본인이 한 번 짜본 뒤 위임.
안티패턴 7: "레거시 코드 리팩터링을 에이전트에게 통째로 위임"
→ 레거시는 암묵 지식. 인간 리뷰가 필수.
안티패턴 8: "에이전트가 짠 동시성 코드를 단위 테스트로만 검증"
→ Race는 단위 테스트로 안 잡힌다. ThreadSanitizer, loom.
안티패턴 9: "팀 컨벤션을 AGENTS.md에 안 적는다"
→ 에이전트는 모르면 추측한다. 명시화가 multiplier.
안티패턴 10: "AI 결과를 PR 자동 merge로 푼다"
→ 인간 리뷰가 마지막 안전망. 자동 merge는 신뢰가 너무 비싸다.
14장 · 개발자 체크리스트 (calibration 도구)
작업을 시작하기 전:
- [ ] 이 작업의 **실패 모드**가 위 10가지 중 몇에 해당하는가?
- [ ] 인간 검토가 필요한 단계는 어디인가? (PR? 디자인? 머지 전?)
- [ ] 자동화 안전망(CI, lint, SAST)이 박혀 있는가?
- [ ] AGENTS.md에 팀 컨벤션이 명시되어 있는가?
- [ ] 새 라이브러리/API가 포함된다면 — 본인이 패턴을 한 번 짜봤는가?
- [ ] 멀티 레포 변경이라면 — 첫 1~2개는 직접 하는가?
- [ ] 보안/동시성/성능 크리티컬 부분이 포함되는가? 전문가 리뷰 일정이 있는가?
작업 중:
- [ ] 같은 가설을 4시간 이상 쫓고 있지 않은가?
- [ ] 세션 길이가 4시간을 넘었는가? drift 점검.
- [ ] 에이전트가 "옛 API 패턴"으로 회귀하지 않는가?
작업 후:
- [ ] 결과를 인간이 한 번 읽었는가?
- [ ] 성능 회귀 테스트, 보안 스캔이 돌았는가?
- [ ] 멀티 레포라면 — 각 레포의 빌드가 다 통과했는가?
에필로그 — multiplier로서의 개발자
다시 말하지만, 이 글은 AI 회의론이 아니다.
> **AI 코딩 어시스턴트는 진짜 multiplier다.** 그러나 multiplier는 **0이 아닌 값에 곱해질 때만 의미가 있다.** 그 "0이 아닌 값"이 당신의 판단이다.
판단이 0이면 — 즉, 작업을 100% 에이전트에 넘기고 결과를 검토하지 않으면 — 어떤 multiplier도 0을 곱하면 0이다. 가끔은 음수다. (에이전트가 어렵게 잘못한 코드를 정리하는 게 처음부터 짜는 것보다 오래 걸린다.)
판단이 1이면 — 즉, 위 10가지 실패 모드를 알고, 적절히 안전망을 설치하고, 가설 터널링을 깨고, 세션을 쪼개고, 보안/동시성/성능을 적절히 사람에게 넘기면 — 그때 비로소 AI는 진짜 multiplier가 된다.
> 2026년 mid의 개발자에게 가장 중요한 스킬은 **AI를 의심하는 능력**이 아니라, **AI의 신뢰 구간을 정확히 추정하는 능력**이다.
AI 코딩 어시스턴트의 능력은 폭발적으로 좋아진다. 그러나 위 10가지 실패 모드 중 일부는 **모델 크기로 해결되지 않을** 것이다. 가설 터널링, 암묵 지식, 팀 선호, 보안의 negative space — 이것들은 **사람의 컨텍스트**가 필요하다. 그 컨텍스트는 한동안 사람의 머리에만 있을 것이다.
당신의 일은 줄어들지 않는다. **모양이 바뀐다.** 코드를 타이핑하는 시간이 줄고, **무엇을 신뢰할지 결정하는 시간**이 늘어난다. 그게 multiplier로서의 개발자의 모양이다.
다음 글 예고
- **"AI 코드의 PR 리뷰 — 인간 리뷰어가 봐야 할 7가지 시그널"** — AI 코드는 어디서 의심스러운가, 어떤 패턴이 "통과 후 사고"로 이어지는가, PR 리뷰 체크리스트.
- **"AGENTS.md 작성법 — 팀 컨벤션을 에이전트에게 가르치기"** — 실제 working AGENTS.md 예시, 어떤 정보가 효과 있고 어떤 게 노이즈인가.
참고 / References
벤치마크와 평가
- SWE-bench Verified leaderboard — [https://www.swebench.com/](https://www.swebench.com/) (에이전트 성능 ceiling 추적)
- OSWorld benchmark — [https://os-world.github.io/](https://os-world.github.io/) (데스크탑 환경 작업의 한계)
- MLE-bench — [https://github.com/openai/mle-bench](https://github.com/openai/mle-bench) (ML 엔지니어링 작업의 에이전트 평가)
- HumanEval과 LiveCodeBench — 단순 함수 작성 능력과 실제 엔지니어링 능력의 갭
Context rot, hypothesis tunneling, attention dilution
- "Lost in the Middle" — Liu et al., 2023, 긴 컨텍스트의 attention dilution을 처음으로 정량화한 논문
- "Context Rot" — Anthropic, Claude 4 시리즈의 long-context degradation 분석
- "Confirmation Bias in LLM-based Agents" — 최근 평가 연구들에서 반복 보고되는 패턴
동시성과 보안의 LLM 한계
- "LLMs and Concurrency: A Survey" — 2025년 연구, formal verification이 여전히 필요한 이유
- "Security Implications of Code Generated by LLMs" — Pearce et al., 2025년 업데이트, common CWE에서의 빈도
실용 가이드와 의견
- Simon Willison's blog — [https://simonwillison.net/](https://simonwillison.net/) — calibrated take의 모범
- "When AI Coding Assistants Fail" — 다양한 엔지니어링 블로그의 실패 사례 모음
- Anthropic's "Best practices for agentic coding" — 공식 가이드, 실패 모드를 명시
도구
- Claude Code, Cursor, Codex CLI — 본문 언급
- semgrep, gosec, bandit — 보안 자동화 도구 (AI 보조용)
- ThreadSanitizer, loom — 동시성 검증 도구
- TLA+ — 형식 검증
> **TL;DR** — AI 코딩 어시스턴트는 강력하지만 균일하지 않다. 깊은 디버깅·아키텍처·성능 회귀·동시성·보안·레거시·모호함·새 기술·멀티 레포·긴 세션 — 이 10가지 영역에서 인간 판단은 여전히 multiplier다. AI를 회의하지 마라. AI의 신뢰 구간을 정확히 추정하라. 그것이 2026년 mid의 개발자의 가장 가치 있는 스킬이다.
현재 단락 (1/183)
지난 18개월 동안의 AI 코딩 콘텐츠는 대부분 **세 가지 모드** 중 하나였다.