[NextJS] Next.JS 공식문서 튜토리얼 번역하며 공부하기 (1)

Jay·2022년 2월 25일
3
post-thumbnail

Next.JS의 공식문서 튜토리얼을 번역합니다
※ 각 챕터 내 Setup 파트는 생략했습니다. 실습하던 프로젝트로 계속 진행하시면 됩니다.
※ 필자 입맛대로 한 번역이므로 주의 요함
※ 오역, 오타에 대한 피드백 두 팔 벌려 환영

Create a Next.js App

React로 완벽한 웹 어플리케이션을 만들기 위해서는 많은 세부사항을 고려해야 합니다.

  • 코드는 웹펙과 같은 번들러를 사용해 번들되어야 하고, 바벨과 같은 컴파일러를 사용해 변환되어야 합니다.
  • 코드 스플리팅과 같은 운영상의 최적화가 필요합니다.
  • 당신은 퍼포먼스와 SEO를 고려하여 어떠한 페이지들은 정적으로 프리렌더링 되기를 원할 거예요. 서버사이드 렌더링이나 클라이언트 사이드 렌더링을 원할 수도 있구요.
  • 리액트 앱과 데이터 저장소의 연결을 위해 서버사이드 코드를 작성해야 할 수도 있겠네요.

프레임워크는 이러한 문제들을 해결해 줍니다. 하지만 이런 프레임워크는 적정 수준의 추상화 레벨을 가지고 있어야 합니다. 그렇지 않다면 그건 딱히 유용하지 않을 거예요. 또한 프레임워크는 코드를 작성하면서 당신과 당신 팀이 멋진 경험을 보장하는 탁월한 "개발 경험"을 시켜 주어야 해요.

리액트의 프레임워크인 Next.js

Next.js는 리액트 프레임워크입니다. Next.js는 위에 언급된 모든 문제들을 해결해 주죠. 하지만 가장 중요한 건, Next.js는 당신과 당신 팀이 리액트 어플리케이션을 빌드하는 데에 있어 극락을 경험시켜 줄 거라는 거죠.

Next.js는 최고의 개발자 경험과 많은 빌트인 기능을 제공하는 것을 목표로 합니다.

1. Setup

Setup

먼저, 개발환경을 준비합시다.

  • Node.js가 설치되어 있지 않다면, 이곳에서 설치하세요. Node.js의 버전은 10.13 이상이어야 합니다.
  • 이 튜토리얼은 여러분이 사용하던 텍스트 에디터와 터미널 앱을 가지고 따라하면 돼요.

Create a Next.js app

Next.js 앱을 생성하기 위해, 터미널을 열고 cd 명령어를 통해 앱을 생성하고 싶은 곳의 디렉토리 경로를 지정한 후, 아래의 명령어를 실행시킵니다.

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

명령어를 자세히 보면, create-next-app 이라는 툴을 사용하고 있는데, 이건 Next.js 앱을 새로 생성할 때 필요한 것들을 알아서 설치해 주는 CLI 툴입니다. 또한 --example 이라는 옵션을 통해 이 템플릿을 사용하도록 하고 있죠.

Run the development server

자, 이제 nextjs-blog라는 새로운 디렉토리가 생겼습니다. cd를 이용해 해당 디렉토리 안으로 들어가 주세요.

cd nextjs-blog

그런 다음, 아래의 명령어를 입력해 주세요.

npm run dev

그럼 당신의 Next.js 앱의 개발 서버가 3000번 포트에서 실행됩니다. 작동하는지 확인해 봅시다. 브라우저에서 http://localhost:3000를 열어 보세요.

2. Welcome to Next.js

http://localhost:3000로 접속했을 때, 아래와 같은 페이지가 보여야 해요. 해당 템플릿 페이지는 Next.js에 관한 유용한 정보를 담고 있죠.

3. Editing the Page

시작 페이지를 편집해 봅시다.

  • Next.js 개발 서버가 실행되고 있어야 합니다.
  • 에디터에서 pages/index.js 파일을 열어 주세요.
  • <h1> 태그 아래의 "Welcome to" 라고 쓰인 텍스트를 "Learn" 으로 수정해 보세요.
  • 파일을 저장하세요.

파일을 저장하자마자, 브라우저는 수정된 페이지를 자동적으로 업데이트합니다.

Next.js 개발 서버는 Fast Refresh가 가능합니다. 당신이 파일을 수정하게 되면, Next.js는 브라우저로 하여금 눈깜짝할 사이에 수정사항을 반영시켜요. 새로고침이 필요 없죠!

