[NextJS] 넥스트JS 기본지식

선영·2023년 5월 3일
0

📚 Library

목록 보기
7/14

Data Fetching

nextJS가 제시하는 data fetching(데이터 가져오기) 방법

1. ssr(server side render)

  • 서버가 데이터를 가져와서 그린다.
  • getServerSideProps()는 서버에서 가져온 데이터를 페이지에 props로 전달해줘서 자유롭게 사용할 수 있다.
    ...
    export async function getServerSideProps() {
      console.log('server')
    
      return {
        props: { time: new Date().toISOString() }
      }
    }
    
    export default function Home({ time }) {
      return (
            <h1 className="title">
              {time}
            </h1>
    	)
    }

2. csr(client side render)

  • 클라이언트(브라우저)가 데이터를 가져와서 그린다.
  • react에서 사용하던 방법과 똑같이 하면 된다.
    ...
    export default function CSR() {
      const [time, setTime] = useState()
    
      useEffect(()=>{
        console.log('client')
        setTime(new Date().toISOString())
      },[])
    
      return (
        ...
      )
    }

3. ssg(static site generation)

  • 정적인 사이트를 데이터를 가져와서 그려둔다. 즉, 데이터를 그려두는 주체는 빌드머신 자체이다.
  • getStaticProps()를 사용했을때, npm run dev로 실행시킨 개발환경에서는 ssg가 제대로 동작하지 않아서 ssg가 ssr처럼 동작한다. npm run build를 해야 build하는 타이밍에 보여지는 페이지가 미리 만들어진다. 즉, 빌드하는 타이밍에 데이터를 다 가져와서 static page를 생성해버리는 것이다.
  • ssr에 비해 서버에 부하없이 서비스를 제공할 수 있는 이점이 있다. 블로그같이 정적인 페이지를 만들 때 좋다.
  • getStaticPaths() 는 미리 그려놔야할 경로에 대해서 사용하는 메서드이다.
  • getStaticProps()getStaticPaths()는 함께 사용하는 것을 권장한다.
    ...
    export async function getStaticProps() {
      console.log('server')
    
      return {
        props: { time: new Date().toISOString() }
      }
    }
    
    export default function SSG({ time }) {
      return (
            <h1 className="title">
              {time}
            </h1>
    	)
    }

4. isr(incremental static regeneration)

  • (특정 주기로) 정적인 사이트를 데이터를 가져와서 다시 그려둔다.
  • getStaticProps() 에 revalidate값을 설정하면 된다. 이런식으로 구현을 하면 새로고침이 된다. 즉, 캐싱을 미리 갖고있다가 1초마다 다시 패칭을 해서 다시 생성을 한다. 결론적으로 ssg, ssr의 장점을 적절하게 사용할 수 있다.
    ...
    export async function getStaticProps() {
      console.log('server')
    
      return {
        props: { time: new Date().toISOString() },
        revalidate: 1,
      }
    }
    
    export default function ISR({ time }) {
      return (
            <h1 className="title">
              {time}
            </h1>
    	)
    }

Pages

