TIL 92 | Next.js 차근차근 시작해보기

meow·2020년 12월 21일
1

React

목록 보기
31/33
post-custom-banner

SSR을 하는 이유 -> 어서와, SSR은 처음이지?
Next.js 공식 튜토리얼(en)
Next.js 필요한 것만 빨리 배우기(kr)

Next.js?

리액트를 기반으로 한 SPA를 빠르게 빌들할 수 있도록 도와주는 서버사이드 프레임워크이다. 매우 간단하지만 커스터마이징이 매우 용이하다는 장점이 있다. 서버사이드 렌더링의 장점은 네이버 기술블로그에 있는 어서와, SSR은 처음이지? 를 참고해보시길.

아래 내용은 next.js 공식 사이트에 있는 learning course를 간략하게 번역 요약한 것이다. 따라만 하면 나도 next.js 하루만에 마스터 쌉possible!

0. Set up

Node.js의 10.13 이상 버전이 설치되어 있어야 한다. 여기에서 설치 가능하다.

1. Create a Next Next.js app

터미널에서 원하는 경로에 진입 후 앱을 만든다. 아래 커맨드를 입력하면 된다.

$ npx create-next-app nextjs-blog --use-npm --example "https://github.com/vercel/next-learn-starter/tree/master/learn-starter"

Run the dev server

생성된 nextjs-blog에 진입 후 개발 서버를 실행한다.

$ cd nextjs-blog
$ npm run dev

성공적으로 컴파일 되었다는 메세지가 뜬다면 http://localhost:3000 에서 확인이 가능하다.

pages/index.js 파일을 수정시 development 서버가 자동으로 리프레쉬 되는 것을 확인할 수 있다. Next.js가 알아서 변화를 브라우저에 바로바로 적용시켜주기 때문이다.

2. Navigate Between Pages

Pages in Next.js

Next.js에서 route는 pages 디렉토리 아래 파일의 이름과 연관되어있다.
예를 들어, 개발기에서 pages/index.js/ 루트와 연결되고,
pages/posts/first-post.js/posts/first-post루트와 연결된다.

디렉토리의 path가 곧 URL path가 되는 것이다.

pages 폴더 아래에 posts 디렉토리를 만들고 그 안에 first-post.js 파일을 생성한다.

export default function FirstPost() {
  return <h1>First Post</h1>
}

컴포넌트의 이름은 상관이 없지만 반드시 default로 export 해야 한다. 서버가 돌아가고 있을 때 http://localhost:3000/posts/first-post 에서 first-post.js 페이지를 확인할 수 있다. 이렇게 Next.js에서 새로운 페이지를 생성하는 것은 참 쉽 다 !

HTML tag 로는 웹사이트에서 페이지 간 이동할 때 <a> 태그를 사용한다. Next.js 에서는 Link 컴포넌트를 next/link에서 import 해서 <a> 태그를 감싸면 된다. <Link> 가 웹앱의 다른 페이지 간에 client-side 네비게이션을 할 수 있도록 한다.

pages/index.js를 열고 Link 컴포넌트를 import 한다.

import Link from 'next/link'

아래의 h1 태그를 찾고 Link를 추가하여 코드를 수정한다.

<h1 className="title">
  Learn <a href="https://nextjs.org">Next.js!</a>
</h1>

이렇게 수정한다.

<h1 className="title">
  Read{' '}
  <Link href="/posts/first-post">
    <a>this page!</a>
  </Link>
</h1>

first-post.js 파일은 아래와 같이 내용을 수정한다.

import Link from 'next/link'


export default function FirstPost() {
  return (
  <>
    <h1>First Post</h1>
    <h2>
      <Link href="/">
        <a>Back to home</a>
      </Link>
    </h2>
  </>
)}

이제 index 페이지에서 first-post 페이지로 왔다갔다 이동이 가능해졌다.

Client-Side Navigation

Link 컴포넌트는 같은 Next.js 앱에서 두 페이지간 client-side navigation을 가능하게 한다. Client-side navigation 이라는 것은 이러한 페이지 변화가 자바스크립트를 사용하여 일어난다는 것을 의미하며, 이는 브라우저로 작동하는 기본 navigation보다 빠르다는 장점이 있다.

이를 확인해보고 싶다면 개발자도구를 통해 페이지에서 <html>에 background-color 값을 주고 페이지 이동을 해보면 된다. yellow 값이 계속 유지되는 것을 볼 수 있다. Link 컴포넌트가 아닌 a 태그를 썼다면 브라우저는 완전히 새로고침을 하기 때문에 배경색이 유지되지 않는다.

Code splitting and prefetching

Next.js는 자동으로 코드 스플리팅을 하기 때문에 각 페이지는 그 페이지에 필요한 것만을 로드한다. 따라서 홈페이지가 다시 렌더될 때, 다른 페이지를 위한 코드는 처음에 전달되지 않는다. 이런 점이 수백개의 페이지를 제공한다고 하더라도, 홈페이지가 빠르게 로드될 수 있도록 해준다.

리퀘스트 보낸 페이지만을 로드한다는 것은, 각 페이지가 분리되어있다는 것을 의미하며, 이는 특정 페이지가 에러를 던져도 나머지 앱의 페이지들은 정상적으로 작동함을 의미하기도 한다.