튜토리얼을 계속 진행하기 위해선 개발서버가 돌아가고 있어야 하지만, 서버를 새로 작동시키고 싶다면 Ctrl+c를 눌러 서버를 멈출 수 있습니다.

지금까지 우리가 만든 Next.js 앱은 하나의 페이지 뿐이었어요. 일반적으로 웹사이트와 웹 어플리케이션은 여러 개의 페이지를 가지고 있죠.

페이지 추가 방법에 대해 알아 봅시다.

이 레슨을 통해,

  • 통합된 파일 시스템 라우팅을 사용해서 새로운 페이지를 만듭니다.
  • Link 컴포넌트를 사용하여 페이지 간의 클라이언트 사이드 네비게이션을 어떻게 가능하게 하는지 배웁니다.
  • 내장 지원인 코드 스플리팅과 프리페칭(prefetching)에 대해 배웁니다.

1. Pages in Next.js

Next.js에서 페이지란 pages 폴더 내의 파일에서 export 되어진 리액트 컴포넌트입니다.

페이지들은 각자의 파일명에 기반하여 라우팅 됩니다. 예를 들어, 개발 단계에서

  • pages/index.js/ 로 라우팅 됩니다.
  • pages/posts/first-post.js/posts/first-post로 라우팅 됩니다.

pages/index.js 파일은 이미 존재하고 있으니, pages/posts/first-post.js를 생성하여 라우팅 기능을 살펴 봅시다.

Create a New Page

pages 폴더 아래에 posts 폴더를 생성합니다.
posts 폴더 안에 first-post.js 라는 파일을 만들고 아래의 코드를 넣어 주세요.

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

컴포넌트는 어떤 이름이든 가질 수 있지만, 반드시 export default 형태로 export 되어야 합니다.

자, 개발 서버가 제대로 돌고 있는지 확인하고, http://localhost:3000/posts/first-post로 접속해 보세요. 아래와 같은 페이지가 보여야 해요.

이게 Next.js에서 다른 페이지를 생성하는 방법이에요.
pages 폴더 아래에 JS 파일을 생성하면, 그 파일의 경로가 URL path가 되는 겁니다.

이건 HTML과 PHP 파일을 사용하여 웹사이트를 만드는 것과 비슷한 방법이에요. HTML을 작성하는 대신 JSX 문법과 리액트 컴포넌트를 사용하는 거죠.

이제 네비게이션을 위해 새로 생성한 페이지에 링크를 추가해 봅시다.

웹사이트에서 페이지를 연결시킬 때, <a> 라는 HTML 태그를 사용합니다.

Next.js에서는 next/link로부터 Link 컴포넌트를 가져와 <a> 태그를 감싸야 합니다. <Link>는 어플리케이션 내에서 다른 페이지로의 클라이언트 사이드 네비게이션이 가능하도록 해 줍니다.

먼저, pages/index.js 파일을 열고, 페이지 상단에 아래의 코드를 추가하여next/link로부터 Link 컴포넌트를 import 합시다.

import Link from 'next/link'

그리고 아래와 같은 h1 태그를 찾아서,

<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>

{''} 여러 줄로 된 텍스트를 나누는 데에 쓰일 공란을 추가합니다.

다음으로, pages/posts/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>
    </>
  )
}

Link 컴포넌트는 <a> 태그 사용법과 비슷하긴 하지만, <a href="..."> 대신에 <Link href="..."> 사용하고 그 안에 <a> 태그를 넣어 줍니다.

제대로 작동하는지 확인해 봅시다. 각 페이지 내에 뒤로 가기와 앞으로 가기를 가능하게 하는 링크가 있어야 해요.

3. Client-Side Navigation

Link 컴포넌트는 동일한 Next.js 앱 내에서 두 개의 페이지 간에 클라이언트 사이드 네비게이션이 가능하게 해 줍니다.

클라이언트 사이드 네비게이션이란 자바스크립트를 사용한 페이지 전환을 의미하는데, 이는 브라우저에 의한 기본 네비게이션보다 더 빠르게 작동합니다.

이를 확인해 볼 수 있는 간단한 방법이 있어요.

  • 브라우저의 개발자 도구에서 <HTML>background CSS 속성을 yellow로 변경해 주세요.
  • 링크를 클릭하여 두 페이지 간의 뒤로 가기와 앞으로 가기를 작동해 보세요.
  • 페이지 전환이 이루어 질 때, 노란색 배경색이 계속 적용되는 것을 볼 수 있습니다.

