๊ฐœ๋ฐœ/Next.js

NEXT.js14 API Routes ์‚ฌ์šฉํ•˜๊ธฐ (with. MONGODB)

๋ฐ(Ming) ๐Ÿˆ‍โฌ› 2024. 1. 3. 13:05
728x90
๋ฐ˜์‘ํ˜•

 

API Routes

API Routes๋Š” API๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋Š” Endpoint๋ฅผ ์ƒ์„ฑํ•ด์ฃผ๋Š”๋ฐ, ์‰ฝ๊ฒŒ ๋งํ•ด๋ณด์ž๋ฉด Next.js์˜ ํŒŒ์ผ ๊ธฐ๋ฐ˜์œผ๋กœ API๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ฒŒํ•ด์ค€๋‹ค. ๊ทธ๋Ÿฌ๋‹ˆ๊น ๋‹ค๋ฅธ ๋ฐฑ์—”๋“œ ํ”„๋ ˆ์ž„์›Œํฌ ํ•„์š”์—†์ด, ๋”ฐ๋กœ api๋ฅผ ๋งŒ๋“ค์–ด์„œ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•„๋„ DB ์—ฐ๊ฒฐ๊นŒ์ง€ ํ•  ์ˆ˜ ์žˆ๊ณ , ๋ฐ์ดํ„ฐ ์ „์†ก์ด ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ๋ง์ด๋‹ค. Routing๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ํŒŒ์ผ๊ธฐ๋ฐ˜์œผ๋กœ ์ด๋ฃจ์–ด์ง€๋Š”๋ฐ Nextjs14์˜ ๊ฒฝ์šฐ๋Š” pages๊ฐ€ ์•„๋‹Œ app ํด๋”์— ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜๊ณ (14๋ฒ„์ ผ ์ด์ „์€ pages/api), ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•˜๋ฉด ๋œ๋‹ค. 

 

API Routes๋Š” Serverless function์œผ๋กœ ์ด๋ฃจ์–ด์ ธ์žˆ๋‹ค. Serverless Function์˜ ์ปจ์…‰์€ ์š”์ฒญ(์ด๋ฒคํŠธ)์ด ๋“ค์–ด์˜ฌ ๋•Œ๋งˆ๋‹ค ์ง€์ •๋œ ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰์‹œ์ผœ ์›ํ•˜๋Š” API๋ฅผ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— web socket๊ณผ ๊ฐ™์ด ์ง€์†์ ์ธ ์ปค๋„ฅ์…˜์„ ๊ฐ€์งˆ ์ˆ˜ ์—†๋‹ค. ํ•˜์ง€๋งŒ ๊ฐ„๋‹จํ•œ ๋ฐ์ดํ„ฐ ์ „์†ก๊ณผ ์บ์‹ฑ ๊ธฐ๋Šฅ์ด ์žˆ๊ธฐ๋•Œ๋ฌธ์— ๋ณต์žกํ•œ ์„œ๋น„์Šค๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด ์•„์ฃผ ๋น ๋ฅด๊ณ  ์‹ถ๊ฒŒ ์„œ๋น„์Šค๋ฅผ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค. 

 

์‚ฌ์šฉ ๋ฐฉ๋ฒ•

api๋กœ ์ฃผ๊ณ  ๋ฐ›์„ ๋ฐ์ดํ„ฐ ์Šคํ‚ค๋งˆ ์ƒ์„ฑํ•ด์ค๋‹ˆ๋‹ค. ๋ฌผ๋ก  db์—๋„ ๋˜‘๊ฐ™์ด ์ด๋Ÿฐ ํ˜•ํƒœ๋กœ ๋“ค์–ด๊ฐˆ๊ฑฐ๊ณ  ๊ฐ€์ ธ์˜ฌ๊ฑฐ๋‹ค. db๋Š” mongoDB๋ฅผ ์‚ฌ์šฉํ–ˆ๊ณ , ์—ฐ๊ฒฐ์€ mongoose๋ฅผ ์ด์šฉํ–ˆ๋‹ค. 

 

models.js

import mongoose from "mongoose";

