AI 에이전트로 실제 앱을 구축해 보았다 — 장점, 단점, 그리고 환각(Hallucination)
요약
실제 복잡한 SaaS 앱 구축 과정에서 AI 코딩 에이전트를 사용하며 겪은 경험을 다룹니다. 데모와 실제 프로덕션 환경 사이의 기술적 간극과 환각 현상을 분석합니다.
핵심 포인트
- 단순 데모와 실제 프로덕션 앱 구축 사이에는 큰 기술적 격차가 존재함
- 인증, 결제, DB 등 복잡한 멀티 서비스 환경에서의 에이전트 활용 한계
- Claude Code, GitHub Copilot, Cursor 등 다양한 에이전트 스택 경험
누군가가 AI 에이전트에 "SaaS 앱을 만들어줘"라고 입력하자 30초 만에 완전히 작동하는 제품이 튀어나오는 데모 영상을 볼 때의 그 기분을 아시나요? 네, 저도 속았습니다. 약 일주일 동안은 말이죠.
그 후 저는 실제로 AI 코딩 에이전트(AI coding agents)를 사용하여 실제 프로젝트에 적용해 보았습니다. 단순한 Todo 앱이나 카운터 컴포넌트가 아니라, 인증(auth), 결제(payments), 데이터베이스(database)를 갖춘 실제 멀티 서비스 앱이었습니다. 그리고 말씀드리자면, "데모"와 "프로덕션(production)" 사이의 간극은 그랜드 캐니언만큼이나 큽니다.
제가 2주 동안 AI 에이전트에게 개발을 맡겼을 때 실제로 어떤 일이 일어났는지 알려드리겠습니다.
AI 생성 일러스트레이션: 로봇 뇌 신경망 디지털 아트 섹션
AI 생성 일러스트레이션: 로봇 뇌 신경망 디지털 아트 섹션
설정 (The Setup)
저는 프리랜서와 클라이언트를 연결하는 플랫폼을 구축하고 있습니다. 꽤 일반적인 내용이죠. Next.js 16 프론트엔드, Node.js 백엔드, PostgreSQL, 캐싱을 위한 Redis, 결제를 위한 Stripe를 사용합니다. 엄청난 것은 아니지만, 단일 개발자가 모든 것을 연결하는 데 몇 주가 걸릴 만큼 충분한 구성 요소들이 움직이고 있습니다.
제가 사용한 에이전트 스택은 다음과 같습니다:
- Claude Code (터미널 에이전트 — Anthropic의 CLI)
- GitHub Copilot Agent Mode (VS Code 내에서)
- Cursor Agent (Composer/Agent 모드)
- OpenAI Codex CLI (새로 등장한 신예)
저는 각 에이전트를 동일한 작업 세트에 실행하고 결과를 비교했습니다. 과학적인 실험실 테스트는 아니었으며, 그저 실제 상황에서의 "이 기능을 만들 수 있는가?"라는 느낌을 확인한 것이었습니다.
장점 — 실제로 작동했던 것들 (The Good — What Actually Worked)
보일러플레이트 생성 (Boilerplate Generation)은 기본적으로 해결됨
모든 에이전트가 CRUD 생성을 매우 능숙하게 처리했습니다. 저는 각 에이전트에게 새로운 "projects" 기능 — 데이터베이스 스키마 (database schema), API 라우트 (API routes), TypeScript 타입 (TypeScript types), 그리고 기본적인 UI를 만들어 달라고 요청했습니다. 네 가지 에이전트 모두 첫 시도에 컴파일되는 작동 가능한 코드를 반환했습니다.
이 부분에서 Claude Code가 가장 빨랐으며, 약 90초 만에 6개 파일에 걸쳐 약 400줄의 코드를 생성했습니다. Cursor가 2분으로 근소한 차이로 2위를 차지했습니다. Copilot Agent는 약 3분이 걸렸지만 상세한 에러 핸들링 (error handling)을 포함했습니다. Codex CLI는 견고한 코드를 생성했지만, 제 프로젝트의 기존 패턴과 일치시키기 위해 두 번째 작업이 필요했습니다.
핵심은 보일러플레이트 (boilerplate)가 AI가 빛을 발하는 영역이라는 점입니다. 문서를 읽고, 패턴을 이해하며, 일관된 코드를 생성합니다. 이 부분은 진정으로 유용하며, 기능 하나당 아마도 3~4시간 정도를 절약해 줍니다.
단위 테스트 (Unit Tests) — 놀라울 정도로 좋음
AI 에이전트들이 제 프로젝트의 테스트 설정 (test setup)을 모르기 때문에 테스트에는 형편없을 것이라고 예상했습니다. 하지만 솔직히 말하자면? 그들은 완벽하게 해냈습니다.
Cursor는 단 하나의 파일만 보고도 제가 Vitest와 testing-library를 사용하고 있다는 것을 파악했고, 그 후 자신이 작성하는 모든 새로운 테스트에 대해 해당 패턴을 일치시켰습니다. 테스트가 완벽하지는 않았습니다 — 일부 엣지 케이스 (edge cases)가 누락되기도 했습니다 — 하지만 해피 패스 (happy path)와 기본적인 에러 케이스 (error cases)에 대해 견고한 커버리지 (coverage)를 제공했습니다.
Copilot Agent는 기존 테스트 파일들을 살펴보고 정확한 패턴을 복제할 수 있었기 때문에 이 부분에서 가장 뛰어났습니다. __mocks__ 디렉토리의 모든 모의 객체 (mocks), 동일한 어설션 (assertion) 스타일, 동일한 describe/it 구조까지 모두 갖추었습니다. 마치 컨벤션 (conventions)에 실제로 주의를 기울이는 주니어 개발자와 페어 프로그래밍 (pair programming)을 하는 듯한 느낌이었습니다.
데이터베이스 스키마 설계 (Database Schema Design)
이 부분은 저를 놀라게 했습니다. 엉망인 결과물을 예상했지만, 네 가지 에이전트 모두 적절한 인덱스 (indexes), 외래 키 (foreign keys), 그리고 마이그레이션 파일 (migration files)까지 포함된 합리적인 PostgreSQL 스키마를 생성했습니다.
[— Claude Code는 스키마를 작성하기 전에 명확한 질문을 던졌습니다 — "프로젝트와 사용자 간의 관계는 무엇인가요?" — 이 질문은 저를 당황하게 만들었습니다. 나머지 세 모델은 그저 자신들이 옳다고 생각하는 것을 작성했고, 솔직히 말해서 그 결과물들은 충분히 근접했기에 저는 외래 키 제약 조건 (foreign key constraint) 하나만 수정하면 될 정도였습니다.
단점 — 상황이 꼬이기 시작한 지점
의존성 지옥 (Dependency Hell)은 실재한다
데모 영상에서는 아무도 말하지 않는 사실이 있습니다. AI 에이전트들은 패키지 설치하는 것을 정말 좋아한다는 점입니다. 그리고 스스로 뒷정리를 하지 않습니다.
Codex CLI는 제 Next.js 프로젝트에 React Router를 두 번이나 설치했습니다. Claude Code는 제가 이미 어떤 것을 사용하고 있는지 결정하지 못해 세 가지의 서로 다른 UUID 라이브러리를 끌어왔습니다. Cursor는 제가 Drizzle ORM을 사용하고 있음에도 불구하고 계속해서 Prisma를 설치하려고 시도했습니다.
첫 번째 기능 구현 단계가 끝난 후, 저는 의존성 (dependencies)을 감사 (auditing)하는 데 거의 두 시간을 소비했습니다. package.json은 마치 벼룩시장 같았습니다. 무작위 패키지들이 사방에 흩어져 있고, 명확한 패턴도 없으며, 여러 라이브러리가 동일한 기능을 수행하고 있었습니다.
교훈은 무엇일까요? CLAUDE.md 또는 cursorrules 파일에 기술 스택 (tech stack)을 명시하세요. 에이전트에게 당신이 어떤 ORM, 어떤 스타일링 솔루션, 어떤 HTTP 클라이언트를 사용하는지 정확히 알려주어야 합니다. 그렇지 않으면 에이전트는 추측을 할 것이고, 그 추측은
Codex CLI는 Redis 캐싱 라이브러리 전체를 새로 만들어냈습니다. 실제 패키지가 아니라, 그냥 존재하지 않는 것을 만들어내고 그것을 임포트(import)하는 코드를 작성한 것입니다. 임포트 경로는 @acme/redis-cache였고, 요청 중복 제거(request deduplication) 기능을 수행해야 했지만, 당연하게도 npm install은 실패했습니다. 저는 이것이 환각(hallucination)된 패키지라는 것을 깨닫기 전까지 왜 안 되는지 알아내느라 20분을 허비했습니다.
Copilot Agent가 이 부분에서 가장 신뢰할 수 있었습니다. 실제 API에 가장 가깝게 유지되었기 때문입니다. Microsoft가 더 나은 가드레일(guardrails)을 갖추고 있어서일 수도 있고, 혹은 생성하는 내용에 대해 더 보수적이기 때문일 수도 있습니다.
컨텍스트 윈도우(Context Windows)는 빠르게 채워진다
데모에서는 항상 간단한 요청으로 시작하는 새로운 대화만을 보여주는 것을 알고 계실 겁니다. 하지만 실제 프로젝트는 그렇게 작동하지 않습니다.
3일 차가 되었을 때, Claude Code의 컨텍스트 윈도우(context window)는 이미 제 전체 프로젝트 구조를 담기에는 너무 작아졌습니다. 인증 미들웨어(authentication middleware)를 어떻게 설정했는지 잊어버리기 시작했고, 기존 코드와 충돌하는 패턴을 제안하곤 했습니다.
Cursor는 이 문제를 더 잘 처리했는데, 이는 모든 것을 컨텍스트에 쏟아붓지 않고도 코드베이스를 쿼리할 수 있는 MCP (Model Context Protocol)를 가지고 있기 때문입니다. 하지만 그럼에도 불구하고, 10개 이상의 파일에 영향을 미치는 복잡한 기능의 경우 때때로 전체 아키텍처(architecture)를 놓치기도 했습니다.
해결 방법은 무엇일까요? 기능을 더 작은 청크(chunks)로 나누는 것입니다. "전체 메시징 시스템을 구축해줘"라고 하는 대신, "메시지를 위한 데이터베이스 스키마(database schema)를 생성해줘", 그다음 "API 라우트(routes)를 작성해줘", 그다음 "실시간 구독(real-time subscription) 기능을 구축해줘"와 같이 진행하는 것입니다. 각 청크는 컨텍스트 안에 들어갈 수 있습니다.
추한 면 — 놀라운 동작
에이전트에게는 개성이 있다
이상하게 들릴 수도 있겠지만, 서로 다른 에이전트들은 진정으로 서로 다른 "스타일"을 가지고 있습니다.
Claude Code는 가장 신중했습니다. Stripe 연동 코드를 작성하기 전에, 잠시 멈추고 제가 환경 변수(environment variables)에 웹훅 비밀키(webhook secret)를 설정했는지 물어보았습니다. 심지어 Stripe CLI로 먼저 테스트해 볼 것을 제안하기도 했습니다. 그런 종류의 가드레일(guardrail)은 진정으로 도움이 됩니다. 무슨 뜻인지 아시겠죠?
Cursor가 가장 공격적이었습니다. 코드를 작성하고, 즉시 리팩터링(refactor)한 다음, 리팩터링된 버전을 다시 리팩터링하곤 했습니다. 가끔 PR(Pull Request)을 검토하다 보면 동일한 파일 내에서 같은 문제에 대한 세 가지 서로 다른 접근 방식을 발견하기도 했습니다.
Codex CLI는 가장 창의적이었지만 동시에 가장 신뢰할 수 없었습니다. 제가 전혀 생각지도 못했을 아름다운 TypeScript 제네릭(generics)을 작성해 놓더니, 곧바로 알려진 어떤 API와도 일치하지 않는 함수 시그니처(function signature)를 환각(hallucination)해냈습니다.
Copilot Agent는 가장 기업적인(corporate) 느낌이었습니다. 깔끔하고, 예측 가능하며, 지루했습니다. 흥미로운 것도, 잘못된 것도 없었습니다. 만약 제가 "내 프로젝트의 패턴을 따르는 REST 엔드포인트(endpoint)를 작성해 줘"라고 요청한다면, 매번 완벽하게 결과물을 내놓았습니다.
에러 메시지가 의존 대상이 되다
여기 제가 예상치 못했던 메타적인(meta) 문제가 있습니다. 에러 메시지를 읽는 일을 에이전트에게 의존하기 시작한 것입니다. 테스트가 실패하면 제가 직접 읽는 대신 에러를 에이전트에 붙여넣었습니다. 이는 저 자신의 기술 발전에 매우 좋지 않은 현상입니다.
8일째 되는 날 제가 이런 행동을 하고 있다는 것을 깨닫고 강제로 리셋을 했습니다. 이제는 에러를 먼저 읽고, 스스로 고쳐보려고 노력하며, 10분 이상 막혔을 때만 에이전트에게 물어봅니다. 에이전트들이 저보다 에러 디버깅(debugging)을 더 잘하게 되었습니다. 이는 유용하지만, 동시에 두려운 일이기도 합니다.
다르게 시도했을 점
만약 이 실험을 다시 해야 한다면, 저의 플레이북(playbook)은 다음과 같습니다:
-
사전에 PROJECT.md 또는 CLAUDE.md를 작성하세요. 모든 라이브러리, 모든 컨벤션 (convention), 모든 아키텍처 결정 사항을 나열하세요. 에이전트들은 이 파일들을 존중하며, 이를 통해 환각 (hallucination)을 아마 80% 정도 줄일 수 있습니다.
-
에이전트가 감독 없이 패키지를 설치하게 두지 마세요. 모든
npm install이 실행되기 전에 검토하세요. 에이전트들은 당신이 이미 무엇을 가지고 있는지 알지 못합니다. -
전체 기능이 아닌 블록 단위로 에이전트를 사용하세요. 단일 에이전트 호출은 2,000줄이 아니라 50~200줄 정도를 생성해야 합니다. 더 작은 청크 (chunk) = 더 적은 환각 (hallucination) = 더 적은 디버깅 (debugging)을 의미합니다.
-
생성된 코드의 모든 줄을 읽으세요. 이것이 "속도"라는 목적에 어긋난다는 것을 알지만, 그렇지 않으면 환각된 Stripe 메서드나 가짜 Redis 라이브러리를 배포하게 될 수도 있습니다. 패턴을 신뢰할 수 있을 때까지 처음 몇 주 동안은 모든 것을 검토하세요.
-
인증 (auth) 및 결제 (payments)에는 반드시 인간이 개입(human in the loop)하도록 하세요. 에이전트들은 다른 무엇보다 결제 흐름을 가장 자주 틀렸습니다 — 잘못된 에러 핸들링 (error handling), 누락된 멱등성 (idempotency), 잘못된 엣지 케이스 (edge case) 처리 등입니다. 이러한 영역에서 "적당히 괜찮은" 수준은 "실제 돈을 잃는 것"을 의미합니다.
공지: 이 기사의 일부 링크는 제휴 링크입니다. 이를 통해 구매하시면 귀하에게 추가 비용 없이 저에게 수수료가 지급될 수 있습니다. 저는 진심으로 유용하다고 생각하는 제품만을 추천합니다.
결론
솔직한 견해는 다음과 같습니다: 2026년의 AI 코딩 에이전트들은 믿을 수 없을 정도로 유용하지만, 조만간 개발자를 대체하지는 못할 것입니다. 에이전트가 잘하는 일은 다음과 같습니다:
- 보일러플레이트 (boilerplate) 제거 — 기능당 3~4시간 절약
- 훌륭한 초안 생성 — 테스트, 스키마 (schema), 기본 구현
- 패턴 파악 — 기존 코드 스타일을 맞추는 데 탁월함
- 탐색적 코딩 (exploratory coding) — 당신이 생각하지 못했을 접근 방식을 시도함
에이전트가 잘하지 못하는 일:
- 의존성 관리 (dependency management) — 모든 것을 설치해 버릴 것입니다
- 복잡한 다중 파일 리팩토링 (refactors) — 컨텍스트 윈도우 (context window)가 여전히 너무 작습니다
- 프로덕션 결제 흐름 — 환각 (hallucination)의 대가가 비쌉니다
- 당신의 판단을 대체하는 것 — 여전히 모든 줄을 검토해야 합니다
결국 저는 Cursor Agent와 Copilot Agent를 일상적인 워크플로우(workflow)에 계속 유지하게 되었습니다. 어려운 작업에는 Claude Code를 사용합니다. Codex CLI는 유망하지만, 실제 프로덕션(production) 작업에 사용하기에는 아직 부족합니다.
총 월간 지출액은 얼마일까요? $30 (Cursor Pro $20 + Copilot Pro $10)입니다. 제가 얻고 있는 결과물 — 대부분의 날에 제 생산성이 대략 2배 정도 향상되는 것 — 을 고려하면, 이는 현재 소프트웨어 분야에서 가장 가성비 좋은 거래입니다.
실제 프로젝트에서 AI 코딩 에이전트(AI coding agents)를 사용해 보셨나요? 여러분의 경험이 어떠했는지 진심으로 궁금합니다. 댓글을 남겨 제가 잘못 알고 있는 부분이 있다면 알려주세요.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기