이는 브라우저가 전체 페이지를 로드하지 않으며 클라이언트 사이드 네비게이션이 작동하고 있음을 보여 줍니다.

만일 <Link href="..."> 대신 <a href="...">를 사용했다면, 링크 클릭시 배경색은 사라졌을 겁니다. 브라우저가 전체 새로고침 되기 때문이죠.

Code splitting and prefetching

Next.js는 자동적으로 코드 스플리팅을 합니다. 그래서 해당 페이지에 필요한 것만 불러옵니다. 홈페이지가 렌더링 될 때, 다른 페이지를 위한 코드는 가져오지 않습니다.

이는 당신이 아무리 수많은 페이지를 갖고 있더라도 홈페이지의 신속한 로드를 보장해 줍니다.

사용자가 요청한 페이지에 대한 코드만 가져온다는 것은 페이지는 분리 상태가 된다는 것을 의미합니다. 만일 특정 페이지가 에러를 발생시킨다 해도, 나머지 페이지는 작동할 겁니다.

더군다나, Next.js의 운영 빌드에서 언제든 브라우저의 뷰포트에 Link 컴포넌트가 나타난다면, Next.js는 백그라운드에 그 링크에 연결된 페이지에 대한 코드를 자동적으로 프리패치(prefetch) 합니다. 그래서 링크를 클릭하게 되면, 해당 페이지의 코드가 미리 백그라운드에 로드되어 있기에, 페이지 전환이 거의 즉각적으로 이루어지게 됩니다.

Summary

Next.js는 최고의 퍼포먼스를 위해 코드 스플리팅, 클라이언트 사이드 네비게이션, 프리페칭(운영에서)으로써 당신의 어플리케이션을 최적화합니다.

당신은 pages 폴더 아래에 파일로 라우팅을 구현할 수 있고, 빌트인 <Link> 컴포넌트를 사용할 수 있습니다. 라우팅 라이브러리는 필요하지 않죠.

next/link에 대한 API reference라우팅 문서에서 Link 컴포넌트에 대해 더 알아볼 수 있습니다.

Note : 만일 Next.js 앱 외부 페이지로 링크를 걸어야 한다면, Link 없이 <a> 태그를 사용하면 됩니다.
만일 className과 같은 속성을 추가하고자 한다면, Link가 아닌 <a> 태그에 추가하면 됩니다.

Assets, Metadata, and CSS

우리가 추가한 두 번째 페이지는 현재 어떤 스타일링도 되어 있지 않아요. 이 페이지에 CSS 작업을 추가해 봅시다.

Next.js는 CSS와 Sass에 대한 내장 지원을 가지고 있습니다. 이번 과정에선 CSS를 사용할 겁니다.

또한 이 레슨에선 Next.js가 어떻게 이미지 파일이나 title 태그와 같은 페이지 메타데이터 등의 정적 파일을 다루는지에 대해 배워볼 겁니다.

What You'll Learn in This Lesson

이 레슨에서, 당신은 아래와 같은 것을 배우게 될 거예요.

  • Next.js에서 정적 파일(이미지파일 등)을 추가하는 방법
  • 각 페이지의 <head> 태그를 커스터마이징하는 방법
  • CSS 모듈로 스타일링 된 재사용 가능한 리액트 컴포넌트를 생성하는 방법
  • pages/_app.js 내에 전역 CSS를 추가하는 방법
  • Next.js에서의 스타일링에 관한 유용한 팁

Prerequisites(선수지식)

  • CSS에 대한 기초 지식이 필요합니다. 이 과정은 Next.js 앱에 CSS를 추가하는 방식에 대해 배우는 거지, CSS에 대한 기초 지식을 익히진 않거든요.

Next.js에서의 스타일링에 대한 자세한 문서가 필요하다면, 이 CSS 문서를 읽어 보세요.

1. Assets

Next.js는 최상위 레벨의 public 폴더 안에 있는 정적 파일을 사용합니다. public 폴더 안에 있는 파일들은 pages와 같은 어플리케이션의 루트 폴더에서 참고될 수 있습니다.

public 폴더는 robots.txt, Google Site Verification, 그리고 다른 정적 파일에 있어 유용합니다. 자세한 내용은 정적 파일 서빙에 대한 문서를 확인해 보세요.

Download Your Profile Picture

