Skip to content

Instantly share code, notes, and snippets.

@altnight
Created June 20, 2024 06:18
Show Gist options
  • Save altnight/25d8c858200491ff2a6b4c731f341dd4 to your computer and use it in GitHub Desktop.
Save altnight/25d8c858200491ff2a6b4c731f341dd4 to your computer and use it in GitHub Desktop.
2024/06/20 2024年6月時点でのPythonでのWebAPIの実装について(FastAPI, GraphQL, DRF, Django Ninja)

2024/06/20 2024年6月時点でのPythonでのWebAPIの実装について(FastAPI, GraphQL, DRF, Django Ninja)

結論

FastAPI

  • 公式:
  • Webフレームワークの技術選定の話
    • Django or FastAPI で FastAPI を選定するか
    • 小規模なら、なんでもよい(規模が小さければどういう技術スタックでもだいたいどうにでもなる)
    • 個人開発なら、なんでもよい(影響範囲が自分だけなので、好きな技術スタックでやるといい)
    • 業務かつ中規模以上の場合、本当に適切か?
  • FastAPIが適している要件
    • 管理画面が不要
    • RDB(ORM)が不要
      • 主にSQLAlchemyを使いたい場合
        • ただ、「SQLAlchemyでないと厳しい場合」って具体的にはどういうのがあるのか? そこまで複雑ならもう生SQLにしたくならないか?
      • (主に外部の)列志向のDBを使いたい場合
  • 逆に言うと、「管理画面もORMも使用しない」という要件が業務でどれだけ存在するか??あまり多くないのでは
    • 例:
      • 「システム管理者が一覧画面のチェックをした項目を削除する」とか
      • 「システム管理者がちょっとした項目を編集して運用する」とか
      • 「システム管理者がCSVダウンロードしたくなる」とか
    • 「管理画面が存在しない = 運用がエンジニア」という前提にできるか?
      • ドキュメントにコマンドを記載して運用で手で打ってもらうとかもできるが...運用者がsshする前提のプロダクトはそんなに多くなくない?
  • FastAPIという命名にパワーがあり、性能を求めがちだが、実際問題Webフレームワークレベルでは優位な差が見出しにくいのでは
    • 結局I/Oがネックになるのでは?
      • DBへの問い合わせを非同期にする試みはあるが、実際に使いこなせるか?
    • ほんとにWebのリクエストを高速化したいのか? バッチ処理やSQLなどアプリ設計、またはキャッシュなどインフラ設計で最適化した方がいいのでは?
    • AWS等にデプロイする前提なら、スケールアップ/スケールアウトで簡単に対応できるのでは?
  • 管理画面(テンプレート)とORM等をFastAPIで使用するのであれば、自前でそのあたりを整備することになるので、Djangoのようなフルスタックフレームワークとやっていることがほぼ変わらない
    • むしろ、DBマイグレーションやテスト環境を整えることや、ライブラリのバージョンアップ対応もあるので、工数がかかる
      • ライブラリのバージョンアップが止まったりとか
    • ライブラリ同士の結合も自前でやる必要がある
    • FastAPIのSchema(Pydantic)とORMの型を変換したりすることもある
      • SQLModelというライブラリでがんばってたりもするようだけど...手間を増やしていない?
    • (あまり詳しくないが) 「フルスタックフレームワークは学習コストが高いのでRailsやLaravelはやめました!」って言うのか?
  • 「マイクロサービスなのでFastAPIを採用しました」という話は、実際どうなんだろう
    • どういった背景なのかがわからないので、どうとも言えない
    • 「マイクロサービス」にするのが合ってるのか
      • むやみにシステム分割やリポジトリを分割しているだけ、という場合もある
  • 「FastAPIを使いたかった」という場合、明言した方が技術的には誠実
    • 「FastAPIが技術的に今回の要件に適していた」という結論は、もっともらしいが個人的には若干疑わしく見えることがある

