Dart 로 Local Server 구성하기

원장·2025년 7월 6일

플러터 기초

목록 보기
31/36

Dart Shelf

Dart Shelf는 Dart 언어로 작성된 웹 서버 프레임워크로, 간단하고 조합 가능한 웹 애플리케이션을 구축하는 데 사용됩니다.

주요 특징

미들웨어 기반 아키텍처: Shelf는 미들웨어(middleware) 패턴을 중심으로 설계되어 있습니다. 각 미들웨어는 HTTP 요청을 처리하고 다음 미들웨어로 전달하거나 응답을 반환할 수 있습니다.

간단한 API: 핵심 개념은 RequestResponse 객체, 그리고 이들을 연결하는 Handler 함수입니다. Handler는 Request를 받아 Response를 반환하는 함수입니다.

조합 가능성: 여러 미들웨어를 쉽게 조합하여 복잡한 웹 애플리케이션을 구성할 수 있습니다. 예를 들어 로깅, 인증, CORS 처리 등을 각각의 미들웨어로 분리할 수 있습니다.

기본 사용법

import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart' as io;

void main() async {
  // 간단한 핸들러 정의
  var handler = const Pipeline()
      .addMiddleware(logRequests())
      .addHandler(_echoRequest);

  // 서버 시작
  var server = await io.serve(handler, 'localhost', 8080);
  print('Server running on localhost:${server.port}');
}

Response _echoRequest(Request request) {
  return Response.ok('Hello, World!');
}

주요 컴포넌트

Pipeline: 여러 미들웨어를 순차적으로 연결하는 클래스입니다.

Router: URL 경로 기반 라우팅을 제공하는 패키지(shelf_router)입니다.

Static Files: 정적 파일 서빙을 위한 미들웨어(shelf_static)도 제공됩니다.

Shelf는 Express.js나 Flask와 비슷한 철학을 가지고 있지만, Dart의 강타입 시스템과 async/await 패턴을 활용하여 더 안전하고 현대적인 웹 개발 경험을 제공합니다. 특히 Flutter 개발자들에게 백엔드 개발 시 일관된 언어 환경을 제공한다는 장점이 있습니다.

Dart create name -t server-shelf
cd test
dart run bin/server.dart

위와 같이 입력하면 localhost:8080으로 접근 시 server open

Shelf 외의 웹 프레임워크

주요 Dart 웹 프레임워크들

Angel3: 풀스택 웹 프레임워크로 ORM, 인증, 웹소켓 등 다양한 기능을 내장하고 있습니다. Express.js나 Django와 비슷한 포지션입니다.

Aqueduct: 과거에 인기가 있었던 프레임워크지만 현재는 개발이 중단되었습니다. 대신 Conduit이 후속 프로젝트로 이어지고 있습니다.

Conduit: Aqueduct의 후속 프로젝트로, RESTful API 개발에 특화되어 있습니다.

Serverpod: 비교적 새로운 풀스택 프레임워크로, 타입 안전성과 실시간 통신에 중점을 둡니다. 클라이언트-서버 간 코드 공유가 가능합니다.

Dart Frog: Vercel의 Next.js에서 영감을 받은 풀스택 프레임워크로, 파일 기반 라우팅과 빠른 핫 리로드를 제공합니다.

Vania: Laravel에서 영감을 받은 프레임워크로, 웹 개발에 필요한 다양한 기능을 제공합니다.

선택 기준

간단한 API나 마이크로서비스: Shelf가 적합합니다.

풀스택 애플리케이션: Angel3, Serverpod, Dart Frog 등이 좋은 선택입니다.

RESTful API 중심: Conduit이나 Shelf + Router 조합이 적합합니다.

빠른 프로토타이핑: Dart Frog가 좋은 선택지입니다.

각 프레임워크마다 철학과 접근 방식이 다르므로, 프로젝트의 요구사항과 개발자의 선호도에 따라 선택하시면 됩니다. Shelf는 이 중에서도 가장 미니멀하고 유연한 선택지라고 할 수 있습니다.

Shelf로 Swagger 사용하는 법!

Dart Shelf에서 Swagger를 구성하는 방법을 설명드리겠습니다.