먼저, 당신의 프로필 이미지를 가져와 봅시다.

  • .jpg 확장자의 이미지 파일을 다운로드하세요.
  • public 폴더 안에 images 폴더를 생성하세요.
  • 이미지 파일을 public/images 폴더 안에 profile.jpg라는 이름으로 저장해 주세요.
  • 이미지 사이즈의 가로,세로 길이는 대략 400px이어야 합니다.
  • public 폴더 아래의 사용하지 않는 SVG 로고 파일은 지워도 돼요.

Unoptimized Image

보통의 HTML에선 아래와 같이 프로필 파일을 추가했을 거예요.

<img src="/images/profile.jpg" alt="Your Name" />

그리고 당신이 직접 다음과 같은 항목의 작업들을 처리했어야 하죠.

  • 각기 다른 화면 사이즈에 대한 이미지의 반응형 작업
  • 써드파티 툴이나 라이브러리에서의 이미지 최적화
  • 뷰포트에 진입했을 때만 로드되는 이미지

대신에 Next.js는 당신으로 하여금 위의 과정에서 벗어나게 해 줄 Image 컴포넌트를 제공합니다.

Image Component and Image Optimization

next/image는 HTML의 <img> 엘리먼트의 확장형이자 모던 웹을 위해 진화한 컴포넌트입니다.

또한 Next.js는 이미지 최적화를 기본으로 지원합니다. 이미지의 리사이징과 최적화, 그리고 브라우저의 지원 여부에 따라 WebP와 같은 모던 포맷의 이미지 또한 제공이 가능합니다. 이는 작은 뷰포트를 가진 기기에서 큰 사이즈의 이미지가 로드되는 것을 방지합니다. 또한 Next.js는 자동적으로 차세대 이미지 포맷을 채택하고 그 포맷을 지원하는 브라우저에 해당 이미지를 제공합니다.

자동 이미지 최적화는 모든 이미지 형식에 적용됩니다. 이미지가 CMS와 같은 외부 데이터 소스로부터 호스팅 됐다 해도 최적화가 돼요.

Using the Image Component

Next.js는 빌드 타임에 이미지를 최적화하는 대신 사용자가 이미지를 요청하는 때에 최적화 작업을 합니다. 당신이 제공하는 이미지가 열 장이든 천만 장이든, 다른 정적 사이트 생성기와는 다르게 당신의 빌드 타임은 증가하지 않습니다.

이미지는 원래 지연되어 로드됩니다. 이는 페이지 속도가 뷰포트를 벗어나는 이미지 때문에 불이익을 받는 건 아니라는 겁니다. 이미지는 뷰포트 내로 스크롤될 때 로드됩니다.

아래는 next/image를 사용하여 우리의 프로필 사진을 보여주기 위한 예제 코드입니다. heightwidth 프롭스는 원본 이미지와 동일한 비율을 가진 렌더링 사이즈여야 합니다.

Note: 이 컴포넌트는 나중에 "Polishing Layout"에서 사용할 거니깐, 아직 복사할 필요 없습니다.

import Image from 'next/image'

const YourComponent = () => (
  <Image
    src="/images/profile.jpg" // Route of the image file
    height={144} // Desired size with correct aspect ratio
    width={144} // Desired size with correct aspect ratio
    alt="Your Name"
  />
)

2. Metadata

만일 <title> 태그와 같은 페이지의 메타데이터를 수정하고 싶으면 어떻게 해야 할까요?

<title><head>태그의 일부입니다. Next.js에서 <head>태그를 어떻게 수정하는지 알아 봅시다.

pages/index.js 파일을 열고 아래의 코드를 찾아 보세요.

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

<Head><head> 대신에 사용된 게 보일 거예요. <Head>는 Next.js 내에 빌트되어 있는 리액트 컴포넌트입니다. 이 컴포넌트로 페이지의 <head>를 수정할 수 있어요.

Head 컴포넌트는 next/head 모듈로부터 가져올 수 있습니다.

Adding Head to first-post.js

아직 posts/first-post 라우트 내에 <title> 태그를 넣지 않았죠? 해 봅시다.

pages/posts/first-post.js 파일을 열고 파일의 시작 부분에 next/head로부터 Head 컴포넌트를 임포트 해 오겠다는 코드를 추가해 주세요.

import Head from 'next/head'

그리고, FirstPost 컴포넌트가 Head 컴포넌트를 포함하도록 업데이트 해 주세요. 이제 title 태그만 추가하면 됩니다.

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