const recordsSchema = new mongoose.Schema(
    {
        userId: {
            type: Number,
            required: true,
            unique:true,
        },
        username:{
            type: String,
            required: true,
            unique: true,
            minlength: 3,
            maxlength: 10
        },
        time: {
            type: Number,
            required: true,
        },
        section:{
            type: String,
            required: true,
            minlength: 1,
            maxlength: 50
        },
    },
    {timestamps: true }
)

export const Record = mongoose.models?.Record || mongoose.model("Record", recordsSchema);

 

 

 

/api/routes.js

export const POST = async(req, res) => {
    try {
     // db ์—ฐ๊ฒฐ
      ConnectToDb();
      
      const data  = await req.json()
      
      // db์— ์ €์žฅํ•ด์ฃผ๊ธฐ, ๋งŒ๋“ค์–ด ๋‘” ์Šคํ‚ค๋งˆ๊ฐ€์ ธ์™€์„œ ์ƒˆ๋กœ ์ƒ์„ฑํ•ด์„œ ์ €์žฅํ•ด์ฃผ๊ธฐ
      const newRecord = new Record(data);
      await newRecord.save();
      
      // post๋ผ์„œ response๋ฅผ ์ด๋ ‡๊ฒŒ ์ค„ ํ•„์š”๋Š” ์—†์ง€๋งŒ get ์‚ฌ์šฉํ•  ๋•Œ๋Š” ํ•„์ˆ˜
      return NextResponse.json(data);

    } catch (err) {
      console.log(err);
      throw new Error("Failed to fetch posts!");
    }

}

 

revalidatePath ์ด๋ผ๊ณ  next์—์„œ ์ œ๊ณตํ•˜๋Š” ํ•จ์ˆ˜์ธ๋ฐ, /URL์— ์žˆ๋˜ ์บ์‹œ๋ฅผ ์‚ญ์ œํ•˜๊ณ  ๋‹ค์‹œ ์ƒ์„ฑ, ํŽ˜์ด์ง€๋ฅผ ๋‹ค์‹œ ๋กœ๋“œํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ์ด ์žˆ๋‹ต๋‹ˆ๋‹ค. ๋ณ€๊ฒฝ๋œ ๊ฒƒ๋งŒ ๋ฐ”๊ฟ”์ฃผ๋Š” ๊ธฐ๋Šฅ์ด๋ผ์„œ ๋„ฃ์–ด์คฌ์Šต๋‹ˆ๋‹ค. ๊ด„ํ˜ธ์•ˆ์—๋Š” ํ•ด๋‹น ํŽ˜์ด์ง€ ๊ฒฝ๋กœ๋ฅผ ๋„ฃ์–ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 

 

 

/ํ•ด๋‹นํŒŒ์ผ.jsx

export async function postRecord(req) { 
  try {
    const res = await fetch('http://localhost:3000/api/record', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(req),
    });

    if (!res.ok) {
      throw new Error(`Failed to save record. Status: ${res.status}`);
    }
  } catch (error) {
    console.error('Error:', error);
  }

}

 

์„œ๋ฒ„๋กœ ๋ณด๋‚ผ ํ•จ์ˆ˜ fetchํ•œ ์ฝ”๋“œ. sever client๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ ํ•ด๋‹น ํŒŒ์ผ ๊ตฌ์„ฑ์ƒ ๊ทธ๋ ‡๊ฒŒ ์“ธ ์ˆ˜ ์—†๋Š” ์ƒํ™ฉ์ด์—ฌ์„œ use client ๋กœ ๊ตฌํ˜„์„ ํ•ด์•ผํ–ˆ๋‹ค. api/record๋Š” ์œ„์˜ post ํ•จ์ˆ˜๊ฐ€ ๋“ค์–ด๊ฐ€์žˆ๋Š” ํŒŒ์ผ ๊ฒฝ๋กœ์ด๋‹ค. method๋ฅผ 'POST'๋กœ ํ•ด์ฃผ๊ณ  fetch ํ•จ์ˆ˜ ์“ฐ๋“ฏ์ด ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค. 

 

 

 


 

 

 

