[Next js] Next 14 세팅하기(pnpm)

임보라·2024년 10월 23일

Next.js

목록 보기
9/23

Next공식문서

넥스트 14버전

npx create-next-app@14.2.15 --use-pnpm

pnpm 추가기능들 설치

//prettier, tailwindcss-prettier
pnpm add -D prettier prettier-plugin-tailwindcss

//supabase, zustand, tanstack-query, icons
pnpm add @supabase/ssr @supabase/supabase-js zustand @tanstack/react-query react-icons

util

공통적으로 사용되는 유틸리티 함수나 로직을 모아 두는 용도

util > middleware.ts

Next.js의 미들웨어 정의

import type { NextRequest } from 'next/server';
import { updateSession } from './utils/supabase/middleware';

export const middleware = async (request: NextRequest) => {
  return await updateSession(request);
};

export const config = { //config : 미들웨어가 적용될 경로 지정
  matcher: ['/'] //모든 경로에 미들웨어 적용(빈값이면 안댐)
};

util > supabase > 관련파일

client.ts

브라우저 환경에서 Supabase 클라이언트를 생성하는 함수인 createClient을 정의

  • 클라이언트 측에서 Supabase와 상호작용할 때 사용
import { createBrowserClient } from '@supabase/ssr';
import { SupabaseClient } from '@supabase/supabase-js';

export const createClient = (): SupabaseClient =>
  createBrowserClient(process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!);

const browserClient: SupabaseClient = createClient();

export default browserClient;

middleware.ts

Supabase 클라이언트를 사용하여 세션을 업데이트하는 미들웨어 함수 정의

  • 주로 사용자의 인증 상태를 확인하고, 필요에 따라 리다이렉션을 처리
import { createServerClient } from '@supabase/ssr';
import { type NextRequest, NextResponse } from 'next/server';

export const updateSession = async (request: NextRequest) => {
  try {
    let response = NextResponse.next({
      request: {
        headers: request.headers
      }
    });

    const supabase = createServerClient(
      process.env.NEXT_PUBLIC_SUPABASE_URL!,
      process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
      {
        cookies: {
          getAll() {
            return request.cookies.getAll();
          },
          setAll(cookiesToSet) {
            cookiesToSet.forEach(({ name, value }) => request.cookies.set(name, value));
            response = NextResponse.next({
              request
            });
            cookiesToSet.forEach(({ name, value, options }) => response.cookies.set(name, value, options));
          }
        }
      }
    );

    // 여기 부분은 리다이렉트

    // const { data } = await supabase.auth.getUser();

    // 로그인 한 상태라면 메인페이지로 리다이렉트
    // if (
    //   data?.user &&
    //   (request.nextUrl.pathname.startsWith('/login') || request.nextUrl.pathname.startsWith('/signup'))
    // ) {
    //   return NextResponse.redirect(new URL('/', request.url));
    // }

    // // 로그인을 하지 않았는데 접근한다면 로그인 페이지로 리다이렉트
    // if (
    //   !data?.user &&
    //   (request.nextUrl.pathname.startsWith('/mypage') || request.nextUrl.pathname.startsWith('/update-password'))
    // ) {
    //   return NextResponse.redirect(new URL('/login', request.url));
    // }

    return response;
  } catch (e) {
    console.log(e, 'error');
    return NextResponse.next({
      request: {
        headers: request.headers
      }
    });
  }
};

server.ts

Supabase 클라이언트를 생성하는 함수인 createClient을 정의

  • Supabase 클라이언트를 생성할 때 필요한 URL과 익명 키를 환경 변수에서 가져오며, 쿠키를 설정하고 가져오는 메서드를 제공
import { createServerClient } from '@supabase/ssr';
import { cookies } from 'next/headers';

export const createClient = () => {
  const cookieStore = cookies();

  return createServerClient(process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, {
    cookies: {
      getAll() {
        return cookieStore.getAll();
      },
      setAll(cookiesToSet) {
        try {
          cookiesToSet.forEach(({ name, value, options }) => {
            cookieStore.set(name, value, options);
          });
        } catch (error) {
          console.log('error: ', error);
        }
      }
    }
  });
};

providers > RQRovider.tsx

tanstack-query 사용하기 위한 컴포넌트

  • QueryClientProvider를 사용하여 React Query 클라이언트를 애플리케이션의 하위 컴포넌트에 제공하는 역할
'use client';

import { isServer, QueryClient, QueryClientProvider } from '@tanstack/react-query';

//서버 환경
function makeQueryClient() {
  return new QueryClient({ //새로운 QueryClient 인스턴스를 생성
    defaultOptions: { //기본옵션
      queries: {
        staleTime: 60 * 1000 //60초
      }
    }
  });
}

//브라우저 환경에서 사용할 QueryClient 인스턴스를 저장
let browserQueryClient: QueryClient | undefined = undefined; 

//서버와 브라우저 환경에 따라 QueryClient 인스턴스를 반환
function getQueryClient() {
  if (isServer) {
    return makeQueryClient();
  } else {
    if (!browserQueryClient) browserQueryClient = makeQueryClient();
    return browserQueryClient;
  }
}

export default function RQProviders({ children }: { children: React.ReactNode }) {
  const queryClient = getQueryClient(); //getQueryClient를 호출

  //QueryClientProvider의 client 속성으로 전달
  //자식 컴포넌트에 React Query 기능을 제공
  return <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>;
}

app > layout.tsx

RQProviders로 감싸주기

return (
    <html lang="en">
      <body className={`${geistSans.variable} ${geistMono.variable} antialiased`}>
        <RQProviders>{children}</RQProviders>
      </body>
    </html>
  );

0개의 댓글