URL로 접속해 보세요. 브라우저 탭에 "First Post"라고 적혀 있을 거예요. 브라우저의 개발자 도구를 통해서도 <head> 안에 title 태그가 추가된 걸 확인할 수 있습니다.

3. Third-Party JavaScript

써드파티 자바스크립트는 써드파티 소스로부터 추가된 모든 스크립트를 의미합니다. 보통, 써드파티 스크립트는 사이트에

Adding Third-Party Javascript

Next.js 앱에 써드파티 스크립트를 어떻게 추가할 수 있는지 알아 봅시다.

pages/posts/first-post.js 파일에서 아래의 코드를 찾아 주세요.

<Head>
  <title>First Post</title>
</Head>

메타데이터 말고도, 즉시 로드되고 실행되어야 하는 스크립트도 또한 일반적으로 페이지의 <head> 태그 내에 추가합니다. 일반적인 <script> 엘리먼트를 사용해서 외부 스크립트를 가져올 때는 아래와 같이 하죠.

<Head>
  <title>First Post</title>
  <script src="https://connect.facebook.net/en_US/sdk.js" />
</Head>

이 스크립트는 페이스 북의 소셜 플러그인과 다른 기능을 위해 흔히 쓰이는 Facebook SDK 입니다. 이 방식도 작동은 하지만, 동일 페이지의 다른 자바스크립트 코드에 대해

Using the Script Component

next/script<script> 엘리먼트의 확장형이자 다른 스크립트를 불러오거나 실행할 때 최적화 해 줍니다.

같은 파일의 상단에 next/script 로부터 Script를 불러오는 코드를 추가해 주세요.

import Script from 'next/script'

이제, FirstPost 컴포넌트 안에 Script 컴포넌트를 추가해 줍니다.

export default function FirstPost() {
  return (
    <>
      <Head>
        <title>First Post</title>
      </Head>
      <Script
        src="https://connect.facebook.net/en_US/sdk.js"
        strategy="lazyOnload"
        onLoad={() =>
          console.log(`script loaded correctly, window.FB has been populated`)
        }
      />
      <h1>First Post</h1>
      <h2>
        <Link href="/">
          <a>Back to home</a>
        </Link>
      </h2>
    </>
  )
}

Script 컴포넌트에 정의된 몇 가지 속성을 알아 봅시다.

  • strategy는 언제 써드파티 스크립트를 로드할지를 컨트롤 합니다. lazyOnload라는 값은 Next.js로 하여금 이 스크립트를 브라우저의 유휴 시간에 불러오도록 명령합니다.
  • onLoad는 스크립트의 로딩이 끝나는 즉시 자바스크립트 코드를 실행 시킵니다. 이 예제에선 스크립트 로드가 제대로 되었다는 문구를 콘솔창에 찍히도록 해 두었습니다.

URL에 접속해 보세요. 브라우저의 개발자 도구의 Console 패널에 메시지가 찍히는 걸 확인할 수 있습니다. 또한 window.FB를 통해 스크립트가 전역 변수에서 담겨 있는 것을 볼 수 있습니다.

Note: 페이스북 SDK는 써드파티 스크립트를 앱에 어떻게 추가하는지를 익히기 위해 고안한 예제입니다. Next.js의 써드파티 기능에 대해 이해가 되었다면, 다음 과정 진행에 앞서 FirstPost에서 해당 Script 컴포넌트를 삭제해도 좋습니다.

4. CSS Styling

CSS 스타일링에 대해 얘기해 봅시다.

여러분도 봤듯, 우리의 인덱스 페이지는 이미 스타일링 작업이 좀 되어 있어요. pages/index.js 파일을 보면 아래와 같은 코드가 보일 겁니다.

<style jsx>{`
  …
`}</style>

이 페이지는 styled-jsx라는 라이브러리를 사용했습니다. 이건 'CSS-in-JS' 라이브러리인데, 리액트 컴포넌트 내에 CSS를 작성할 수 있게 해 주고, CSS 범위는 해당 컴포넌트로 한정되어 집니다. (다른 컴포넌트는 영향 받지 않는다는 뜻)

Next.js는 style-jsx를 내장 지원하지만, styled-components 혹은 emotion과 같은 다른 유명 CSS-in-JS 라이브러리도 사용할 수 있습니다.

Writing and Importing CSS

Next.js는 CSS와 Sass를 내장 지원합니다. .css.scss 파일의 import를 허용해 주죠.