더 나아가 Link 컴포넌트가 브라우저의 뷰포트에 존재한다면, Next.js는 자동으로 연결된 페이지들의 코드를 미리 가져온다. 따라서 링크를 클릭하자마자, 연결될 페이지의 코드는 이미 백그라운드에 로드되어있고, 거의 바로 페이지가 전환될 수 있는 것이다. 따로 라우팅을 위한 라이브러리를 쓰지 않아도 된다.

  • 외부로 연결되는 링크의 경우 <a> 태그를 사용하면 된다.
  • className과 같은 속성값을 추가하고 싶다면 Link 태그가 아닌 a 태그 안에 넣으면 된다.

3. Assets, Metadata, and Css

Assets

public 폴더 안에 넣어 사용한다. (기존 html 방식과 같음)

<img src="/vercel.svg" alt="Vercel Logo" className="logo" />

Metadata

<title>과 같은 메타데이터들은 Head 컴포넌트를 next/head 모듈로부터 임포트해서 해당 컴포넌트 안에 넣으면 된다.

import Head from 'next/head'
  ...

<Head>
  <title>Create Next App</title>
  <link rel="icon" href="/favicon.ico" />
</Head>

CSS Styling

Next.js에서는 styled-jsx, styled-component, 또는 emotion과 같은 CSS-in-JS 라이브러리를 사용할 수 있다.

Layout Component

모든 페이지에서 공통으로 사용할 Layout 컴포넌트를 만들어보자.

  • components라는 top-level 디렉토리를 만들고,
  • 그 안에 layout.js 파일을 만든다.
export default function Layout({ children }) {
  return <div>{children}</div>
}

first-post.js 파일을 열고 Layout 컴포넌트를 임포트한 뒤, 모든 컴포넌트를 감싼다.

import Head from 'next/head'
import Link from 'next/link'
import Layout from '../../components/layout'

export default function FirstPost() {
  return (
    <Layout>
      <Head>
        <title>First Post</title>
      </Head>
      <h1>First Post</h1>
      <h2>
        <Link href="/">
          <a>Back to home</a>
        </Link>
      </h2>
    </Layout>
  )
}

CSS 붙이기

Layout 컴포넌트에 스타일 값을 줄 CSS 파일을 만들고 임포트하자. component/layout.module.css 파일을 만들고 아래와 같이 작성한다.

.container {
  max-width: 36rem;
  padding: 0 1rem;
  margin: 3rem auto 6rem;
}
  • CSS Modules를 이용하기 위해서는 CSS 파일 이름을 반드시 .module.css로 끝내야 한다.

layout.js 파일에 CSS 파일을 임포트한다. styles와 같은 이름을 부여한다. className은 styles.container와 같은 형식으로 작성한다.

import styles from './layout.module.css'

export default function Layout({ children }) {
  return <div className={styles.container}>{children}</div>
}

로컬호스트 서버에 가보면 컨테이너가 적용된 것을 볼 수 있다. 개발자도구에서 보면 Layout 컴포넌트가 유니크한 클래스네임을 갖게 된 것을 확인할 수 있다. 이게 CSS Modules가 하는 것이다. 알아서 유니크한 클래스네임을 생성하기 때문에 클래스네임이 충돌하는 것을 걱정하지 않아도 된다.

Global Styles

CSS Modules를 사용할 수도 있지만, 모든 페이지에 공통으로 적용되는 CSS가 필요할 수도 있다. global CSS를 로드하기 위해서는 pages/_app.js라는 파일을 아래와 같이 만든다.

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

App 컴포넌트는 top-level 컴포넌트로 모든 페이지에 접근한다. 이 App 컴포넌트를 다른 페이지 간 이동을 할때 항상 상태를 유지할 수 있다.

Restart the Development Server

중요! pages/_app.js 파일을 추가했다면 Ctrl+c로 서버를 멈추고 다시 run 해야 한다.

$ npm run dev

Adding Global CSS

styles 디렉토리 안에 global.css 파일을 만들어 작성하고, 이를 pages/_app.js 파일에 임포트만 해주면 된다.

global.css

html,
body {
  padding: 0;
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu,
    Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
  line-height: 1.6;
  font-size: 18px;
}

* {
  box-sizing: border-box;
}

a {
  color: #0070f3;
  text-decoration: none;
}

a:hover {
  text-decoration: underline;
}

img {
  max-width: 100%;
  display: block;
}

pages/_app.js

import '../styles/global.css'

export default function App({ Component, pageProps }) {
  return <Component {...pageProps} />
}
profile
🌙`、、`ヽ`ヽ`、、ヽヽ、`、ヽ`ヽ`ヽヽ` ヽ`、`ヽ`、ヽ``、ヽ`ヽ`、ヽヽ`ヽ、ヽ `ヽ、ヽヽ`ヽ`、``ヽ`ヽ、ヽ、ヽ`ヽ`ヽ 、ヽ`ヽ`ヽ、ヽ、ヽ`ヽ`ヽ 、ヽ、ヽ、ヽ``、ヽ`、ヽヽ 🚶‍♀ ヽ``ヽ``、ヽ`、
post-custom-banner

2개의 댓글

comment-user-thumbnail
2020년 12월 26일

저도 요새 눈물 흘리면서 next.js하고 있는데 잘 보고 갑니다!

1개의 답글