| ํญ๋ชฉ | ๋ด์ฉ |
|---|---|
| Invoke | /feature:create |
| Aliases | /feature, /feature:new |
| Category | kobic-workflow |
| Complexity | high |
| MCP Servers | serena, sequential, context7, magic |
/feature:create โ ๊ธฐ๋ฅ ํ๋๋ฅผ ์ฒ์๋ถํฐ ๋๊น์ง ์๋ ์กฐ๋ฆฝ#
ํ๋ง๋๋ก#
์ ๊ธฐ๋ฅ ํ๋๋ฅผ ๋ง๋ค ๋, ์๋ฒ(๋ฐฑ์๋)๋ถํฐ ํ๋ฉด(ํ๋ก ํธ์๋)๊น์ง ํ ๋ฒ์ ์๋์ผ๋ก ๋ง๋ค์ด ์ฃผ๋ "์กฐ๋ฆฝ ๋ผ์ธ" ์ ๋๋ค. ๊ฐ๊ตฌ ํ๋๋ฅผ ๋ถํยท์ค๋ช ์ยท์กฐ๋ฆฝยท๊ฒ์๊น์ง ํ ๋ฒ์ ๋๋ด ์ฃผ๋ ํ์ธํธ ์ฃผ๋ฌธ์ด๋ผ๊ณ ๋ณด๋ฉด ๋ฉ๋๋ค.
๋๊ฐยท์ธ์ ์ฐ๋์#
- ์๋ก์ด ๊ธฐ๋ฅ์ ๋ฐ๋ฐ๋ฅ๋ถํฐ ๋๊น์ง ํ ๋ฒ์ ๋ง๋ค๊ณ ์ถ์ ๋
- ์๋ฒ(Serverpod)์ ์ฑ ํ๋ฉด(Flutter)์ ๋์์ ๋ง๋ค์ด์ผ ํ ๋
- ์ ํด์ง ํ์ค ๊ตฌ์กฐ(Clean Architecture)๋๋ก ๋น ์ง์์ด ๋ง๋ค๊ณ ์ถ์ ๋
๋ฌด์์ ํด์ฃผ๋์#
๊ธฐ๋ฅ ์ด๋ฆ ํ๋๋ง ์ฃผ๋ฉด, ๋ค์์ ์์์ ๋ง๋ค๊ณ ๊ฒ์ฌ๊น์ง ํด ์ค๋๋ค.
- ์๋ฒ ์ชฝ: ๋ฐ์ดํฐ ๋ชจ๋ธ, ์๋ํฌ์ธํธ(์๋ฒ ๊ธฐ๋ฅ), ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ฐ์
- ์ฑ ์ชฝ: ํ๋ฉด, ์ํ ๊ด๋ฆฌ ์ฝ๋, ๋ฐ์ดํฐ ์ฐ๊ฒฐ ์ฝ๋
- ํ
์คํธ: ์๋ ํ
์คํธ(BDD
.featureํ์ผ ํฌํจ) - ๋ง๋ฌด๋ฆฌ ๊ฒ์ฌ: ์ฝ๋ ๋ถ์, ํ ์คํธ ์คํ, ๊ทธ๋ฆฌ๊ณ ์ค์ ์๋ฒ๋ฅผ ๋์ ์ฑ๊ณผ ์ ๋ง๋ฌผ๋ฆฌ๋์ง๊น์ง ํตํฉ ์ ๊ฒ
์ฆ, "๊ธฐ๋ฅ ํ๋"์ ํ์ํ ๋ชจ๋ ํ์ผ๊ณผ ๊ฒ์ฆ์ด ํ ๋ฌถ์์ผ๋ก ๋ง๋ค์ด์ง๋๋ค.
์ด๋ป๊ฒ ์ฐ๋์#
# ์ปค๋ฎค๋ํฐ ๊ฒ์๊ธ ๊ธฐ๋ฅ ๋ง๋ค๊ธฐ
/feature:create community Post
--location application
--caching swr
--endpoint-type app
--fields " title:String, content:String, category:PostCategory, imageUrls:List < String > ? "
# ์ฑํ
๋ฉ์์ง ๊ธฐ๋ฅ ๋ง๋ค๊ธฐ
/feature:create chat Message
--location application
--caching cache-first
--endpoint-type app
--fields " content:String, senderId:int, chatRoomId:int, readAt:DateTime? "
# ๊ด๋ฆฌ์ ๋์๋ณด๋ ๊ธฐ๋ฅ ๋ง๋ค๊ธฐ
/feature:create dashboard Stats
--location console
--caching none
--endpoint-type console
--fields " totalUsers:int, totalPosts:int, activeUsers:int "
-
์ฒซ ๋ฒ์งธ ๊ฐ์ ๊ธฐ๋ฅ ์ด๋ฆ(์:
community), ๋ ๋ฒ์งธ ๊ฐ์ ๋ฐ์ดํฐ ์ด๋ฆ(์:Post)์ผ๋ก, ๋ ๋ค ๊ผญ ํ์ํฉ๋๋ค. -
--location: ์ด๋์ ๋ง๋ค์ง (application์ผ๋ฐ ์ฑ /common๊ณต์ฉ /console๊ด๋ฆฌ์, ๊ธฐ๋ณธ๊ฐapplication) -
--caching: ๋ฐ์ดํฐ ์ ์ฅ ๋ฐฉ์ (swr/cache-first/none, ๊ธฐ๋ณธ๊ฐswr) -
--endpoint-type: ์๋ฒ ๊ธฐ๋ฅ ์ข ๋ฅ (app/console/both, ๊ธฐ๋ณธ๊ฐapp) --fields: ์ด๋ค ๋ฐ์ดํฐ ํญ๋ชฉ์ ๋ด์์ง (์:"title:String, content:String")--with-bdd: ํ ์คํธ๋ ๊ฐ์ด ๋ง๋ค์ง (๊ธฐ๋ณธ๊ฐ ์ผ์งtrue)
์์์ ๋ฌด์จ ์ผ์ด ๋ฒ์ด์ง๋์#
ํฌ๊ฒ ์ฌ์ฏ ๋จ๊ณ๋ฅผ ์ฐจ๋ก๋ก ์งํํ๋ฉฐ, ๋จ๊ณ๋ง๋ค ํ์ํ ํ์ผ์ ๋ง๋ค๊ณ ํ์ธํฉ๋๋ค.
- ์ฌ์ ์ ๊ฒ(Phase 0) โ ์์ ์ ํ์ํ ๋๊ตฌ(๋ฐํ์ ๊ฒ์ฆ์ฉ MCP)๊ฐ ์ค๋น๋๋์ง ํ์ธํ๊ณ , ์์ผ๋ฉด ์๋์ผ๋ก ์ค์นยท์ฐ๊ฒฐํฉ๋๋ค.
- ์๊ตฌ์ฌํญ ํ์ธ(Phase 1) โ ๊ธฐ๋ฅ ์ด๋ฆ, ๋ด์ ๋ฐ์ดํฐ ํญ๋ชฉ, ํ์ํ ๊ธฐ๋ฅ ๋ฒ์(๋ชฉ๋ก/์ถ๊ฐ/์์ /์ญ์ ), ์ ์ฅ ๋ฐฉ์, ํ ์คํธ ํฌํจ ์ฌ๋ถ๋ฅผ ์ ๋ฆฌํฉ๋๋ค.
- ์๋ฒ ๋ง๋ค๊ธฐ(Phase 2) โ ๋ฐ์ดํฐ ๋ชจ๋ธ๊ณผ ์๋ฒ ๊ธฐ๋ฅ์ ๋ง๋ค๊ณ , ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ฐ์ํฉ๋๋ค.
- ์ฑ ๋ง๋ค๊ธฐ(Phase 3) โ ๋ฐ์ดํฐ ๊ตฌ์กฐ, ๋ฐ์ดํฐ ์ฐ๊ฒฐ, ํ๋ฉด๊ณผ ์ํ ๊ด๋ฆฌ ์ฝ๋๋ฅผ ๋ง๋ญ๋๋ค.
- ํ ์คํธ ๋ง๋ค๊ธฐ(Phase 4) โ ์๋๋ฆฌ์ค ๊ธฐ๋ฐ ์๋ ํ ์คํธ(BDD)๋ฅผ ์์ฑํฉ๋๋ค.
-
ํตํฉยท๊ฒ์(Phase 5) โ ์ฝ๋ ๋ถ์๊ณผ ํ
์คํธ๋ฅผ ๋๋ฆฌ๊ณ , ์ค์ ์๋ฒ๋ฅผ ๋์(
serverpod start) ์๋ฒ์ ์ฑ์ด ์ค์ ๋ก ์ ๋ง๋ฌผ๋ฆฌ๋์ง๊น์ง ์ต์ข ํ์ธํฉ๋๋ค.
โ๏ธ ์์ธ ์ต์ ยท์คํ ๋ช ์ธ (๊ฐ๋ฐ์ / AI ์์ด์ ํธ์ฉ)
Triggers#
- When creating a new Feature from start to finish
- When implementing Serverpod backend and Flutter frontend simultaneously
- When a complete Clean Architecture workflow is needed
Context Trigger Pattern#
/feature:create {feature_name} {entity_name} [--options]Parameters#
| Parameter | Required | Description | Example |
|---|---|---|---|
feature_name | โ | Feature module name (snake_case) | community, chat, wallet |
entity_name | โ | Entity name (PascalCase) | Post, Message, Transaction |
--location | โ | Location | application, common, console (default: application) |
--caching | โ | Caching strategy | swr, cache-first, none (default: swr) |
--endpoint-type | โ | Endpoint type | app, console, both (default: app) |
--fields | โ | Field Definition | "title:String, content:String" |
--with-bdd | โ | BDD Test Generation | true, false (default: true) |
--bdd-from | โ | BDD Scenario source | .claude/docs/{feature}/bdd/ |
Execution Flow#
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Phase 0: Preflight (MCP & ํ๊ฒฝ ์ ๊ฒ) โญ fvm ๊ณ ๋ ค โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ 0-1. marionette_mcp ์คํ ํ์ผ ์กด์ฌ ํ์ธ โ
โ 0-2. ๋ฏธ์ค์น ์ `fvm dart pub global activate` ์๋ ์คํ โ
โ 0-3. Claude Code MCP ๋ฑ๋ก ์ํ ํ์ธ (claude mcp list) โ
โ 0-4. ์คํจ ์ ์ ๋ ๊ฒฝ๋ก๋ก ์ฌ๋ฑ๋ก + PATH ์ฃผ์
โ
โ 0-5. Cursor/Zed MCP ์ค์ ํ์ผ ์กด์ฌ/๋๊ธฐํ ํ์ธ(์ ํ) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Phase 1: Requirements gathering (Interactive) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ 1. Feature/Entity ์ด๋ฆ ํ์ธ โ
โ 2. ํ๋ ์ ์ ์์ง โ
โ 3. CRUD ๋ฉ์๋ ๋ฒ์ ํ์ธ โ
โ 4. ์บ์ฑ ์ ๋ต ์ ํ โ
โ 5. BDD ํ
์คํธ ํฌํจ ์ฌ๋ถ ํ์ธ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Phase 2: Backend implementation โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Step 1: /serverpod:model โ
โ Step 2: /serverpod:endpoint โ
โ Step 3: melos run backend:pod:generate โ
โ Step 4: ๋ง์ด๊ทธ๋ ์ด์
(ํ์ ์) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Phase 3: Frontend implementation โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Step 5: /feature:domain โ
โ Step 6: /feature:data โ
โ Step 7: /feature:presentation โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Phase 4: BDD ํ
์คํธ ์์ฑ (--with-bdd true ์) โญ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Step 8: /bdd:generate {feature_name} โ
โ Step 9: melos run test:bdd --scope={feature} โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Phase 5: Integration and verification โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Step 10: DI ๋ฑ๋ก ํ์ธ โ
โ Step 11: Route ๋ฑ๋ก ํ์ธ โ
โ Step 12: melos run build โ
โ Step 13: melos run analyze โ
โ Step 14: melos run test --scope={feature} โ
โ Step 15: melos run test:bdd --scope={feature} โ
โ Step 16: ๋ก์ปฌ ํ์คํ ํตํฉ ๊ฒ์ฆ โญ (serverpod start) โ
โ โณ server+๋ด์ฅ Postgres+app ๊ธฐ๋ โ ๋ก์ปฌ ๋ฐฑ์๋ ๋์ ํตํฉ โ
โ โณ backend: dart test -t integration / front: ๋ก์ปฌ ๋ฐฑ์๋ โ
โ โณ ๋ฐฑ์๋ ๋ณ๊ฒฝ ์ ๋ง์ด๊ทธ๋ ์ด์
/๋ก๊ทธ๋ Serverpod MCP ํ์ฉ โ
โ โณ ํด๋ฐฑ(3.x): docker compose up -d + dart run โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโPhase 0: Preflight (MCP & ํ๊ฒฝ ์ ๊ฒ)#
๋ชฉ์ : ๊ธฐ๋ฅ ์์ ์ ์ ๋ฐํ์ ๊ฒ์ฆ(marionette_mcp)์ด ๊ฐ๋ฅํ ์ํ์ธ์ง ํ์ธํ๊ณ , ํ์ํ๋ฉด ์๋ ์ค์นยท์ฌ๋ฑ๋ก. fvm ํ๊ฒฝ์ ์ ์ ๋ก ํจ.
Step 0-1. ์คํ ํ์ผ ์กด์ฌ ํ์ธ#
MCP_BIN= " $HOME/.pub-cache/bin/marionette_mcp "
if [ ! -x " $MCP_BIN " ]; then
echo " โ ๏ธ marionette_mcp ๋ฏธ์ค์น โ ์๋ ์ค์น๋ฅผ ์์ํฉ๋๋ค. "
NEEDS_INSTALL=1
else
echo " โ
marionette_mcp ์ค์น๋จ: $MCP_BIN "
fiStep 0-2. fvm ๊ฒฝ์ ์๋ ์ค์น#
์ค์: dart๋ zshrc alias(fvm dart)๋ผ GUI ์ฑ์ subprocess ํ๊ฒฝ์์๋ ๋์ํ์ง ์์ โ ํญ์ fvm dart๋ก ์คํ.
if [ " $NEEDS_INSTALL " = " 1 " ]; then
# fvm default SDK๋ก ๊ธ๋ก๋ฒ ํ์ฑํ (ํ๋ก์ ํธ๋ณ SDK์ ๋ณ๊ฐ)
fvm dart pub global activate marionette_mcp
# PATH ํ์ธ
case " :$PATH: " in
* " :$HOME/.pub-cache/bin: " *) ;;
*)
echo ' export PATH= " $PATH:$HOME/.pub-cache/bin " ' > > " $HOME/.zshrc "
export PATH= " $PATH:$HOME/.pub-cache/bin "
;;
esac
fiStep 0-3. Claude Code MCP ๋ฑ๋ก ์ํ ํ์ธ#
if ! claude mcp list 2 > & 1 | grep -q " marionette:.*โ Connected " ; then
echo " โ ๏ธ marionette MCP ์ฐ๊ฒฐ ์คํจ โ ์ ๋ ๊ฒฝ๋ก๋ก ์ฌ๋ฑ๋ก "
claude mcp remove marionette 2 > /dev/null || true
claude mcp add --transport stdio marionette -- " $HOME/.pub-cache/bin/marionette_mcp "
claude mcp list | grep marionette
fiStep 0-4. Cursor / Zed ์ค์ ๋๊ธฐํ (์ ํ)#
GUI ์ฑ์
~/.zshrc์ PATH/alias๋ฅผ ์ฝ์ง ์์ โ ์ ๋ ๊ฒฝ๋ก +env.PATH์ฃผ์ ํ์.
Cursor (~/.cursor/mcp.json):
{
" mcpServers " : {
" marionette " : {
" command " : " /Users/dongwoo/.pub-cache/bin/marionette_mcp " ,
" env " : { " PATH " : " /Users/dongwoo/fvm/default/bin:/usr/bin:/bin " }
}
}
}Zed (~/.config/zed/settings.json):
{
" context_servers " : {
" marionette " : {
" command " : {
" path " : " /Users/dongwoo/.pub-cache/bin/marionette_mcp " ,
" env " : { " PATH " : " /Users/dongwoo/fvm/default/bin:/usr/bin:/bin " }
}
}
}
}Step 0-5. ๋์ Flutter ์ฑ ์ ์ ์กฐ๊ฑด ์๋ด#
MCP๋ ๋ ์์ด๋ ๋์ ์ฑ์ marionette_flutter ํตํฉ์ด ์์ผ๋ฉด ๋ถ์ง ๋ชปํจ. Phase 4.7(์ค ๋์ ๊ตฌํ) ์ง์ ์ ์ ๊ฒ:
# pubspec.yaml
dev_dependencies:
marionette_flutter: ^latest// main.dart (debug build ํ์ )
void main() {
MarionetteBinding.ensureInitialized();
runApp(const MyApp());
}
snapshot ๋ฒ์ ๋ถ์ผ์น(exit 253): fvm ํ๋ก์ ํธ SDK ์ ํ ํ ๋ฐ์ ๊ฐ๋ฅ. ๋ํผ๊ฐ
dart pub global run์ผ๋ก fallbackํ์ง๋ง ๋ฐ๋ณต๋๋ฉดfvm dart pub global activate marionette_mcp์ฌ์คํ.
Preflight ๊ฒ์ดํธ#
์ 5๋จ๊ณ ๋ชจ๋ ํต๊ณผํด์ผ Phase 1 ์ง์ . ์คํจ ์ ์ฌ์ฉ์์๊ฒ ์์ธ ๋ณด๊ณ ํ ์ค๋จ.
Phase 1: Requirements Gathering#
Interactive Mode#
## Feature Creation Requirements
### default ์ ๋ณด
- **Feature name**: {feature_name}
- **Entity name**: {entity_name}
- **Location**: application / common / console
### Entity Fields
| Field Name | Type | Required | Description |
|--------|------|------|------|
| title | String | โ
| Title |
| content | String | โ
| Content |
| category | Enum | โ
| Category |
### CRUD Methods
- [x] List query (pagination)
- [x] Single item query
- [x] Create
- [x] Update
- [x] Delete
### Caching Strategy
- [x] SWR (Stale-While-Revalidate)
- [ ] Cache-First
- [ ] NonePhase 2: Backend Implementation#
Step 1: Serverpod Model#
# Run /serverpod:model command
/serverpod:model {feature_name} {entity_name}
--fields " {fields} "
--has-crud trueGenerated Files:
backend/.../model/entities/{entity_name}.spy.yamlbackend/.../model/dto/...backend/.../model/enum/...
Step 2: Serverpod Endpoint#
# Run /serverpod:endpoint command
/serverpod:endpoint {feature_name} {entity_name}
--type {endpoint_type}Generated Files:
backend/.../endpoint/{feature_name}_endpoint.dartbackend/.../service/{feature_name}_service.dart
Step 3: Code Generation#
melos run backend:pod:generateStep 4: Migration#
melos run backend:pod:create-migration
melos run backend:pod:run-migrationPhase 3: Frontend Implementation#
Step 5: Domain Layer#
# Run /feature:domain command
/feature:domain {feature_name} {entity_name}
--location {location}Generated Files:
- Entity, Repository Interface, UseCase
- UseCase Test
Step 6: Data Layer#
# Run /feature:data command
/feature:data {feature_name} {entity_name}
--location {location}
--caching {caching}Generated Files:
- Repository Implementation์ฒด, Serverpod Mixin
- Cache Strategy, Local DB (Drift)
Step 7: Presentation Layer#
# Run /feature:presentation command
/feature:presentation {feature_name} {entity_name}
--location {location}Generated Files:
- BLoC (Event, State), BLoC Test
- Page, Widget, Widget Test
- Route, Widgetbook UseCase
Phase 4: BDD Test Generation#
--with-bdd true (default) executed:
Step 8: BDD Scenario and Step Generation#
# Run /bdd:generate command
/bdd:generate {feature_name}
--entity-name {entity_name}
--location {location}
--from-claude-docs true # .claude/docs์ BDD ํ์ผ์ด ์๋ ๊ฒฝ์ฐGenerated Files:
feature/{location}/{feature_name}/
โโโ build.yaml # BDD ๋น๋ ์ค์
โโโ test/src/bdd/
โโโ {feature}_list.feature
โโโ {feature}_detail.feature
โโโ {feature}_form.feature
โโโ step/
โ โโโ common_steps.dart # ๊ณต์ฉ ์คํ
import
โ โโโ {feature}_steps.dart # Feature ์ ์ฉ ์คํ
โโโ hooks/
โโโ hooks.dart # Setup/TeardownStep 9: Generate BDD test code#
# Run bdd_widget_test builder
melos run test:bdd --scope={feature_name}Generation result: Auto-generated test code from .feature files
Phase 5: Integration and Verification#
Step 10: Dependency Wiring Verification#
Items to verify: No di/ folder, no getIt usage, direct BlocProvider creation
// ํ์ด์ง์์ BLoC ์ง์ ์์ฑ
BlocProvider(create: (_) => {Feature}Bloc())
Step 9: Route Registration Verification#
File to verify: feature/{type}/{feature}/lib/src/route/{feature}_route.dart (TypedGoRoute/GoRouteData per-feature; kobic์๋ ๋จ์ผ app_router.dart๊ฐ ์๊ณ ๋ผ์ฐํธ๋ feature ๋ชจ๋๋ณ๋ก ๋ถ์ฐ ์ ์๋จ)
Step 10-12: Build and test#
melos run build
melos run analyze
melos run test --scope={feature_name}Step 16: ๋ก์ปฌ ํ์คํ ํตํฉ ๊ฒ์ฆ (Serverpod 4 / ๋ก์ปฌ ํ์คํ) โญ#
๋ชฉ์ : ์์ ฏ/์ ๋ ํ ์คํธ(mock)์ ๋ณ๊ฐ๋ก, ์ค์ ๋ฐฑ์๋๋ฅผ ๋์ด ์ํ์์ backendโfront ๊ณ์ฝ์ ๊ฒ์ฆํ๋ค. Serverpod 4์ ๋ด์ฅ Postgres ๋๋ถ์ Docker ์์ด ์์ ๋ก์ปฌ๋ก ํตํฉํ ์คํธ๊ฐ ๊ฐ๋ฅํ๋ค.
์ธ์ ์ผ๋๊ฐ: Phase 2(Backend)์์ ๋ชจ๋ธ/์๋ํฌ์ธํธ๊ฐ ์ถ๊ฐยท๋ณ๊ฒฝ๋์๊ฑฐ๋, Phase 3 data layer๊ฐ ์ค์ endpoint๋ฅผ ํธ์ถํ ๋. ์์ ์์ ฏ/์ ๋๋ง ๋ฐ๋ ๊ฒฝ์ฐ๋ ์๋ต ๊ฐ๋ฅ(๊ธฐ์กด mock ํ ์คํธ๋ก ์ถฉ๋ถ).
๋ก์ปฌ ํ์คํ ๊ธฐ๋ โ
serverpod startํ ๋ช ๋ น์ผ๋ก ๋ฐฑ์๋ ์๋ฒ + ๋ด์ฅ Postgres + Flutter ์ฑ์ ํจ๊ป ๊ธฐ๋ํ๋ค(์๋ฒยทDBยท์นยท์ฑ sub-second stateful ํซ๋ฆฌ๋ก๋, ์ฌ์ปดํ์ผ/์ฌ์์ ์์). ์ฑ์ dev flavor์์ ๋ก์ปฌ ์๋ฒ(http://localhost:8080/)๋ก ์ฐ๊ฒฐ๋๊ณ Staging์ ํด๋ฐฑ์ด๋ค. ํซ๋ฆฌ๋ก๋๊ฐ ๋งํ๋ฉดserverpod startํฐ๋ฏธ๋์์ R ํค๋ก ์๋ฒ+์ฑ ๊ฐ์ ์ฌ์์.๋ก์ปฌ ๋ฐฑ์๋ ๋์ ํตํฉ ๊ฒ์ฆ
- ๋ฐฑ์๋:
withServerpodํฌํผ ๊ธฐ๋ฐ ํตํฉํ ์คํธ๋ฅผdart test -t integration์ผ๋ก ์คํ(๋ด์ฅ Postgres๋ผ Docker ๋ถํ์, ๊ธฐ๋ฅ ๊ตฌํ ์ค ๋ฐ๋ก endpoint ํตํฉํ ์คํธ ๊ฐ๋ฅ). - ํ๋ก ํธ: feature/Patrol/ํตํฉ ํ ์คํธ๋ mock์ด ์๋๋ผ ๋ฐฉ๊ธ ๋์ด ๋ก์ปฌ ๋ฐฑ์๋๋ฅผ ๋์์ผ๋ก ์ํ. base-URL์ ์ฑ์ ๊ธฐ์กด client/OpenApiService/flavor ์ค์ ์ ๋ฐ๋ฅด๊ณ ํ๋์ฝ๋ฉํ์ง ์๋๋ค.
- ๋ฐฑ์๋:
๋ฐฑ์๋ ๋ณ๊ฒฝ ์ ๋ง์ด๊ทธ๋ ์ด์ ยท๋ก๊ทธ๋ Serverpod MCP ํ์ฉ โ ์คํ ์ค์ธ ๋ก์ปฌ ์๋ฒ์ ์์ด์ ํธ๊ฐ ์ฐ๊ฒฐํด DB ๋ง์ด๊ทธ๋ ์ด์ ์์ฑยท์ ์ฉ, ์๋ฒ ๋ก๊ทธ ์ฝ๊ธฐ, ์ฑ ๊ตฌ๋+์คํฌ๋ฆฐ์ท ๊ฒํ ๋ฅผ ์ํํ๋ค.
Serverpod 3.x ํ๊ฒฝ ํด๋ฐฑ โ ๋ด์ฅ Postgres๊ฐ ์๋ 3.x(legacy)์์๋
docker compose up -d๋ก DB๋ฅผ ๋์ด ๋คdart run bin/main.dart๋ก ์๋ฒ๋ฅผ ๊ธฐ๋ํ๊ณ ๋์ผํ๊ฒdart test -t integration์ํ.
์์ธ ์ ์ฐจ๋ serverpod-local-fullstack, serverpod-mcp-guide ์คํฌ์ ์ฐธ์กฐ.
TodoWrite Template#
TodoWrite([
// Phase 0: Preflight
{"content": "marionette_mcp ์ค์น ํ์ธ (fvm dart pub global activate)", "status": "pending", "activeForm": "marionette_mcp Preflight ์ค"},
{"content": "Claude Code MCP ๋ฑ๋ก ์ํ ํ์ธ/์ฌ๋ฑ๋ก", "status": "pending", "activeForm": "MCP ๋ฑ๋ก ํ์ธ ์ค"},
// Backend
{"content": "Generate Serverpod model", "status": "pending", "activeForm": "Generate Serverpod model in progress"},
{"content": "Generate Serverpod endpoint", "status": "pending", "activeForm": "Generate Serverpod endpoint in progress"},
{"content": "backend:pod:generate ์คํ", "status": "pending", "activeForm": "backend:pod:generate running"},
// Frontend - Domain
{"content": "Generate Domain Entity", "status": "pending", "activeForm": "Generate Domain Entity in progress"},
{"content": "Generate Repository Interface", "status": "pending", "activeForm": "Generate Repository Interface in progress"},
{"content": "Generate UseCase", "status": "pending", "activeForm": "Generate UseCase in progress"},
{"content": "Generate UseCase tests", "status": "pending", "activeForm": "Generate UseCase tests in progress"},
// Frontend - Data
{"content": "Generate Repository implementation", "status": "pending", "activeForm": "Generate Repository implementation in progress"},
{"content": "Generate Serverpod Mixin", "status": "pending", "activeForm": "Generate Serverpod Mixin in progress"},
// Frontend - Presentation
{"content": "Generate BLoC", "status": "pending", "activeForm": "Generate BLoC in progress"},
{"content": "Generate BLoC tests", "status": "pending", "activeForm": "Generate BLoC tests in progress"},
{"content": "Generate Page/Widget", "status": "pending", "activeForm": "Generate Page/Widget in progress"},
{"content": "Generate Widget tests", "status": "pending", "activeForm": "Generate Widget tests in progress"},
{"content": "Define Routes", "status": "pending", "activeForm": "Define Routes in progress"},
{"content": "Generate Widgetbook UseCase", "status": "pending", "activeForm": "Generate Widgetbook UseCase in progress"},
// BDD ํ
์คํธ (--with-bdd true ์)
{"content": "Generate BDD .feature files", "status": "pending", "activeForm": "Generate BDD .feature files in progress"},
{"content": "Generate BDD Step definitions", "status": "pending", "activeForm": "Generate BDD Step definitions in progress"},
{"content": "Configure BDD Hooks", "status": "pending", "activeForm": "Configure BDD Hooks in progress"},
{"content": "Generate BDD test code", "status": "pending", "activeForm": "Generate BDD test code in progress"},
// Integration
{"content": "Code generation and analysis", "status": "pending", "activeForm": "Code generation and analysis in progress"},
{"content": "Run unit tests", "status": "pending", "activeForm": "Run unit tests in progress"},
{"content": "Run BDD tests", "status": "pending", "activeForm": "Run BDD tests in progress"},
{"content": "๋ก์ปฌ ํ์คํ ๊ธฐ๋ (serverpod start: server+๋ด์ฅ Postgres+app)", "status": "pending", "activeForm": "๋ก์ปฌ ํ์คํ ๊ธฐ๋ ์ค"},
{"content": "๋ก์ปฌ ๋ฐฑ์๋ ๋์ ํตํฉ ๊ฒ์ฆ (backend dart test -t integration / front ๋ก์ปฌ ๋ฐฑ์๋)", "status": "pending", "activeForm": "๋ก์ปฌ ๋ฐฑ์๋ ํตํฉ ๊ฒ์ฆ ์ค"},
])
MCP Integration#
| Phase | MCP Server | Purpose |
|---|---|---|
| Requirements analysis | Sequential | Complex analysis and planning |
| Backend | Serena, Context7 | Pattern analysis, Serverpod Document |
| Domain | Serena, Context7 | UseCase Pattern, Clean Architecture |
| Data | Serena, Context7 | Mixin Pattern, Drift Document |
| Presentation | Magic, Serena | UI generation, BLoC Pattern |
| Verification | Serena | Symbol search, reference verification |
Reference Agents#
Reference ${CLAUDE_PLUGIN_ROOT}/commands/agents/feature-orchestrator-agent.md for detailed implementation rules
Examples#
Create Community Post Feature#
/feature:create community Post
--location application
--caching swr
--endpoint-type app
--fields " title:String, content:String, category:PostCategory, imageUrls:List < String > ? "Create Chat Message Feature#
/feature:create chat Message
--location application
--caching cache-first
--endpoint-type app
--fields " content:String, senderId:int, chatRoomId:int, readAt:DateTime? "Create Admin Dashboard Feature#
/feature:create dashboard Stats
--location console
--caching none
--endpoint-type console
--fields " totalUsers:int, totalPosts:int, activeUsers:int "Success Criteria#
- โ All files generated in correct locations
- โ
melos run analyzeNo errors - โ
melos run test --scope={feature_name}Passes - โ
melos run test:bdd --scope={feature_name}Passes (--with-bdd true when) - โ DI Registration complete
- โ Route Registration complete
- โ Components verifiable from Widgetbook
- โ BDD .feature File Gherkin ๋ฌธ๋ฒ ์ค์
- โ
๋ก์ปฌ ํ์คํ(
serverpod start: server+๋ด์ฅ Postgres+app) ๊ธฐ๋ ์ฑ๊ณต โ ๋ฐฑ์๋ ๋ณ๊ฒฝ ์ - โ
๋ก์ปฌ ๋ฐฑ์๋ ๋์ ํตํฉ ๊ฒ์ฆ ํต๊ณผ (backend
dart test -t integration/ front๋ ๋ก์ปฌ ๋ฐฑ์๋ ๋์). 3.x ํด๋ฐฑ:docker compose up -d+dart run
Core Rules Summary#
Backend#
- Korean comments on all fields
- Follow import order
- Separate business logic into Service
Domain#
- UseCase const constructor + Optional Constructor Injection
- getIt/@injectable prohibited
- All UseCase tests required
Data#
- Serverpod Mixin
as podnamespace required - SWR/Cache-First caching strategy
Presentation#
- BLoC Event: sealed class + private implementation
- UseCase Optional Constructor Injection (
Bloc(useCase: mockUseCase)Test) - Widget
super.keylast position - BLoC/Widget tests required
- Widgetbook reflection required