[번역] Next.js 시작하기 3. Assets, Metadata, and CSS

여름노래불러줘·2020년 5월 10일
2

1.

현재 우리가 추가해 넣은 두번째 페이지는 스타일링이 없습니다. CSS를 조금 추가해서 페이지 스타일을 지정해보죠.

Next.js 는 CSS와 Sass 를 기본적으로 지원합니다.
이 코스의 목적을 위해 우리는 CSS 를 사용할 것입니다.

또한, 이 레슨에서 Next.js 가 이미지와 정적 정보 및 'title' 태그와 같은 페이지 메타데이터들을 어떻게 핸들링 하는지 이야기해줄 것입니다.

이 레슨에서 배울 것들

이 레슨에서 이것들을 해 볼 겁니다:

  • Next.js 에 정적 파일(이미지 등)을 추가하는 방법
  • 각 페이지의 <head> 내부에 들어갈 내용을 커스터마이징 하는 방법
  • CSS모듈을 사용해 스타일된 재사용 가능한 React 컴포넌트를 만드는 방법.
  • 'pages/_app.js' 내에 글로벌 CSS를 추가하는 방법
  • Next.js에서 스타일링을 위한 몇가지 쓸만한 팁

세부적인 Next.js의 스타일링 도큐먼테이션을 찾고 있다면, CSS 도큐먼테이션을 보세요.

2.

이전 레슨부터 계속하고 있다면, 이 페이지를 건너뛰어도 됩니다. 3. 으로 이동하세요.

스타터 코드 다운로드(선택적)
이전 레슨부터 계속하고 있지 않다면, 이 레슨 아래의 스타터 코드를 다운로드, 설치 및 실행할 수 있습니다. 이전 레슨의 결과와 동일하게 'Next-js-blog' 디렉토리를 설정합니다.

다시, 만약 당신이 이전 레슨을 완료했다면 이 작업은 필요하지 않습니다.

npm init next-app nextjs-blog --example "https://github.com/zeit/next-learn-starter/tree/master/assets-metadata-css-starter"

그리고 커맨드 출력의로부터의 명령을 따라하세요. ('cd'로 디렉토리로 이동한 다음, 개발 서버를 시작하세요)

3.

정보 제공

먼저, Next.js가 이미지와 같은 정적 자산을 핸들하는 방법에 대해 이야기 하겠습니다.

Next.js 는 최상위 'public' 디렉토리 밑에 이미지와 같은 정적 파일을 제공할 수 있습니다. 'public' 내의 파일들은 'pages' 와 비슷한 앱의 루트에서 참조될 수 있습니다.

당신의 앱에서 'pages/index.js' 를 열고, <footer>를 보세요. 이렇게 로고 이미지를 참조합니다.

Powered by <img src="..." alt="..." />

이 로고 이미지는 당신의 앱 최상위 디렉토리 'public' 내에 있습니다.

'public' 디렉토리는 'robots'txt', 구글 사이트 확인 및 어떤 정작 자산에도 유용합니다.
정적 파일 제공 도큐먼테이션을 확인해 더 학습해보세요.

4.

메타데이터

<title> HTML 태그와 같은, 페이지의 메타데이터를 수정하고 싶다면?

<title> 은 <head> HTML 태그의 일부입니다, 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> 를 수정할 수 있게 해주죠.

'next/head' 모듈로부터 <Head> 컴포넌트를 import 할 수 있습니다.

'first-post.js' 에 <Head> 추가하기

'/posts/first-post' 라우트에 <title>을 추가하지 않았습니다. 하나 추가해보죠.

'pages/posts/first-post.js' 파일을 여세요.

먼저, 'next/head'로 부터 'Head'를 import 하세요.

import Head from 'next/head'

그 다음, 'FirstPost' 컴포넌트에 추가하세요. 지금은 그냥 'title' 태그를 추가할 것입니다:

export default function FirstPost() {
  return (
    <>
      <Head>
        <title>First Post</title>
      </Head>
      …
    </>
  )
}

http://localhost:3000/posts/first-post 에 접속해보세요. 이제 브라우저 탭이 "First Post" 를 보여줘야 합니다. 브라우저의 개발자 도구를 사용해 'title'태그가 <head> 내에 추가 된것을
보세요.

