프로젝트 선택구현 사항 중 ui 컴포넌트를 모아 놓은 라이브러리를 사용하는 것이 있어서 한번 프로젝트에 적용해보았다. 다들 alert를 많이 사용하고 있어서 alert ui를 통일해보장

 

shadcn/ui

Beautifully designed components that you can copy and paste into your apps. Accessible. Customizable. Open Source.

ui.shadcn.com

 

 

 

설치

npx shadcn-ui@latest add alert

 

 

사용법

기본적으로 제공하고 있는 코드를 넣어주면 사용 완료..

import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"

<Alert>
  <Terminal className="h-4 w-4" />
  <AlertTitle>Heads up!</AlertTitle>
  <AlertDescription>
    You can add components and dependencies to your app using the cli.
  </AlertDescription>
</Alert>

 

 

Tailwind CSS

<Alert className="z-50 bg-slate-50 fixed w-1/3 top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-white">
        <AlertTitle className="text-xl font-bold">{alertTitle}</AlertTitle>
        <AlertDescription className="mt-3">{alertMessage}</AlertDescription>
        <AlertDescription className="text-center mt-3">
          <button
            className="bg-main-color p-2 px-3 rounded-md text-white"
            onClick={() => setAlert(false, "", "")}
          >
            확인
          </button>
        </AlertDescription>
      </Alert>

 

 

 

적용

const {
    data: { user },
  } = await supabase.auth.getUser();

  // TODO: /api로 시작하는 주소는 무시
  if (
    !user &&
    !request.nextUrl.pathname.startsWith("/api") &&
    !request.nextUrl.pathname.startsWith("/auth")
  ) {
    // no user, potentially respond by redirecting the user to the login page
    const url = request.nextUrl.clone();
    url.pathname = "/auth/login";
    return NextResponse.redirect(url);
  }

 

Supabase의 getUser 메서드를 사용하여 현재 인증된 사용자의 정보를 가져온다.

  • user 객체가 존재하지 않는 경우 (즉, 사용자가 인증되지 않은 경우)
  • 요청된 URL 경로가 /api로 시작하지 않는 경우
  • 요청된 URL 경로가 /auth로 시작하지 않는 경우

조건을 모두 만족하면, 사용자를 로그인 페이지로 리다이렉션한다. NextResponse.redirect(url) 메서드는 사용자를 /auth/login 경로로 리다이렉션 시킨다.

 

🔗 Local font 사용 공식문서 참조

 

Optimizing: Fonts | Next.js

Optimize your application's web fonts with the built-in `next/font` loaders.

nextjs.org

✨ next/font 를 사용하면 폰트를 최적으로 로드할 수 있다. 모든 글꼴 파일에 대한 자동 자체 호스팅이 내장되어 있어, 레이아웃 이동 없이 최적으로 글꼴을 로드 할 수 있다.

 

 

 

Next.js Local 폰트 적용

next/font/google

  • layout의 기본세팅은 inter font로 되어있다.
  • 구글 폰트의 CDN 서비스를 통해 폰트를 불러올 수 있다.
  • 서버사이드 렌더링(SSR)과 클라이언트사이드 렌더링(CSR)을 지원한다.

next/font/local

  • 웹 폰트 다운로드 시간을 절약하고, 오프라인 사용 가능성을 제공한다.
  • 이미지와 마찬가지로 클라이언트 측에서 파일을 다운로드할 필요가 없으므로 페이지 로드 속도를 향상시킬 수 있다.

 

 

 

📁 app / 📁 fonts 폴더 생성

위 경로대로 폴더를 생성하고 다운받은 font 파일을 넣어준다. localFont import 후에 body 태그 안에 {myFont.className} 이라고 써주면 body 태그 내에서 모든 폰트가 적용된다.

import type { Metadata } from "next";
import "./globals.css";
import QueryProvider from "./provider";
import localFont from "next/font/local";

export const metadata: Metadata = {
  title: "Pokémon",
  description: "포켓몬 도감 웹페이지 입니다.",
};

const myFont = localFont({
  src: "./fonts/DungGeunMo.ttf",
  weight: "400",
  style: "normal",
  display: "swap",
});

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="ko">
      <body className={myFont.className}>
        <div className="flex flex-col justify-center items-center">
          <h1 className="text-center w-[300px] mx-auto my-10">
            <img src="/pokemon.png" alt="포켓몬 로고" className="w-[100%]" />
          </h1>
          <QueryProvider>{children}</QueryProvider>
        </div>
      </body>
    </html>
  );
}

 

 

 

id 값으로 동적라우팅

params를 props로 받아 구조분해 할당 후 사용할 수 있다. props는 types 폴더에 인터페이스로 따로 정의해 주었다.

const DetailPokemonPage = async ({ params }: Props) => {
  const { id } = params;
  const fetchPokemonData = async () => {
    try {
      const response = await axios.get(
        `http://localhost:3000/api/pokemons/${id}`
      );
      return response.data;
    } catch (error) {
      console.error("데이터를 가져오지 못했습니다.", error);
      return [];
    }
  };

 

사용방법 1)

