모든 세대는 잘못된 스택을 선택했다. Vibe Coders도 다르지 않다.
요약
노코드와 바이브 코딩(Vibe Coding)이 아키텍처 이해의 필요성을 제거한다고 주장하지만, 서비스가 확장됨에 따라 결국 기술적 한계에 직면하게 됨을 경고합니다. LLM과 에이전트가 코딩을 가속화하더라도, 근본적인 시스템 구조를 이해하지 못하면 결국 대규모 재작성이 필요하게 됩니다.
핵심 포인트
- 노코드와 바이브 코딩은 초기 구축을 쉽게 하지만 아키텍처 이해를 생략하게 만듦
- 시스템이 복잡해지면 결합도 문제와 플랫폼 한계로 인해 재작성이 불가피함
- LLM은 개발 패턴을 제거하는 것이 아니라 오히려 이러한 패턴을 가속화함
- 지속 가능한 서비스를 위해서는 하부 스택과 아키텍처에 대한 이해가 필수적임
이제 하부에서 무엇이 실행되고 있는지 이해하지 않고도 앱을 구축할 수 있습니다.
보세요, 작동만 한다면 작동하는 것입니다... 하지만 단순한 홈 도구 이상의 야망이 있다면, 즉 그것을 진화시키고, 확장하고, 결국 판매하고 싶다면, 어느 시점에는 직접 손을 더럽혀야(get your hands dirty) 할 것입니다. 노코드(no-code) 파도는 코딩할 필요가 없다고 말했습니다. 바이브 코딩(vibe coding) 파도는 아키텍처(architecture)를 이해할 필요가 없다고 말합니다. 두 가지 모두 사실이지만, 더 이상 사실이 아닌 시점이 옵니다. 그리고 그것들이 더 이상 사실이 아니게 될 때, 여러분은 다시 작성(rewrite)해야 합니다.
LLM(대규모 언어 모델)은 이 패턴을 제거하지 않습니다. 오히려 가속화합니다.
똑같은 대본, 3번의 반복
80년대 어느 시점에, BASIC이 아주 단순한 제안과 함께 등장했습니다: 포인터(pointer)를 이해하거나 메모리(memory)를 관리할 필요 없이, 그저 로직(logic)만 작성하면 된다는 것이었습니다. 그리고 한동안 이것은 완전히 사실이었습니다. 저수준(low-level)의 세부 사항을 전혀 건드리지 않고도 실제 프로그램을 구축할 수 있었으며, 이는 그저 작동하는 무언가를 원했던 많은 사람에게 진정으로 해방감을 주었습니다. 문제는 약속 자체가 아니었습니다. 문제는 그 약속이 무엇을 계속 보이지 않게 만들었느냐 하는 것이었습니다. 여러분의 BASIC 프로그램이 충분히 복잡해지면, 결합도(coupling)는 예정대로 찾아옵니다. UI 로직과 비즈니스 로직(business logic)이 깨끗한 경계 없이 뒤엉키고, 모든 것을 건드리지 않고서는 아무것도 테스트할 수 없는 상태가 됩니다. 재작성(rewrite)은 BASIC의 실패가 아니었습니다. 그것은 처음부터 거래에 포함되어 있던 것이었습니다.
서랍 어딘가에 제 여동생의 생일 카드 목록을 자동화했던 BASIC 프로그램이 담긴 1993년산 플로피 디스크가 아직 남아 있습니다. 47개의 봉투 주소를 대륙 이동 속도와 비슷한 속도로 도트 매트릭스 프린터로 인쇄하던 것이었죠. 제가 왜 지금 이 생각을 하고 있는지 전혀 모르겠습니다.
Visual Basic은 줄 번호(line numbers) 대신 폼(forms)과 이벤트 핸들러(event handlers)를 사용했을 뿐, 2000년대 중반까지 동일한 방식을 유지했습니다. 그 후 **노코드 (no-code)**가 훨씬 더 깔끔한 버전의 제안을 들고 나타났습니다. 코딩이 전혀 필요 없다는 것이었죠. 이 역시 사실입니다. 플랫폼이 지원하지 않는 기능이 필요하거나, 가격 상한선(pricing ceiling)에 부딪히거나, 플랫폼이 접근할 수 없는 곳으로 데이터를 이동해야 할 때까지는 말이죠. 노코드의 한계는 곧 플랫폼의 경계입니다. 당신은 가장 많은 것이 걸려 있는 최악의 순간에 그 한계에 부딪히게 됩니다.
**바이브 코딩 (Vibe coding)**은 제3막입니다. 제안은 업그레이드되었지만, 그 밑바닥은 거의 토씨 하나 틀리지 않고 동일합니다. 아키텍처 (architecture)를 이해할 필요가 없다는 것이죠. 그저 원하는 것을 설명하기만 하면, 에이전트 (agent)가 나머지를 처리합니다. 많은 경우, 한동안은 사실입니다. 이 세 파동 모두에서 일관되게 나타나는 것은 도구가 아닙니다. 제안에서 생략된 각주입니다. "당신의 문제가 X의 형태를 띠고 있을 때를 제외하고는, X를 이해할 필요가 없습니다." 그리고 그 조건은, 시작하는 사람이 선택하는 순간에는 볼 수 없는 것입니다. 바로 그 점이 재작성 (rewrite)이 시작될 때까지 그 약속이 진짜처럼 느껴지게 만듭니다.
당신의 에이전트는 대중적인 문제를 알고 있다
이번 주에 저는 AI가 생성한 코드를 중심으로 무엇을 오케스트레이션 (orchestrate)해야 하는지에 대한 스레드들을 읽어왔습니다. 상태 관리 (state management), 재시도 로직 (retry logic), 롤백 (rollback) 등 에이전트가 만들어내는 결과물을 둘러싼 모든 배관 작업 (plumbing)에 관한 것들이었습니다. 해당 스레드에 등장하는 도구들은 기술적으로 옳습니다. 실제 문제들을 해결하죠. 하지만 그들이 해결하는 실제 문제들은 상류 (upstream)에서, 즉 이전의 선택들에 의해 만들어진 것들입니다. 완전한 React SPA, 두꺼운 클라이언트 (thick client), 여러 서비스에 분산된 복잡한 상태 같은 것들 말이죠. 만약 당신에게 그런 문제들이 없다면, 그런 솔루션들도 필요하지 않습니다.
그리고 누군가 오케스트레이션의 복잡성을 어떻게 처리해야 하는지 물을 때마다, 모든 스레드에는 적어도 한 개의 댓글이 달립니다. "그냥 에이전트에게 처리하라고 말하세요." 이는 완전히 맞는 말입니다. 하지만 동시에 더 유용한 질문, 즉 왜 그 에이전트들이 애초에 그런 복잡성을 만들어냈는가에 대한 질문은 회피합니다. (제 컴퓨터에서는 잘 작동합니다. 다만 그 컴퓨터가 작동하려면 Docker에서 14개의 서비스가 실행되어야 할 뿐이죠.)
에이전트에게 앱을 만들어 달라고 요청하면, 에이전트는 자신이 가장 자주 학습한 문제 유형에 대해 **통계적으로 확률이 높은 응답 (statistically probable response)**을 생성합니다. 즉, 당신의 실제 제약 조건에 맞는 응답이 아니라, 이러한 종류의 질문이 던져졌던 모든 사례를 통틀어 정답일 가능성이 가장 높은 응답을 내놓는 것입니다. 에이전트는 **최빈값 답변 (modal answer)**을 최적화하며, 이는 실제로 생태계 내의 지배적인 패턴을 의미합니다. 그래서 당신이 앱을 요청하면 기본 스택(default stack)을 받게 됩니다. 번들러를 포함한 React, 상태 관리 레이어, 그리고 그 모든 설정들 말이죠. 제 생각에 에이전트는 자신이 해야 할 일을 정확히 수행하고 있는 것입니다. 단지 당신의 구체적인 문제에는 그 중 그 어떤 것도 필요하지 않다는 사실을 알 수 없을 뿐입니다.
저는 코드 대신 툴링(tooling)에 대해서도 동일한 연습을 수행해 보았습니다: CLI가 실제로 프로덕션 에이전트에 적합한지 아니면 MCP가 적합한지. 인기 있는 옵션도 동일한 문제를 안고 있습니다.
프롬프트를 입력하기 전에
저는 현재 대략 비슷한 시기에, 동일한 개발자가, 동일한 AI 보조 워크플로우(AI-assisted workflow)를 사용하여 구축한 두 개의 프로젝트를 운영하고 있습니다.
첫 번째는 가벼운 도구입니다. 서버 사이드 렌더링(Server-rendered), Hono JSX, 프론트엔드 번들러가 전혀 없는 구조입니다. 제 에이전트의 첫 번째 시도는 23개의 런타임 의존성(runtime dependencies)을 가져왔습니다. 저에게 필요한 것은 단 1개뿐이었습니다. 추가된 것들이 절대적인 의미에서 틀린 것은 아니었습니다. 각각은 실제 맥락에서 실제 문제를 해결하지만, 그 맥락 중 어느 것도 저의 맥락은 아니었습니다. (Claude Code는 클라이언트 상태가 전혀 없는 서버 사이드 렌더링 앱에 React Query를 계속 제안했습니다. 저는 세 번이나 거절했습니다. 네 번째 프롬프트에 이르러서야 마침내 제안을 그만두었습니다.) 여기에는 이름을 붙일 만한 상태 복잡성도 없고, 상태 머신(state machine)을 정당화할 만큼 복잡한 흐름도 없습니다. XState를 사용하는 것은 존재하지 않는 문제를 해결하기 위한 엔지니어링이 되었을 것입니다.
You Died.
두 번째 프로젝트는 유료 고객이 있는 SaaS이며, 실패 모드 (failure modes)가 실제로 중요한 다단계 임포트 흐름 (multi-step import flow)을 가지고 있습니다. 만약 2단계가 실패하면, 3단계는 실행되지 않습니다. 임포트가 중간에 중단되면, 사용자는 일반적인 에러가 아니라 정확한 실패 상태를 보게 됩니다. 그 프로젝트는 React 18과 XState v5를 사용하지만, 정확히 그 하나의 흐름을 위해 단 하나의 머신 (machine)만 사용합니다. 앱의 나머지 부분은 XState를 건드리지 않습니다. 그럴 필요가 없기 때문입니다. 제품은 보통 단순한 많은 인터페이스와 실제 상태 복잡성 (state complexity)을 가진 하나의 인터페이스로 구성됩니다. 실수는 제품 전체를 가장 어려운 부분의 복잡성을 가진 것처럼 취급하는 것입니다.
두 프로젝트를 위해 단 하나의 프롬프트 (prompt)도 작성하기 전에, 저는 스스로에게 한 가지 질문을 던졌습니다: 이 문제는 명시적인 전이 (transitions)와 별도의 실패 모드를 가진 **뚜렷하게 명명된 상태 (distinct named states)**를 가지고 있는가? 도구(tool)의 경우에는 아니었습니다. SaaS 임포트 흐름의 경우에는 예, 하지만 오직 그 특정 흐름에 대해서만 그러했습니다.
에이전트 (agent)는 그 질문에 답할 수 없습니다. 에이전트는 그 질문을 던질 수 있을 만큼 당신의 문제를 충분히 잘 알지 못합니다.
당신의 에이전트는 대중적인 문제에 최적화되어 있습니다. 당신의 문제가 실제로 그러한 문제인지 확인하십시오.
위임할 수 없는 제약 사항
모든 파도 속에서도 온전하게 살아남은 기술은 당신의 문제가 실제로 어떤 복잡성을 요구하는지 아는 것입니다.
세 번의 파도 중 그 어떤 것도 이 기술을 구축하지 못했습니다. 왜냐하면 그들 중 누구도 그럴 필요가 없었기 때문입니다. BASIC이 처음으로 이를 수행했고, 그다음에는 노코드 (no-code)가 동일한 약속을 드래그 앤 드롭 (drag-and-drop) 방식으로 패키징했으며, 이제 바이브 코딩 (vibe coding)이 자연어로 동일한 전략을 실행하고 있습니다. 천장은 매번 동일합니다.
바이브 코딩은 방정식의 양면, 즉 구축 (building)과 부채 (debt)를 모두 가속화합니다. 첫 번째 재작성 (rewrite)은 결코 오지 않는 것이 아니라 더 빨리 찾아옵니다. 아키텍처 (architecture)에 대한 질문은 사라지지 않습니다. 그것은 풀어야 할 코드가 더 많아지고, 변경하는 데 비용이 드는 결정들이 이미 박혀 있는 순간으로 미뤄질 뿐입니다.
위임할 수 없는 것은 코딩이 아닙니다. 바로 진단 (diagnosis) 입니다. 프롬프트 (prompt)를 열기 전, 에이전트 (agent)에게 앱을 설명하기 전에 스스로 물어보세요. 이 프로젝트에서 왜 X가 필요하지 않은지를 평이한 언어로 설명할 수 있습니까? 에이전트는 일반적으로 X가 유용하다는 사실을 이미 알고 있습니다. 문제는 실제 제약 조건이 있는 당신의 특정 프로젝트가 왜 지금 당장 그것을 필요로 하지 않는가 하는 점입니다. 만약 당신이 그 질문에 답할 수 있다면, 에이전트가 일반적인 (modal) 스택 대신 적절한 스택을 사용하도록 제한할 수 있습니다. 만약 답할 수 없다면, 에이전트는 대중적인 것을 기본값으로 선택할 것이며, 그것은 기술적으로 틀린 것은 아니겠지만 당신에게는 적합하지 않을 것입니다.
저는 프롬프트 계약 (prompt contracts)이 실제로 에이전트를 어떻게 제한하는가에서 정확한 메커니즘을 설명했습니다. 제약 조건은 에이전트가 당신을 대신해 해줄 수 없는 단 한 단계입니다. 그 외의 모든 것은 에이전트가 꽤 잘 처리합니다.
또한 이것은 BASIC, Visual Basic, 그리고 노코드 (no-code)가 모두 배울 필요 없다고 말했던 바로 그 기술이기도 합니다. 주목할 만한 가치가 있습니다.
보닛 아래에 무엇이 있는지 전혀 모르는 상태로 차를 정비소에 맡기면, 수리비는 항상 놀라움을 선사합니다. 정비사는 자신의 일을 알고 있습니다. 당신은 단지 무엇을 질문해야 할지, 무엇에 대해 반박해야 할지를 모를 뿐입니다. 당신의 앱도 마찬가지입니다. 무언가를 변경하고 싶거나 다른 사람에게 앱을 넘겨줘야 하는 순간, 그 밑에서 무엇이 돌아가고 있는지 깨닫게 될 것입니다. 청구서(invoice)도 그에 상응하는 경향이 있습니다.
출처 (Sources)
- Andrej Karpathy, 원문 vibe coding 트윗, 2025년 2월. https://x.com/karpathy
- "Vibe Coding: From a Throwaway Tweet to a $6.6 Billion Industry." Reborn.hr, 2026년 4월. https://reborn.hr/unwrapped/vibe-coding-from-a-throwaway-tweet-to-a-6-6-billion-industry
이 포스트에는 제휴 링크가 포함되어 있을 수 있습니다. 링크를 클릭하시면 저에게 소정의 수수료가 지급될 수 있으나, 귀하에게는 비용이 발생하지 않으며 제가 매일 양질의 글을 계속 발행하는 데 도움이 됩니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기