1. 패키지 설치

pubspec.yaml에 필요한 패키지들을 추가합니다:

dependencies:
  shelf: ^1.4.1
  shelf_router: ^1.1.4
  shelf_swagger_ui: ^1.0.0
  swagger_dart_code_generator: ^2.0.0
  json_annotation: ^4.8.1

dev_dependencies:
  build_runner: ^2.4.7
  json_serializable: ^6.7.1

2. Swagger 문서 작성

먼저 OpenAPI 스펙 파일을 작성합니다 (openapi.yaml):

openapi: 3.0.0
info:
  title: My API
  version: 1.0.0
  description: API documentation for my Dart Shelf application

paths:
  /users:
    get:
      summary: Get all users
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/User'
    post:
      summary: Create a new user
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateUser'
      responses:
        '201':
          description: User created successfully

components:
  schemas:
    User:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        email:
          type: string
    CreateUser:
      type: object
      required:
        - name
        - email
      properties:
        name:
          type: string
        email:
          type: string

3. 서버 코드 구성

import 'dart:io';
import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart' as io;
import 'package:shelf_router/shelf_router.dart';
import 'package:shelf_swagger_ui/shelf_swagger_ui.dart';

void main() async {
  final app = Router();

  // API 라우트
  app.get('/users', _getUsers);
  app.post('/users', _createUser);

  // Swagger UI 설정
  app.mount('/docs/', swaggerUI('openapi.yaml'));
  
  // OpenAPI 스펙 파일 서빙
  app.get('/openapi.yaml', (Request request) {
    final file = File('openapi.yaml');
    return Response.ok(
      file.readAsStringSync(),
      headers: {'content-type': 'application/x-yaml'},
    );
  });

  final handler = Pipeline()
      .addMiddleware(logRequests())
      .addMiddleware(_corsHeaders())
      .addHandler(app);

  final server = await io.serve(handler, 'localhost', 8080);
  print('Server running on localhost:${server.port}');
  print('Swagger UI available at: http://localhost:${server.port}/docs/');
}

Response _getUsers(Request request) {
  return Response.ok(
    '[{"id": 1, "name": "John", "email": "john@example.com"}]',
    headers: {'content-type': 'application/json'},
  );
}

Response _createUser(Request request) {
  // 실제로는 request body를 파싱하고 처리해야 함
  return Response(
    201,
    body: '{"id": 2, "name": "Jane", "email": "jane@example.com"}',
    headers: {'content-type': 'application/json'},
  );
}

Middleware _corsHeaders() {
  return (handler) {
    return (request) async {
      final response = await handler(request);
      return response.change(headers: {
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
        'Access-Control-Allow-Headers': 'Content-Type, Authorization',
      });
    };
  };
}

4. 대안 방법 - 수동 Swagger UI 설정

만약 shelf_swagger_ui 패키지를 사용하지 않는다면, 직접 HTML을 서빙할 수도 있습니다:

app.get('/docs/', (Request request) {
  return Response.ok('''
<!DOCTYPE html>
<html>
<head>
  <title>API Documentation</title>
  <link rel="stylesheet" type="text/css" href="https://unpkg.com/swagger-ui-dist@4.15.5/swagger-ui.css" />
</head>
<body>
  <div id="swagger-ui"></div>
  <script src="https://unpkg.com/swagger-ui-dist@4.15.5/swagger-ui-bundle.js"></script>
  <script>
    SwaggerUIBundle({
      url: '/openapi.yaml',
      dom_id: '#swagger-ui',
      presets: [
        SwaggerUIBundle.presets.apis,
        SwaggerUIBundle.presets.standalone
      ]
    });
  </script>
</body>
</html>
  ''', headers: {'content-type': 'text/html'});
});

5. 실행

서버를 실행한 후 http://localhost:8080/docs/에 접속하면 Swagger UI를 통해 API 문서를 확인하고 테스트할 수 있습니다.

이 방법으로 Shelf 애플리케이션에 Swagger 문서화를 추가할 수 있으며, API의 스펙을 시각적으로 확인하고 테스트할 수 있는 환경을 제공할 수 있습니다.

profile
나 원장이 아니다

0개의 댓글