Front-end/Next.js

๐Ÿš€ Next.js๋กœ API ๋งŒ๋“ค๊ธฐ: ์‰ฝ๊ณ  ๊น”๋”ํ•œ ๋ฐฑ์—”๋“œ ๊ตฌ์ถ•๋ฒ• ๐Ÿ’ก

xeunnie 2025. 2. 17. 01:00
728x90
๋ฐ˜์‘ํ˜•

๐Ÿš€ Next.js๋กœ API ๋งŒ๋“ค๊ธฐ: ์‰ฝ๊ณ  ๊น”๋”ํ•œ ๋ฐฑ์—”๋“œ ๊ตฌ์ถ•๋ฒ• ๐Ÿ’ก

 

Next.js๋Š” ์„œ๋ฒ„ ์‚ฌ์ด๋“œ ๋ Œ๋”๋ง(SSR)๊ณผ ์ •์  ์‚ฌ์ดํŠธ ์ƒ์„ฑ(SSG)์— ๊ฐ•์ ์„ ๊ฐ€์ง„ React ํ”„๋ ˆ์ž„์›Œํฌ๋กœ ๋„๋ฆฌ ์•Œ๋ ค์ ธ ์žˆ์ง€๋งŒ, ์‚ฌ์‹ค API ๊ตฌ์ถ•์—๋„ ๋†€๋ผ์šด ๋Šฅ๋ ฅ์„ ์ž๋ž‘ํ•ฉ๋‹ˆ๋‹ค. ๐ŸŽ‰

 

Next.js๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ณต์žกํ•œ ์„œ๋ฒ„ ์„ค์ • ์—†์ด๋„ ๋ฐฑ์—”๋“œ API๋ฅผ ์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ค๋Š˜์€ Next.js๋กœ API๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ๊ธฐ์ดˆ๋ถ€ํ„ฐ ์‹ค๋ฌด ํ™œ์šฉ๊นŒ์ง€ ๊ฝ‰๊ฝ‰ ๋ˆŒ๋Ÿฌ ๋‹ด์•„ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค! ๐Ÿงณ

 

๐ŸŒŸ Next.js API์˜ ๊ธฐ๋ณธ ๊ตฌ์กฐ

 

Next.js์—์„œ๋Š” API๋ฅผ ์œ„ํ•œ ๋ณ„๋„์˜ ์„œ๋ฒ„๋ฅผ ์„ค์ •ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. /pages/api ํด๋”์— ํŒŒ์ผ์„ ์ถ”๊ฐ€ํ•˜๋ฉด ํ•ด๋‹น ํŒŒ์ผ์ด ๊ณง API ์—”๋“œํฌ์ธํŠธ๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.

 

๐Ÿ—‚๏ธ ํด๋” ๊ตฌ์กฐ

 

my-next-app/

โ”œโ”€โ”€ pages/

โ”‚   โ”œโ”€โ”€ api/

โ”‚   โ”‚   โ”œโ”€โ”€ hello.js       // ๊ธฐ๋ณธ API ํŒŒ์ผ

โ”‚   โ”‚   โ”œโ”€โ”€ users.js       // ์‚ฌ์šฉ์ž ๋ฐ์ดํ„ฐ API

โ”‚   โ”‚   โ”œโ”€โ”€ posts/

โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ index.js   // ๊ฒŒ์‹œ๋ฌผ ๋ชฉ๋ก API

โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ [id].js    // ํŠน์ • ๊ฒŒ์‹œ๋ฌผ API

 

**/pages/api/hello.js**๋Š” http://localhost:3000/api/hello๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” API๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

 

๐Ÿ”ง API ๊ธฐ๋ณธ ์ฝ”๋“œ

 

Hello API ๋งŒ๋“ค๊ธฐ

 

/pages/api/hello.js ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด ๊ฐ„๋‹จํ•œ ์‘๋‹ต์„ ๋ณด๋‚ด๋Š” API๋ฅผ ์ž‘์„ฑํ•ด๋ด…์‹œ๋‹ค.

 

