본문 바로가기
프론트엔드/Next.JS

Next.JS 타입

by 학습하는 청년 2024. 5. 24.

최종 수정 : 2024-05-24

Next.js에서 특별하게 사용하는 타입은 많지 않기에 공식문서만 읽어보아도 충분하다.

https://nextjs.org/docs/pages/building-your-application/configuring/typescript

 

Configuring: TypeScript | Next.js

Next.js provides a TypeScript-first development experience for building your React application.

nextjs.org


커스텀 App

_app.tsx 파일에서는 웹 사이트 전체에 공통적으로 렌더링 되는 App이라는 컴포넌트를 만든다. 이 컴포넌트의 Props 형태는 정해져 있다. AppProps라는 타입을 next/app 패키지에서 불러와서 사용하면 된다.

import Head from 'next/head';
import { AppProps } from 'next/app';
import Header from '@/components/Header';
import '@/styles/global.css';

export default function App ({ Component, pageProps }: AppProps) {
  return (
    <>
      <Head>
        <title>Codeitmall</title>
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <Header />
      <Component {...pageProps} />
    </>
  );
}

프리 렌더링

정적 생성

Next.js에서는 빌드 시점에 리액트 코드를 미리 렌더링 해둘 수 있는데, 이를 정적 생성(Static Generation)이라고 한다.

import Image from 'next/image';

export async function getStaticPaths () {
  const res = await fetch('https://learn.codeit.kr/api/codeitmall/products/');
  const data = await res.json();
  const products = data.results;
  const paths = products.map((product) => ({
    params: { id: String(product.id) },
  }));

  return {
    paths,
    fallback: true,
  };
};

export async function getStaticProps(context) {
  const productId = context.params ['id'];

  let product;
  try {
    const res = await fetch(`https://learn.codeit.kr/api/codeitmall/products/${productId}`);
    const data = await res.json();
    product = data;
  } catch {
    return {
      notFound: true,
    };
  }

  return {
    props: {
      product,
    },
  };
}

export default function ProductPage({ product }) {
  return (
    <div>
      <h1>{product.name}</h1>
      <Image
        src={product.imgUrl}
        width="480"
        height="480"
        alt={product.name}
      />
    </div>
  );
}

 

Next.js에서는 기본적으로 화살표 함수로 만든 다음에 GetStaticPaths, GetStaticProsp 타입을 지정하는 것을 권장한다.

 

why?

import { GetStaticPaths, GetStaticProps } from 'next';
// ...

export const getStaticPaths: GetStaticPaths = async () => {
  // ...

  return {
    paths,
    fallback: true,
  };
};

export const getStaticProps: GetStaticProps = async (context) => {
  // ...

  return {
    props: {
      product,
    },
  };
}

// ProductPage
interface Props {
  product: Product;
}

export const getStaticProps: GetStaticProps<Props> = async (context) => {
  // ...
  return {
    props: {
      product,
    },
  };
};

export default function ProductPage({ product }: Props) {
  return (
    <div>
      <h1>{product.name}</h1>
      <Image
        src={product.imgUrl}
        width="480"
        height="480"
        alt={product.name}
      />
    </div>
  );
}

 

서버사이드 렌더링

Nexr.js 서버에 리퀘스트가 들어올 때마다 렌더링을 해서 보내준다.

import Image from 'next/image';

export async function getServerSideProps(context) {
  const productId = context.params['id'];

  let product;
  try {
    const res = await fetch(`https://learn.codeit.kr/api/codeitmall/products/${productId}`);
    const data = await res.json();
    product = data;
  } catch {
    return {
      notFound: true,
    };
  }

  return {
    props: {
      product,
    },
  };
}

export default function ProductPage({ product }) {
  return (
    <div>
      <h1>{product.name}</h1>
      <Image
        src={product.imgUrl}
        width="480"
        height="480"
        alt={product.name}
      />
    </div>
  );
}

 

정적 생성에서 했던 방식과 동일하게 화살표 함수로 변경한다음 진행한다.

interface Props {
  product: Product;
}

export const getServerSideProps: GetServerSideProps<Props> = async (context) => {
  // ...
  return {
    props: {
      product,
    },
  };
};

export default function ProductPage({ product }: Props) {
  return (
	// ...
  );
}

 

API 라우트

리퀘스트와 스프론스 타입을 지정하면 된다.

import type { NextApiRequest, NextApiResponse } from 'next'
 
export default function handler(req: NextApiRequest, res: NextApiResponse) {
  // ...
}

댓글