pages폴더 안에 있는 파일들은 url과 매칭

  • pages/index.js/
  • pages/ssg.js/ssg
  • pages/products/[slug].js/products/*

Pre-renders와 SEO의 상관관계

nextJS는 모든 페이지를 기본적으로 pre-render, 즉 미리 그려둔다. CSR만 제공한다면 클라이언트(=브라우저)처럼 동작하지 않는 검색엔진의 경우 아무런 데이터도 조회해갈 수 없다. 아래의 이미지에서 오른쪽의 경우 처럼 js가 동작하지 않는 엔진에서는 아무것도 읽을 수 없을 것이다. 그래서 pre-render를 해두면 클라이언트처럼 동작하지 않는 검색엔진에게 필요한 데이터를 제공 할 수 있다. 결국 SEO는 다양한 검색엔진들이 내가 만든 사이트를 잘 읽어서 상위에 노출시켜줄 수 있도록 하는 것인데, SEO를 위해서는 pre-render가 필요하다.

nextJS의 Pre-rendering 방식

  • ssr은 요청 타임에 pre-render, 사용자가 해당 url로 요청(방문)할 때 마다 서버에 부하가 갈 수 있다.
  • ssg(⭐️recommended)는 빌드 타임에 pre-render, 서버에 부하가 덜하다.
    • page의 내용물이 외부 데이터에 의존적인 상황, 즉 외부 서버/api에 의해 내부 데이터가 바뀔 수 있는 상황 ⇒ getStaticProps() 사용
    • page의 paths까지 외부 데이터에 의존적인 상황, 즉 api까지 바뀔 수 있는 상황 ⇒ getStaticProps() && getStaticPaths() 사용

Layout

하나의 공통된 layout을 사용하는 경우 여러 페이지들의 공통처리(모듈화)

하나의 공통된 Layout을 쓰는 경우, components/Layout.js를 만든 다음에, 해당 컴포넌트를 pages/_app.js에서 활용하면 된다. 여러개의 레이아웃을 중첩적으로 쓰는 방법 등이 있다.

// /pages/_app.js
// => next.js 자체에서 제공하는 모든 페이지를 품을 수 있는 파일이다.
import Layout from "../components/Layout";

export default function App({Component, pageProps}) {
	// 하나의 레이아웃을 사용하는 경우
    // return (
    //     <Layout>
    //         <Component {...pageProps} />
    //     </Layout>
    // )

		// 여러개의 레이아웃을 중첩적으로 사용하는 경우
    const getLayout = Component.getLayout || ((page) => <Layout>{page}</Layout>)

    return getLayout(<Component {...pageProps} />)
}

Images

nextJS가 제공하는 최적화 Image Component

모든 사이트에서 보여지는 리소스 중에 가장 많은 부분을 차지하는게 이미지이기 때문에 이미지 최적화가 필요하다.

Routing

네트워크 용어. 특정 주소가 있고, 그 주소와 매핑되어있는 데이터들을 받아서 사용하는 일련의 과정

nextJS의 라우터는 파일 시스템 기반이다. 즉, pages/혹은 src/pages/ 경로에 파일을 만들면 그것이 라우터로 인지 되고, url 주소와 매핑이 된다. pages/ 폴더가 더 우선순위를 가진다. 단, pages/product 혹은 pages/settings와 같이 특정 경로에 바로 접근할 수 있으려면 해당 폴더에 first-item.js, info.js 파일들 외에 index.js 파일을 생성해야만 한다.

  • pages/product/first-item.js => /product/first-item
  • pages/settings/my/info.js => /settings/my/info

만약 위의 경로에서 depth가 더 깊어진다면, 절대경로로써 src를 접근할 수 있도록 아래와 같이 설정을 해주자.

// jsconfig.json - 절대경로로써 src를 접근할 수 있게 된다.
{ "compilerOptions": { "baseUrl": "src" } }

다이나믹한 경로설정은 slug를 사용하자. 단, 경로에서 명시해놓은 곳을 우선으로 이동한다.

  • pages/category/[slug].js => /category/:slug (ex. /category/food)
  • pages/[username]/info.js => /:username/info (ex. /jimmy/info)
  • pages/cart/[...date].js => /cart/* (ex. /cart/2022/06/24)

Shallow Routing

getServerSideProps() getStaticProps() 등을 다시 실행시키지 않고, 즉 현재 상태를 잃지 않고 url을 바꾸는 방법이다. 이것은 사용자가 어떤 동작을 했고, 그 기록을 query로 남기고 싶을때 사용한다. 왜냐면 query로 남기면 사용자가 새로고침을 해도 유지되기 때문이다.

아래의 경로에서 [slug] 값을 활용해서 화면에 보여주려면 어떻게 해야할까?

// pages/category/[slug].js
...
import { useRouter } from 'next/router';

export default function CategorySlug() {
  const router = useRouter();
  const {slug} = router.query

  return (
    <>
      <h1 className="title">Category {slug}</h1>
    </>
  );
}
...

아래와 같이 query가 있다면? { “slug”: “food”, “from”: “event” }와 같이 꺼내서 활용할 수 있다.

  • /category/food?from=event

아래와 같이 query에 slug가 있다면? nextJS는 폴더구조의 slug를 우선시 한다. 그래서 뒤에 slug쿼리가 붙었을 경우엔 그 값이 무시된다.

  • /category/food?slug=book

다중 슬러그

// pages/[username]/[info].js
...
import { useRouter } from 'next/router';

export default function CategorySlug() {
  const router = useRouter();
  const {username, info} = router.query

  return (
    <>
      <h1 className="title">{username}'s {info}</h1>
    </>
  );
}
...
// pages/cart/[...slug].js => slug는 배열, /cart 로 접근하면 404가 뜬다. 
// pages/cart/[[...slug]].js => 옵셔널 slug, slug가 존재하지 않아도 받는다
...
import { useRouter } from 'next/router';

export default function CategorySlug() {
  const router = useRouter();
  const { date } = router.query

  return (
    <>
      <h1 className="title">{JSON.stringify(date)}</h1>
    </>
  );
}
...

라우팅

// pages/cart/[[...slug]].js
...
import Link from 'next/link';
import { useRouter } from 'next/router';

export default function CategorySlug() {
  const router = useRouter();
  const { date } = router.query;

  return (
    <>
      <h1 className="title">{JSON.stringify(date)}</h1>
      <Link href="/cart/2023/04/21">
        <a>오늘의 날짜로 이동한다</a>
      </Link>
      <button onClick={() => router.push('/cart/2023/04/21')}>오늘 날짜로 이동한다</button>
    </>
  );
}
...

API Routes

API(Application Programming Interface)란 컴퓨터나 컴퓨터 프로그램 사이의 연결, 즉 응용프로그래밍 인터페이스이다. nextJS가 제공하는 api routes는 pages/api/* 의 방식으로 사용하면 된다.

profile
Superduper-India

0개의 댓글