Tailwind CSS와 같은 유명 CSS 라이브러리도 지원합니다.

이 과정에서, 우리는 어떻게 Next.js에서 CSS 파일을 작성하고, import 하는지에 대해 알아볼 겁니다. Next.js의 내장 지원인 CSS Modules과 Sass도 알아볼 거예요.

5. Layout Component

첫 번째로, 모든 페이지에서 사용될 Layout 컴포넌트를 생성해 봅시다.

  • components 라는 이름의 최상위 레벨 폴더를 생성해 주세요.
  • components 안에 layout.js라는 파일을 만들고, 아래의 코드를 복사해 주세요.
export default function Layout({ children }) {
  return <div>{children}</div>
}

그런 다음, pages/posts/first-post.js 파일을 열고, Layout 컴포넌트를 import한 후, 가장 바깥쪽 컴포넌트로 만드세요.

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>
  )
}

Adding CSS

이제, Layout 컴포넌트에 스타일링을 해 봅시다. 리액트 컴포넌트에 CSS 파일을 import 해 주는 CSS Modules를 사용할 겁니다.

components 폴더에 layout.module.css 파일을 생성하고, 아래의 코드를 넣어 주세요.

.container {
  max-width: 36rem;
  padding: 0 1rem;
  margin: 3rem auto 6rem;
}

중요 CSS Modules를 쓰기 위해선, CSS 파일 이름이 반드시 .module.css 로 끝나야 합니다.

container 클래스를 components/layout.js 에서 사용하기 위해선,

  • CSS 파일을 styles 라는 이름으로 import 해 옵니다.
  • styles.containerclassName으로써 사용합니다.

components/layout.js 파일을 열고, 아래 코드로 덮어 씌워 주세요.

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

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

URL로 접속하면, 텍스트가 컨테이너의 중앙에 위치해 있는 걸 볼 수 있습니다.

Automatically Generates Unique Class Names

브라우저의 개발자도구에서 HTML을 본다면, Layout 컴포넌트에 의해 렌더링 된 div의 클래스명이 layout_container__... 와 같은 식으로 되어 있는 게 보일 거예요.

CSS Modules가 그렇게 한 겁니다. 자동적으로 고유한 클래스 명을 생성하거든요. CSS Modules를 사용하는 한, 클래스명 중복 같은 건 걱정하지 않아도 돼요.

더군다나, Next.js의 코드 스플리팅 기능은 CSS Modules에서도 잘 작동합니다. 각 페이지에 대한 최소량의 CSS를 로드해 오는 것을 보장하죠. 이는 곧 작은 번들 사이즈로 귀결됩니다.

CSS Modules는 빌드 타임 때 자바스크립트 번들에서 꺼내져 오고 Next.js에 의해 자동적으로 로드된 .css 파일들을 생성합니다.

6. Global Styles

CSS Modules는 컴포넌트 레벨 스타일에 유용합니다. 하지만 모든 페이지에 사용할 CSS 코드가 필요하다면? 이또한 Next.js는 할 수 있습니다.

전역 CSS 파일을 불러오기 위해선, pages/_app.js 라는 파일을 생성하고 아래의 코드를 넣어 주세요.

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

App 컴포넌트는 다른 페이지들에 공통적으로 적용될 상위 레벨 컴포넌트입니다. 예를 들면, 페이지 이동이 이뤄질 떼 상태 유지를 위해 App 컴포넌트를 사용합니다.

Restart the Development Server

중요: pages/_app.js를 추가하는 경우 개발 서버를 재시작해야 합니다. Ctrl+c를 눌러 서버를 재시작시키세요.

Adding Global CSS

Next.js에서 전역 CSS를 추가하기 위해선 pages/_app.js 에 전역 CSS 파일을 import 해 와서 사용합니다. 아무 곳에서나 전역 CSS를 import 할 수 없습니다. pages/_app.js 가 아닌 곳에서 전역 CSS를 import 할 수 없는 이유는 전역 CSS가 페이지의 모든 엘리먼트에 영향을 끼치기 때문입니다.

만일 메인 페이지에서 /posts/first-post 페이지로 이동한다면, 메인 페이지에 대한 전역 스타일링 코드가 /posts/first-post 에 의도치 않게 영향을 끼칠 수도 있어요.

