배워서 남 주자

Next.js 14의 API Layer : 클라이언트 컴포넌트에서 Route Handlers를 fetch하는 방법

미래에서 온 개발자 2024. 5. 12. 14:50

 
Next.js 공홈의 Learn Next.js를 따라가며 docs를 보는 스터디를 하고 있다. Learn Next.js의 실습은 SQL을 사용해 DB에 직접 쿼리를 날리는 방식 위주여서 API Layer 방식의 데이터 패칭은 어떻게 하는 것인지 도무지 와닿지가 않았다. 공홈의 문서를 봐도 route.ts 파일에서 Route Handler를 선언하는 코드만 나와있고, 이 선언된 코드의 사용부에 대한 내용이 당최 없다. Lee Robinson이 설명하는 youtube 예제에서도 API Layer에 대한 내용은 없다. 
 

Routing: Route Handlers | Next.js

Create custom request handlers for a given route using the Web's Request and Response APIs.

nextjs.org

 
 
예제를 찾아 검색을 거듭하던 중 아래의 블로그 포스팅에서 /app/test 디렉토리에 route.js 파일을 작성한 다음, 브라우저에서 http://localhost:3000/api/test 로 접속하면 return 값을 볼 수 있다는 걸 알게 되었다. 

export async function GET(Request) {
  return new Response("This is a new API route");
}

 

Using Next.js Route Handlers - LogRocket Blog

Explore the route handling features in Next.js v13.2, demo how to use it, and compare it to the previous routing system.

blog.logrocket.com

 
 
하지만 이 다음에도 이걸 어떻게 페이지, 또는 컴포넌트에서 호출해서 사용하란 거지? 도무지 영문을 모르겠던 나날을 보내던 중.. Nomad Coder의 Next.js 강의를 듣게 되었다. 첫 강의에서 Server Actions을 설명하기 전 Route Handler를 간단하게 소개하고 넘어가는데, 여기에서 기존 리액트에서 하던 방식과 똑.같.이 사용하면 된다는 걸 알게 되었다...! 
 

// /api/users/route.ts

import type { NextRequest } from "next/server";

export async function GET(request: NextRequest) {
  return Response.json({ ok: true });
}

export async function POST(request: NextRequest) {
  const data = await request.json();

  // cookie 등 확인해서 서버에서 사용자를 로그인 시켜준다.
  // const cookies = request.cookies.get("");
  console.log("log the user in!");

  return Response.json(data);
}

 

// /login/page.tsx

"use client";

import FormInput from "@/components/form-input";
import FormButton from "@/components/form-button";
import SocialLogin from "@/components/social-login";
import { useEffect } from "react";

export default function Login() {
  useEffect(() => {
    async function fetchData() {
      const data = await fetch("api/users");
      console.log(await data.json()); // {ok: true}
    }

    fetchData();
  }, []);

  const onClick = async () => {
    const response = await fetch("/api/users", {
      method: "POST",
      body: JSON.stringify({
        username: "kim",
        password: "123456",
      }),
    });

    console.log(await response.json());
  };

  return (
    <div className="px-6 py-8 flex flex-col gap-10">
      <div className="flex flex-col gap-2 *:font-medium">
        <h1 className="text-2xl">안녕하세요!</h1>
        <h2 className="text-xl">Log in with your email and password.</h2>
      </div>
      <form className="flex flex-col gap-3">
        <FormInput type="email" placeholder="Email" required errors={[""]} />
        <FormInput
          type="password"
          placeholder="Password"
          required
          errors={[""]}
        />
      </form>
      <span onClick={onClick}>
        <FormButton loading={false} text="Create account" />
      </span>
      <SocialLogin />
    </div>
  );
}
login 페이지

 
 
Create account 버튼을 클릭하면, 클라이언트(브라우저)의 콘솔과 서버(터미널)에는 각각의 다음의 로그가 찍히는 걸 볼 수 있다. 
 

 
아, 이래서 눈을 씻고 찾아봐도 예제가 없었던 거구나... 허망했던 순간... 
Server Actions처럼 API Layer에서도 Route Handler를 사용하는 Next.js 만의 컨벤션이 있을 거라고 생각했다. 
 
그런데 잠깐만.. 이거 어디서 보던 거잖아. Next.js 13의 nextConfig에서 rewrites로 api endpoint나 key 같은 민감한 정보를 마스킹할 수 있는 거랑 똑같잖아? 
 

/** @type {import('next').NextConfig} */

const API_KEY = process.env.API_KEY;

const nextConfig = {
  reactStrictMode: true,
  async rewrites() {
    return [
      {
        source: "/api/movies",
        destination: `https://api.themoviedb.org/3/movie/popular?api_key=${API_KEY}`,
      },
    ];
  },
};

module.exports = nextConfig

 

// /api/movies/router.js 

export async function GET() {
  const res = await fetch(
    `https://api.themoviedb.org/3/movie/popular?api_key=${API_KEY}`,
    {
      headers: {
        "Content-Type": "application/json",
      },
    }
  );
  const data = await res.json();

  return Response.json(data);
}

 
 
작년 취업 준비를 하면서 next.js 13 버전 page 라우터를 사용하는 아주아주 작은 개인 프로젝트를 만들어본 게 next.js 사용 경험의 전부여서 next.js에 대한 감이 정말 없다. 너무 당연한 걸 장님이 코끼리 다리 더듬듯 더듬더듬하다가 갑자기 안대를 벗은 것 마냥 유레카! 적인 순간이었다. 
 
Learn Next.js에는 총 16개의 챕터가 있는데 얼추 후반부에 도달해 간다. 역시 뭘 직접 만들어봐야 그제서야 그게 내 것이 되니, 이제는 직접 내 코드를 작성해 봐야할 시간이다.