LogoSkills

serverpod:endpoint

Serverpod endpoint and service class generation

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

/serverpod:endpoint โ€” ์„œ๋ฒ„ API ์ฐฝ๊ตฌ ์ž๋™ ์ƒ์„ฑ๊ธฐ#

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

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

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

  • ์ƒˆ๋กœ์šด ์„œ๋ฒ„ API ์ฐฝ๊ตฌ๊ฐ€ ํ•„์š”ํ•  ๋•Œ (์˜ˆ: ๋ฐฐ๋„ˆ ๋ชฉ๋ก ๋ถˆ๋Ÿฌ์˜ค๊ธฐ, ์ฑ… ์ •๋ณด ์ €์žฅํ•˜๊ธฐ)
  • ๋ฐฑ์—”๋“œ์—์„œ ์‹ค์ œ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋กœ์ง์„ ์งœ์•ผ ํ•  ๋•Œ
  • ์ „์ฒด ๊ธฐ๋Šฅ์„ ํ•œ ๋ฒˆ์— ๋งŒ๋“œ๋Š” /feature:create ์ž‘์—…์˜ 2๋ฒˆ์งธ ๋‹จ๊ณ„๋กœ ์ž๋™ ํ˜ธ์ถœ๋  ๋•Œ

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

๊ธฐ๋Šฅ ํด๋” ์•ˆ์— ์•„๋ž˜ ๊ฐ™์€ ์‹ค์ œ ์ฝ”๋“œ ํŒŒ์ผ๋“ค์„ ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค.

  • {๊ธฐ๋Šฅ์ด๋ฆ„}_endpoint.dart โ€” ์•ฑ์ด ์“ฐ๋Š” ์ผ๋ฐ˜ ์ฐฝ๊ตฌ (๋กœ๊ทธ์ธํ•œ ์‚ฌ์šฉ์ž์šฉ)
  • {๊ธฐ๋Šฅ์ด๋ฆ„}_console_endpoint.dart โ€” ๊ด€๋ฆฌ์ž ์ฝ˜์†”์šฉ ์ฐฝ๊ตฌ (๊ด€๋ฆฌ์ž ์ „์šฉ, ์„ ํƒ)
  • {๊ธฐ๋Šฅ์ด๋ฆ„}_service.dart โ€” ์‹ค์ œ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ๋กœ์ง(์ฃผ๋ฐฉ)
  • {๊ธฐ๋Šฅ์ด๋ฆ„}_validator.dart โ€” ์ž…๋ ฅ๊ฐ’ ๊ฒ€์‚ฌ (์„ ํƒ)

๋ชฉ๋ก ์กฐํšŒ, ๋‹จ๊ฑด ์กฐํšŒ, ์ƒ์„ฑ, ์ˆ˜์ •, ์‚ญ์ œ ๊ฐ™์€ ๊ธฐ๋ณธ ๋™์ž‘์ด ๋“ค์–ด๊ฐ€๊ณ , ๊ถŒํ•œ ์ฒดํฌยท์—๋Ÿฌ ๊ธฐ๋กยท์‚ญ์ œ ํ‘œ์‹œ(soft delete) ๊ฐ™์€ ์•ˆ์ „์žฅ์น˜๋„ ๊ทœ์น™๋Œ€๋กœ ํ•จ๊ป˜ ๋“ค์–ด๊ฐ‘๋‹ˆ๋‹ค.

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

# ๋ฐฐ๋„ˆ์šฉ ์ฐฝ๊ตฌ ๋งŒ๋“ค๊ธฐ (์ผ๋ฐ˜ + ๊ด€๋ฆฌ์ž ๋‘˜ ๋‹ค)
/serverpod:endpoint banner Banner --type both

# ์ฑ…์šฉ ์ฐฝ๊ตฌ ๋งŒ๋“ค๊ธฐ (์•ฑ์šฉ๋งŒ, ์›ํ•˜๋Š” ๋™์ž‘๋งŒ ๊ณจ๋ผ์„œ)
/serverpod:endpoint books Book --type app
  --methods  " getBooks, getBook, createBook " 

 # ๊ด€๋ฆฌ์ž ๋Œ€์‹œ๋ณด๋“œ ์ฐฝ๊ตฌ ๋งŒ๋“ค๊ธฐ
