6개월 동안 운영 중인 ERP의 코드 리뷰에 AI를 사용해 보았습니다. 실제로 실패했던 지점은 다음과 같습니다.
요약
실제 운영 중인 ERP 시스템의 코드 리뷰에 AI를 6개월간 도입하여 얻은 실무적인 경험담입니다. AI는 중복 코드, 계산 버그, React 상태 변이 탐지에는 탁월한 성능을 보였으나, 경쟁 상태(Race conditions), 메모리 누수, 복잡한 CSS 레이아웃 문제와 같은 동적이고 실행 경로가 복잡한 오류는 잡아내지 못했습니다.
핵심 포인트
- AI는 중복 함수, 독립된 유틸리티 내 계산 오류, React의 직접적인 상태 변이 탐지에 매우 효과적임
- 비동기 작업 간의 경쟁 상태(Race conditions)는 AI의 정적 분석 능력으로는 탐지하기 어려움
- 모든 실행 경로를 고려해야 하는 메모리 누수(Memory leaks) 문제는 AI가 놓칠 가능성이 높음
- AI 리뷰는 컴파일 전 1차 검토 단계로 활용하는 것이 적절하며, 복잡한 런타임 이슈는 인간의 검토가 필수적임
6개월 전, 저는 배포되기 전의 모든 사소하지 않은 코드 조각들을 AI를 통해 검토하기 시작했습니다. 프로토타입이 아닙니다. 반대편에 유료 고객이 있는 실제 ERP 및 CRM 모듈들이었습니다. 배치 처리 (Batch processing) 테이블, MRP 할당 로직, 동적 인보이스 빌더, 실시간 대시보드 등이 대상이었습니다. 제가 발견한 사실은 다음과 같습니다.
AI가 실제로 잘하는 것
중복 함수 (Duplicate functions). 수개월 동안 여러 개발자가 손을 댄 코드베이스에서 이것은 AI의 가장 확실한 승리입니다. AI는 다음과 같은 것들을 찾아냈습니다: "이것은 utils/formatters.ts의 formatCurrency를 미러링합니다" — 이런 종류의 사항은 모두가 다른 누군가가 이미 확인했을 것이라고 가정하기 때문에 인간의 리뷰에서 놓치기 쉽습니다.
독립된 유틸리티 내의 계산 버그 (Calculation bugs). Off-by-one 에러, 잘못된 연산자 우선순위, 잘못된 단위 변환 — 함수가 격리되어 있고 외부 상태 (External state)에 의존하지 않는다면, AI는 이러한 것들을 일관되게 잡아냅니다. ERP 시스템에서 잘못된 도착 원가 (Landed cost) 공식이나 세금 계산은 즉각적인 고객 신뢰 손상으로 이어집니다. AI는 여기서 저를 여러 번 구해주었습니다.
직접적인 React 상태 변이 (Direct React state mutations). 배열에 직접 푸시하거나, 스프레드 연산자 (Spread operator) 없이 중첩된 객체를 변이시키는 행위 — AI는 단순한 컴포넌트에서 이러한 사항들을 안정적으로 찾아냅니다. 획기적이진 않지만, 컴파일 전 첫 번째 검토 단계로서 유용합니다.
AI가 완전히 실패한 지점
경쟁 상태 (Race conditions). 이것은 지난 6개월 동안 제가 겪은 가장 고통스러운 운영 버그였습니다. 우리의 배치 아이템 테이블은 빠른 동시 변이 (Concurrent mutations)를 허용합니다. 사용자가 연쇄적인 계산을 트리거하면, 여러 개의 비동기 상태 업데이트 (Async state updates)가 겹치게 되고, 하나의 오버라이드가 조용히 승리하게 됩니다. 전형적인 경쟁 상태입니다. 저는 당시 사용하던 모든 AI 도구에 해당 컴포넌트를 돌려보았습니다. 경고가 단 하나도 없었습니다. "이 부분을 확인해 볼 가치가 있을지도 모릅니다"라는 말조차 없었습니다. 이 버그는 고객이 특정 상호작용 시퀀스를 매우 빠른 속도로 연속해서 실행했을 때만 나타났습니다. AI는 정적 분석 (Static analysis)을 수행합니다. 불규칙한 사용자 상호작용 타이밍을 시뮬레이션할 수는 없습니다. 경쟁 상태는 AI에게 보이지 않습니다.
Web Worker 메모리 누수 (Web Worker memory leaks). 저는 무거운 클라이언트 측 계산을 위해 워커 (Workers)를 구현했습니다.
빠른 이벤트 기반 생성 (event-driven spawning)으로 인한 잠재적 누수가 의심되어, 제가 사용하는 AI 스택 전체에 정리 (cleanup) 패턴을 감사하도록 과제를 부여했습니다. 모든 도구가 자신 있게 '통과 (green pass)' 판정을 내렸습니다. 하지만 제가 수동으로 브라우저 프로파일링 (browser profiling)을 수행한 결과, 특정 런타임 예외 (runtime exceptions) 상황에서 워커 (workers)가 안정적으로 종료되지 않는 것을 발견했습니다. 유령 프로세스 (Ghost processes)들이 살아있는 상태였습니다. AI는 정리 (cleanup) 코드가 존재한다는 사실은 확인했습니다. 하지만 그 정리 코드가 모든 실행 경로 (execution path)에서 실제로 실행되는지는 확인하지 못했습니다.
커스텀 컴포넌트의 CSS 레이아웃 버그 (CSS layout bugs). 엄격한 UX 요구 사항을 충족하기 위해 자체적인 데이터 그리드 (data grid)를 처음부터 구축했습니다. 특정 데이터 페이로드 (data payloads) 상황에서 패딩 불일치 (padding misalignments)와 레이아웃 붕괴 (layout collapse) 현상이 발생했습니다. AI는 거의 쓸모가 없었습니다. 제가 시각적 버그를 설명하면 AI는 수정할 수 있다고 주장했지만, 렌더링된 결과물은 여전히 깨져 있었습니다. 실제 렌더링 환경 (rendering environment) 없이는 AI가 캐스케이드 (cascade) 동작을 추측할 뿐이기 때문입니다.
아무도 말하지 않는 사실: 청킹 (chunking). 이것이 제가 얻은 가장 큰 운영상의 발견이었습니다. 저는 수백 개의 행에 걸쳐 수량, 공급 제약, 이행 우선순위가 계층적으로 이어지는 MRP 할당 테이블 (MRP allocation table)을 구축하고 있었습니다. 저는 전체 사양 (spec)을 한 번에 AI에 입력했습니다. 모든 도구가 실패했습니다. 단순히 '약간 틀린' 수준이 아니라, 실행 과정을 추적하기 전까지는 올바르게 보이지만 논리적으로는 확신을 가지고 틀린 결과를 내놓았습니다. 깨진 의존성 (dependencies), 잘못 할당된 수량, 특정 엣지 케이스 (edge cases)에서 조용히 실패하는 상태 업데이트 (state updates) 등이 나타났습니다.
그래서 저는 이를 나누었습니다:
- 프롬프트 하나 — 핵심 할당 수학 (allocation math)만 담당
- 프롬프트 하나 — 데이터 유효성 검사 제약 조건 (data validation constraints)만 담당
- 프롬프트 하나 — 불변 (immutable) React 상태 업데이트 패턴만 담당
- 마지막 프롬프트 — 각 모듈을 다른 모듈과 대조하여 감사
모든 조각이 깨끗하게 통과되었습니다. 조립된 시스템은 운영 환경 (production)에서 완벽하게 작동했습니다.
사고 모델의 전환: AI는 토큰 길이 (token length)가 아니라 복합적인 논리적 의존성 (compound logical dependencies) 하에서 성능이 저하됩니다. ERP 모듈은 중첩된 유효성 검사 경로, 세금 계산, 데이터베이스 상태 요구 사항을 가지고 있습니다. 이 모든 것을 동시에 입력하는 것은 모델의 상황적 논리 (situational logic)에 과부하를 줍니다. 만약 당신이 작업 범위를 시니어 개발자에게 2분 안에 말로 설명할 수 없다면, LLM에 전달하기 전에 반드시 청킹 (chunk) 하십시오.
신뢰성 문제: 이 부분이 실제로 제가 우려하는 지점입니다. 제 Web Worker (웹 워커)에서 메모리 누수 (memory leak)가 발생했을 때, 어떤 도구도 "이 구문은 유효해 보이지만, 런타임 (runtime) 정리 동작은 확인할 수 없습니다. 수동으로 프로파일링 (profile) 하십시오"라고 말하지 않았습니다. 그들은 괜찮아 보인다고 했습니다. 깨끗하게 통과되었습니다. 그대로 배포하십시오. 제가 정립한 프레임워크는 다음과 같습니다: AI의 버그 플래그 (bug flag)는 신호가 높으므로 즉시 조치하십시오. AI의 통과 (clean pass)는 약한 증거입니다. 이는 코드가 안전하다는 뜻이 아니라, 눈에 띄는 패턴이 일치하지 않았음을 의미할 뿐입니다. 마감 기한의 함정은 실재합니다. 스프린트 (sprint)를 맞추기 위해 몰아붙일 때, "AI가 괜찮다고 했어"라는 말이 실제 테스트를 대신하는 대체재가 됩니다. 바로 그 지점에서 운영 환경의 회귀 (regression)가 발생합니다.
6개월 후의 실제 도구 스택:
Codeium — 단일 파일 작업용 인라인 자동 완성 (inline autocomplete). 파일 간 추론 (cross-file reasoning) 단계에서는 빠르게 한계에 부딪힙니다.
ChatGPT — 고립된 로직 감사 (logic audit)에는 유용하지만, 스니펫 (snippet) 출력 방식은 대규모 작업 시 통합 마찰 (integration friction)을 일으킵니다.
Cursor (Claude Sonnet) — 리팩터링 (refactoring)을 위한 주력 도구. 전체 파일 편집 컨텍스트 (full-file editing context)는 그 어떤 채팅 인터페이스보다 진정으로 뛰어납니다.
Google Gemini Code Assist — 주요 일상적 도구. 거대한 컨텍스트 윈도우 (context window)를 가졌으며, 무거운 ERP 작업에 비용 효율적입니다.
Claude 직접 사용 — 아키텍처 감사 (architectural audit) 및 상위 수준의 로직 설계. 맹목적인 통과 대신 주의 사항과 함께 문제를 지적해 주는 데 가장 적극적입니다.
OpenAI Codex App — PR (Pull Request) 전 단계의 저장소 전체 감사. 샌드박스화된 워크트리 (worktree) 내에서 병렬 에이전트 (parallel agents)를 실행합니다. 내 로컬 환경을 건드리지 않고 작동합니다.
각 도구는 별도의 단계를 수행합니다. 도구 사이를 전환하는 것은 단순한 도구 갈아타기가 아니라, 작업에 적합한 올바른 도구를 사용하는 것입니다.
빠른 참조
AI를 신뢰할 수 있는 경우:
- 명확한 I/O를 가진 50줄 미만의 유틸리티 함수 (Utility functions)
- 대규모 리포지토리 (Repos) 전반의 중복/불필요한 모듈 탐지
- 검증된 안전한 로직을 더 깔끔한 패턴으로 리팩터링 (Refactoring)
- 상용구 (Boilerplate) 성격의 React hooks, contexts, 기본 reducers
수동으로 검증해야 하는 경우:
- 빠른 사용자 상호작용이 발생하는 다계층 상태 기반 컴포넌트 (Multi-tiered stateful components)
- Web Workers, Sockets, 비동기 라이프사이클 관리 (Async lifecycle management)
- 커스텀 시각적 컴포넌트 (라이브러리 미사용)
- 핵심 금융/결제 계산 로직
- 동료에게 2분 안에 설명할 수 없는 모든 것
전송 전 나누어야 하는 청크 (Chunk):
- 상호작용하는 2개 이상의 서브시스템 (Subsystems)에 걸친 기능
- 연쇄적인 상태 변화가 발생하는 전체 ERP 모듈 (MRP, 재고 할당 등)
- 제약 조건을 정의하는 데만 여러 단락이 필요한 모든 프롬프트 (Prompt)
AI를 가장 잘 활용하는 엔지니어는 AI를 맹목적으로 신뢰하는 사람들이 아닙니다. 그들은 그 신뢰가 어디서 멈춰야 하는지를 정확히 아는 사람들입니다.
전체 MRP 사례 연구, 도구별 상세 노트, 그리고 실무 체크리스트가 포함된 전체 분석 내용은 여기에서 확인하세요 → stacknovahq.com
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기