export interface Props {
  params: {
    id: number;
  };
}

 

사용방법 2)

const DetailPokemonPage = async ({ params }: { params: { id: number; };) => {
  const { id } = params;
  };

 

 

 

 

Image 세팅

next에서 기본으로 제공해주는 Image 기능을 사용해보려고 한다. 그러기 위해선 필수로 next.config.mjs를 설정해주어야한다.

/** @type {import('next').NextConfig} */
const nextConfig = {
  images: {
    remotePatterns: [
      {
        protocol: "https",
        hostname: "raw.githubusercontent.com",
      },
    ],
  },
};

export default nextConfig;

 

width, height, alt 속성을 꼭 채워주어야한다. 안그럼 오류가 나더라.. Next.js에서 제공하는 Image 태그를 사용하는 이유는 큰 이미지를 작은 이미지로 줄여주고, 웹사이트 용량이 줄어들기 때문이다. 

<Image
   src={pokemonData.sprites.front_default}
   width={150}
   height={150}
   alt="포켓몬 이미지"
/>

 

이미지 크기를 고정하고싶지 않을 때는 fill 속성을 사용하면 된다. 대신 부모태그에 position: relative 를 써주어야한다.

 

'Next.js' 카테고리의 다른 글

[Next.js] shadcn/ui와 Tailwind css 함께 사용해보기  (0) 2024.07.16
[Next.js] middleware.ts  (0) 2024.07.10
[Next.js] CSR, SSR, SSG, ISR 정리  (0) 2024.07.02

Next.js❓

Next.js는 풀스택 웹 어플리케이션을 구축하기 위한 React 프레임워크이다. 프론트 UI구성은 React로 하고, Next.js를 사용하여 추가 기능과 최적화를 수행한다. 내부적으로 Next.js는 번들링, 컴파일 등과 같이 React에 필요한 도구를 추상화하고 자동으로 구성한다. 이를 통해 구성에 시간을 낭비하는 대신 어플리케이션 구축에 집중할 수 있다.

💡 프레임워크?
개발자가 기능 구현에만 ‘딱’ 집중할 수 있도록 필요한 모든 프로그래밍적 재원을 지원하는 ‘기술의 조합’

 

제어의 역전(IoC : Inversion Of Control)

라이브러리는 개발자가 직접 제어하고 세팅한다. 반대로 프레임워크는 개발자가 직접 제어할 필요 없이 이미 정해진 기능을 적재적소에 사용만 해주면 된다.

 

 

 

 

✔️ Next.js 사용 이유

1. Full Stack

  • API Route를 지원하여 full stack 웹 개발이 가능

2. 다양한 렌더링 기법

  • 기존 SPA 라이브러리에서 사용하던 CSR에서 벗어나 SSR, ISR, SSG등을 가능케 함
  • Next.js는 코드스플리팅을 default로 지원

3. Data Fetching

  • 여러 옵션을 통해 한 번만 값을 가져올지, 일정 주기별로 가져올지, 지속적으로 계속 가져올지 결정할 수 있다.

4. 쉬운 배포

  • vercel로 일괄 배포

 

✔️ Next.js의 6가지 개발 원칙

  1. out-of-the-box functionality requiring no setup => 설정이 필요없다.
  2. JavaScript everywhere + all functions are written in JavaScript => 자바스크립트를 어디서나 사용할 수 있다.
  3. automatic code-splitting and server-rendering => 코드 스플리팅과 서버 렌더링이 자동화되어있다.
  4. configurable data-fetching => 다양한 방식으로 데이터를 가져올 수 있는 유연한 옵션을 제공한다.
  5. anticipating requests => 사용자가 원하는 것이 무엇인지를 먼저 예측 = 요구사항 예측
  6. simplifying deployment => 배포가 간단하다.

 


 

 

 

CSR(Client Side Rendering)

브라우저에서 JavaScript를 이용해 동적으로 페이지를 렌더링하는 방식

  • React의 CSR에서, 브라우저는 최소한의 HTML 파일과 페이지에 필요한 최소한의 JS 코드만을 다운로드 받는다.
  • 그 후 클라이언트는 JS를 사용하여 DOM을 업데이트하고, 페이지를 렌더링한다.
  • 애플리케이션이 처음 로드되었을 때, 사용자는 그들이 전체 페이지를 보기 전에 약간의 지연을 겪게 된다. 
    • root 라는 div 안에 번들링이 큰 components가 들어있기 때문에 로드되기까지 시간이 소요된다.
    • 이는 모든 JS 코드가 다운로드 되어 파싱되고, 실행되기 전까지 페이지가 렌더링되지 않기 때문이다.

장점

  • 사용자와의 상호작용이 빠르고 부드럽다.
  • 서버에게 추가적인 요청을 보낼 필요가 없기 때문에, 사용자 경험이 좋다.
  • 서버 부하가 적음

단점

  • 첫 페이지 로딩 시간(Time To View)이 길다.
  • JavaScript가 로딩되고 실행될 때까지 페이지가 비어있어 검색 엔진 최적화(SEO)에 불리하다.
CSR을 통해 SPA을 구축하는 라이브러리로 페이지의 전환 없이 한 페이지에서 바뀐 부분에 대해서만 
화면 전환이 이루어지기 때문에 사용자 경험을 향상시키는 데 유리하다. 
하지만 이런 React에도 단점이 존재하는데 CSR이기 때문에 서버에서 화면에 보여줄 수 있는 html파일을 보내주는 게 
아니라 처음에는 빈 html파일을 보여주고 그 이후에 필요한 resource들을 다운 받아서 보여주기 때문에 
1) 초기 로딩 속도가 느리다는 문제와 2) 처음에 빈 html을 보여주기 때문에 검색 엔진 최적화 측면에서 불리하다는 
문제가 있다.

 

 

