Dart Frog 튜토리얼 파트 2: 첫 번째 실제 REST API 구축 (Todos와 함께하는 전체 CRUD) 🐸

발행: (2026년 1월 14일 오전 06:07 GMT+9)
3 min read
원문: Dev.to

Source: Dev.to

Planning & Best Practices

Quick plan – we’ll create a Todo model with id, title, and completed status, stored in‑memory (a Map for fast lookup). This keeps the example simple while being easy to replace with a real database later.

Best practices

  • Use dynamic routes with [id].dart
  • Generate unique IDs with the uuid package
  • Validate JSON request bodies
  • Return appropriate HTTP status codes: 200, 201, 204, 400, 404, 405

설정

UUID 의존성 추가

# pubspec.yaml
dependencies:
  uuid: ^4.5.0

패키지 관리자를 실행하세요:

dart pub get   # or flutter pub get

Todo 모델

다음 파일을 생성하세요 lib/src/todo.dart:

/// Represents a Todo item.
class Todo {
  /// Creates a new Todo.
  Todo({
    required this.id,
    required this.title,
    this.isCompleted = false,
  });

  /// Creates a Todo from a JSON map.
  factory Todo.fromJson(Map json) => Todo(
        id: json['id'] as String,
        title: json['title'] as String,
        isCompleted: json['isCompleted'] as bool? ?? false,
      );

  /// Unique identifier.
  final String id;

  /// Title of the todo.
  final String title;

  /// Completion status.
  bool isCompleted;

  /// Converts the Todo to JSON.
  Map toJson() => {
        'id': id,
        'title': title,
        'isCompleted': isCompleted,
      };
}

인‑메모리 스토어

lib/src/todo_repository.dart 파일을 생성하세요:

import 'package:my_project/src/todo.dart';
import 'package:uuid/uuid.dart';

const _uuid = Uuid();
final _todos = {};

/// Returns all todos.
List getAllTodos() => _todos.values.toList();

/// Returns a todo by its [id] or `null` if not found.
Todo? getTodoById(String id) => _todos[id];

/// Creates a new todo with the given [title].
void createTodo(String title) {
  final id = _uuid.v4();
  _todos[id] = Todo(id: id, title: title);
}

/// Updates an existing todo.
void updateTodo(String id, {String? title, bool? isCompleted}) {
  final todo = _todos[id];
  if (todo == null) return;
  _todos[id] = Todo(
    id: id,
    title: title ?? todo.title,
    isCompleted: isCompleted ?? todo.isCompleted,
  );
}

/// Deletes a todo.
void deleteTodo(String id) => _todos.remove(id);

라우트

컬렉션 라우트 – routes/todos/index.dart

import 'package:dart_frog/dart_frog.dart';
import 'package:my_project/src/todo_repository.dart';

Future onRequest(RequestContext context) async {
  switch (context.request.method) {
    case HttpMethod.get:
      final todos = getAllTodos();
      return Response.json(
        body: todos.map((e) => e.toJson()).toList(),
      );

    case HttpMethod.post:
      final body = await context.request.json() as Map;
      final title = body['title'] as String?;
      if (title == null || title.isEmpty) {
        return Response(statusCode: 400, body: 'Title is required');
      }
      createTodo(title);
      return Response(statusCode: 201, body: 'Todo created');

    default:
      return Response(statusCode: 405);
  }
}

동적 아이템 라우트 – routes/todos/[id].dart

import 'package:dart_frog/dart_frog.dart';
import 'package:my_project/src/todo_repository.dart';

Future onRequest(RequestContext context, String id) async {
  final todo = getTodoById(id);
  if (todo == null) return Response(statusCode: 404);

  switch (context.request.method) {
    case HttpMethod.get:
      return Response.json(body: todo.toJson());

    case HttpMethod.put:
      final body = await context.request.json() as Map;
      final title = body['title'] as String?;
      final isCompleted = body['isCompleted'] as bool?;
      updateTodo(id, title: title, isCompleted: isCompleted);
      return Response.json(body: getTodoById(id)!.toJson());

    case HttpMethod.delete:
      deleteTodo(id);
      return Response(statusCode: 204);

    default:
      return Response(statusCode: 405);
  }
}

테스트

Quick curl examples:

# Get all todos
curl http://localhost:8080/todos

# Create a new todo
curl -X POST http://localhost:8080/todos \
  -H "Content-Type: application/json" \
  -d '{"title": "Learn Dart Frog"}'

# Get a specific todo (replace <id> with the actual id)
curl http://localhost:8080/todos/<id>

API는 오류를 우아하게 처리하며 견고한 프로덕션‑준비 기반을 제공합니다.

소스 코드

Show some ❤️ by starring the repo and following the author:
https://github.com/techwithsam/dart_frog_full_course_tutorial

This is your first real Dart Frog REST API — congrats! Next up: connect a Flutter app to it.

Back to Blog

관련 글

더 보기 »

2026년 Dart 서버 사이드: Dart Frog 소개 🐸

2026년 올해 내 계획 중 하나는 서버 측에서 Dart를 더 많이 탐구하는 것입니다. Flutter가 계속해서 cross‑platform development를 장악하고 있으며, 전체의 40% 이상을 차지하고 있기 때문입니다.

Todo 앱

소개 첫 번째 논리 중심 프로젝트인 Counters를 완료한 후, 나는 UI를 개선하는 것이 아니라 복잡성의 다음 자연스러운 단계로 나아가고 싶었다 — ...

REST API에 대한 모든 것

Forem 피드 !Forem 로고https://media2.dev.to/dynamic/image/width=65,height=,fit=scale-down,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.co...