본문 바로가기

Next.js9

Next.js 킬포 Pre-rendering 1. Static-Generation

 

Next.js의 킬링포인트 Pre-rendering 개념은 잘 보고 왔지?

 

Next.js Pre-rendering

안녕친구들! 스타일링까지 잘 따라오고 있어? Next.js 스타일링 팁 (classnames, postCSS, Sass) 튜토리얼 잘 따라오고 있어? 오늘은 쉬어가는 페이지! 알아두면 좋은 몇가지 라이브러리들을 소개할께! 지�

ppsu.tistory.com

Pre-rendering 첫번째 시간!

Static-Generation을 실습할꺼야!

Next.js의 Static-Generation은 말그대로 그냥 빌드타임에 미리 HTML을 생성해 두는 건데, 요기 또 쿨한 옵션이 하나 있다!

페이지를 생성할 때, 외부 데이터를 읽어와서 조합할 수 있다는 거야!

내용과는 상관없는 외계인 동상. 외부인임을 암시하는 사진  Photo by  Brian McMahon  on  Unsplash

빌드할때 API를 호출한 결과로 페이지 내용을 채울 수도 있고, 그냥 데이터 파일을 읽어서 만들수도 있지.

어떻게 하냐고?

불러올 데이터 호출하는 부분을 "getStaticProps" 메서드에 구현하면되! 

코드 한번 볼까?

export default function Home(props) { ... }

export async function getStaticProps() {
  // 외부 데이터 호출(파일, API, DB)
  const data = ...

  // props의 키값들이 Home 컴포넌트에 전달됨.
  return {
    props: ...
  }
}

외부데이터를 호출해서 리턴되는 객체에 props를 넣어주는데, 요기 들어가는 데이터가 Home 컴포넌트의 props로 들어가는 거야. 

'getStaticProps' 메서드는 "빌드타임"에 맨먼저 실행된다는거! 잊으면 안되!

그리고 우리는 지금 개발모드로 진행하고 있어서, 요청시마다 호출됨! 참고! 

 

우리 실습 코드에 한번 넣어보자!

프로젝트 디렉토리 루트에 '/posts' 디렉토리를 만들고, (pages/posts아님)

'pre-rendering.md' 생성

---
title: '두종류의 Pre-Rendering'
date: '2020-05-29'
---

Next.js는 두개의 pre-rendering이 있음 : **언제** HTML을 생성하는지에 따라 **Static Generation**, **Server-side Rendering** 이 있음.

- **Static Generation** **빌드타임**에 생성. 생성된 HTML은 사용자 요청시마다 _재사용_.
- **Server-side Rendering** **요청시 마다** 생성.

중요한건 각페이지별로 여러분이 **선택** 할 수 있다는 것. "하이브리드" Next.js 앱을 만들수 있음.

'bumuk-zzikmuk.md'파일을 만들자

---
title: 찍먹인가? 부먹인가?
date: '2020-05-28'
---

탕수육 소스를 부어 먹을 것이냐(**부먹**), 찍어 먹을 것이냐(**찍먹**)는 꾸준히 논쟁이 벌어지는 소재이다.

원래 중국집에서 탕수육을 주문하면, 소스가 부어져서 나오거나 소스와 함께 볶아져서 나온다. 하지만 이후 탕수육을 배달하게 되면서 배달 중 눅눅해지는 것을 방지하기 위해 고기와 소스를 따로 포장한 것이 소스를 부어먹느냐 찍어먹느냐의 대립을 만들게 된 것이다. 즉, 배달 탕수육을 기준으로 논쟁이 생긴 것. 중국집 매장에서 먹는 경우 소스와 고기가 섞여 나오는 것이 기본이므로 찍먹을 원한다면 음식이 완성되기 전에 미리 고기와 소스를 따로 달라고 요청해야 한다.

부먹파는, 소스가 튀김에 스며들어 고기와 어우러지는 맛과 식감을 좋아하며 이렇게 먹는 것이 탕수육의 본래 형태라고 주장한다. 또한 찍먹시에 여러 사람들의 입과 침이 닿은 젓가락과 튀김이 반복적으로 소스 그릇에 담궈진다는 위생상의 이유에서 부먹을 선호하는 사람도 있다. 반면에 찍먹파는 바삭한 튀김에 소스를 가볍게 입힌 맛을 좋아하는데 소스를 부어 버리면 튀김이 과도하게 눅눅해진다고 주장한다.

과연 여러분의 선택은?

확장자 이미 봐서 알겠지만, md파일 즉, 마크다운 파일이야. 

마크다운 파일 구조

마크다운이 뭔지 궁금한 친구들은 위키문서 참고!

상단에  title, date는 YAML Front Matter라고해! 

글에대한 정보를 담은 메타데이터로, 앞으로 사용할  gray-matter 라는 라이브러리에서 읽을 데이터지.

눈치 빠른 친구들 이미 알겠지만, 앞으로 우리의 실습이 바로 마크다운 파일을 파싱해서 HTML을 생성하는 거라는거!

앞으로 우리의 할일

  1. 마크다운 파일을 파싱한다.
  2. 파싱한 데이터를 페이지컴포넌트의 배열로 props에 넘긴다.
  3. 첫 index페이지에서 블로그포스트 리스트가 노출된다.

 

getStaticProps 메서드 구현!

먼저, gray-matter을 설치하자.

npm install gray-matter

파일을 파싱할 코드는 별도로 작성해서 관리 할꺼야.