✔️ pre-rendering

 

SSG(Static Side Generation)

서버에서 페이지를 렌더링하여 클라이언트에게 HTML을 전달하는 방식

  • 최초 빌드 시에 HTML이 생성되고 매 요청마다 HTML을 재사용 한다.
  • SSG에서 HTML은 next build 명령어를 사용할 때 생성
  • 그 후에는 CDN으로 캐시가 되어지고 요청마다 HTML을 재사용
  • 주로 about 페이지와 같이 정적으로 생성된 정보를 요청마다 동일한 정보로 반환하는 경우에 사용한다.
  • 사전에 미리 정적페이지를 여러개 만들어놓음 → 클라이언트가 홈페이지 요청을 하면, 서버에서는 이미 만들어져있는 사이트를 바로 제공 → 클라이언트는 표기만 함

장점

  • 첫 페이지 로딩 시간이 매우 짧아(TTV) 사용자가 빠르게 페이지를 볼 수 있다. 또한, SEO에 유리
  • CDN(Content Delivery Network) 캐싱 가능

단점

  • 정적인 데이터에만 사용할 수 있음
  • 사용자와의 상호작용이 서버와의 통신에 의존하므로, 클라이언트 사이드 렌더링보다 상호작용이 느릴 수 있다.
  • 계속해서 서버에 요청하기 때문에 서버 부하가 크다. 
  • 마이페이지처럼 데이터에 의존하여 화면을 그려주는 경우 사용 불가

 

 

ISR(Incremental Static Regeneration)

정적 페이지를 먼저 보여주고, 필요에 따라 서버에서 페이지를 재생성하는 방식

  • SSG에 포함되는 개념이며 SSG와의 차이는 설정한 시간마다 페이지를 새로 렌더링 한다는 점
  • SSG는 빌드 시에 페이지를 생성하기 때문에 데이터가 변경되면 다시 빌드를 해야하지만, ISR은 일정 시간마다 특정 페이지만 다시 빌드하여 페이지를 업데이트

장점

  • 정적 페이지를 먼저 제공하므로 사용자 경험이 좋으며, 콘텐츠가 변경되었을 때 서버에서 페이지를 재생성하므로 최신 상태 유지
  • CDN 캐싱 가능

단점

  • 동적인 콘텐츠를 다루기에 한계가 있을 수 있습니다. 실시간 페이지 X
  • 마이페이지처럼 데이터에 의존하여 화면을 그려주는 경우 사용 불가

코드 ➡️ revalidate

import React from 'react';

function HomePage({ data }) {
  return <div>{data}</div>;
}

export async function getStaticProps() {
  const res = await fetch('https://...'); // 외부 API 호출
  const data = await res.json();

  return { 
    props: { data },
    revalidate: 60, // 1초 후에 페이지 재생성
  };
}

export default HomePage;

 

 

 

SSR(Server Side Rendering)

빌드 시점에 모든 페이지를 미리 생성하여 서버 부하를 줄이는 방식

  • 클라이언트가 페이지 요청할 때마다 html을 생성한다.
  • 항상 최신 상태를 유지해야하는 웹 페이지나, 분석 차트 등 사용자의 요청마다 동적으로 페이지를 생성해서 다른 내용을 보여주어야 하는 경우에 사용

장점

  • 빠른 로딩 속도(TTV)와 높은 보안성을 제공
  • SEO 최적화
  • 실시간 데이터 사용
  • 마이페이지처럼 데이터에 의존한 페이지 구성 가능
  • CDN 캐싱 불가

단점

  • 사이트의 콘텐츠가 변경되면 전체 사이트를 다시 빌드하는 과정에서 시간이 오래 걸릴 수 있다. → 서버 과부하
  • 요청할 때 마다 페이지를 만들어야 함  서버 과부하

 

 

전체 비교

  CSR SSR SSG ISR
빌드시간 느림 빠름 빠름 빠름
SEO 나쁨 좋음 좋음 좋음
요청에 따른 응답시간 보통 길다 짧다 짧다
최신 정보 O O X O/X

 

+ Recent posts