'next/head'에 대해 더 학습해봅시다. API 레퍼런스 도큐먼테이션을 확인해보세요.

예를 들어 'lang' 속성을 <html> 태그에 추가하는 커스터마이징을 하고 싶다면, 커스텀 컴포넌트 'Document' 를 생성하는 것으로 이 작업을 할 수 있습니다. API 레퍼런스 도큐먼테이션에서 더 학습해보세요.

5.

CSS 스타일링

이제 CSS 스타일링에 대해서 이야기 해봅시다.
볼 수 있듯, 우리의 인덱스 페이지에는 이미 조금 스타일링이 되어있습니다. 'pages/index.js' 에서 이런 코드를 보세요:

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

이것은 styled-jsx 라이브러리를 사용한 것입니다. 이것은 "CSS-in'JS" 라이브러리 입니다. CSS를 포함해 React 컴포넌트를 작성해보죠. 그리고 CSS 스타일의 범위가 지정될 것입니다. (다른 컴포넌트들은 영향을 받지 않습니다.)

CSS 작성하기와 가져오기

Next.js는 '.css' 와 '.scss' 파일들을 가져올 수 있는 CSS와 Sass 를 기본적으로 지원합니다.

Tailwind CSS 같은 인기 있는 라이브러리를 사용하는 것도 지원됩니다.

이번 레슨에서 우리는 Next.js 앱에 CSS를 작성하는 방법과 CSS 파일을 가져오는 방법에 대해서 이야기 할 것입니다. 또한 CSS 모듈과 Sass에 대한 NEx.js의 기본 지원에 대해서도 이야기 할 것입니다.

6.

레이아웃 컴포넌트

먼저, 모든 페이지에서 공통으로 사용될 레이아웃 컴포넌트를 만들어 봅시다.

  • 최상위 디렉토리에 'components' 폴더를 만드세요.
  • 그 안에, 'layout.js' 파일을 만들고 아래와 같이 작성하세요:
function Layout({ children }) {
  return <div>{children}</div>
}

export default Layout

그리고 'Layout' 을 'pages/posts/first-post.js' 내에 가져오고, 가장 최상위 컴포넌트로 만드세요.

CSS 추가

이제, 'Layout' 컴포넌트를 위한 스타일을 추가해봅시다. 이걸 하기 위해 CSS 모듈을 사용할 것입니다. CSS 모듈은 CSS 파일을 React 컴포넌트에 가져올 수 있게 해줍니다.

'components' 디렉토리 안에 'layout.module.css' 파일을 만들고, 그 안에 다음과 같이 내용을 채우세요:

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

중요: CSS 모듈을 사용하기 위해서, CSS파일 이름은 반드시 'module.css' 로 끝아야 합니다.

'Layout' 안에서 이것을 사용하려면, 이 작업들을 해야합니다.

  • 'styles' 라는 이름으로 import 하세요.
  • 'styles.<class-name> 을 'className' 으로 사용하세요.
  • 이 경우, 클래스 이름은 'container' 입니다. 그래서 'styles.container' 를 사용할 것입니다.
import styles from './layout.module.css'

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

이제 http://localhost:3000/posts/first-post 에 방문해보면, 텍스트가 가운데 위치한 컨테이너 안에 있는 것이 보일 것입니다.

자동으로 고유한 클래스 이름을 생성

이제 브라우저의 개발자 도구 안에서 HTML 태그를 보면, 'div' 태그가 'layout_container__...'. 같은 이름을 가지고 있는 것을 볼 수 있습니다.

이것이 CSS 모듈이 하는 일입니다: CSS 모듈을 사용하는 한 자동으로 고유한 클래스 이름을 생성합니다. 클래스 이름에 대한 충돌을 걱정할 필요가 없습니다.

더욱이, Next.js의 코드 스플리팅 기능은 CSS 모듈에서도 잘 작동합니다. 이것은 각 페이지에서 필요한 CSS 의 로드가 최소량으로 되는 것을 보장합니다. 그 결과 번들 사이즈가 더 작아집니다.