GraphQL

  • 公式:
  • 個人的にはプロダクションレベルで実装したことがないので、どうとも言えない
    • 生のGraphQLやGraphene-Djangoのチュートリアルを触った程度
  • バックエンドのパフォーマンス問題は常につきまとわっている
  • 開発体制でフロントエンドとバックエンドを完全に分離している場合は便利そうという印象
    • ただ、パフォーマンス問題の責任はどう折り合いをつけるんだろう?
  • 会社内の知見だと、GraphQL特有の実装の注意点がある様子
  • 今の会社だと、主にバックエンド開発者がフロントエンドも実装するという体制なので、そもそも分業しない
    • = フロントエンドの変更に合わせてAPIを変更しやすいので、フロント側で自由にクエリを発行できるというのが利点にならず、システムの複雑性が上がるだけのように見える

DRF

  • 公式:
  • 長らくDjangoでのWebAPI開発ではDRF(Django Rest Framework)が主流だった
    • 素のDjangoと比較するとWebAPI開発に便利な機能がある
      • viewまわり
      • serializer
        • formsetを使用しなくていい
      • 例外
      • ドキュメント
  • ただ、DRFはRESTというだけあって、2015年ごろのRESTの思想でできているので、2024年現在だと若干合わない箇所がある
    • RESTful で実装することはほぼない
    • 「モデリングをちゃんとすればRESTで表現できる」という話もあるが、実際チーム開発でそこまでレビューしきれるだろうか?
    • OpenAPIの対応は標準でははいっておらず外部ライブラリで実現
    • APIのバージョニングやXMLでのやりとりなど、現代では使う可能性が低い機能もある
      • バージョニングできるといいつつ、実際には /api/v1 以外つくらないよねという
  • また、よくも悪くもライブラリとして安定しているので、個人的には飽きてきた
  • Genericにひっぱられる重力を避けたい
    • ModelSerializer, ModelViewSet による CRUD APIの実装補助
      • Django 的には ModelForm
      • なので、良くも悪くもserializerでsaveするという設計になっている
    • 結局DjangoはActiveRecordモデルで一気通貫で実装できるのが大きな強みなので、GenericViewが使えれば使いたくなる
      • RESTとフレームワークの思想的にはとても合っている
    • ただ、業務アプリでの実装には最終的に合わないことの方が多い
    • 「簡単なCRUDはGenericで実装、そうでないところは自前で実装」というパターンもあったが、アプリ内の設計がブレるので、イマイチ
      • 初期実装の工数を1日程度減らせるくらいじゃないか
    • アプリ内の設計とフレームワークの提供している機能を混同してしまいがち
  • フックの理解が面倒
    • 自分は長年DjangoやDRFを触ってきたからどこのクラスにどういうフックが存在して、どのレイヤーに処理を書けばいいかだいたいわかるけど
    • 初学者に改めて覚えてもらうのは若干厳しさを感じる
    • クラスViewを使わず関数Viewでもよいが、その場合アプリ内の設計をちゃんとやる必要がある
      • フレームワークが面倒を見ていた箇所をどう意図的に避けて実装するか
      • 関数Viewでアプリの設計をちゃんとするという方針の場合、後述のDjango Ninja の方が手軽では

Django Ninja

  • 公式:
  • 2024年6月現在、WebAPI実装でのおすすめのライブラリ
  • 結局のところ「RESTfulにせずGraphQLも使用せずDjangoで自前実装をする。そのときに素のDjangoよりはサポートが手厚くて、ついでにFastAPIみたいな書き味や提供機能がほしい」というケースが多いのでは
  • いいところ
    • Schema定義をすれば、OpenAPI(Swagger)の定義を自動生成できる
      • OpenAPIの定義があれば、フロントエンド(主にTypeScript)で使用する型定義を簡単に生成できる
      • Schemaの定義にDjangoのModel(ModelSchema)が使用できる
        • 動的にスキーマ作成もできる
    • (DRFと比較して) ライブラリが薄いので、覚えることが少ない
    • (DRFと比較して) GenericViewやModelSerializerがないので、Modelの重力にひっぱられない
  • もし Django Ninja をやめないといけなくなっても、似たようなライブラリで再実装できる
    • それこそDRFとか
    • ただ実際問題、ライブラリの寿命よりプロダクトの寿命の方が短いことも多い
      • もしライブラリのメンテが厳しい場合、Contributeしたいところではある
    • であれば、アプリの設計で「Django Ninjaを採用し、HTTPレイヤーの責務のみを果たす」という方針を徹底する方がよい
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment