
창업 리드 플레이북: AI 에이전트와 2명의 인간으로 제품, 아키텍처 및 엔지니어링 운영하기
요약
AI 코딩 에이전트를 활용하여 최소한의 인원으로 제품 정의부터 백엔드 엔지니어링까지 운영하는 실전 플레이북을 소개합니다. 전통적인 개발 파이프라인을 재구조화하여 조정 지연 시간을 줄이고, 인간의 판단력을 중심으로 업무를 수행하는 모델을 제안합니다.
핵심 포인트
- AI 에이전트를 활용해 백엔드, 인프라, 테스트 등 기술 실행 전반을 자동화
- 전통적인 협업 지연 시간을 줄이는 대신 인간의 판단 부하(Judgment Load)에 집중
- 제품 정의, 시스템 설계, 기술 실행 단계를 독립된 모드로 분리하여 실행
- 컨텍스트 스위칭을 방지하기 위해 단계별 명확한 산출물 생성 필수
여기에는 피상적인 'AI를 활용한 10배 성장' 글들이 많이 있습니다. 이것은 그런 글 중 하나가 아닙니다. 이것은 제가 단독으로 제품(product), 아키텍처(architecture), 백엔드 엔지니어링을 운영하는 실제 운영 모델이며, 프론트엔드 개발자라는 인간 협업자 1명과 AI 코딩 에이전트가 나머지 모든 작업을 처리하도록 하는 방식입니다.
핵심 전제는 이렇습니다. 이해관계자가 저에게 한 문장짜리 목표를 제시합니다. 그 순간부터 저는 제품 정의(product definition), 시스템 설계(system design), 기술 실행을 처음부터 끝까지 책임집니다. 제가 참여하는 인간은 단 한 명뿐입니다. 나머지 모든 것—백엔드, 마이그레이션(migrations), 테스트, 인프라 스크립트(infra scripts)—은 제가 지시하고, 검토하며, 통제하는 AI 코딩 에이전트를 통해 실행됩니다.
'이것이 확장 가능한가?'라는 질문에 대한 솔직한 대답은 '예'입니다. 하지만 이는 단순히 어떤 도구를 사용하느냐가 아니라, 일하는 방식을 재구조화해야만 가능합니다. 전통적인 PM → 아키텍트 → 엔지니어 파이프라인에 AI 에이전트를 붙인다고 해서 시간표가 무너지는 것이 아닙니다. 단지 병목 지점(bottleneck)을 사용자의 주의력으로 옮길 뿐입니다. 여기에는 제가 고치기 전에 문제가 되었던 부분들을 포함하여 실제 플레이북이 담겨 있습니다.