lib디렉토리를 프로젝트 디렉토리 루트에 만들고 posts.js라는 파일을 아래와 같이 작성!

import fs from 'fs'
import path from 'path'
import matter from 'gray-matter'

const postsDirectory = path.join(process.cwd(), 'posts')

export function getSortedPostsData() {
  // posts 디렉토리의 파일들을 읽음
  const fileNames = fs.readdirSync(postsDirectory)
  const allPostsData = fileNames.map(fileName => {
    // ".md" 확장자를 지우고 id를 가져옴
    const id = fileName.replace(/\.md$/, '')

    // 마크다운 파일을 스트링으로 읽음
    const fullPath = path.join(postsDirectory, fileName)
    const fileContents = fs.readFileSync(fullPath, 'utf8')

    // gray-matter를 사용해 메타데이터 부분 파싱
    const matterResult = matter(fileContents)

    // 데이터와 id 결합
    return {
      id,
      ...matterResult.data
    }
  })
  // 날짜기준으로 정렬
  return allPostsData.sort((a, b) => {
    if (a.date < b.date) {
      return 1
    } else {
      return -1
    }
  })
}
  • 파일명을 id값으로 사용하고
  • 제목이랑 날짜 파싱은 gray-matter가 해서 데이터를 생성.
  • 날짜기준으로 내림차순 정렬해서 리턴

요걸 pages/index.js 파일 맨 위에 import하자!

import { getSortedPostsData } from '../lib/posts'

이제 getStaticProps메서드 추가!

export async function getStaticProps() {
  const allPostsData = getSortedPostsData()
  return {
    props: {
      allPostsData
    }
  }
}

페이지 컴포넌트에서 꺼내 읽어야 겠지? 컴포넌트 정의 하는 곳 파라미터를 넣자!

export default function Home ({ allPostsData }) {

마지막으로 읽은 데이터 뿌려주기! 

내 전체 코드는 아래랑 같아!

import Head from 'next/head'
import Link from 'next/link'
import Layout, { siteTitle } from '../components/layout'
import utilStyles from '../styles/utils.module.css'
import { getSortedPostsData } from '../lib/posts'

export default function Home({ allPostsData }) {
  return (
    <Layout home>
      <Head>
        <title>{siteTitle}</title>
      </Head>
      <section className={utilStyles.headingMd}>
        <p>반가워요 PPSU라고 합니다!</p>
        <p>
         요기는 샘플 웹사이트예요 - 여러분도 이렇게 사이트를 만들수 있어요! 
        </p>
      </section>
<h1 className="title">
	  한번볼래? <Link href="/posts/first-post"><a> 내가만든 첫번째 페이지!</a></Link>
        </h1>
      <section className={`${utilStyles.headingMd} ${utilStyles.padding1px}`}>
        <h2 className={utilStyles.headingLg}>블로그 글 목록</h2>
        <ul className={utilStyles.list}>
          {allPostsData.map(({ id, date, title }) => (
            <li className={utilStyles.listItem} key={id}>
              {title}
              <br />
              {id}
              <br />
              {date}
            </li>
          ))}
        </ul>
      </section>


    </Layout>
  )
}

export async function getStaticProps() {
  const allPostsData = getSortedPostsData()
  return {
    props: {
      allPostsData
    }
  }
}

http://localhost:3000 에 접속하면?

뾰로롱!

getStaticProps 에 대해 잊지 말아야 할것!

아직 끝난게 아니란 말씀!  getStaticProps 메서드가 멋진 대신, 제대로 알고 써야 삽질을 안할 수 있어!

1. 외부 API나 DB접근을 할수 있다.

알다시피 요 getStaticProps메서드는 "빌드타임"에 (개발모드는 리프레시 할때마다) 서버에서 호출된다는 말씀! 

당연한 말이지만 브라우저에서 다운받는 JS 번들에는 포함되지 않아! 서버에서만 사용할 코드를 작성해도 된다는 말이지.

 

2. Page컴포넌트에서만 getStaticProps 메서드를 export 할 수 있음.

리액트는 페이지가 렌더링되기 전에 모든 props데이터가 준비되어 있어야 하기 때문이야. 페이지 컴포넌트는 next.js가 관리하니까 가능함.

 

3. 요청시마다 데이터를 호출하고 싶다면?

이전 글에서 한번 언급했지만 그럴 경우는 Static-Generation에 안맞는 경우야.

Server-side Rendering을 해야 하지.

휴 요건 다음 시간에 하자!

휴식도 중요하다고!

커피 한잔 하고와!

 

지금까지 한 내용 정리

  • 블로그 글 내용을 담고 있는 마크다운 파일 파싱
  • index.js에 있는 페이지 컴포넌트 Home에 Static-Generation시 사용되는 getStaticProps 메서드 추가
  • 페이지 컴포넌트 Home에 블로그 제목 및 날짜 추가

 

Next.js 킬포2 Servier-side Rendering & Client-side Rendering

 

Next.js 킬포 Pre-rendering 2. Server-side Rendering

Pre-rendering중 하나인 Static-Generation은 저번시간에 실습해봤고, 이번엔 Server-side Rendering이야 Next.js 킬포 Pre-rendering 1. Static-Generation Next.js의 킬링포인트 Pre-rendering 개념은 잘 보고..

ppsu.tistory.com

다음시간엔 Server-side Rendring과 Next.js에서의 Client-side Rendering에 대해 알아볼께!