NextJS - 5 ( 정적 생성)

J-USER·2021년 8월 5일
0

NextJS

목록 보기
6/6
post-thumbnail

이전 포스팅에서 SSR에 대해 알아보았는데요. 이번에는 NextJS 의 다른 렌더링에 대해 알아보도록 하겠습니다.

Pre-rendering

NextJS의 경우 기본적으로 모든 페이지는 pre-render 하게 배치하는 특징을 가지고 있습니다.

🙋 프리랜더링이 뭐였죠?
🤖 프리랜더링은 사전에 HTML 파일들을 만든다는 의미입니다. 맞춤제작이 아닌 기성품 같은 느낌이죠.

NextJs가 프리랜더링을 기본적으로 채택하는 이유는 기존에 만들어 놓았기 때문에 (기성품 처럼..) 많은 클라이언트의 요청에도 신속하게 대응할 수 있고 이는 곳 퍼포먼스의 향상으로 이어지게 됩니다.
그리고 NextJS를 사용하는 큰 이유라고 볼 수 있는 SEO의 향상이 있죠. 프리 랜더링의 경우 HTML 파일이기 때문인 이유이죠.

🙋 생성된 프리 랜더링은 어떻게 동작하나요?
🤖 기본에 만들어진 HTML 파일에 최소한의 JS를 첨부한 형식으로 브라우저에 로드가 될때 나머지 완전한 JS 가 적용이 되는 형식입니다.
🙋 이해가 잘 안되네요 ㅠㅠㅠ 그래서 프리 랜더 한거랑 안한거 차이가 뭔가요?

만약에 JS 파일을 서버로 부터 받아오지 못했다는 가정하에 프리랜더링한 페이지와 안한 페이지는 아래와 같이 나타날 수 있습니다.👇

먼저 JS가 로드 되기전에는 아무것도 나오지 않고 서버로부터 JS 파일을 받고 적용한 순간 원하던 웹 페이지가 도출될 것입니다.

그러나 프리랜더링이 적용이 되어있다면, 로드한 순간에 이미 기본적으로 만들어진 HTML 파일이 아래 👇 와 같이 보이고 , 이후 JS 파일이 로드 된 후부터 Link 같은 컴포넌트들이 작동하기 시작하는 것이지요.
이러한 과정을 Hydration(수분공급 💧) 이라고 합니다.

Hydration 은 정적인 무언가에 마치 생기를 불어넣는듯한 그런 작업들을 진행하는 것을 의미합니다.

이전 포스팅에서도 다뤘다시피 사전랜더에는 두 가지 종류가 있습니다.
이 둘의 차이점은 언제 렌더링 하느냐!입니다.

정적 생성

정적 생성은 빌드 시에 HTML파일을 생성하는 사전랜더링 방식입니다. 그리고 이렇게 생성된 HTML 파일을 요청하는 유저들에게 제공하게 됩니다. 같은 파일을 여럿이서 보는 것이죠.

🙋 언제 쓰나요?

페이지를 만들어두고 CDN을 통해
재사용하기 때문에 대부분의 케이스에서 정적생성이 빠르고 좋습니다.

  • 마케팅페이지
  • 블로그 게시물
  • 제품 목록
  • 도움말,문서

SSR

반대로 SSR 은 사용자의 요청에 맞게 그때그때 만들어 렌더링을 진행하게 됩니다.

🙋 이건 언제 쓰나요?

정적생성의 경우 기존에 만들어 놓은 기성품이기 때문에 최신 유행을 반영하기 쉽지 않은것 같이 항상 최신 상태를 유지해야하는 경우에 SSR을 사용하게 됩니다.

  • 관리자 페이지
  • 분석 차트

해보자!!!

getStaticProps

기존에 만들어놨던 페이지를 정적생성으로 재탄생 시킬 예정이다.