핵심 변화: 지연 시간 감소, 판단 부하 유지
다인원 팀에서는 많은 일정 시간이 사람 간의 맥락을 조정하는 데 쓰입니다—PRD 검토, 아키텍처 정렬(alignment), 티켓 정리(ticket grooming). 이러한 역할을 한 사람에게 통합하면 그 '조정(coordination)' 지연 시간은 대부분 사라집니다. 하지만 사라지지 않는 것, 그리고 사람들이 과소평가하는 것이 바로 판단 부하(judgment load)입니다. 여전히 모든 제품 결정, 모든 아키텍처 트레이드오프(tradeoff), 그리고
여전히 당신이 아키텍처, 제품 비전(product vision), 그리고 최종 품질 게이트(quality gate)를 책임집니다. 에이전트는 보일러플레이트(boilerplate), 마이그레이션 스크립트(migration scripts), 테스트 스캐폴딩(test scaffolding), 그리고 비즈니스 로직의 초안을 담당합니다. 프론트엔드 개발자는 UI/UX와 상호작용(interaction)을 담당하며, 당신을 기다리느라 작업이 막히는 일이 결코 없어야 합니다.
파트 1: 단계별 실행 루프 (The execution loop, phase by phase)
이 모델에서 발생하는 단 하나의 가장 큰 실패 모드(failure mode)는 사고 도중에 발생하는 컨텍스트 스위칭(context-switching)입니다. 즉, 기능이 무엇인지 결정하기도 전에 코드를 작성하는 것입니다. 각 단계를 별도의 결과물(artifact)을 생성하는 독립된 모드로 취급하고, 현재 단계에서 구체적인 산출물이 나오기 전까지는 다음 단계로 넘어가지 마세요.
1단계 — 제품 정의 (Product definition): "무엇(what)"과 "어떻게(how)"를 분리하십시오.
모호한 목표가 전달되었을 때(예: "멀티 테넌트 빌링 애그리게이터(multi-tenant billing aggregator)가 필요합니다"), 에디터를 여는 것을 참으십시오. 첫 번째 단계는 제품 프레이밍(product framing)입니다:
"이 목표를 분석하십시오. 허영심을 자극하는 기능(vanity features)은 제거하십시오. MVP를 정의하는 3가지 핵심 사용자 흐름(user flows)은 무엇입니까? 미룰 수 없는 첫날의 엣지 케이스(edge cases)는 무엇입니까?"
에이전트의 출력물을 명세서(spec)가 아닌 초안(first draft)으로 취급하십시오. 에이전트는 범위를 과하게 설정하거나, 그럴듯해 보이지만 요청하지 않은 요구사항을 환각(hallucinate)하여 만들어낼 것입니다. 당신의 역할은 뺄셈입니다. 이해관계자(stakeholder)에게 실제로 방어할 수 있는 사용자 스토리(user stories) 백로그로 내용을 축소하십시오.
2단계 — 시스템 설계 (System design): 코드가 존재하기 전에 스키마(schema)와 계약(contract)을 견고하게 만드십시오.
여기서 중요한 산출물은 데이터 스키마(data schema)와 API 계약(API contract)이지, 단순히 보여주기 위한 다이어그램이 아닙니다. 구체적인 프롬프트 예시는 다음과 같습니다:
"이 사용자 스토리들을 위한 PostgreSQL 스키마를 설계하십시오. 모든 테넌트 소유 테이블에는 단순히 격리를 암시적으로 가정하는 것이 아니라, 명시적인
tenant_id외래 키(foreign key)가 필요합니다. 마이그레이션을 생성하십시오. 그런 다음 엔드포인트(endpoints)를 위한 OpenAPI 3.0 명세를 생성하고, 상태를 변경하는(mutating) 엔드포인트 중 멱등성 키(idempotency keys)가 필요한 항목을 표시하십시오."
명시적으로 바로잡아야 할 점이 하나 있습니다. Postgres의 행 수준 보안 (Row-Level Security, CREATE POLICY)은 실제적이고 유효한 테넌트 격리 (tenant-isolation) 메커니즘이지만, 유일한 방법은 아닙니다. 대부분의 애플리케이션 계층 멀티테넌시 (multi-tenancy)의 경우, 서비스 계층에서 인덱싱된 tenant_id 컬럼으로 필터링하는 것이 (이때 해당 값은 클라이언트를 절대 신뢰하지 말고 항상 인증된 토큰에서 유도해야 합니다) 애플리케이션 코드 외부에 존재하여 새 테이블에 활성화하는 것을 잊기 쉬운 RLS 정책보다 추론하고 테스트하기에 더 간단합니다. 하나의 메커니즘을 의도적으로 선택하여 일관되게 적용하십시오. 팀을 괴롭히는 실제 버그는 "어떤 메커니즘인가"가 아니라, 누군가 범위를 지정하는 것을 잊어버린 "단 하나의 테이블"입니다.
스키마와 컨트랙트 (contract)를 승인하면, 해당 OpenAPI 문서는 백엔드 구현과 프론트엔드 통합 모두를 위한 단일 진실 공급원 (single source of truth)이 됩니다. 그 누구도 타인의 코드로부터 컨트랙트를 추론해서는 안 됩니다.
3단계 — 실행: 고정된 컨트랙트에 따른 에이전트 기반 구현 (agentic implementation).
컨트랙트가 고정되면, 에이전트가 이를 직접 참조하도록 지정하십시오:
"
billing-openapi.yaml에 정의된 엔드포인트들을 구현하십시오. 구현 이후가 아니라 구현과 동시에 통합 테스트 (integration tests)를 작성하십시오. 제3자 결제 게이트웨이는 모킹 (Mock) 하십시오. 모든 소프트 삭제 (soft-deletable) 가능한 엔티티는 기본적으로 조회에서 제외되어야 합니다 — 이를 주석이 아닌 테스트로 검증하십시오."
에이전트가 라우트를 작성하고, 데이터 계층을 연결하며, 테스트가 통과할 때까지 스스로 테스트를 실행하며 반복하는 과정을 지켜보십시오. 당신의 역할은 리뷰로 전환됩니다: 생성된 코드가 당신이 요청한 불변성 (invariant)을 실제로 구현하고 있는가, 아니면 언뜻 보기에는 괜찮아 보이지만 동시 쓰기 (concurrent-write) 또는 소프트 삭제 엣지 케이스 (edge case)에서 무너지는가? 이 단계는 에이전트 출력물에 대한 검증되지 않은 신뢰가 가장 값비싼 버그를 유발하는 단계입니다 — 아래의 '함정 1'을 참조하십시오.
4단계 — 프론트엔드 핸드셰이크 (handshake): 인간이 병목 현상이 되게 하지 마십시오.
에이전트가 백엔드를 작업하는 동안, 당신의 프론트엔드 개발자는 실제 서버가 존재하기를 기다리며 결코 유휴 상태로 있어서는 안 됩니다. 해결책은 빠른 가짜 (fast fake)를 만드는 것입니다:
- OpenAPI 명세(spec)로부터 직접 모의 서버(mock server, 예: Prism)를 즉시 실행(Spin up)합니다.
- 동일한 명세로부터 TypeScript 타입(types)을 생성하여 전달합니다. 이는 수동으로 작성하는 것이 아니라, 항상 계약(contract)으로부터 유도되어야 하며, 계약으로부터 조용히 벗어나는(drift) 일이 없도록 해야 합니다.
- 다음 내용을 포함한 티켓(ticket)을 전달합니다: UI 요구사항, 정확한 엔드포인트 계약(endpoint contracts), 생성된 타입, 그리고 모의 서버 URL.
프론트엔드 개발자는 백엔드 구현이 완료된 후가 아니라, 백엔드 구현과 병렬적으로, 실제 API의 형태와 정확히 일치하게 동작하는 가짜(fake)를 대상으로 빌드합니다.
5단계 — 병합(merge) 전 심층 방어 리뷰 (Defense-in-depth review).
백엔드 구현과 프론트엔드 PR(Pull Request)이 모두 준비되면, 단순히 승인 도장을 찍는 것이 아니라 의도적으로 적대적인 관점(adversarial pass)에서 검토를 수행합니다:
"새로 병합된 라우트(routes)에 대해 SQL 인젝션(SQL injection) 위험, 처리되지 않은 프로미스 거부(unhandled promise rejections), N+1 쿼리 패턴(N+1 query patterns), 그리고 소유권/테넌트 권한(ownership/tenant claim)을 확인하지 않고 ID만으로 변이(mutation)를 필터링하는 엔드포인트가 있는지 감사(audit)하십시오."
그 다음 프론트엔드 PR을 수동으로 읽고, 실제 스택(real stack)을 구동하며(단순한 유닛 테스트가 아니라 실제로 흐름을 실행), 엔드투엔드(end-to-end) 통합 스모크 테스트(integration smoke test)를 실행합니다. 자동화된 감사(automated audits)는 패턴 매칭이 가능한 부류의 버그는 잡아낼 수 있지만, "이 엔드포인트는 논리적으로는 올바르지만 코드베이스의 다른 곳에서 의존하는 불변성(invariant)을 위반한다"와 같은 문제는 잡아내지 못합니다. 그런 문제는 여전히 코드베이스를 잘 아는 인간이 필요합니다.
파트 2: 숨겨진 함정들
선형적으로 설명하면 매끄러워 보입니다. 하지만 실제로는 명시적인 대응책을 구축하지 않으면 당신을 물어뜯을 세 가지 구체적인 실패 모드(failure modes)가 존재합니다.
함정 1: 조용히 잘못되어 있는, 확신에 찬 듯 보이는 코드
AI 코딩 에이전트는 구문론적으로 올바르고 그럴싸해 보이는 대량의 코드를 매우 빠르게 생성합니다. 에이전트는 특정 지름길(shortcut)을 선택했을 때 6개월 뒤에 그것을 감당하는 것이 얼마나 고통스러울지에 대한 체감(felt sense)이 없습니다. 더 위험하게도, 에이전트는 불변성(invariant, 예: 소프트 삭제(soft-delete), 테넌트 스코핑(tenant scoping), 트랜잭션 원자성(transactional atomicity))을 실제로 준수하지 않더라도, 겉모습(surface pattern)이 맞으면 마치 준수하는 것처럼 보이는 코드를 기꺼이 생성할 것입니다. 실체(substance)는 그렇지 않더라도 말입니다.
실패 양상의 구체적인 예: 다른 모든 곳에서 사용하는 것과 동일한 리포지토리(repository) 메서드를 사용하기 때문에 소프트 딜리트(soft-delete)를 준수하는 것처럼 보이는 조회 헬퍼(lookup helper)가 있다고 가정해 봅시다. 하지만 근처의 "빠른 수정(quick fix)" 작업으로 인해 ORM의 기본 필터링을 완전히 우회하는 가공되지 않은 UPDATE/increment 호출로 교체됩니다. 컴파일 타임에는 아무런 오류도 발생하지 않습니다. 리포지토리를 모킹(mock)하는 얕은 단위 테스트(unit test)에서도 아무런 문제가 없습니다. 하지만 실제 운영 환경에서, 제외되었어야 할 실제 행(row)을 대상으로 조용히 실패하게 됩니다.
실제로 효과가 있는 완화 방법:
- 작고 단일 책임(single-responsibility)을 가진 파일과 모듈. 분해를 강제하십시오. 거대한 파일은 우회된 불변성(invariant)이 가장 오래 숨어 있을 수 있는 곳입니다.
- 구현 이후가 아닌, 구현과 동시에 작성되는 테스트. 만약 에이전트가 당신이 중요하게 생각하는 정확한 불변성(소프트 딜리트 제외, 테넌트 격리(tenant isolation), 멱등성(idempotency))에 대해 스스로 작성한 코드가 테스트를 통과하지 못한다면, 그것은 테스트가 틀린 것이 아니라 설계가 불충분하게 정의되었다는 신호입니다.
- 정기적인 "우리가 무엇을 우회했는가"에 대한 감사. 주기적으로 명시적으로 질문하십시오: "ORM의 기본 스코핑(scoping)을 건너뛰는 직접적인
UPDATE/increment/raw-query 호출을 grep으로 찾아라 — 모든 항목을 나열하고 각각의 이유를 정당화하라." 이는 일반적인 코드 품질 검사에서 놓치는 종류의 버그를 잡아냅니다. 왜냐하면 코드가 형편없이 작성된 것이 아니라, 지켜야 할 불변성을 알고 있을 때만 문제가 되는 방식으로 정밀하게 틀렸기 때문입니다. - 설계 문서의 자체 설명이 아닌, 실제 엔티티/스키마(entity/schema)를 기준으로 주장을 검증하십시오. 설계 문서는 내부적으로 일관될 수 있지만 현재 코드가 무엇을 하는지에 대해서는 여전히 틀릴 수 있습니다. 유일한 진실의 근거(ground truth)는 파일 그 자체입니다.
함정 2: 컨텍스트 스위칭 피로 (Context-switch fatigue)
20분마다 제품 프레이밍(product framing), 시스템 설계, 그리고 저수준 디버깅(low-level debugging) 사이를 오가는 것은 의사 결정의 질을 눈에 띄게 저하시킵니다. 뇌의 절반이 여전히 이전 모드에 머물러 있기 때문에, 오후 중반쯤 되면 어설픈 트레이드오프(tradeoff)를 하기 시작합니다. 해결책은 의지력이 아니라 스케줄링입니다:
| 시간 블록 (Time block) | 모드 (Mode) | 집중 분야 (Focus) |
|---|---|---|
| 딥 포커스 블록 (Deep-focus block) | 제품 및 아키텍처 (Product & architecture) | 요구사항 (Requirements), 스키마 (schema), 계약 (contracts). 구현은 하지 않음. |
| ... |
경계를 보호하세요. "잠깐 아키텍처 질문 좀 해도 될까?"라는 말이 실행(execution) 블록을 침범하게 두지 마세요. 또한, 무언가 5분 안에 해결 가능해 보인다는 이유만으로 구현 도중에 설계(design) 모드로 컨텍스트 스위칭(context-switching)을 하지 마세요. 대신 그것을 적어두었다가 다음 설계 블록에서 다시 다루세요.
함정 3: AI 지원 백엔드와 인간 프론트엔드 작업 사이의 속도 격차
AI의 지원을 받는 백엔드는 프론트엔드 구현 및 디자인 반복 작업을 수행하는 인간보다 몇 배 더 빠르게 움직일 수 있습니다. 만약 이러한 가공되지 않은 속도를 필터링 없이 하류(downstream)로 밀어낸다면, 당신의 프론트엔드 협업자는 끊임없이 뒤처지게 되고, 조금씩 흘러나오는 변경 사항마다 컨텍스트 스위칭을 해야 하며, 합리적으로 자신이 밀려나고 있다는 느낌을 받기 시작할 것입니다.
완화 방법:
- 조금씩 흘리지 말고, 배치(Batch)로 처리하세요. 모든 증분 변경 사항(incremental change)이 발생하는 즉시 밀어넣는 대신, 예측 가능한 주기에 따라 일관된 기능 단위의 핸드오프(handoff)로 백엔드 변경 사항을 묶어서 전달하세요.
- 핸드오프 노트(handoff note)를 직접 작성하세요. 자동 생성된 API 문서는 인터페이스의
_형태(shape)_를 설명할 뿐, 각 요소가 어떻게 결합되어야 하는지 또는 어떤 상태가 까다로운지에 대해서는 설명하지 않습니다. 실제로 설계 트레이드오프(tradeoff)를 수행한 사람이 평이한 언어로 몇 분간 맥락을 설명해 주는 것이, 상대방이 디프(diff)를 통해 의도를 역공학(reverse-engineering)하는 데 몇 시간을 허비하는 것을 막아줍니다.
파트 3: 재사용 가능한 프롬프트 스캐폴딩 (Reusable prompt scaffolding)
다음은 제가 스택에 관계없이 유용하도록 일반화하여 계속 재사용하고 있는 실제 시스템 프롬프트(system-prompt) 형태들입니다.
아키텍처 모드 시스템 프롬프트 (Architecture-mode system prompt):
당신은 클라우드 네이티브(cloud-native) 시스템을 위한 수석 수준의 솔루션 아키텍트(solution architect)로서 행동합니다.
기교보다는 보안, 비용, 그리고 장기적인 유지보수 가능성(maintainability)을 최적화하세요.
...
머지 전 리뷰 프롬프트 (Pre-merge review prompt):
이 디프(diff)를 결벽증이 있고 보안에 집중하는 리뷰어로서 검토하세요. 특히 다음 사항을 확인하십시오:
- 인젝션(Injection) 위험 또는 ORM의 기본 스코핑(scoping)을 우회하는 모든 로우 쿼리(raw query)
(소프트 삭제(soft-delete) 필터, 테넌트/소유자(tenant/owner) 필터).
...
실제 현실 점검
이러한 방식의 작업은 진정으로 더 빠릅니다. 컬럼 하나를 변경하기 위해 회의를 기다리거나, 기본적인 엔드포인트(endpoint)를 검증하기 위해 QA 사이클(QA cycle)을 기다릴 필요가 없기 때문입니다. 하지만 이 속도는 오직 한 가지 조건에 전적으로 달려 있습니다. 바로 여러분의 리뷰 규율(review discipline)이 산출량(output)에 맞춰 확장되는가 하는 점입니다. AI 코딩 에이전트(AI coding agent)는 여러분이 명세(specification)를 작성하는 속도만큼 빠르게 코드를 작성할 것입니다. 에이전트는 명세 자체가 잘못되었을 때 이를 알려주지 않으며, 자신의 출력물이 겉보기에는 올바르게 보일지라도, 중요하다고 전달받지 못한 불변성(invariant)을 위반할 때 이를 알아차리지 못할 것입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기