본문 바로가기

Front-end/React

Next

page


page 디렉토리 내 .js, .jsx, .ts, tsx 확장자를 가지는 파일들을 filename 기반으로 라우팅 됨
// pages/about.js

export default function About() {
	return <div>About</div>
}

 

dynamic Rountes

pages/posts/[id].js -> posts/1 처럼 동적인 url 을 가지는 페이지를 구성할 수 있음
// pages/[id].tsx

import { useRouter } from "next/router";

export default () => {
  const router = useRouter();

  return (
    <>
      <h1>post</h1>
      <p>postid: {router.query.id}</p>
    </>
  );
};

pre-rendering

  • static generation: HTML 이 빌드시에 생성되고 각 request 에서 재사용됨
  • server-side rendering: HTML 이 각 request 마다 생성됨

next 는 두가지를 hybrid로 섞어 두가지 rendering 방식을 동시에 사용할 수 있음

 

 

page with data

ssg(static site generation)

  1. page내에 content가 외부 데이터에 의존적일때
export default function Blog({ posts }) {
  // Render posts...
}

// This function gets called at build time
export async function getStaticProps() {
  // Call an external API endpoint to get posts
  const res = await fetch('https://.../posts')
  const posts = await res.json()

  // By returning { props: { posts } }, the Blog component
  // will receive `posts` as a prop at build time
  return {
    props: {
      posts,
    },
  }
}

 2. page내에 path가 외부데이터에 의존적일때

export default function Post({ post }) {
  // Render post...
}

export async function getStaticPaths() {
  // Call an external API endpoint to get posts
  const res = await fetch('https://.../posts')
  const posts = await res.json()

  // Get the paths we want to pre-render based on posts
  const paths = posts.map((post) => ({
    params: { id: post.id },
  }))

  // We'll pre-render only these paths at build time.
  // { fallback: false } means other routes should 404.
  return { paths, fallback: false }
}

// This also gets called at build time
export async function getStaticProps({ params }) {
  // params contains the post `id`.
  // If the route is like /posts/1, then params.id is 1
  const res = await fetch(`https://.../posts/${params.id}`)
  const post = await res.json()

  // Pass post data to the page via props
  return { props: { post } }
}

 

ssr

export default function Page({ data }) {
  // Render data...
}

// This gets called on every request
export async function getServerSideProps() {
  // Fetch data from external API
  const res = await fetch(`https://.../data`)
  const data = await res.json()

  // Pass data to the page via props
  return { props: { data } }
}

 

Layouts


single shared layout

전체 application 을 하나의 layout으로 관리할때

// pages/_app.js

import Layout from '../components/layout'

export default function MyApp({ Component, pageProps }) {
  return (
    <Layout>
      <Component {...pageProps} />
    </Layout>
  )
}

 

per-page layouts

여러개의 중첩된 layout을 사용하는 경우

page에 getLayout 속성을 추가하여 layout에 react component를 반환하는것을 가능하게 해줌

// pages/index.js

import Layout from '../components/layout'
import NestedLayout from '../components/nested-layout'

export default function Page() {
  return (
    /** Your content */
  )
}

Page.getLayout = function getLayout(page) {
  return (
    <Layout>
      <NestedLayout>{page}</NestedLayout>
    </Layout>
  )
}

 

이미지 최적화


이미지 컴포넌트를 사용하여 src로 local 또는 remote 경로를 받아 사용

 

1. local file 

 - width와 height가 자동으로 설정됨

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"
      />
      <p>Welcome to my homepage!</p>
    </>
  )
}

 

2. remote file

-  빌드시에 접근할 수 없기때문에 width, height를 설정해줘야함

 

 

metafile


_document.tsx

meta 태그를 정의하거나, 전체 페이지에 관여하는 컴포넌트
서버에서만 렌더링됨
- console은 서버에서만 노출되고 클라이언트에서 실행되지 않음
- react lifecycle 훅도 실행되지 않고, staticd 한 상황에서만 실행
- <Main> 컴포넌트 외부는 browser에서 초기화 되지 않으므로 application logic을 추가하면 안되고 layout에 추가하길 권장
// pages/_document.tsx
import Document, { Html, Head, Main, NextScript } from "next/document";
export default class CustomDocument extends Document {
  render() {
    return (
      <Html>
        <Head>
          // 모든페이지에 아래 메타테크가 head에 들어감
          <meta property="custom" content="123123" />
        </Head>
        <body>
          <Main />
        </body>
        <NextScript />
      </Html>
    );
  }
}

 

_app.tsx

이곳에서 렌더링 하는 값들은 모든 페이지에 영향을 줌
최초 실행되는 component
각페이지가 update 되기전에 전처리
function MyApp({ Component, pageProps }) {
// component -> 요청한 페이지 ex) /pages/index.js 의 component
// pageProps => 페이지의 getInitialProps를 통해 내려받은 props
  return <Component {...pageProps} />;
}

export default MyApp;

 

server side lifeCycle


  1. nextJs 서버가 GET 요청을 받는다.
  2. GET 요청에 맞는 pages/Component를 찾는다. 
  3. _app.tsx의 getInitialProps가 있다면 실행한다.
  4. route에 맞는 페이지의 Component의 (getServerSideProps, getStaticProps)가 있다면 실행한다. pageProps들을 받아온다.
  5. _document.tsx의 getInitialProps가 있다면 실행한다. pageProps들을 받아온다.
  6. 모든 props들을 구성하고, _app.tsx -> page Component 순서로 렌더링
  7. 모든 Content를 구성하고 _document.tsx를 실행하여 html 형태로 출력한다.

 

dynamic component import


lazy component import 를 위한 방식
초기 데이터 없이 사용될 수 없는 component의 경우 import 하지 않음으로 초기 화면 렌더링 속도가 상승함
import React, { useState } from "react";
import dynamic from "next/dynamic";

const DynamicComponent = dynamic<{ nowTab: number }>(() =>
  import("./DynamicComponent")
);

const Index = () => {
  const [nowTab, setNowTab] = useState(0);

  return (
    <>
      {nowTab === 0 && <div>0 tab</div>}
      {nowTab === 1 && <DynamicComponent nowTab={nowTab} />}
    </>
  );
};

 

환경변수


https://nextjs.org/docs/basic-features/environment-variables

 

 

 

 

 

 

참고자료

https://nextjs.org/docs

https://kyounghwan01.github.io/blog/React/next/basic/

 

'Front-end > React' 카테고리의 다른 글

controlled & uncontrolled input  (0) 2023.02.02
useRef & Refs  (0) 2023.01.30
Styled-component  (0) 2022.12.05
React Query  (0) 2022.11.28
Redux  (0) 2022.11.23