티스토리 뷰

웹/next js

next js 시작하기

안양사람 2021. 12. 13. 02:12
728x90
SMALL

배경

예전부터 이름은 들어서 알고 있었다. 최근에 밤에 이것저것 찾아보다가 급 관심을 가지게 되었는데 찾아보니 진짜 혁명이였다. 서버사이드 렌더링에 코드 스플리팅, lazy loading, 이미지 최적화까지 전부 다 지원한다고 한다. 하나하나가 굉장히 귀찮으면서도 꼭 해야만 하는 작업들인데 이걸 전부다 그냥 해준다니 진짜 말도안된다... 그래서 새벽에 블로그를 잠깐 찾아보다가 자기전에 한시간동안 유튜브에서 강의 영상까지 봤다.

 

어떻게 시작할건데

리액트를 처음 사용할 때는 cra를 사용한다. 나는 지금은 직접 설정하지만 처음에 시작할 때는 설정하기가 쉽지 않다. 그래서 일단은 create next app을 이용하려고 한다.

npx create-next-app@latest --typescript

yarn create next-app --typescript

둘 중 하나를 입력하면 기본 세팅이 끝난다.

 

라우팅 방식

리액트에서는 라우팅을 지원하지 않는다. 우아한테크캠프에서는 직접 라우터를 구현했었고 보통은 react-router-dom이라는 라이브러리를 이용한다. 리액트는 라이브러리다. 그래서 라우터가 존재하지 않을 수 있다. 그런데 nextjs는 리액트를 이용한 프레임워크다. 즉 정해진 규칙이 있고 그 규칙을 따라야 한다.

 

규칙은 pages폴더안에 폴더나 파일을 만들면 끝이다. react router의 params를 원한다면 [id]이런식으로 만들어주면 된다.

pages/login.tsx => /login

pages/login/1.tsx => /login/1

pages/list/[id]/index.tsx => /login/~~

 

페이지 이동

spa이기 때문에 당연히 a태그의 href로 이동하면 안된다. 리액트 라우터에서는 Link가 존재하는데 여기도 비슷하다. Link에 href 속성을 넣고 a태그를 안에 넣어주면 된다. 또 classname같은 attribute는 a 태그에 적용해야 한다.

import Link from 'next/link';
          <Link href="/">
            <a>Home</a>
          </Link>

 

이것뿐만이 아니다. code spliting과 prefetching이 자동으로 적용된다. 코드 스플리팅 덕분에 빠른 로딩속도를 보장하고 링크된 페이지를 프리패칭해서 페이지를 빠르게 이동시킬 수 있다.

 

라우터 정보

useRouter라는 훅스를 제공한다.

import { useRouter } from 'next/router';

  const router = useRouter();
  console.log(router);
  
  ServerRouter {
  route: '/photos/[id]',
  pathname: '/photos/[id]',
  query: { id: '1' },
  asPath: '/photos/1',
  isFallback: false,
  basePath: '',
  locale: undefined,
  locales: undefined,
  defaultLocale: undefined,
  isReady: false,
  domainLocales: undefined,
  isPreview: false,
  isLocaleDomain: false
}

 

 

이미지

이미지 컴포넌트도 제공한다. 최적화와 레이지 로딩을 지원한다.

import Image from 'next/image'
import profilePic from '../public/me.png'

function Home() {
  return (
    <>
      <h1>My Homepage</h1>
      <Image
        src={profilePic}
        alt="Picture of the author"
        // width={500} automatically provided
        // height={500} automatically provided
        // blurDataURL="data:..." automatically provided
        // placeholder="blur" // Optional blur-up while loading
      />
      <p>Welcome to my homepage!</p>
    </>
  )
}

 

또한 외부 url의 이미지를 사용할 때는 다음과 같이 next.config.js에 추가해주면 된다.

module.exports = {
  images: {
    domains: ['example.com', 'example2.com'],
  },
}

 

head

head태그도 페이지마다 각각 설정할 수 있다. 기존에는 라이브러리를 설치했지만 말이다.

import Head from 'next/head';
import React from 'react';

const Layout: React.FC = ({ children }) => {
  return (
    <>
      <Head>
        <title>My Blog</title>
      </Head>
      <div>{children}</div>
    </>
  );
};

export default Layout;

 

공통 레이아웃

기존에는 공통 레이아웃을 사용하기 위한 방법이 여러가지가 있었다. nextjs는 프레임워크인 만큼 정해진 방법이 있다. layout 컴포넌트를 만들고 pages/_app.tsx에서 기존 컴포넌트를 다음과 같이 레이아웃으로 감싸주면 된다.

 