/serverpod:endpoint dashboard Stats --type console
  --methods  " getOverview, getUserStats, getContentStats "
  • ์ฒซ ๋ฒˆ์งธ ๊ฐ’(banner)์€ ๊ธฐ๋Šฅ ์ด๋ฆ„, ๋‘ ๋ฒˆ์งธ ๊ฐ’(Banner)์€ ๋ฐ์ดํ„ฐ ์ด๋ฆ„์ž…๋‹ˆ๋‹ค. (๋‘˜ ๋‹ค ํ•„์ˆ˜)
  • --type ์œผ๋กœ ์ฐฝ๊ตฌ ์ข…๋ฅ˜๋ฅผ ๊ณ ๋ฆ…๋‹ˆ๋‹ค: app(์•ฑ์šฉยท๊ธฐ๋ณธ๊ฐ’) / console(๊ด€๋ฆฌ์ž์šฉ) / both(๋‘˜ ๋‹ค).
  • --methods ๋กœ ๋งŒ๋“ค๊ณ  ์‹ถ์€ ๋™์ž‘๋งŒ ๊ณจ๋ผ์„œ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

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

  1. ๊ธฐ์กด ๋ฐฉ์‹ ์‚ดํŽด๋ณด๊ธฐ โ€” ์ด๋ฏธ ๋งŒ๋“ค์–ด์ง„ ๋น„์Šทํ•œ ์ฐฝ๊ตฌ ์ฝ”๋“œ๋ฅผ ๋ถ„์„ํ•ด ๊ฐ™์€ ์Šคํƒ€์ผ์„ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค.
  2. ์ฐฝ๊ตฌ ์ฝ”๋“œ ๋งŒ๋“ค๊ธฐ โ€” ์•ฑ์šฉ ์ฐฝ๊ตฌ์™€ (ํ•„์š” ์‹œ) ๊ด€๋ฆฌ์ž์šฉ ์ฐฝ๊ตฌ๋ฅผ ์ •ํ•ด์ง„ ๊ทœ์น™๋Œ€๋กœ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
  3. ์ฒ˜๋ฆฌ ๋กœ์ง ๋งŒ๋“ค๊ธฐ โ€” ์‹ค์ œ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒยท์ €์žฅํ•˜๋Š” service ์ฝ”๋“œ๋ฅผ ๋ถ„๋ฆฌํ•ด์„œ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
  4. ๋งˆ๋ฌด๋ฆฌ ๋“ฑ๋ก โ€” ๋งŒ๋“  ์ฐฝ๊ตฌ๋ฅผ ์„œ๋ฒ„๊ฐ€ ์ธ์‹ํ•˜๋„๋ก ์ฝ”๋“œ ์ƒ์„ฑ ๋ช…๋ น(melos run backend:pod:generate)์„ ๋Œ๋ฆฝ๋‹ˆ๋‹ค.

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

Triggers#

  • When a new Serverpod API endpoint is needed
  • When backend business logic implementation is needed
  • Called in Step 2 of /feature:create orchestration

Context Trigger Pattern#

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

Parameters#

ParameterRequiredDescriptionExample
feature_nameโœ…Feature module name (snake_case)banner, books
entity_nameโœ…Entity name (PascalCase)Banner, Book
--typeโŒEndpoint typeapp, console, both (default: app)
--methodsโŒMethods to generate"getList, get, create, update, delete"

Behavioral Flow#

1. Analyze Existing Patterns#

Use Serena MCP to analyze existing endpoint patterns:
- backend/kobic_server/lib/src/feature/banner/endpoint/banners_endpoint.dart
- backend/kobic_server/lib/src/feature/banner/service/banner_service.dart

2. Follow Import Order (Required)#

// 1. Serverpod framework
import 'package:serverpod/server.dart';

// 2. Generated protocol (models)
import 'package:kobic_server/src/generated/protocol.dart';

// 3. Feature internal services
import 'package:kobic_server/src/feature/{feature}/service/{feature}_service.dart';

// 4. Common utilities
import 'package:kobic_server/src/common/authenticated_mixin.dart';