// pages/api/hello.js

export default function handler(req, res) {

  res.status(200).json({ message: "Hello, Next.js API!" });

}

 

req: ํด๋ผ์ด์–ธํŠธ ์š”์ฒญ ๊ฐ์ฒด.

res: ์„œ๋ฒ„ ์‘๋‹ต ๊ฐ์ฒด.

 

๐Ÿ‘‰ ์ด API๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ JSON ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค:

 

{

  "message": "Hello, Next.js API!"

}

 

๐ŸŒ HTTP ๋ฉ”์„œ๋“œ ๋‹ค๋ฃจ๊ธฐ

 

Next.js API๋Š” GET, POST, PUT, DELETE ๋“ฑ ๋‹ค์–‘ํ•œ HTTP ๋ฉ”์„œ๋“œ๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

Users API

 

/pages/api/users.js๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๋‹ค์–‘ํ•œ ๋ฉ”์„œ๋“œ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” API๋ฅผ ๋งŒ๋“ค์–ด๋ด…์‹œ๋‹ค.

 

export default function handler(req, res) {

  const { method } = req;

 

  switch (method) {

    case "GET":

      res.status(200).json({ users: ["Alice", "Bob", "Charlie"] });

      break;

 

    case "POST":

      const { name } = req.body;

      res.status(201).json({ message: `User ${name} created!` });

      break;

 

    default:

      res.setHeader("Allow", ["GET", "POST"]);

      res.status(405).end(`Method ${method} Not Allowed`);

  }

}

 

์š”์ฒญ ๋ฐ ์‘๋‹ต ์˜ˆ์‹œ

1. GET ์š”์ฒญ:

URL: http://localhost:3000/api/users

์‘๋‹ต:

 

{

  "users": ["Alice", "Bob", "Charlie"]

}

 

 

2. POST ์š”์ฒญ:

URL: http://localhost:3000/api/users

Body: { "name": "Dave" }

์‘๋‹ต:

 

{

  "message": "User Dave created!"

}

 

๐Ÿ› ๏ธ ๋™์  ๋ผ์šฐํŒ…๊ณผ ํŒŒ๋ผ๋ฏธํ„ฐ ์ฒ˜๋ฆฌ

 

Next.js API์—์„œ๋Š” ํŒŒ์ผ๋ช…์œผ๋กœ ๋™์  ๋ผ์šฐํŒ…์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

๊ฒŒ์‹œ๋ฌผ API

 

/pages/api/posts/[id].js๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ํŠน์ • ๊ฒŒ์‹œ๋ฌผ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” API๋ฅผ ๋งŒ๋“ค์–ด๋ด…์‹œ๋‹ค.

 

export default function handler(req, res) {

  const { id } = req.query;

 

  if (req.method === "GET") {

    res.status(200).json({ postId: id, content: `Content of post ${id}` });

  } else {

    res.setHeader("Allow", ["GET"]);

    res.status(405).end(`Method ${req.method} Not Allowed`);

  }

}

 

์š”์ฒญ ๋ฐ ์‘๋‹ต ์˜ˆ์‹œ

1. GET ์š”์ฒญ:

URL: http://localhost:3000/api/posts/123

์‘๋‹ต:

 

{

  "postId": "123",

  "content": "Content of post 123"

}

 

๐Ÿ”’ API ๋ณด์•ˆ: ํ™˜๊ฒฝ ๋ณ€์ˆ˜์™€ ์ธ์ฆ ์ฒ˜๋ฆฌ

 

ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ์‚ฌ์šฉ

 

Next.js์—์„œ๋Š” **process.env**๋ฅผ ์‚ฌ์šฉํ•ด ๋ฏผ๊ฐํ•œ ์ •๋ณด๋ฅผ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

1. ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ์„ค์ •

