Next.js & FastAPI & PostgreSQL on Docker

はじめに

こんにちは、インダストリーワン エンジニアの松崎です。

Next.js & FastAPI & PostgreSQL on Docker と題して、フロントエンドにNext.js、バックエンドにFastAPI、データベースにPostgreSQLを採用してサクッと技術検証できるようにするための第一段階としてDocker Composeで動作環境が構築できるようにしたので記事にします。

サクッと技術検証できるようにしたかった理由としては、プロダクトにそのまま流用したいというよりもライブラリなどをサンドボックス的に試したかったからです。

技術の選定理由については、個人的な興味によるものです。

成果物

ソースはこちら GitHub - fumiya-matsuzaki/nextjs-fastapi-ex

※現時点ではフロントエンドとバックエンドの疎通を確認できるだけの状態です。

※現時点では、バックエンドとデータベースの接続は行なっておりません。

フロントエンド

Next.jsを採用し、Route Handlersを利用してバックエンドと疎通します。

起動後にhttp://localhost:3000にアクセスするとNext.jsの初期画面が表示されます。

また、http://localhost:3000/demoにアクセスするとデモページに遷移し、バックエンドのAPIから取得したメッセージが表示されます。

デモページを表示するコンポーネント

'use client'

import { useEffect, useState } from "react";
import axios from "axios";

export default function DemoPage() {

  const [routerMessage, setRouterMessage] = useState("");
  const [serverMessage, setServerMessage] = useState("");

  const getDemoServerMessage = async () => {
    const response = await axios.get("/api/demo/get-server");
    setServerMessage(response.data.message);
  }

  const getDemoRouterMessage = async () => {
    const response = await axios.get("/api/demo/get-router");
    setRouterMessage(response.data.message);
  }


  useEffect(() => {
    getDemoServerMessage();
    getDemoRouterMessage();
  }, []);

  return (
    <div>
      <p>{serverMessage}</p>
      <p>{routerMessage}</p>
    </div>
  );
}

RouteHandlerがバックエンドを経由せず、メッセージを返す

import { NextRequest, NextResponse } from 'next/server';


export async function GET(req: NextRequest) {
    return NextResponse.json({ message: 'Hello from APIRouter!'});
}

RouteHandlerがバックエンドにリクエストを送信し、メッセージを返す

import { NextRequest, NextResponse } from 'next/server';
import { api } from '@/domain/demo/constant'
import axios from 'axios';


export async function GET(req: NextRequest) {
    const response = await axios.get(`${api.baseURL}${api.V1.getMessage}`);
    return NextResponse.json(response.data);
}

バックエンド

PythonフレームワークであるFastAPIを用いてAPIサーバを構築し、フロントエンドからのリクエストを受け取ります。

起動後にhttp://localhost:8000/docsにアクセスするとFastAPIが作成するエンドポイントの一覧画面(Swagger UI)が表示されます。

デモ用のエンドポイント

こちらでmessageをレスポンスするエンドポイントを定義

from fastapi import APIRouter, status, HTTPException
from fastapi.responses import ORJSONResponse


V1_GET_DEMO_MESSAGE = "/webapi/v1/demo/message"


router = APIRouter(tags=["Demo"], default_response_class=ORJSONResponse)


@router.get(
    path=V1_GET_DEMO_MESSAGE,
    status_code=status.HTTP_200_OK,
    responses={
        status.HTTP_200_OK: {
            "description": "Get demo message",
        },
        status.HTTP_500_INTERNAL_SERVER_ERROR: {
            "description": "Internal server error"
        }
    }
)
async def get_demo_message():
    try:
        return ORJSONResponse(
                status_code=status.HTTP_200_OK,
                content=(
                    {
                        "message": f"Hello from the FastAPI!"
                    }
                )
            )
        
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=str(e)
        )

データベース

PostgreSQLを採用し、バックエンドと疎通します。

今後

現在採用している技術だけでなく、他の技術についても取り組んでいきたいです。 フロントエンド/バックエンドについては下記に取り組んでいきたいです。

フロントエンド

  • Server ComponentClient Componentを適切に使い分ける
  • shadcn/uiを導入し、UIを構築する
  • React QuerySWRを導入し、バックエンドと接続する
  • JestPlaywrightを導入し、テストを行う
  • Auth.jsを導入し、認証認可を行う
  • その他諸々...

バックエンド

  • SQLAlchemyを導入し、データベースとの接続を行う
  • alembicを導入し、データベースのマイグレーションを行う
  • Pytestを導入し、テストを行う
  • その他諸々...

おわりに

インダストリー・ワンでは一緒に働く仲間を募集しています。
少しでも興味を持っていただいた方は、是非以下から応募していただければと思います。もちろんカジュアル面談からでも OK!
どうぞ宜しくお願いいたします。

herp.careers