์ด๋ ‡๊ฒŒ ๊ฐ„๋‹จํ•œ ๊ฑด๋ฐ, ์‚ฌ์‹ค ์ด ๋ถ€๋ถ„ ๊ตฌํ˜„์ด ํ•˜๋ฃจ์ข…์ผ ๊ฑธ๋ ธ๋‹ค. 'POST' method๋ฅผ fetch๋ฅผ ํ•˜๊ธดํ•˜๋Š”๋ฐ, payload๋กœ ๋ฐ์ดํ„ฐ๋„ ์ œ๋Œ€๋กœ ๋ณด๋‚ด๋Š”๋ฐ, ๊ณ„์† sever error๊ฐ€ ๋‚˜๋Š” ๊ฒƒ์ด๋‹ค. api๋ฅผ ์˜๋Š”๋ฐ request body ๊ฐ’์ด ์ œ๋Œ€๋กœ ์•ˆ ๋“ค์–ด์˜จ๋‹ค๊ณ  500 ์—๋Ÿฌ๊ฐ€ ๊ณ„์† ๋‚จ. request์— ๋“ค์–ด๊ฐ€๋Š” ์š”์†Œ๋“ค์ด ๋‹ค ํ•„์ˆ˜๋ผ๊ณ  ์Šคํ‚ค๋งˆ์— ์ ์–ด๋‘ฌ์„œ ์ œ๋Œ€๋กœ ์•ˆ ๋“ค์–ด์˜ค๋ฉด error ๋œจ๋Š”๊ฑฐ. ๋งจ๋‚  ํด๋ผ์ด์–ธํŠธ์ชฝ๋งŒํ•ด์„œ ์ด๊ฑธ ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ•ด์•ผํ• ์ง€๋„ ๋ชจ๋ฅด๊ฒ ๊ณ , ์‹ฌ์ง€์–ด payload์—๋Š” ๋‹ค ๋„˜์–ด๊ฐ€๊ณ  ์žˆ๋Š” ์ƒํ™ฉ์ด์—ฌ์„œ ๋” ์˜ค๋ฆฌ๋ฌด์ค‘. ๋‚ด๊ฐ€ ํ‰์ƒ์‹œ์— ๋‹ค๋ฃจ์ง€ ๋ชป ํ–ˆ๋˜ ๋ถ€๋ถ„์ด๋ผ์„œ ๋” ํŒจ๋‹‰. 

 

์—ฌ๊ธฐ์ €๊ธฐ console.log๋ฅผ ์ฐ์—ˆ๋Š”๋ดค๋Š”๋ฐ POST ํ•จ์ˆ˜์ชฝ์—์„œ request๋ฅผ ์ฐ์–ด๋ณด๋ฉด undefined๋กœ ์•„๋ฌด๊ฒƒ๋„ ์•ˆ ์ฐํžˆ๋Š” ์ƒํ™ฉ.

const data  = await req.json() ์ด ๋ถ€๋ถ„์„ ์ œ๋Œ€๋กœ ์•ˆ ์ ์–ด์ค˜์„œ ๊ทธ๋Ÿฐ๊ฑฐ 

์•„๋ž˜์˜ ๋ธ”๋กœ๊ทธ๋ฅผ ๋ณด๋ฉด post handling์„ ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ•˜๋Š”์ง€ ์ ํ˜€์žˆ๋‹ค. ์ด๋ถ„๋„ ๋‚˜์™€๊ฐ™์€ ์˜ค๋ฅ˜๋ฅผ ๊ฒช์œผ์‹ ๋“ฏ.

https://dev.to/iambstha/http-get-post-request-in-nextjs-stable-app-router-557m

 

HTTP GET & POST Request in NextJS Stable App Router

When the app router was released in NextJS 13.2 , being a frontend developer, I was stuck with...

dev.to

 

 

 

 

 

 

์ฐธ๊ณ  ํ•™์Šต์ž๋ฃŒ

  • ๊ณต์‹๋ฌธ์„œ

https://nextjs.org/docs/pages/building-your-application/routing/api-routes

 

Routing: API Routes | Next.js

Next.js supports API Routes, which allow you to build your API without leaving your Next.js app. Learn how it works here.

nextjs.org

 

 

 

728x90