.env.local ํŒŒ์ผ ์ƒ์„ฑ:

 

API_KEY=your-secret-api-key

 

 

2. API์—์„œ ์‚ฌ์šฉ

 

export default function handler(req, res) {

  const apiKey = process.env.API_KEY;

  res.status(200).json({ apiKey });

}

 

JWT ์ธ์ฆ ์ฒ˜๋ฆฌ

 

๊ฐ„๋‹จํ•œ JWT ์ธ์ฆ์„ API์— ์ถ”๊ฐ€ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

import jwt from "jsonwebtoken";

 

export default function handler(req, res) {

  const { authorization } = req.headers;

 

  if (!authorization) {

    return res.status(401).json({ error: "No token provided" });

  }

 

  try {

    const token = authorization.split(" ")[1];

    const decoded = jwt.verify(token, process.env.JWT_SECRET);

    res.status(200).json({ message: "Authenticated!", user: decoded });

  } catch (err) {

    res.status(401).json({ error: "Invalid token" });

  }

}

 

โšก ์‹ค๋ฌด ํ™œ์šฉ ์˜ˆ์‹œ: ํด๋ผ์ด์–ธํŠธ์—์„œ API ํ˜ธ์ถœํ•˜๊ธฐ

 

API ํ˜ธ์ถœ ์ฝ”๋“œ (React ์ปดํฌ๋„ŒํŠธ)

 

import { useEffect, useState } from "react";

 

export default function Users() {

  const [users, setUsers] = useState([]);

 

  useEffect(() => {

    fetch("/api/users")

      .then((res) => res.json())

      .then((data) => setUsers(data.users));

  }, []);

 

  return (

    <ul>

      {users.map((user, index) => (

        <li key={index}>{user}</li>

      ))}

    </ul>

  );

}

 

๐ŸŒŸ Next.js API์˜ ์žฅ์ 

1. ์„ค์ • ๊ฐ„์†Œํ™”: ๋ณ„๋„์˜ ์„œ๋ฒ„ ์„ค์ • ์—†์ด API๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

2. ํด๋” ๊ธฐ๋ฐ˜ ๋ผ์šฐํŒ…: ๋””๋ ‰ํ† ๋ฆฌ ๊ตฌ์กฐ๋กœ ๋ผ์šฐํŠธ๋ฅผ ์ง๊ด€์ ์œผ๋กœ ๊ด€๋ฆฌ.

3. SSR๊ณผ ํ†ตํ•ฉ: API์™€ ์„œ๋ฒ„ ๋ Œ๋”๋ง์„ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๊ฒฐํ•ฉ ๊ฐ€๋Šฅ.

4. ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ์ง€์›: ๋ฏผ๊ฐํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ๊ด€๋ฆฌ.

5. ๋ฌดํ•œ ํ™•์žฅ ๊ฐ€๋Šฅ: ๊ฐ„๋‹จํ•œ ํ”„๋กœ์ ํŠธ๋ถ€ํ„ฐ ๋ณต์žกํ•œ ๋ฐฑ์—”๋“œ๊นŒ์ง€ ๋Œ€์‘ ๊ฐ€๋Šฅ.

 

๐ŸŽ‰ ๋งˆ๋ฌด๋ฆฌ

 

Next.js์˜ API๋Š” ๋ฐฑ์—”๋“œ ์„ค์ •์˜ ๋ณต์žกํ•จ ์—†์ด ๊ฐ•๋ ฅํ•œ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋ฐฑ์—”๋“œ ๋กœ์ง๊นŒ์ง€ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๋Š” ์‹œ๋Œ€, ์ด์ œ Next.js๋กœ ์‹œ์ž‘ํ•ด๋ณด์„ธ์š”! ๐Ÿš€

 

๐ŸŒท์ „์„ค์˜ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋˜์–ด๋ด…์‹œ๋‹น!๐ŸŒท

728x90
๋ฐ˜์‘ํ˜•