index.js
2. 컴포넌트에서 리스트를 따로 받을 수 있었고.
export default function Home({list}) {
3. 아래와 같이 리스트를 가져오는 코드는 쓸모 X
  // const API_URL = process.env.NEXT_PUBLIC_API_URL
  // const [list,setList] = useState([]);
  // const [isLoading, setIsLoading] = useState(true);
  // useEffect(() => {
  //   axios.get(API_URL)
  //   .then((res) =>{
  //   setList(res.data)
  //   console.log(res.data)
  //   setIsLoading(false);
  //   })
  // }, [])
  return (
    <div>
      <Head>
        <title>HOME | JUSER</title>
      </Head>
      {/* {
        isLoading && (<div style= {{padding : "300px 0"}}> 
          <Loader inline="centered" active>
            Loading
          </Loader>
        </div>)
      }
      {
        !isLoading &&( */}
          <>
          <Header as ="h3" style={{paddingTop : 40}}>Best Item</Header>
          <Divider />
          <ItemList list = {list.slice(0,9)}/>
          <Header as ="h3" style={{paddingTop : 40}}>New Item</Header>
          <Divider />
          <ItemList list = {list.slice(9)}/>
      </>
        )
      {/* } */}
      
    </div>
  )
}
// 1. 정적생성에서 list 데이터를 만들었기 때문에 
export async function getStaticProps() {
  // 빌드시에 딱 한번만 호출되고 바로 static file로 빌드됨. = 이후 수정 불가.
  const apiUrl = process.env.API_URL;
  const res = await axios.get(apiUrl);
  const data= res.data

  return {
    props: {
      list : data,
      name : process.env.name
    }
  }
}

getStaticPath.

위의 getStaticProps 의 경우는 내가 이미 만들어둔 컴포넌트를 스테틱 파일로 만들어 두는 것으로 속도를 향상시켰습니다.

🙋 그럼 다이나믹 페이지는 불가능한가욧!?
🤖 10가능.

물론 가능합니다. 이때 사용하는 기능이 getStaticPath 입니다. 다이나믹 페이지는 [].js 페이지로 해당 아이디에 따라 새롭게 생성하는 페이지를 의미합니다. 그렇기 때문에 어떤 id 가 올지 모르기 때문에 기존의 getStaticProps로 페이지를 생성할 수 없습니다. 그런데 만약 갯수가 한정적이고, 미리 들어올 id를 알 수 있으면 가능합니다.

먼저 위의 3개의 id 만 static 파일을 생성한다고 했을때,

# [id].js - getStaticProps 적용.

const Post = ({item , name}) => {
  return <>{ item && (<>
  <Head>
    <title>{item.name}</title>
    <meta name = "description" content ={item.description}></meta>
  </Head>
  {name} 환경입니다.
  <Item item ={item}/></>)}</>
}

export default Post;

export async function getStaticProps(context) {
  // context : 여러가지 정보, params, 요청,
  const id = context.params.id;
  const apiUrl = `http://makeup-api.herokuapp.com/api/v1/products/${id}.json`
  const res = await axios.get(apiUrl);
  const data = res.data

  return {
    props: {
      item: data,
      name: process.env.name
    }
  }

}

여기에서 👇

# [id].js - getStaticPaths 적용.
const Post = ({ item, name }) => {
  return <>{item && (<>
    <Head>
      <title>{item.name}</title>
      <meta name="description" content={item.description}></meta>
    </Head>
    {name} 환경입니다.
    <Item item={item} /></>)}</>
}

export default Post;

export async function getStaticPaths() {
  return {
    paths: [
      { params: { id: '740' } },
      { params: { id: '730' } },
      { params: { id: '729' } }
    ],
    fallback: false, // fallback : 없는 페이지에 대한 대응을 할지 안할지 설정.

  };
}

저렇게 적용을 하면 해당 id 740,730,729 의 상품 페이지는 미리 만들어두지만, fallback속성이 false 이기 때문에 이 3가지 상품 이외에는 상품 페이지를 만들어 두지 않게 된다.
(3가지 상품페이지만 만들어진 상태.)

이 3가지 제품 말고는 404에러가 발생하게 된다.

그렇다면 저 부분을 true 로 바꾸면???

처음엔 3가지 상품에 대한 파일 밖에 없었지만 , 스크롤을 내릴 수록 해당 상품들의 페이지가 나오게 됩니다.
그리고 속도 역시 어마무시하게 향상이 됩니다. js를 꺼도 정상적으로 나오고 체감이 될정도로 빠릅니다!

🙋 이게 어떻게 가능한겨...??
🤖 Link의 prefetch 덕분임 ㅋ

우리가 썼던 Next Link의 경우엔 prefetch라는 속성이 있는데 디폴트가 true 이고 이 속성의 기능이

첫 화면이나 스크롤을 내렸을 때, 그 viewport 안에 있는 페이지는 모두 프리로드가 됩니다.

profile
호기심많은 개발자

0개의 댓글