CSS 모듈은 빌드시 자바스크립트 번들로부터 추출되고, Next.js 에 의해 자동으로 로드되는 .css파일을 생성합니다.

7.

글로벌 스타일

CSS 모듈은 컴포넌트-레벨 스타일에 유용합니다. 그러나 모든 페이지에 로드될 CSS를 사용하려면, Next.js는 그것 또한 잘 지원합니다.

글로벌 CSS 파일을 로드하기 위해 'pages' 디렉토리 밑에 '_app.js' 파일을 만들고, 아래와 같이 내용을 채워넣으세요:

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

'App' 컴포넌트는 다른 모든 페이지에서 공통으로 사용할 최상위 레벨 컴포넌트 입니다. 예를 들면 이 'App' 컴포넌트를 사용해 페이지 간을 탐색할 때, 컴포넌트의 state 를 유지할 수 있습니다.

개발서버 재시작 하기

중요: '_app.js'를 추가 할때는 ctrl+c 를 눌러 개발서버를 멈추고 아래 명령어를 입력해 개발서버를 재시작해야 합니다.

npm run dev

글로벌 CSS 추가

Next.js 에서는, '_app.js' 로부터 글로벌 CSS 파일들을 가져와 추가할 수 있습니다. 글로벌 CSS는 다른 곳에서 가져올 수 없습니다.

'_app.js' 의 외부에서 글로벌 CSS를 가져올 수 없는 이유는 글로벌 CSS가 페이지의 모든 엘리먼트에 영향을 끼치기 때문입니다.

홈페이지에서 'posts/first-post' 페이지로 이동 하면, 홈페이지에서의 글로벌 스타일이 의도치 않게 'posts/first-post' 에 영향을 줍니다.

  • 최상위에 '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;
}

드디어, 이것을 '_app.js' 에서 가져오세요:

import '../styles/global.css'

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

이제, http://localhost:3000/posts/first-post, 에 접근하면, 이 스타일이 적용된 것을 볼 수 있습니다:

안됐다면: '_app.js'를 추가할 때, 개발서버를 다시 시작했는지 확인하세요.

우리가 지금까지 배운 것을 요약:

  • CSS 모듈을 사용하려면, 컴포넌트에 '*.module.css' 의 이름을 가진 CSS 파일 가져오기
  • 글로벌 CSS를 사용하려면, 'pages/_app.js'에 CSS 파일을 가져오기

8.

레이아웃 연마하기

지금까지 우리는 CSS 모듈과 같은 개념을 설명하기 위해 오직 최소한의 React 와 CSS 코드를 추가했습니다. 다음 레슨(데이터 가져오기)으로 이동하기전에, 우리의 페이지 스타일링과 코드를 갈고 닦아보죠.

프로필 사진을 다운로드 하세요

첫째, 우리는 최종 디자인을 위해 당신의 프로필 사진을 사용할 것입니다.

  • 깃헙, 트위터, 링크드인 등 어디서든지 당신의 프로필 사진을 다운받으세요. (혹은 이 파일을 쓰세요).
  • 'public' 디렉토리 안에 'images' 디렉토리를 생성하세요.
  • 'pubic/images' 디렉토리 안에 'profile.jpg' 라는 이름으로 사진을 저장하세요.
  • 이미지의 크기는 약 400*400px 입니다.
  • 'public' 디렉토리 밑의 사용되지 않은 SVG 로고 파일은 제거해도 됩니다.

'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;
}

.headerImage {
  width: 6rem;
  height: 6rem;
}

.headerHomeImage {
  width: 8rem;
  height: 8rem;
}

.backToHome {
  margin: 3rem 0 0;
}

'styles/utils.module.css' 생성하기

셋째, 타이포그래피와 여러 컴포넌트에 유용하게 사용될 CSS 클래스를 만듭시다.

'styles/utils/module.css' 에 아래의 코드를 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: #999;
}

'components/layout.js' 업데이트하기

넷째, 아래의 코드를 'components/layout.js'에 복사하세요. 그리고 상단의 'Your Name' 을 당신의 이름으로 바꾸세요. 새로운 것들은 다음과 같습니다:

  • 'meta' 태그('og: image' 같은)
  • 제목과 이미지를 조정할 Boolean 값 'home' prop
  • home 이 false 일 경우 하단에 "Back to home" 링크
