본문 바로가기
학습 내용/Front-End

[Next.js] Next.js에서 CSS 사용하기

by yein 2021. 10. 3.

📟 Next.js 문서의 "Built-In CSS Support" 부분을 번역한 것으로 오역이 있을 수 있습니다. (원문: https://nextjs.org/docs/basic-features/built-in-css-support)

 

Next.js에선 자바스크립트 파일에서 CSS를 import 해올 수 있습니다. 이는 Next.js가 import의 개념을 자바스크립트의 것 이상으로 확장하기 때문입니다.

 

[전역 스타일시트(global stylesheet) 추가하기]

  • 애플리케이션에 스타일시트를 전역으로 추가하려면, pages/_app.js 파일에 CSS를 import 해오세요.
  • 예를 들어, 아래와 같은 style.css라는 이름의 스타일시트가 있다고 합시다.
    /* styles.css */
    body {
      font-family: 'SF Pro Text', 'SF Pro Icons',
      		'Helvetica Neue', 'Helvetica',
        		'Arial', sans-serif;
      padding: 20px 20px 60px;
      max-width: 680px;
      margin: 0 auto;
    }​
  • 그럼 이제 아래와 같이 pages/_app.js 파일에서 style.css 파일을 import 해오세요.
    // pages/_app.js
    import '../styles.css'
    
    export default function MyApp({ Component, pageProps }) {
      return <Component {...pageProps} />
    }​
  • 이렇게 불러온 스타일들은 우리 애플리케이션의 모든 페이지와 컴포넌트에 적용이 됩니다. 스타일시트의 전역적 특성을 고려하고, 충돌을 방지하기 위해, pages/_app.js 파일에서만 이와 같은 방식으로 스타일시트를 import 해올 수 있습니다.
  • 개발 과정에서 이와 같은 방식을 사용할 경우, 스타일시트를 수정할 때마다 핫 리로드되기 때문에 애플리케이션의 상태를 유지할 수 있습니다.
  • 배포 시에는 모든 CSS 파일이 minified된 하나의 .css 파일로 자동적으로 연결될 것입니다.

 

node_modules로부터 스타일 불러오기

  • Next.js 9.5.4부터는 애플리케이션의 어디에서든지 node_modules로부터 CSS 파일을 import 해올 수 있습니다.
  • 예를 들어 써드 파티 컴포넌트에 필요한 CSS는 아래와 같이 컴포넌트 단위에서 import 해올 수 있습니다.
    // components/ExampleDialog.js
    import { useState } from 'react'
    import { Dialog } from '@reach/dialog'
    import VisuallyHidden from '@reach/visually-hidden'
    import '@reach/dialog/styles.css'
    
    function ExampleDialog(props) {
      const [showDialog, setShowDialog] = useState(false)
      const open = () => setShowDialog(true)
      const close = () => setShowDialog(false)
    
      return (
        <div>
          <button onClick={open}>Open Dialog</button>
          <Dialog isOpen={showDialog} onDismiss={close}>
            <button className="close-button" onClick={close}>
              <VisuallyHidden>Close</VisuallyHidden>
              <span aria-hidden>×</span>
            </button>
            <p>Hello there. I am a dialog</p>
          </Dialog>
        </div>
      )
    }​
  • 다만 bootstrap(프론트엔드 프레임워크), nprogress(progress bar 라이브러리)와 같은 전역 스타일시트의 경우에는 아래와 같이 pages/_app.js 파일에서 스타일시트를 import 해야 합니다.
    // pages/_app.js
    import 'bootstrap/dist/css/bootstrap.css'
    
    export default function MyApp({ Component, pageProps }) {
      return <Component {...pageProps} />
    }​

 

[컴포넌트 레벨의 CSS 추가하기]

  • Next.js는 CSS 모듈도 지원하는데요, CSS 파일 이름을 지을 때 아래의 네이밍 컨벤션에 따라 작성하면 됩니다.
    [name].module.css​
    * CSS 모듈: CSS 모듈은 모든 클래스 이름과 애니메이션 이름이 기본적으로 지역 범위(scoped locally) 내에 정의되는 CSS 파일을 의미한다. (자세한 사용 방법 및 개념 참고)
  • CSS 모듈 방식을 사용하면 알아서 유니크한 클래스명이 생성되어 CSS가 지역 스코프를 갖게 됩니다. 즉, 서로 다른 CSS 모듈 파일에서 동일한 클래스명을 짓더라도 그 둘이 충돌될 걱정을 하지 않아도 되는 것입니다.
  • 이와 같은 CSS 모듈은 컴포넌트 레벨의 CSS를 추가할 수 있는 이상적인 방법으로, CSS 모듈 파일은 애플리케이션 어디에서든지 import 해올 수 있습니다.
  • 다음의 예제를 봅시다. components/ 폴더 안에 재사용이 가능한 Button 컴포넌트를 만들고자 합니다. 우선은 components/Button.module.css 파일을 아래와 같이 만들어줍니다.
    /*
    .error가 다른 css 파일 또는 module.css 파일과
    충돌하지 않을지 걱정하지 않아도 됩니다.
    */
    .error {
      color: white;
      background-color: red;
    }​
  • 이제, 위의 CSS 파일을 불러와서 components/Button.js 파일을 만들어줍시다.
    import styles from './Button.module.css'
    
    export function Button() {
      return (
        <button
          type="button"
          className={styles.error}
        >
          파괴하기
        </button>
      )
    }​
    
    // "error" 클래스는 CSS 모듈 파일로부터 import 해온
    // styles 객체의 프로퍼티로서 접근할 수 있습니다.
  • CSS 모듈 방식은 선택적인 기능이며, .module.css 확장자를 가진 파일에 한하여 가능합니다. 물론 일반적인 <link> 스타일시트와 전역 CSS 파일도 여전히 지원됩니다.
  • 배포 시에는 자동적으로 모든 CSS 모듈 파일들이 minified 되고 code-split 된 여러 개의 css 파일로 연결될 것입니다. 이 css 파일들은 애플리케이션에서 hot execution paths(즉각적인? 실행 경로)를 나타내며, 애플리케이션이 그려야 할 최소한의 CSS가 확실하게 로드될 수 있도록 합니다.

 

[Sass 지원]

  • Next.js에선 .scss.sass 확장자를 통해 Sass를 사용할 수 있습니다. 뿐만 아니라 .module.scss와 .module.sass 확장자를 통해 CSS 모듈 방식의 컴포넌트 레벨 Sass도 사용할 수 있습니다.
    * Sass는 확장자에 따라 다음의 두 가지의 문법을 지원한다. .scss 확장자의 경우 SCSS Syntax를 따라야 하며, .sass 확장자의 경우 Sass라고 불리는 Indented Syntax를 따라야 한다. 만약 어느 것부터 시작해야 할지 모르겠다면, CSS의 수퍼셋(superset, 상위확장)인 .scss 확장자부터 시작하는 것을 제안한다. .sass 확장자의 경우 Indented Syntax를 따로 학습해야 하기 때문이다. (참고)
  • 이러한 Next.js의 Sass 지원 기능을 이용하기 전엔 반드시 sass를 사전에 설치해야 합니다.
    npm install sass​
  • 여태까지 언급한 Next.js의 CSS 관련 지원 기능과 마찬가지의 부분들(사용 가능 기능, 제한 기능 등)이 Sass 사용 시에도 적용이 됩니다.

 

Sass 옵션 커스텀하기

  • 아래와 같이 next.config.js에서 sassOptions를 사용하여 Sass 컴파일러에 대한 설정을 할 수 있습니다.
    const path = require('path')
    
    module.exports = {
      sassOptions: {
        includePaths: [path.join(__dirname, 'styles')],
      },
    }​

 

[CSS-in-JS]

CSS-in-JS의 대표적인 예: Styled JSX, Styled Components, Emotion, Tailwind CSS + Emotion 등
  • 현존하는 어떠한 종류의 CSS-in-JS든지 간에 Next.js에서 사용할 수 있습니다. 가장 단순한 방법은 아래와 같이 인라인 스타일로 작성하는 것입니다.
    function HiThere() {
      return <p style={{ color: 'red' }}>hi there</p>
    }
    
    export default HiThere
  • Next.js는 각각의 독립적인 스코프를 갖는 CSS를 지원하기 위해, styled-jsx를 번들링합니다.
  • 다양한 CSS-in-JS가 있는데요, Next.js에서 이것들이 각각 어떻게 사용되는지에 대한 예제는 여기를 참고해주세요.
  • 하나만 간단히 소개해드리자면, styled-jsx를 사용한 컴포넌트는 아래와 같습니다.
    function HelloWorld() {
      return (
        <div>
          Hello world
          <p>scoped!</p>
          <style jsx>{`
            p {
              color: blue;
            }
            div {
              background: red;
            }
            @media (max-width: 600px) {
              div {
                background: blue;
              }
            }
          `}</style>
          <style global jsx>{`
            body {
              background: black;
            }
          `}</style>
        </div>
      )
    }
    
    export default HelloWorld​