LogoSkills

serverpod:model

Serverpod .spy.yaml model file generation

ํ•ญ๋ชฉ๋‚ด์šฉ
Invoke/serverpod:model
Categorykobic-workflow
Complexitymoderate
MCP Serversserena, context7

/serverpod:model โ€” ๋ฐฑ์—”๋“œ ๋ฐ์ดํ„ฐ ์„ค๊ณ„๋„ ๋งŒ๋“ค๊ธฐ#

ํ•œ๋งˆ๋””๋กœ#

์„œ๋ฒ„๊ฐ€ ๋‹ค๋ฃฐ ๋ฐ์ดํ„ฐ์˜ "์„ค๊ณ„๋„"๋ฅผ ์ž๋™์œผ๋กœ ๊ทธ๋ ค์ฃผ๋Š” ๋‹จ๊ณ„์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด "๋ฐฐ๋„ˆ"๋ผ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋งŒ๋“ ๋‹ค๋ฉด, ๋ฐฐ๋„ˆ์— ์–ด๋–ค ์ •๋ณด(์ œ๋ชฉ, ์ด๋ฏธ์ง€ ์ฃผ์†Œ ๋“ฑ)๊ฐ€ ๋“ค์–ด๊ฐ€๋Š”์ง€ ์ •ํ•ด์ง„ ์–‘์‹์˜ ํŒŒ์ผ๋กœ ํ•œ ๋ฒˆ์— ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค. ์ง‘์„ ์ง“๊ธฐ ์ „์— ๋ฐฉยท์ฐฝ๋ฌธ ์œ„์น˜๋ฅผ ์ •ํ•œ ๋„๋ฉด์„ ๊ทธ๋ฆฌ๋Š” ๊ฒƒ๊ณผ ๊ฐ™์•„์š”.

๋ˆ„๊ฐ€ยท์–ธ์ œ ์“ฐ๋‚˜์š”#

  • ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ ์ข…๋ฅ˜(๋ฐฐ๋„ˆ, ์ฑ…, ๊ฒฐ์ œ ๋‚ด์—ญ ๋“ฑ)๋ฅผ ์„œ๋ฒ„์— ์ถ”๊ฐ€ํ•ด์•ผ ํ•  ๋•Œ
  • ๋ฐฑ์—”๋“œ(์„œ๋ฒ„)๊ฐ€ ์ €์žฅํ•˜๊ณ  ์ฃผ๊ณ ๋ฐ›์„ ๋ฐ์ดํ„ฐ ํ˜•ํƒœ๋ฅผ ์ฒ˜์Œ ์ •์˜ํ•  ๋•Œ
  • ์ „์ฒด ๊ธฐ๋Šฅ์„ ํ•œ ๋ฒˆ์— ๋งŒ๋“œ๋Š” /feature:create ์ž‘์—…์˜ 1๋‹จ๊ณ„๋กœ ์ž๋™ ํ˜ธ์ถœ๋  ๋•Œ

๋ฌด์—‡์„ ํ•ด์ฃผ๋‚˜์š”#

๋ฐ์ดํ„ฐ ์„ค๊ณ„๋„ ํŒŒ์ผ(.spy.yaml)๋“ค์„ ์ •ํ•ด์ง„ ํด๋”์— ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค. ๊ธฐ๋Šฅ ์ด๋ฆ„์ด banner๋ผ๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ƒ๊น๋‹ˆ๋‹ค.

  • ๋ณธ์ฒด ์ •์˜ (entities/{์ด๋ฆ„}.spy.yaml) โ€” ์ด ๋ฐ์ดํ„ฐ๊ฐ€ ๊ฐ€์ง„ ํ•ญ๋ชฉ๋“ค(์ œ๋ชฉ, ์ž‘์„ฑ์ž, ์ƒ์„ฑ์ผ์‹œ ๋“ฑ)
  • ์š”์ฒญ์šฉ ์–‘์‹ (dto/{์ด๋ฆ„}_create_request.spy.yaml, ..._update_request.spy.yaml) โ€” ๋ฐ์ดํ„ฐ๋ฅผ ๋งŒ๋“ค๊ฑฐ๋‚˜ ์ˆ˜์ •ํ•  ๋•Œ ์ฃผ๊ณ ๋ฐ›๋Š” ํ˜•์‹
  • ์‘๋‹ต์šฉ ์–‘์‹ (dto/{์ด๋ฆ„}_list_response.spy.yaml) โ€” ๋ชฉ๋ก์„ ๋Œ๋ ค์ค„ ๋•Œ์˜ ํ˜•์‹(๋ชฉ๋ก, ์ „์ฒด ๊ฐœ์ˆ˜, ๋‹ค์Œ ํŽ˜์ด์ง€ ์œ ๋ฌด)
  • ๋ถ„๋ฅ˜๊ฐ’ ์ •์˜ (enum/{์ด๋ฆ„}_category.spy.yaml) โ€” ์ •ํ•ด์ง„ ์„ ํƒ์ง€ ๋ชฉ๋ก(์˜ˆ: ์ผ๋ฐ˜ยท๊ณต์ง€ยท์ด๋ฒคํŠธ)