전역 CSS 파일은 어느 경로에 있어도 되고, 어떤 이름을 써도 좋아요. 따라해 봅시다.

  • styles 라는 상위 폴더 안에 global.css 파일을 생성해 주세요.
  • styles/global.css 파일 안에 아래의 코드를 넣어 주세요. 아래 코드는 몇몇 요소의 스타일을 초기화하고 a 태그의 폰트 색상을 변경합니다.
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를 열고 CSS를 다음과 같이 import 시키세요.

import '../styles/global.css'

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

이제 이 URL로 접속하면, 스타일링이 아래와 같이 적용된 걸 볼 수 있습니다.

작동하지 않는다면, pages/_app.js 파일을 추가하고 개발서버를 재시작했는지 확인해 보세요.

7. Polishing Layout

지금까지 우리는 최소한의 리액트 코드와 CSS 코드를 추가해 왔습니다. 데이터 가져오기라는 다음 과정으로 넘어가기 전에, 우리 페이지의 스타일링과 코드를 다듬어 보죠.

Update components/layout.module.css

components/layout.module.css 파일을 열고, 레이아웃과 프로필 이미지를 위해 좀 더 다듬어 진 아래의 스타일링 코드로 덮어 씌워 주세요.

.container {
  max-width: 36rem;
  padding: 0 1rem;
  margin: 3rem auto 6rem;
}