3. Generate Endpoint Classes#

App Endpoint ({feature}_endpoint.dart):

/// {Feature} endpoint
///
/// - Provides list, single, create, update, delete functionality
/// - Accessible only to authenticated users
class {Feature}Endpoint extends Endpoint with AuthenticatedMixin {
  /// Retrieves the {entity} list.
  Future<{Entity}ListResponse> get{Entity}s(
    Session session, {
    int? limit,
    int? offset,
    {Entity}Category? category,
  }) async {
    return {Feature}Service.get{Entity}s(
      session,
      limit: limit ?? 20,
      offset: offset ?? 0,
      category: category,
    );
  }

  /// Creates a {entity}.
  Future<{Entity}> create{Entity}(
    Session session,
    {Entity}CreateRequest request,
  ) async {
    final user = await requireCurrentUserInfo(session);
    return {Feature}Service.create{Entity}(session, request, user.id!);
  }

  // ... remaining CRUD methods
}

Console Endpoint ({feature}_console_endpoint.dart):

/// {Feature} console endpoint (admin only)
class {Feature}ConsoleEndpoint extends Endpoint {
  @override
  bool get requireLogin => true;

  @override
  Set<Scope> get requiredScopes => {Scope.admin};

  /// Retrieves the full {entity} list (admin only).
  Future<List<{Entity}>> getAll{Entity}s(
    Session session, {
    int? limit,
    int? offset,
    bool includeDeleted = false,
  }) async {
    return {Feature}Service.getAll{Entity}sForAdmin(
      session,
      limit: limit,
      offset: offset,
      includeDeleted: includeDeleted,
    );
  }
}

4. Generate Service Class#

/// {Feature} business logic service
class {Feature}Service {
  /// Retrieves the {entity} list.
  static Future<{Entity}ListResponse> get{Entity}s(
    Session session, {
    required int limit,
    required int offset,
    {Entity}Category? category,
  }) async {
    try {
      final entities = await {Entity}.db.find(
        session,
        where: (t) {
          var condition = t.isDeleted.equals(false);
          if (category != null) {
            condition = condition & t.category.equals(category);
          }
          return condition;
        },
        orderBy: (t) => t.createdAt,
        orderDescending: true,
        limit: limit,
        offset: offset,
      );

      final total = await {Entity}.db.count(session, where: ...);

      return {Entity}ListResponse(
        items: entities,
        total: total,
        hasMore: offset + entities.length < total,
      );
    } on Exception catch (error, stackTrace) {
      session.log(
        '{Feature} list query failed: $error',
        exception: error,
        level: LogLevel.error,
        stackTrace: stackTrace,
      );
      rethrow;
    }
  }

  // ... remaining business logic
}

Output Files#

backend/kobic_server/lib/src/feature/{feature_name}/
โ”œโ”€โ”€ endpoint/
โ”‚   โ”œโ”€โ”€ {feature_name}_endpoint.dart       # App endpoint
โ”‚   โ””โ”€โ”€ {feature_name}_console_endpoint.dart  # Console endpoint (optional)
โ”œโ”€โ”€ service/
โ”‚   โ””โ”€โ”€ {feature_name}_service.dart        # Business logic
โ””โ”€โ”€ validation/
    โ””โ”€โ”€ {feature_name}_validator.dart      # Input validation (optional)

Post-Generation Commands#

# Code generation (endpoint registration)
melos run backend:pod:generate

MCP Integration#

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

Examples#

Create banner endpoint#

/serverpod:endpoint banner Banner --type both

Create book endpoint#

/serverpod:endpoint books Book --type app
  --methods  " getBooks, getBook, createBook "

Create admin dashboard endpoint#

/serverpod:endpoint dashboard Stats --type console
  --methods  " getOverview, getUserStats, getContentStats "

Reference Agent#

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

Core Rules Summary#

  1. Follow import order (Serverpod โ†’ Protocol โ†’ Feature โ†’ Utils)
  2. Use AuthenticatedMixin (for authenticated methods)
  3. Set permissions on Console endpoints (requireLogin, requiredScopes)
  4. Separate business logic into Services
  5. Error handling and logging (session.log)
  6. Apply soft delete pattern