관리 메뉴

Bull

[Next.js] FAST API에서 NextJS로 json 보내기 본문

Software Framework/Next.js

[Next.js] FAST API에서 NextJS로 json 보내기

Bull_ 2024. 5. 24. 18:35

Next 디렉터리 구조

my-next-app/
├── node_modules/
├── public/
├── src/
│   ├── app/
│   │   ├── loading/
│   │   │   └── page.js
│   │   ├── result/
│   │   │   └── page.js
│   ├── api/
│   │   ├── receive/
│   │   │   └── route.js
│   ├── globals.css
│   ├── layout.js
│   └── page.js
├── .gitignore
├── package.json

메인화면 코드는 생략.

localhost:3000/loading

'use client';

import { useEffect } from 'react';
import { useRouter } from 'next/navigation';

export default function LoadingPage() {
  const router = useRouter();

  useEffect(() => {
    // Polling to check if data is available
    const interval = setInterval(async () => {
      const res = await fetch('/api/receive');
      const data = await res.json();
      
      if (data.status === 'completed') {
        router.push('/result');
        clearInterval(interval); // Stop polling once data is received
      }
    }, 2000); // Poll every 2 seconds

    return () => clearInterval(interval); // Cleanup interval on unmount
  }, [router]);

  return (
    <div>
      <h1>Loading...</h1>
    </div>
  );
}

poll 기법을 이용해 2초마다 /api/receive로 데이터 수신 확인.

localhost:3000/api/receive -- route.jsx

import { NextResponse } from "next/server";

let receivedData = null;

export async function POST(req) {
  try {
    const body = await req.json();
    receivedData = body;
    console.log("Data received:", receivedData);
    return NextResponse.json({ message: "Data received" });
  } catch (error) {
    console.error("Error receiving data:", error);
    return NextResponse.json(
      { message: "Internal Server Error" },
      { status: 500 }
    );
  }
}

export async function GET() {
  try {
    if (receivedData) {
      // 10초 후에 receivedData 초기화
      setTimeout(() => {
        receivedData = null;
        console.log("Data has been cleared after 10 seconds");
      }, 10000); 

      console.log("Sending received data:", receivedData);
      return NextResponse.json({ status: "completed", data: receivedData });
    } else {
      return NextResponse.json({ status: "pending" });
    }
  } catch (error) {
    console.error("Error sending data:", error);
    return NextResponse.json(
      { message: "Internal Server Error" },
      { status: 500 }
    );
  }
}

Next에서는  NextResponse.json를 사용해야 한다.

localhost:3000/result 

'use client';

import { useEffect, useState } from 'react';

export default function ResultPage() {
  const [result, setResult] = useState(null);

  useEffect(() => {
    async function fetchResult() {
      const res = await fetch('/api/receive');
      const data = await res.json();
      setResult(data);
    }
    fetchResult();
  }, []);

  if (!result) {
    return <div>Loading...</div>;
  }

  return (
    <div>
      <h1>Result</h1>
      <pre>{JSON.stringify(result, null, 2)}</pre>
    </div>
  );
}

FAST API - main.py

from fastapi import FastAPI, BackgroundTasks, Request
from fastapi.responses import HTMLResponse, JSONResponse
import requests
import time

app = FastAPI()

# In-memory storage for OCR results
result = None

def send_data_to_next(json_data):
    # Next.js 서버의 엔드포인트로 JSON 데이터를 POST 요청으로 전송
    nextjs_url = "http://localhost:3000/api/receive"
    response = requests.post(nextjs_url, json=json_data)
    return response.status_code

@app.post("/process/")
async def process_data(background_tasks: BackgroundTasks):
    global result
    # 데이터 처리 (여기서는 단순히 딜레이를 추가)
    time.sleep(1)
    result = {"status": "completed", "data": {"message": "Processing complete"}}
    
    # 백그라운드 작업으로 Next.js에 데이터 전송
    background_tasks.add_task(send_data_to_next, result)
    
    return JSONResponse(status_code=200, content={"message": "Processing started"})

@app.get("/post_process", response_class=HTMLResponse)
async def post_process():
    html_content = """
    <html>
        <head>
            <title>Post Process</title>
        </head>
        <body>
            <h1>Post Process</h1>
            <form action="/process" method="post">
                <button type="submit">Start Process</button>
            </form>
        </body>
    </html>
    """
    return HTMLResponse(content=html_content)

start process 전에 loading에서 대기

 

2초마다 pooling 중

 

process 버튼 누름

 

결과 렌더링

fast API를 통해 next의 /api/receive로 post 요청으로 데이터를 전송하고 받은 데이터를 2초마다 pooling 중이던 loading 페이지에서는 데이터를 확인하고 /result로 push를 진행한다.