๋ชจ๋“  ํ•ญ๋ชฉ์—๋Š” ํ•œ๊ตญ์–ด ์„ค๋ช…์ด ๋ถ™๊ณ , ์ƒ์„ฑ์ผ์‹œยท์ˆ˜์ •์ผ์‹œ ๊ฐ™์€ ํ•„์ˆ˜ ํ•ญ๋ชฉ๊ณผ ๊ฒ€์ƒ‰์„ ๋น ๋ฅด๊ฒŒ ํ•˜๋Š” ์ƒ‰์ธ(index)์ด ์ž๋™์œผ๋กœ ๋“ค์–ด๊ฐ‘๋‹ˆ๋‹ค.

์–ด๋–ป๊ฒŒ ์“ฐ๋‚˜์š”#

# ๋ฐฐ๋„ˆ ๋ชจ๋ธ ๋งŒ๋“ค๊ธฐ
/serverpod:model banner Banner
  --fields  " title:String, imageUrl:String, linkUrl:String?, sortOrder:int, isActive:bool " 

 # ์ฑ… ๋ชจ๋ธ ๋งŒ๋“ค๊ธฐ
/serverpod:model books Book
  --fields  " title:String, authorId:int, categoryId:int, price:double, coverUrl:String? " 

 # ๊ฒฐ์ œ ๋‚ด์—ญ ๋ชจ๋ธ ๋งŒ๋“ค๊ธฐ
/serverpod:model payments Transaction
  --fields  " amount:double, type:TransactionType, description:String?, balanceAfter:double "
  • ์ฒซ ๋ฒˆ์งธ ๊ฐ’์€ ๊ธฐ๋Šฅ ์ด๋ฆ„(์†Œ๋ฌธ์ž, ์˜ˆ: banner), ๋‘ ๋ฒˆ์งธ ๊ฐ’์€ ๋ฐ์ดํ„ฐ ์ด๋ฆ„(๋Œ€๋ฌธ์ž ์‹œ์ž‘, ์˜ˆ: Banner)์ž…๋‹ˆ๋‹ค. ๋‘˜ ๋‹ค ๋ฐ˜๋“œ์‹œ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
  • --fields ๋กœ ๋“ค์–ด๊ฐˆ ํ•ญ๋ชฉ๋“ค์„ ์ ์Šต๋‹ˆ๋‹ค. ์ด๋ฆ„ ๋’ค์˜ ? ๋Š” "์žˆ์–ด๋„ ๋˜๊ณ  ์—†์–ด๋„ ๋˜๋Š” ํ•ญ๋ชฉ"์ด๋ผ๋Š” ๋œป์ž…๋‹ˆ๋‹ค.
  • --has-crud, --has-enum ์€ ๊ฐ๊ฐ ์ƒ์„ฑ/์ˆ˜์ • ์–‘์‹๊ณผ ๋ถ„๋ฅ˜๊ฐ’ ํŒŒ์ผ์„ ํ•จ๊ป˜ ๋งŒ๋“ค์ง€ ์ •ํ•ฉ๋‹ˆ๋‹ค(๊ธฐ๋ณธ๊ฐ’์€ ๋‘˜ ๋‹ค ๋งŒ๋“ฆ).

์•ˆ์—์„œ ๋ฌด์Šจ ์ผ์ด ๋ฒŒ์–ด์ง€๋‚˜์š”#

  1. ๊ธฐ์กด ๋ฐฉ์‹ ์‚ดํŽด๋ณด๊ธฐ โ€” ์ด๋ฏธ ๋งŒ๋“ค์–ด ๋‘” ๋น„์Šทํ•œ ๋ฐ์ดํ„ฐ(๋ฐฐ๋„ˆยท์ฑ… ๋“ฑ)์˜ ๊ตฌ์กฐ๋ฅผ ์ฐธ๊ณ ํ•ด ๊ฐ™์€ ์Šคํƒ€์ผ๋กœ ๋งž์ถฅ๋‹ˆ๋‹ค.
  2. ์„ค๊ณ„๋„ ํŒŒ์ผ ์ƒ์„ฑ โ€” ๋ณธ์ฒด, ์š”์ฒญยท์‘๋‹ต ์–‘์‹, ๋ถ„๋ฅ˜๊ฐ’ ํŒŒ์ผ์„ ํ•œ ๋ฒˆ์— ๋งŒ๋“ค๊ณ  ๊ฐ ํ•ญ๋ชฉ์— ํ•œ๊ตญ์–ด ์„ค๋ช…์„ ๋ถ™์ž…๋‹ˆ๋‹ค.
  3. ์ ๊ฒ€ โ€” ๋ชจ๋“  ํ•ญ๋ชฉ์— ์„ค๋ช…์ด ๋‹ฌ๋ ธ๋Š”์ง€, ์ƒ์„ฑ์ผ์‹œยท์ˆ˜์ •์ผ์‹œ๊ฐ€ ๋“ค์–ด๊ฐ”๋Š”์ง€, ๊ฒ€์ƒ‰์šฉ ์ƒ‰์ธ์ด ์ž˜ ์ •์˜๋๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

