Upgrade to Pro — share decks privately, control downloads, hide ads and more …

bootcamp2025_バックエンド研修_WebAPIサーバ作成.pdf

 bootcamp2025_バックエンド研修_WebAPIサーバ作成.pdf

Avatar for GENIEE ,Inc

GENIEE ,Inc

October 09, 2025
Tweet

More Decks by GENIEE ,Inc

Other Decks in Programming

Transcript

  1. © Geniee, Inc. 3 講義アジェンダ 1. 講義(1h) a. バックエンドサーバの役割 b.

    Web API c. APIフレームワーク d. アーキテクチャスタイル e. シナリオテスト 2. 課題(2h) 3. 昼休み 4. 課題(5h)
  2. © Geniee, Inc. 6 1-a バックエンドサーバーの役割 バックエンドサーバーの役割 ~単純なCRUDを⾏うアプリケーションでもバックエンドサーバーが必要とされる理由~ • クライアント側から機密情報を隠す

    ◦ DBのアクセス情報 ◦ 認証‧認可の実装 • 難しい処理を実装することができる ◦ SQLでは記述しにくい処理 ◦ 複数のクライアントからのリクエストの処理 • インターフェイスを固定化 ◦ フロントエンドとバックエンドが疎結合になる ▪ フロントの実装を変更なしに、DBの変更等を⾏うことができる ▪ バックエンドサーバーから複数の外部サービスを呼び出すことができる 多分まだまだあるはず、
  3. © Geniee, Inc. 7 1-a バックエンドサーバーの役割 必ずしもバックエンドサーバーが必要か? バックエンドサーバーを介さずにCRUDを⾏う例 (backend as

    a service とも⾒ることができる) • Google Firebaseを利⽤したモバイルアプリ開発 ◦ Google Firebase ▪ フルマネージドなNoSQLデータベース ▪ 簡単な認証‧認可まで⾏ってくれる • Spabase ◦ フルマネージドなPostgreSQL互換のデータベース ◦ Firebaseと同様に簡単な認証‧認可まで⾏ってくれる モバイル(DOOH, SFAのみ) や toC(SWのみ) と相性が良いとされるが、弊社ではそんなに関係ないかも... ⼀番単純な使い⽅としては、デスクトップアプリのSQLiteをwebアプリに移⾏するために、クラウドに保存させる時に利⽤することとか、
  4. © Geniee, Inc. 9 1-b Web API Web API(Web Application

    Programming Interface) • Web APIとは、httpやhttpsなどを⽤いて実現されるAPI ◦ ネットワークを通して提供される機能の規格のこと ◦ 単純にAPIと略されることが多いが、ライブラリの使い⽅などもAPIの⼀種であり、これと区 別するため
  5. © Geniee, Inc. 10 1-b Web API よく使われるWeb API の規格‧スタイル

    • REST API (Representational State Transfer) ◦ 最も⼀般的に使われるWeb APIの設計スタイル ◦ APIの思想としてSOAP APIと対⽐されることもある。LINK ◦ HTTP/1.1またはHTTP/2を使って通信し、リソース(例: /users, /posts)に対してGET, POST, PUT, DELETEなどのHTTPメソッドを使って操作 ◦ データ形式は主にJSON(JavaScript Object Notation)(他にXMLなども可) ◦ スキーマや型は任意のため、型安全性は別途管理が必要(OpenAPIを利⽤) • gRPC ◦ Googleが開発した⾼速なRPC(Remote Procedure Call)プロトコル ◦ HTTP/2をベースに通信し、バイナリ形式を⽤いることで⾼速‧軽量 ◦ マイクロサービス間通信に向いている • tRPC ◦ TypeScript製アプリケーションに特化 ◦ 完全な型安全なAPI開発が可能 ◦ ランタイムではJSONでデータをやりとりを⾏う
  6. © Geniee, Inc. 11 1-b Web API Open API とは、

    • OpenAPI Specification(OAS) はREST-APIの標準仕様 • ⾔語によらないHTTP APIの可視化のインターフェース記述⾔語の仕様 • YAMLまたはJSONで記述される • バージョン ◦ 3.1.1 最新(2024/10/25)※課題では互換のために3.0.0にしている • OpenAPIで扱うことで、Swaggerを使うことができる ◦ 厳密にいうと、Swaggerの規格に合わせてOpneAPIが策定 参考: https://www.openapis.org/what-is-openapi
  7. © Geniee, Inc. 12 1-b Web API そもそも、HTTPとは? • WebブラウザとサーバーがTCP通信を使ってやり取りする通信プロトコル

    • リクエストとレスポンスの形でデータを交換 構成要素 • メソッド: ⽬的を⽰す動詞(例:GET, POST, PUT, DELETE) • パス: /products/123 のようにリソースを表す • クエリ: ?color=blue など、追加情報をURLで渡す • ヘッダー: リクエストの付加情報(例:認証トークン) • ボディ: 主にPOST/PUT時に送るデータ本体
  8. © Geniee, Inc. 13 1-b Web API Swaggerとは • OpenAPIの仕様で書かれたYAML/JSONファイルを扱うツール

    • 簡単にいうと、GUIでhttpリクエストが投げられるツール(=curlのGUI版)
  9. © Geniee, Inc. 14 1-b Web API Swaggerの利⽤ • VScode/CursorにSwagger

    Viewerの拡張機能をインストール ◦ 公式の拡張機能はないので、特に指定なし 参考: https://zenn.dev/nekoniki/articles/acd946cc349d1e
  10. © Geniee, Inc. 15 1-b Web API Swaggerの利⽤ • VScode/Cursorでsample.yamlを開く(本家)

    • コマンドパレットでswaggerと⼊れて swaagger UI を使うみたいな項⽬を選択する • 次のようなのが⾒えたらOK! 実際にリクエストを投げてみる • POSTのタブを広げてTry it outを押下 • パラメーターやボディーを⼊⼒できる • Executeで実際にhttpリクエストが⾶ぶ • 結果が表⽰される ◦ デフォ値で200が返ってくるはずです
  11. © Geniee, Inc. 16 1-b Web API • yamlファイルを⾒て貰えばわかると思うのですが、⾏数がそれなりにあります •

    フロントエンドなど、他のチームから使ってもらうためとは⾔っても、これをコードと⼀緒に⼿ 作業で作成‧保守するのは結構⼤変ですね... • そうだ、コードから⾃動⽣成したらいいんだ! =>ハンドラ駆動と呼ばれるらしい ※逆にOpenAPIのyaml/jsonからコードを⽣成する⽅法もあります(=>スキーマ駆動と呼ばれるらしい) ※ツールが使いにくい場合は、⽣成AIを最⼤限活⽤するのは⼿段としてはあり
  12. © Geniee, Inc. 17 1-b Web API OpenAPI クライアントライブラリの利⽤ •

    OpenAPIクライアントライブラリを活⽤することで、yaml/jsonからコードを⽣成できる ◦ const response = await fetch(url) みたいなコードが⽣成されるイメージ ◦ 代表: Swagger Codegen ▪ OpenAPIの公式 ▪ javaの実⾏環境が必要 ▪ 対応⾔語 ActionScript, Ada, Apex, Bash, C#, C++, Clojure, Dart, Elixir, Elm, Eiffel, Erlang, Go, Groovy, Haskell, Java, Kotlin, Lua, Node.js, Objective-C, Perl, PHP, PowerShell, Python, R, Ruby, Rust, Scala , Swift , Typescript Type script限定で⾔えば、openapi-typescript はjavaに依存しないので楽です。
  13. © Geniee, Inc. 19 1-c APIフレームワーク APIフレームワーク • Web APIサーバーの作成に特化したフレームワーク

    ◦ 例: Gin(Go), FastAPI(Python), Express(node.js), Axum(Rust) ◦ フルスタックフレームワークをAPIモードで扱うことも可能 ▪ Laravel(PHP), Rails(Ruby) • ⾔語標準のhttpサーバーだと記述量が増えがちな部分をシンプルに保ってくれる枠組み ◦ ⾔語によってはそもそもなかったり、⾮推奨だったりする • 代表的なフレームワークだと、⼤体 OpenAPI の⾃動⽣成がある(プラグインの場合もある) • フレームワークによって、ルーティングの記述⽅法だったり、パフォーマンスが異なる
  14. © Geniee, Inc. 20 1-c APIフレームワーク APIフレームワーク(注意点) • 今回の課題では⽐較的に扱いやすい Python

    の FastAPI を利⽤する。 • FastAPIを例に説明を⾏うが、APIフレームワークでは基本的に同じような機能を持っている • FastAPIの詳細についての説明はドキュメントを参照 ◦ ⽇本語: https://fastapi.tiangolo.com/ja/
  15. © Geniee, Inc. 21 1-c APIフレームワーク Pythonの環境構築 • 今回は、pyenvとpoetryで環境を構築します ◦

    pyenv ▪ Pythonの複数のバージョンを扱うため(今回は3.13.2) ▪ グローバルでinstallしたpythonが3.13系なら不要かも ◦ poetry ▪ Pythonのプロジェクトのパッケージマネージャー ▪ lockfileから環境を作成できるので、再現性が⾼い • インストール⽅法(インストール済みの場合は不要) brew install pyenv brew install poetry
  16. © Geniee, Inc. 22 1-c APIフレームワーク FastAPI を使ってみよう 1. 本⽇のディレクトリに移動

    2. 環境の作成 pyenv install $(cat .python-version) pyenv local $(cat .python-version) poetry install 3. アプリの実⾏ poetry run python webapi/main.py
  17. © Geniee, Inc. 23 1-c APIフレームワーク 今回の本筋とは少しずれますが、 Uvicorn: (語源: uvloop

    と ユニコーン) • 軽量/⾼速なpythonのASGIサーバー ◦ ASGI=Asynchronous Server Gateway Interface ▪ https://asgi.readthedocs.io/en/latest/ ◦ ⾮同期処理を⾏うwebサーバーとして機能 Gunicorn: (語源:緑のユニコーン) • WSGI準拠のPythonアプリケーションを実⾏するためのサーバ ◦ WSGI=Web Server Gateway Interface ▪ 標準化されたインタフェース定義のこと ▪ https://docs.python.org/ja/3.13/library/wsgiref.html • Pythonの標準ライブラリのhttp.serverが⾮推奨なため ◦ ※Gin(golang), express(node.js)は⾔語標準のhttpサーバーを利⽤可能
  18. © Geniee, Inc. 24 1-c APIフレームワーク Uvicornの使い⽅ 1. コマンドラインから実⾏する⽅法コードに記述する⽅法 •

    Dockerfileに書くと複雑になりがちな場合(本番とか) • 分かりやすいので本⽇はこちらを利⽤ 2. コマンドラインから実⾏する⽅法 • 確実にホットリロードを使いたい場合(1の⽅法で上⼿くできなかったら) • uvicorn webapi.main:app --reload --port 8000 if __name__ =="__main__": uvicorn.run( “webapi.main:app", host="localhost", port=8080, reload=True, )
  19. © Geniee, Inc. 25 1-c APIフレームワーク FastAPI を使ってみよう FastAPIのチュートリアルの抜粋で、APIフレームワークで普遍的な機能の紹介 ①ルートの記述

    ②パスパラメータ ③クエリパラメーター ④リクエスト、レスポンスボディ ⑤ヘッダー ⑥ミドルウェア ⑦OpenAPIのjsonの⽣成 ⑧Swagger UI の確認 ⑨Redocの確認
  20. © Geniee, Inc. 26 1-c APIフレームワーク FastAPI を使ってみよう ①ルートの記述 初期化を⾏なった後に、そのパスで⾏いたい処理が書かれた関数に

    のようにデコレーターでパスを記述する以下同様 @app.post, @app.put, @app.delete @app.options, @app.head, @app.patch, @app.trace @app.get("/") async def root(): # async関数でも通常の関数でも可 return {"message": "Hello World"} from fastapi import FastAPI app = FastAPI()
  21. © Geniee, Inc. 27 1-c APIフレームワーク FastAPI を使ってみよう ②パスパラメータ パラメータとして当てはめたい部分を{}で記述する

    from fastapi import FastAPI app = FastAPI() @app.get("/items/{item_id}") async def read_item(item_id): return {"item_id": item_id}
  22. © Geniee, Inc. 28 1-c APIフレームワーク FastAPI を使ってみよう ③クエリパラメーター パスパラメータではない関数パラメータを宣⾔すると、それらは⾃動的に

    "クエリ" パラメータとして解釈される from fastapi import FastAPI app = FastAPI() fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}] @app.get("/items/") async def read_item(skip: int = 0, limit: int = 10): return fake_items_db[skip : skip + limit]
  23. © Geniee, Inc. 29 1-c APIフレームワーク FastAPI を使ってみよう ④リクエスト、レスポンスボディ パスパラメータではない関数パラメータをpydacticでモデルを定義して宣⾔する

    Pydantic • データバリデーションライブラリ • データの構造と型を明確に定義 => open API にも反映される • バリデーションに失敗した場合、⾃動的にエラーレスポンスを⽣成
  24. © Geniee, Inc. 30 1-c APIフレームワーク from typing import Union

    from fastapi import FastAPI from pydantic import BaseModel class Item(BaseModel): # BaseModelを継承しリクエスト・レスポンスボディを定義 name: str description: Union[str, None] = None price: float tax: Union[float, None] = None app = FastAPI() @app.post("/items/") async def create_item(item: Item): # 定義したクラスのインスタンスを引数とする return item
  25. © Geniee, Inc. 31 1-c APIフレームワーク FastAPI を使ってみよう リクエスト、レスポンスボディ Pydanticを使わない⽅法もあります。

    リクエストボディについては⾮推奨 レスポンスボディについては @app.get("/items/", response_model=List[str]) のように定義することも可能 (サンプルコードにも⼀部使ってます。) 参考: https://fastapi.tiangolo.com/ja/tutorial/body-multiple-params/#_2
  26. © Geniee, Inc. 32 1-c APIフレームワーク FastAPI を使ってみよう ⑤ヘッダー 関数の引数の型をHeaderとして定義する

    from typing import Union from fastapi import FastAPI, Header app = FastAPI() @app.get("/items/") async def read_items(user_agent: Union[str, None] = Header(default=None)): return {"User-Agent": user_agent}
  27. © Geniee, Inc. 33 1-c APIフレームワーク FastAPI を使ってみよう ⑥ミドルウェア •

    複数のパスで同じ処理をパスの処理の前後に⾏うときに利⽤(例:認証, 計測) • ※Apache / Nginxなどのミドルウェアとはレイヤーが異なる • @app.middleware("http")でミドルウェアを追加することができる import time from fastapi import FastAPI, Request app = FastAPI() @app.middleware("http") async def add_process_time_header(request: Request, call_next): start_time = time.perf_counter() response = await call_next(request) process_time = time.perf_counter() - start_time response.headers["X-Process-Time"] = str(process_time) return response
  28. © Geniee, Inc. 34 1-c APIフレームワーク FastAPI を使ってみよう ⑦OpenAPIのjsonの⽣成 ローカルに保存

    curl http://localhost:8000/openapi.json -o openapi.json ※もしjqをインストールしているなら(エディタにフォーマッターがあればそれでも良い) curl http://localhost:8000/openapi.json | jq > openapi.json jsonのファイルの内容を確認 • FastAPIで登録したパスについての説明がある
  29. © Geniee, Inc. 35 1-c APIフレームワーク FastAPI を使ってみよう ⑧Swagger UI

    の確認 http://localhost:8000/docs にアクセスして Swagger UIが⾒れることを確認 ※使い⽅は先ほどのものと同様
  30. © Geniee, Inc. 36 1-c APIフレームワーク FastAPI を使ってみよう ⑨Redocの確認 https://localhost:8000/redoc

    にアクセスして Redocが⾒れることを確認 Redocの特徴 • Swagger UIのようにリクエストを投げることはできない • レスポンス形式がネストしている時に⾒やすい • 静的なhtmlとして出⼒が可能 (⭕AWS S3等で共有が容易に) ◦ 1ファイルにまとめるには少し⼯夫が必要 (以下参考までに) npm install -g redoc-cli curl http://localhost:8000/openapi.json -o openapi.json npx redoc-cli bundle openapi.json -o redoc.html
  31. © Geniee, Inc. 38 1-d アーキテクチャスタイル バックエンドで APIの定義ができたら、DBなどからデータをどう取得するか DBのアクセスそのものはDB研修で⾏ったはずだが、DBアクセスの関数はどう呼び出すか 話すと⻑くなるから、簡単に

    3層アーキテクチャ(レイヤードアーキテクチャ) • プレゼンテーション層/アプリケーション層/データ層 の3層 • データ →アプリケーション → プレゼンテーション の依存関係 • ⼩さいプロジェクトではコードがシンプルになる オニオンアーキテクチャ • データの整合性にDBのテーブル定義では無くコード上で強いルールを課したい場合に有効 • プレゼンテーション層/ユースケース層/インフラ層/ドメイン層 • 依存注⼊(DI)を⾏うことで、コードの⼤部分がDBに依存しない形にできる ◦ 外の層は中の層のみ import (use, include, require) できる プレゼンテーション層 アプリケーション層 データ層
  32. © Geniee, Inc. 40 1-e シナリオテスト Swagger UIで動作確認ができると⾔っても、⾃動化したいよね... シナリオテスト(APIシナリオテスト)とは、 •

    統合テストと読み替えられる場合もある • 動作させているAPIサーバーに対して、複数のAPIを連続的に呼び出して実⾏するテストケース • APIサーバーに依存させずに実⾏することで、⾔語のテストよりも1階層上で実⾏するイメージ • 例: よくあるユーザー管理のエンドポイントで、 1. ユーザーAの作成 =>作成成功 2. ユーザーAで⾃分の情報を取得 => 取得成功 3. ユーザーAで⾃分の情報を更新 => 更新成功 4. ユーザーAで更新された情報が取得できる => 取得成功 5. ユーザーBでは何も⾒えない => 未認可のユーザー
  33. © Geniee, Inc. 41 1-e シナリオテスト • 例: よくあるユーザー管理のエンドポイントで、 1.

    ユーザーAの作成 =>作成成功 2. ユーザーAで⾃分の情報を取得 => 取得成功 3. ユーザーAで⾃分の情報を更新 => 更新成功 4. ユーザーAで更新された情報が取得できる => 取得成功 5. ユーザーBでは何も⾒えない => 未認可のユーザー • 実現⽅法 ◦ 各⾔語のHTTPライブラリで実装 ▪ 例: bash scriptとcurl ◦ Postman(Newman): LINK ◦ Karate: LINK ◦ runn: LINK ◦ k6: LINK (負荷テストツールを流⽤)
  34. © Geniee, Inc. 42 1-e シナリオテスト シナリオテストのメリット 1. UIテストと⽐べて実⾏スピードが速い 2.

    テストの安定性が⾼い 3. ⾃動テストへの組込みが容易 4. 負荷テストとの相性も良い(実際にDBを呼び出すこともできる) 参考: https://www.docswell.com/s/katzumi/5EN8N1-10-reasons-to-write-api-scenario-tests
  35. © Geniee, Inc. 43 1-e シナリオテスト シナリオテスト(=統合テスト)を重視する考え • Testing Trophy

    という考え⽅に基づいてる React Testing Libraryの開発者であるKent C. Dodds⽒が提唱している、どのテ ストを重視すべきであるかをトロフィーの形で表現した考え⽅ • Integrationが最もコスト/速度と信頼性のバランスに優れており、テスト実装の 労⼒の⼤半はここに費やすべき 参考:https://kentcdodds.com/blog/the-testing-trophy-and-testing-classifications
  36. © Geniee, Inc. 44 1-e シナリオテスト k6 の記述⽅法 jsで記述するけど中⾝はgolang DB接続にはプラグインが必要

    今回はgolangのプロジェクトでないので、プラグインは使わずにscriptで代⽤ • javascript で記述 • http.get()で取得 • check()で値を検証
  37. © Geniee, Inc. 45 1-e シナリオテスト k6 の実⾏⽅法 今回の基礎課題ではテストを実⾏するだけ k6

    run test_scenario/work_00.js を実⾏すると右のようになる 負荷テストのツールなので⾊々な値が⾒れ ますが、 check succeeded が 100.00% になったら成功