layout.tsx

import Head from 'next/head';
import React from 'react';
import Nav from './nav';
import { NextPage } from 'next';

const Layout: NextPage = ({ children }) => {
  return (
    <>
      <Head>
        <title>My Blog</title>
      </Head>
      <Nav />
      <div>{children}</div>
    </>
  );
};

export default Layout;

 

pages/_app.tsx

import '../styles/globals.css';
import type { AppProps } from 'next/app';
import Layout from '../components/layout';

function MyApp({ Component, pageProps }: AppProps) {
  return (
    <Layout>
      <Component {...pageProps} />
    </Layout>
  );
}

export default MyApp;

 

data fetching

nextjs에서는 SSR과 SSG를 지원한다. 하나씩 살펴보자. 참고로 아래 함수는 매개변수 context를 가지고 params를 가지고 있다. 따라서 내부에서는 useRouter를 사용하지 않고 params를 불러올 수 있다.

 

getServerSideProps

getServerSideProps 함수를 만들고 props를 return해준다. 그러면 props로 데이터를 받을 수 있다. 또한 서버사이드 렌더링이 적용된다.

import axios from 'axios';
import type { NextPage } from 'next';

interface IProps {
  posts: any;
}

const Home: NextPage<IProps> = ({ posts }) => {
  console.log(posts);
  return (
    <div>
      <h1>My Home</h1>
    </div>
  );
};

export const getServerSideProps = async () => {
  try {
    const { data } = await axios.get(
      'https://jsonplaceholder.typicode.com/posts?_start=0&_end=10'
    );
    return {
      props: {
        posts: data,
      },
    };
  } catch (err) {
    console.log(err);
  }
};

export default Home;

 

getStaticProps

SSG(static site generation)라는 개념이 등장한다. 말그대로 정적인 사이트 생성이다. 이미 한번 불러온 API라면 그 API가 변경됬는지 신경쓰지 않고 기존의 API를 불러온다. 즉 서버에서 새로운 요청없이 바로 내려주는 것이다. 개발서버에서는 적용되지 않으니 테스트하고 싶다면 build한 후에 production 모드로 실행해보자.

여기서 revalidate 옵션을 적용하면 일정 시간이 지난 후에는 새로 api를 불러온다. 필요한 경우에 사용하면 유용할 것 같다. 추가적으로 몇가지 속성들이 더 있지만 일단은 기본 사용법을 익히는 단계라 더 찾아보진 않았다.

export const getStaticProps = async () => {
  try {
    const { data } = await axios.get(
      'https://jsonplaceholder.typicode.com/posts?_start=0&_end=10'
    );
    return {
      props: {
        posts: data,
      },
      revalidate: 20,
    };
  } catch (err) {
    console.log(err);
  }
};

 

getStaticPaths

데이터를 기반으로 페이지를 미리 렌더링하는 동적 경로를 지정한다. params에 따라 다른 데이터를 불러오는 경우라면 이 옵션을 사용해야 한다. 허용하는 paths를 return해주면 된다. fallback이라는 옵션도 있는데 'blocking'을 지정하면 모든 paths를 허용한다. 그리고 fallback:false면 지정한 paths가 아니라면 오류를 발생시킨다.

export const getStaticProps: GetStaticProps = async (context) => {
  const id = context.params?.id;
  const res = await fetch(`https://jsonplaceholder.typicode.com/photos/${id}`);
  const photo = await res.json();
  return {
    props: {
      photo,
    },
  };
};
export const getStaticPaths = async () => {
  const res = await fetch(
    `https://jsonplaceholder.typicode.com/photos?_start=0&_end=10`
  );
  const photos = await res.json();
  const ids = photos.map((photo: any) => photo.id);
  const paths = ids.map((id: any) => {
    return {
      params: { id: id.toString() },
    };
  });

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

 

 

추가

굉장히 간단한 기본 사용법만 적었다. 일단 처음에는 익숙해지는게 먼저라고 생각하기 때문에 이정도의 정보만으로 api를 이용해 간단한 사이트를 만들어봐야겠다. 그리고 언제가 될지는 모르겠지만 nextjs로 개인 프로젝트를 만들고 배포해서 직접 운영해보고 싶다.

 

 

참조글

https://gingerkang.tistory.com/118?category=926753 

https://www.youtube.com/watch?v=pdWQvfQBSGg&list=LL&index=1 

https://nextjs.org/docs/getting-started

728x90
LIST
댓글
공지사항