import Head from 'next/head'
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.now.sh/${encodeURI(
            siteTitle
          )}.png?theme=light&md=0&fontSize=75px&images=https%3A%2F%2Fassets.zeit.co%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 ? (
          <>
            <img
              src="/images/profile.jpg"
              className={`${styles.headerHomeImage} ${utilStyles.borderCircle}`}
              alt={name}
            />
            <h1 className={utilStyles.heading2Xl}>{name}</h1>
          </>
        ) : (
          <>
            <Link href="/">
              <a>
                <img
                  src="/images/profile.jpg"
                  className={`${styles.headerImage} ${utilStyles.borderCircle}`}
                  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>
  )
}

'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 지원과 관련된 도움이 될만한 기술에 대해 이야기 해봅시다.

9.

스타일링 팁들

도움이 될만한 스타일링 팁 몇 가지 입니다. 그냥 섹션을 따라 읽기만 하면 됩니다. 우리의 앱을 바꿀 필요가 없습니다!

클래스들을 토글하기 위한 'classnames' 라이브러리 사용

'classnames'은 클래스의 이름을 쉽게 토글할 수 있게 해주는 라이브러리 입니다. 'npm intall classnames' 이나 'yarn add calssnames' 를 사용해 설치할 수 있습니다.

자세한 내용을 README를 참조하십시오. 하지만 여기 몇가지 기본적인 사용법이 있습니다:

  • 'success' 또는 'error' 를 'type'으로 허용하는 'Alert' 컴포넌트를 만들고 싶다고 가정합니다.
  • 'success' 면 텍스트의 색상을 초록색으로, 'error' 면 텍스트의 색상을 빨강색으로 바꾸고 싶다면

먼저 CSS 모듈(예를들면 alert.module.css)을 이렇게 작성할 수 있습니다.

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

그리고 'classname' 을 이렇게 사용하세요.

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

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

PostCSS 설정 커스터마이징

Next.js는 설정 없이 PostCSS를 사용해 CSS를 바로 컴파일 합니다.

PostCSS 설정을 커스터마이징 하려면, 최상위 파일 'postcss.config.js'라는 최상위 레벨의 파일을 만들어야 합니다. TailwindCSS 같은 라이브러리를 사용한다면 이것은 유용합니다.

사용되지 않은 CSS를 제거하는 'purgecss' 와 함께 Tailwind CSS 를 사용하기 위한 'postcss.config.js' 의 예제가 있습니다.

-'tailwindcss', '@fullhuman/postcss-purgecss', 그리고 'postcss-preset-env' 를 설치해야 합니다.

  • 'autoprefixer'는 필요 없습니다. Next.js가 기본으로 포함하고 있기 때문 입니다.
module.exports = {
  plugins: [
    'tailwindcss',
    ...(process.env.NODE_ENV === 'production'
      ? [
          [
            '@fullhuman/postcss-purgecss',
            {
              content: [
                './pages/**/*.{js,jsx,ts,tsx}',
                './components/**/*.{js,jsx,ts,tsx}'
              ],
              defaultExtractor: content =>
                content.match(/[\w-/:]+(?<!:)/g) || []
            }
          ]
        ]
      : []),
    'postcss-preset-env'
  ]
}

PostCSS 설정에 대해 더 알아보려면 우리의
도큐먼테이션을 확인하십시오.

Sass 사용

Next.js는 별도의 설정 없이 Sass 를 import 하여 '.scss'와 '.sass' 익스텐션을 둘 다 사용할 수 있습니다. CSS 모듈을 통해 컴포넌트 레벨 Sass를 사용할 수 있습니다. 'module.scss' 나 'module.sass' 익스텐션 또한 가능합니다.

Next.js의 내장 Sass 지원을 사용하기 전 sass를 설치하십시오.

npm install sass

이게 이번 레슨을 위한 전부 입니다!

Next.js의 내장 CSS 지원과 CSS모듈에 대해 더 학습하려면, 도큐먼테이션을 참고하십시오.

0개의 댓글