ํŒŒ์ผ์ด ๋งŒ๋“ค์–ด์ง„ ๋’ค์—๋Š” ์‹ค์ œ ์ฝ”๋“œ์™€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋ฐ˜์˜ํ•˜๊ธฐ ์œ„ํ•œ ๋ช…๋ น(์ฝ”๋“œ ์ƒ์„ฑ, ๋ณ€๊ฒฝ๋ถ„ ๋งŒ๋“ค๊ธฐ, ๋ณ€๊ฒฝ๋ถ„ ์ ์šฉ)์„ ์ด์–ด์„œ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.


โš™๏ธ ์ƒ์„ธ ์˜ต์…˜ยท์‹คํ–‰ ๋ช…์„ธ (๊ฐœ๋ฐœ์ž / AI ์—์ด์ „ํŠธ์šฉ)

Triggers#

  • When a new Serverpod model (Entity, DTO, Enum) is needed
  • When backend data model definition is needed
  • Called in Step 1 of /feature:create orchestration

Context Trigger Pattern#

/serverpod:model {feature_name} {entity_name} [--options]

Parameters#

ParameterRequiredDescriptionExample
feature_nameโœ…Feature module name (snake_case)banner, books, payments
entity_nameโœ…Entity name (PascalCase)Banner, Book, Transaction
--fieldsโŒField definition list"title:String, content:String"
--has-crudโŒAuto-generate CRUD DTOstrue (default)
--has-enumโŒGenerate Enum filetrue (default)

Behavioral Flow#

1. Analyze Existing Patterns#

Use Serena MCP to analyze existing model patterns:
- backend/kobic_server/lib/src/feature/banner/model/ (entities, dto, enum)
- backend/kobic_server/lib/src/feature/books/model/entities/

2. Generate Model Files#

Entity File (entities/{entity_name}.spy.yaml):

### {Entity description}
class: {EntityName}
table: {table_name}

fields:
  ### Unique identifier
  id: int?

  ### {Field1 description}
  {field1}: {Type}

  ### {Field2 description}
  {field2}: {Type}?

  ### Author ID
  authorId: int

  ### Author name
  authorName: String

  ### Author profile image URL
  authorProfileUrl: String?

  ### Created timestamp
  createdAt: DateTime

  ### Updated timestamp
  updatedAt: DateTime?

indexes:
  {entity}_author_idx:
    fields: authorId
  {entity}_created_idx:
    fields: createdAt

Request DTO (dto/{entity_name}_create_request.spy.yaml):

### {Entity} creation request
class: {EntityName}CreateRequest

fields:
  ### {Field description}
  {requiredField}: {Type}
  ### {Optional field description}
  {optionalField}: {Type}?

Response DTO (dto/{entity_name}_list_response.spy.yaml):

### {Entity} list response
class: {EntityName}ListResponse

fields:
  ### {Entity} list
  items: List < {EntityName} > 
   ### Total count
  total: int
  ### Whether next page exists
  hasMore: bool

Enum (enum/{entity_name}_category.spy.yaml):

### {Entity} category
enum: {EntityName}Category
serialized: byName
values:
  - general
  - notice
  - event

3. Verification#

  • Verify Korean comments on all fields
  • Verify required fields (createdAt, updatedAt) included
  • Verify index definitions

Output Files#

backend/kobic_server/lib/src/feature/{feature_name}/model/
โ”œโ”€โ”€ entities/
โ”‚   โ””โ”€โ”€ {entity_name}.spy.yaml
โ”œโ”€โ”€ dto/
โ”‚   โ”œโ”€โ”€ {entity_name}_create_request.spy.yaml
โ”‚   โ”œโ”€โ”€ {entity_name}_update_request.spy.yaml
โ”‚   โ””โ”€โ”€ {entity_name}_list_response.spy.yaml
โ””โ”€โ”€ enum/
    โ””โ”€โ”€ {entity_name}_category.spy.yaml

Post-Generation Commands#

# Model code generation
melos run backend:pod:generate

# Create migration (for Entity changes)
melos run backend:pod:create-migration

# Apply migration
melos run backend:pod:run-migration

MCP Integration#

  • Serena: Analyze existing model patterns, symbol search
  • Context7: Serverpod model definition documentation reference

Examples#

Create banner model#

/serverpod:model banner Banner
  --fields  " title:String, imageUrl:String, linkUrl:String?, sortOrder:int, isActive:bool "

Create book model#

/serverpod:model books Book
  --fields  " title:String, authorId:int, categoryId:int, price:double, coverUrl:String? "

Create payments transaction model#

/serverpod:model payments Transaction
  --fields  " amount:double, type:TransactionType, description:String?, balanceAfter:double "

Reference Agent#

See ${CLAUDE_PLUGIN_ROOT}/commands/agents/backend/serverpod-model-agent.md for detailed implementation rules

Core Rules Summary#

  1. Korean comments (###) required on all fields
  2. createdAt, updatedAt fields required
  3. Appropriate index definitions required
  4. Foreign key relation definitions (when needed)
  5. Default value settings (counters, status fields)