Claude Code 그린필드 워크플로를 사용해 구조, 스크립트, 그리고 매주 실행·테스트·개선 가능한 첫 수직 슬라이스를 설정하세요.

빈 레포에서 시작하는 건 자유롭게 느껴지지만, 종종 엉킨 진행으로 이어집니다: 생성된 파일이 많고 빌드는 반쪽짜리이며 다음 변경을 어디에 둬야 할지 불명확합니다. Claude Code 그린필드 워크플로의 목적은 그 첫 주의 혼란을 피하는 것입니다.
자주 반복되는 몇 가지 실패 패턴:
초기 결정은 모든 것이 그 위에 쌓이기 때문에 되돌리기 고통스러워집니다. 혼란스러운 구조가 계속 강화되고 수동 빌드는 열 가지 다른 설정으로 분화합니다. 간단한 dev 명령을 초기에 고정하지 않으면 변경이 앱을 망가뜨린 건지 환경을 망가뜨린 건지 구분할 수 없습니다.
이 글에서 "실행되는 앱(running app)"은 구체적인 의미를 가집니다: 프로젝트를 시작하는 한 개의 명령, 예측 가능한 출력 표시, 그리고 뭔가 빠졌을 때는 크게 실패하는 것. 로컬 설치를 지우고 레포를 클론한 뒤 그 명령을 실행하면 같은 결과를 볼 수 있어야 합니다.
"수직 슬라이스(vertical slice)"는 앱이 실제로 동작함을 증명하는 최소한의 엔드투엔드 기능입니다. UI 목업이 아니고, 데이터베이스 테이블만 단독으로 만든 것도 아닙니다. 폼이 있는 페이지 하나, 데이터를 저장하는 API 엔드포인트 하나, 데이터베이스에 쓰고 읽는 흐름 하나, 화면에 표시되는 결과 하나처럼 시스템을 끝까지 관통하는 얇은 선입니다.
한 커맨드로 앱을 실행하고 하나의 수직 슬라이스를 배포할 수 있다면, 추측 없이 반복할 수 있는 기반이 됩니다.
명확한 첫 슬라이스는 레포를 정돈하고 프롬프트를 집중시킵니다. 이 단계는 전체 제품이 어떻게 되길 바라는지가 아니라 엔드투엔드로 데모할 것을 결정할 순간입니다.
작업 흐름 전체를 증명하는 가장 작은 사용자 스토리를 고르세요. 좋은 슬라이스는 UI, 데이터, 그리고 실제 동작 하나를 건드립니다. 예: "사용자는 작업을 추가하고 새로고침 후 목록에 표시되는 것을 볼 수 있다." 작지만 라우팅, 검증, 저장소, 기본 화면을 강제합니다.
첫 주는 한 플랫폼만 목표로 삼고 지키세요. 웹으로 시작하면 웹만 하세요. "비상용으로" 모바일 화면을 추가하지 마세요. 나중에 Koder.ai 같은 플랫폼을 쓸 계획이 있어도, 첫 슬라이스를 한 차선(예: React 웹, 혹은 Go API, 또는 Flutter)에 고정하는 쪽이 더 좋습니다.
"1주 차 완료"가 무슨 뜻인지 평범한 용어로 정의하세요:
그런 다음 범위를 보호할 세 가지 비목표를 적으세요. 예: 인증 없음, 테마 시스템 없음, 백그라운드 잡 없음.
결정을 적어두면 생성 프롬프트를 엄격하게 만들 수 있습니다: 슬라이스를 지원하는 것만 만들고 나머지는 TODO로 남기라고 하세요.
Claude에게 무언가 생성해 달라고 하기 전에 일련의 기본값을 고정하세요. 사소해 보이지만 나중에 "이름 전부 바꾸기" 같은 혼란을 막습니다.
먼저 앱의 형태를 결정하세요. 브라우저 UI와 백엔드가 모두 필요하면 두 부분(프론트엔드 + API)과 계약을 공유할 장소(API 타입이나 단순 스키마)를 시작부터 분명히 하세요. 서버 사이드 렌더링 단일 앱으로 충분하면 코드베이스를 하나로 유지해 로컬 개발을 단순하게 만드세요.
다음으로 구성 규칙에 합의하세요. 로컬 env 파일을 사용하되 git에는 포함하지 말고 템플릿(.env.example)을 커밋해 안전한 플레이스홀더와 간단한 주석을 넣으세요. 이로써 온보딩이 쉬워지고 비밀 유출이 줄어듭니다.
기본 dev 포트를 고르고 안정적으로 유지하세요. 포트는 스크립트, 문서, 오류 메시지에 박히므로 나중에 바꾸면 번거롭습니다. 폴더, 서비스, 패키지 이름도 한 규칙을 따르세요. 완벽한 규칙보다 일관성이 더 중요합니다.
간단한 시작 결정 예:
.env, 템플릿은 .env.example 커밋예: web을 포트 3000으로, api를 8080으로 정합니다. env 템플릿에 API_URL=http://localhost:8080과 DATABASE_URL=...을 포함시키면 Claude가 이후 스크립트와 문서를 생성할 때 모든 것이 제자리에 맞춰집니다.
전체 앱을 요청하지 말고 실행 가능한 스캐폴드부터 요청하세요. 기능을 넣기 전에 그걸 담을 장소가 없으면 지저분해지기 쉽습니다.
구조에 대해 명확히 요구하세요. 어떤 파일이 어디에 속하는지, 어디에 두면 안 되는지를 짧은 주석과 함께 폴더 레이아웃을 요구하면 초기 결정이 강제됩니다.
규율을 유지하는 간단한 방법은 프롬프트에 규칙을 두는 것입니다:
재사용 가능한 프롬프트 예시:
You are working in an empty repo. Create a minimal runnable skeleton.
Constraints:
- Keep it small: no real features yet.
- Propose a clear folder structure and add brief comments in each folder’s README.
- Add scripts for: setup, dev, test, build. They must work on a fresh machine.
- Tell me exactly how to run it, and what output I should see.
- After generating, stop and wait for my “ran it” confirmation.
Output:
1) File tree
2) Key files (only)
3) Run instructions
루프를 촘촘히 유지하세요. 한 번에 다섯 가지 변경을 요청하지 마세요. 작은 변경 하나를 생성하고 실행해 에러(또는 성공)를 붙여넣고 최소 수정만 요청하세요. 이 생성-실행-조정 리듬이 프로젝트를 예측 가능하게 만들고 구조가 흐트러지는 걸 어렵게 만듭니다.
한 가지 약속으로 시작하세요: 누구나 레포를 클론하고 한 명령으로 무언가 동작하는 것을 볼 수 있게 합니다. 그러면 AI에게 실제 기능을 추가하기 전에 안정된 기반이 생깁니다.
레포를 만들고 아주 작은 README를 초기 상태에서 작성하세요. 필수사항: 프리리퀘짓, 한 개의 dev 명령, 테스트 실행 방법(지금은 비어있어도 괜찮음).
그다음 탑레벨 레이아웃을 선택하세요. 앱 형태에 맞는 구조를 고르세요.
여러 배포 단위(예: frontend + API)를 만든다면 워크스페이스 레이아웃이 도움이 됩니다:
/
apps/
packages/
scripts/
docs/
README.md
단일 앱이라면 더 단순하게 유지하고 필요할 때까지 레벨을 늘리지 마세요.
이제 코드가 일관성을 유지하도록 최소한의 가드레일을 추가하세요. 포매터와 린터 하나를 고르고 기본값을 수용한 뒤 설정 파일 하나만 추가합니다. 목표는 작은 변경 차이(diff)를 유지하는 것입니다.
개발자 경험을 루트에서 항상 작동하는 한 명령으로 예측 가능하게 만드세요. 간단한 형태 예:
{
"scripts": {
"dev": "echo \"start dev server here\"",
"build": "echo \"build here\"",
"test": "echo \"tests here\"",
"lint": "echo \"lint here\""
}
}
다른 것을 생성하기 전에 dev 명령을 실행해 정상 종료하는지(또는 플레이스홀더 서버가 부팅되는지) 확인한 뒤 스캐폴딩만 포함한 최초 커밋을 만드세요. 팀원이든 미래의 당신이든 기본 설정을 재현할 수 있으면 첫 슬라이스를 만들 준비가 된 것입니다.
좋은 그린필드 구조는 두 가지를 합니다: 코드를 빠르게 찾을 수 있게 하고 Claude가 변경할 때마다 새로운 패턴을 만들어내지 않도록 공간을 줄입니다. 목표는 완벽이 아니라 안정성입니다.
단일 앱 내부(또는 apps/<name>/ 폴더 내)라면 다음의 단순한 내부 레이아웃이 잘 버팁니다:
src/ 앱 코드(기능, 공유 요소, 진입점)config/ 비밀이 아닌 설정tests/ 사용자 행동처럼 읽히는 상위 수준 테스트scripts/ 헬퍼 스크립트(개발 셋업, DB 리셋, 릴리스 작업)docs/ 실제로 유지하는 짧은 노트와 체크리스트src/ 내부에서는 기능 코드와 공유 코드를 변경 패턴에 따라 분리하세요. 기능 코드는 자주 변경되므로 가깝게 두고, 공유 코드는 단순하고 재사용 가능하게 둡니다.
실용적인 규칙: UI 화면, 핸들러, 기능 전용 로직은 src/features/<featureName>/...에 두고, 로깅, API 클라이언트, 디자인 시스템 컴포넌트, 일반 유틸리티는 src/shared/...에 둡니다. 어떤 헬퍼가 한 기능에서만 의미가 있다면 그 기능 내부에 둡니다. 두 번째 실제 사용 사례가 생겼을 때 옮기세요.
폴더 이름은 기술이 아니라 목적을 설명해야 합니다. features와 shared는 스택이 바뀌어도 의미가 유지됩니다. misc나 new 같은 이름은 피하세요.
docs/는 작게 유지하세요. 시작용으로 docs/checklists.md 하나가 있으면 충분합니다: 실행 방법, 테스트 방법, 새 기능 폴더 추가 방법, "완료"가 무엇을 의미하는지.
누구나 같은 명령을 실행해 같은 결과를 얻을 수 있을 때 레포는 실체로 느껴집니다. 스크립트는 가드레일입니다: 추측을 줄이고 변경을 작게 유지하며 무언가 망가졌을 때 명확하게 드러나게 합니다.
작고 단순한 커맨드 집합으로 시작하세요. 새로온 사람이건 몇 주 뒤 돌아온 당신이건 특별한 플래그나 숨은 단계가 없어야 합니다.
모든 스택에 적용할 수 있는 기본 예:
{
"scripts": {
"dev": "node ./scripts/dev.js",
"build": "node ./scripts/build.js",
"test": "node ./scripts/test.js",
"test:quick": "node ./scripts/test.js --quick",
"test:full": "node ./scripts/test.js --full",
"format": "node ./scripts/format.js",
"lint": "node ./scripts/lint.js",
"smoke": "node ./scripts/smoke.js"
}
}
dev 스크립트를 행복한 경로(happy path)로 만드세요. 앱을 시작하고 어디서 실행되는지 출력하며 로그를 읽기 쉽게 유지해야 합니다. 서버가 시작할 수 없다면 필수 env 변수 누락, 포트 중복, DB 접속 불가 같은 하나의 명확한 메시지로 빠르게 실패하세요.
build 스크립트는 항상 깨끗한 출력 디렉터리를 만들어야 합니다. 먼저 이전 출력을 삭제한 뒤 새 아티팩트를 생성하세요. 그래야 어제 파일 때문에 생기는 이상한 버그를 피할 수 있습니다.
테스트는 빠른 검사와 느린 검사를 분리하세요. 빠른 테스트는 변경마다 실행(단위 테스트, 타입 검사), 전체 테스트는 통합 체크를 포함해 머지 전에 실행합니다.
스타일 관리는 하나의 커맨드로 일관되게 유지하세요. 간단한 규칙: format은 문제를 고치고, lint는 문제를 알려줍니다.
마지막으로 디버깅 낭비를 줄이기 위해 스모크 체크를 추가하세요:
build 후 빌드 출력이 존재하는지첫 수직 슬라이스는 UI가 보기 좋다는 것을 증명하는 것이 아니라 엔드투엔드로 앱이 동작함을 증명해야 합니다. 화면, 로직, 어떤 형태의 저장소까지 건드리는 작고 완성 가능한 기능을 고르세요. 저장소가 임시여도 괜찮습니다.
단순하고 유용한 항목을 고르세요. 예: "노트 추가" 또는 "작업 생성". 한 번에 끝낼 수 있을 정도로 작게, 그러나 클릭해서 실제 상태 변화를 볼 수 있을 정도로 완전하게 만드세요.
좋은 슬라이스는 네 부분을 가집니다: 라우트 혹은 화면 하나, 폼 하나, 저장 액션 하나, 표시 하나. 예: 제목 입력, 저장 버튼이 단일 함수 호출, 저장된 작업을 보여주는 목록.
빠르게 진행하려면 플레이스홀더 저장소부터 시작하세요. 메모리 배열, 로컬 JSON 파일, 간단한 스텁 인터페이스로 충분합니다. 핵심은 나중에 교체할 수 있는 경계를 만드는 것입니다. 오늘 코드가 taskRepository.save(task)를 호출하면 나중에 실제 DB로 바꾸는 것은 작은 변경이 됩니다.
UI는 단순하게 유지하세요. 디자인 시스템 논쟁, 빈 상태, 애니메이션은 건너뜁니다.
2분 안에 할 수 있는 수락 기준:
실행 가능한 골격과 하나의 수직 슬라이스가 있으면 목표는: 고장이 분명하게 드러나고 고치기 쉬운 상태로 만드는 것입니다. 많은 그린필드 시작이 무너지는 이유는 기능이 어렵기 때문이 아니라 작은 변경들이 놀라움을 만들기 때문입니다.
슬라이스를 추가할 때마다 충족할 작은 안정성 기준을 정하세요:
구체적 예: 첫 슬라이스가 사용자로 하여금 "Project"를 생성하고 목록에 보이게 한다면, 서버를 시작하고 생성 엔드포인트를 호출한 뒤 목록을 가져와 새 항목이 나타나는지 확인하는 테스트를 추가하세요. 실패하면 "Create Project endpoint returned 500"처럼 하나의 유용한 메시지로 크게 실패해야 합니다.
오류 처리에 관해선 일관된 응답 셋을 유지하세요. 검증 오류는 짧은 메시지("이름은 필수입니다")와 필드명을 반환하고, 예상치 못한 오류는 "문제가 발생했습니다. 다시 시도하세요." 같은 일반 메시지를 반환합니다. 상세 정보는 로그에 남기세요.
로그는 어떤 요청이었고 어떤 사용자(또는 익명), 무엇이 실패했는지, 어디서 실패했는지를 답해줄 때 가장 유용합니다. 개발 환경에서는 요청 ID와 소요 시간을 포함하되 토큰, 비밀번호, API 키, 전체 페이로드는 기본적으로 덤프하지 마세요.
작은 헬스 체크를 추가하세요. 웹이라면 /health 엔드포인트가 ok를 반환하면 충분합니다. 모바일이라면 백엔드에 도달할 수 없을 때 "Offline"으로 바뀌는 연결 상태가 빠른 신호가 됩니다.
그린필드 시작을 낭비하는 가장 빠른 방법은 모델에게 전체 앱을 요청하고 나중에야 실행해 보는 것입니다. 큰 생성은 작은 실수를 숨깁니다: 누락된 의존성, 잘못된 import 경로, 당신이 없는 도구를 전제로 한 스크립트 등. 모든 출력을 몇 분 내에 실행할 수 있어야 한다고 생각하세요.
또 다른 함정은 실제 기능 없이 완벽한 아키텍처를 설계하는 것입니다. 폴더 이름 논쟁은 생산적인 것처럼 보이지만 실제 슬라이스 없이 무엇이 어색한지 알 수 없습니다. 한 개의 작동 경로를 지원하는 단순한 구조가 테스트되지 않은 영리한 구조보다 낫습니다.
커맨드의 분산(command drift)도 흔합니다. AI가 서버를 시작하는 새로운 방법을 추가하고, 당신이 테스트용으로 또 다른 명령을 추가하면 곧 누가 클론한 레포를 "어떻게 실행해?"라고 물을 때 이미 이자를 지불하고 있는 셈입니다.
가장 많은 재작업을 야기하는 실수들:
간단한 예: 로그인, 테마, 빌링이 포함된 "완성된" 앱을 생성했는데 첫 실행이 비밀 키 누락 때문에 실패하고 .env.example도 없다면, 기능이 유용한지 알아보는 대신 셋업을 고치느라 시간을 보냅니다.
정직하게 접근하세요: 한 개의 실행 명령, 한 개의 작은 기능, 하나의 env 템플릿, 그다음 확장.
"한 기능만 더"를 추가하기 전에 프로젝트가 내일이나 다른 사람이 쉽게 잡을 수 있는지 확인하세요. 속도가 목적이 아니라 예측 가능성이 목적입니다.
어느 항목이든 실패하면 지금 고치세요. 레포가 작을 때 스크립트와 명명 규칙을 다듬는 건 저렴합니다.
그린필드 시작이 가치 있으려면 반복할 수 있어야 합니다. 첫 수직 슬라이스가 엔드투엔드로 동작하면 좋은 부분을 작은 템플릿으로 얼려 두세요: 동일한 폴더 패턴, 동일한 스크립트 이름, UI-API-데이터 연결 방식.
첫 슬라이스를 참고 구현(reference implementation)처럼 다루세요. 슬라이스 #2를 시작할 때 코드를 복사하지 말고 형태(shape)를 복사하세요. 슬라이스 #1이 라우트, 핸들러, 데이터 접근 계층, 기본 테스트를 가지고 있다면 슬라이스 #2도 같은 경로를 따라야 합니다.
계획은 가볍게 유지하세요. 다음 2-3개의 슬라이스를 위한 한 페이지 짜리 노트면 충분합니다: 각 슬라이스의 목표와 사용자 행동(한 문장), 필요한 데이터, 완료 체크, 조기에 테스트해야 할 리스크.
그다음 정기적인 유지 관리를 습관으로 만드세요. 주 1회 짧은 정리 시간: 스크립트 정리, README에 새 셋업 단계 반영, env 예제 파일 갱신으로 온보딩을 쉽게 유지하세요.
채팅 중심의 빌드 루프를 선호한다면 Koder.ai (koder.ai)는 플래닝 모드, 스냅샷, 롤백을 지원하고 필요할 때 소스 코드를 내보낼 수 있는 옵션입니다.
목표는 생각하지 않고도 실행할 수 있는 워크플로입니다: 2-3개의 슬라이스를 계획하고, 한 슬라이스를 빌드하고, 안정화하고, 반복하세요.