.header {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.backToHome {
  margin: 3rem 0 0;
}

Create styles/utils.module.css

두 번째로는 타이포그래피와 여러 컴포넌트에서 유용하게 쓰일 CSS 클래스들의 집합을 만들어 봅시다.

styles/utils.module.css 파일을 생성하고 아래의 코드를 넣어 주세요.

.heading2Xl {
  font-size: 2.5rem;
  line-height: 1.2;
  font-weight: 800;
  letter-spacing: -0.05rem;
  margin: 1rem 0;
}

.headingXl {
  font-size: 2rem;
  line-height: 1.3;
  font-weight: 800;
  letter-spacing: -0.05rem;
  margin: 1rem 0;
}

.headingLg {
  font-size: 1.5rem;
  line-height: 1.4;
  margin: 1rem 0;
}

.headingMd {
  font-size: 1.2rem;
  line-height: 1.5;
}

.borderCircle {
  border-radius: 9999px;
}

.colorInherit {
  color: inherit;
}

.padding1px {
  padding-top: 1px;
}

.list {
  list-style: none;
  padding: 0;
  margin: 0;
}

.listItem {
  margin: 0 0 1.25rem;
}

.lightText {
  color: #666;
}

Update components/layout.js

세 번째로, components/layout.js 를 아래의 코드로 덮어 씌운 다음 Your Name 을 당신의 이름으로 변경해 주세요.

import Head from 'next/head'
import Image from 'next/image'
import styles from './layout.module.css'
import utilStyles from '../styles/utils.module.css'
import Link from 'next/link'

const name = 'Your Name'
export const siteTitle = 'Next.js Sample Website'

export default function Layout({ children, home }) {
  return (
    <div className={styles.container}>
      <Head>
        <link rel="icon" href="/favicon.ico" />
        <meta
          name="description"
          content="Learn how to build a personal website using Next.js"
        />
        <meta
          property="og:image"
          content={`https://og-image.vercel.app/${encodeURI(
            siteTitle
          )}.png?theme=light&md=0&fontSize=75px&images=https%3A%2F%2Fassets.vercel.com%2Fimage%2Fupload%2Ffront%2Fassets%2Fdesign%2Fnextjs-black-logo.svg`}
        />
        <meta name="og:title" content={siteTitle} />
        <meta name="twitter:card" content="summary_large_image" />
      </Head>
      <header className={styles.header}>
        {home ? (
          <>
            <Image
              priority
              src="/images/profile.jpg"
              className={utilStyles.borderCircle}
              height={144}
              width={144}
              alt={name}
            />
            <h1 className={utilStyles.heading2Xl}>{name}</h1>
          </>
        ) : (
          <>
            <Link href="/">
              <a>
                <Image
                  priority
                  src="/images/profile.jpg"
                  className={utilStyles.borderCircle}
                  height={108}
                  width={108}
                  alt={name}
                />
              </a>
            </Link>
            <h2 className={utilStyles.headingLg}>
              <Link href="/">
                <a className={utilStyles.colorInherit}>{name}</a>
              </Link>
            </h2>
          </>
        )}
      </header>
      <main>{children}</main>
      {!home && (
        <div className={styles.backToHome}>
          <Link href="/">
            <a>← Back to home</a>
          </Link>
        </div>
      )}
    </div>
  )
}

뭐가 새로 생긴 걸까요?

  • 페이지 컨텐츠를 설명하기 위해 사용되는 og:image 와 같은 meta 태그들
  • boolean 값을 가진 home 이라는 prop은 타이틀과 이미지 사이즈를 조정하는 데에 사용됩니다.
  • homefalse 라면 "Back to home" 링크는 하단에 위치합니다.
  • next/image 로 추가된 이미지는 priority 속성 덕에 사전에 로드됩니다.

Update pages/index.js

마지막으로, 메인 페이지를 수정해 봅시다.

pages/index.js 파일을 열고 아래의 코드를 덮어 씌워 주세요.

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

export default function Home() {
  return (
    <Layout home>
      <Head>
        <title>{siteTitle}</title>
      </Head>
      <section className={utilStyles.headingMd}>
        <p>[Your Self Introduction]</p>
        <p>
          (This is a sample website - you’ll be building a site like this on{' '}
          <a href="https://nextjs.org/learn">our Next.js tutorial</a>.)
        </p>
      </section>
    </Layout>
  )
}

[Your Self Introduction] 라는 텍스트를 여러분의 소개로 바꿔 주세요. 예시를 보여 드리죠.

끝이에요! 이제 우린 데이터 가져오기 레슨으로 넘어가기 위한 정돈된 레이아웃 코드를 갖추게 되었어요.

과정을 마무리하기 전에, 다음 페이지에서 Next.js의 CSS 내장 기능과 관련된 유용한 기술 몇 가지를 얘기해 볼게요.

8. Styling Tips

스타일링에 대한 몇 가지 유용한 팁입니다.

이 섹션은 읽고만 넘어가도 괜찮습니다. 실습 중인 앱을 변경할 필요 없어요!

Using classnames library to toggle classes

classnames 는 간단히 클래스명 토글을 구현해 주는 라이브러리입니다. npm install classnames 혹은 yarn add classnames 라는 명령어로 설치하면 됩니다.

기본적인 사용법은 이곳에서 보면 되지만, 자세한 내용은 이 문서를 참고하세요.

  • 당신은 sucesserror 가 될 수 있는 type 값을 갖는 Alert 컴포넌트를 만들고 싶어 한다고 가정해 봅시다.
  • success 일 때는 텍스트 색상을 초록색으로, error 일 때는 빨간색으로 변경하길 원합니다.

먼저 CSS 묘듈(e.g. alert.module.css)에 해당 코드를 작성합니다.

.success {
  color: green;
}
.error {
  color: red;
}

그리고 classnames 는 아래와 같이 사용합니다.

import styles from './alert.module.css'
import cn from 'classnames'

export default function Alert({ children, type }) {
  return (
    <div
      className={cn({
        [styles.success]: type === 'success',
        [styles.error]: type === 'error'
      })}
    >
      {children}
    </div>
  )
}

Customizing PostCSS Config

Next.js는 PostCSS를 사용하여 configuration 없이 CSS를 컴파일합니다.

PostCSS config를 커스텀하기 위해선 상위 레벨에 postcss.config.js 라는 파일을 생성해야 합니다. 이건 Tailwind CSS 라이브러리를 사용하는 경우에도 유용합니다.

아래는 Tailwind CSS를 추가하는 방법이니다. 먼저 패키지를 설치해 주세요.

npm install -D tailwindcss autoprefixer postcss

그리고, postcss.config.js 파일을 생성합니다.

// postcss.config.js
module.exports = {
  plugins: {
    tailwindcss: {},
    autoprefixer: {}
  }
}

tailwind.config.jscontent 옵션에 configuring content sources를 명시할 것을 추천합니다.

// tailwind.config.js
module.exports = {
  content: [
    './pages/**/*.{js,ts,jsx,tsx}',
    './components/**/*.{js,ts,jsx,tsx}'
    // For the best performance and to avoid false positives,
    // be as specific as possible with your content configuration.
  ]
}

Using Sass

Next.js에서는 .scss.sass 확장자의 Sass 파일이 import 가능합니다. CSS Modules와 .module.scss 혹은 .module.sass 확장자 파일을 통해 컴포넌트 레벨의 Sass를 사용할 수 있습니다.

Next.js의 Sass 내장 지원 기능을 사용하기 이전에, sass 를 꼭 설치해 주세요.

npm install -D sass
profile
개발할래요💻

0개의 댓글