티스토리 뷰

반응형

목차

Next js 튜토리얼 7편 : 컴포넌트 스타일링  - 현재 글

Next js 튜토리얼 8편 : 배포 

Styling Components

지금까지 컴포넌트의 스타일링을 많이 하지 않았습니다. 하지만 앱에는 스타일이 필요합니다.
리엑트 앱에는 스타일을 적용하는 많은 기술들이 있으며, 크게 두가지의 방법으로 분류할 수 있습니다

1. 전통적인 css 파일 기반에 스타일링 (SASS, PostCSS 등)

2. CSS in Js 스타일링


전통적인 css 파일에는 고려해야하는 문제들이 많이 있으므로(특히 SSR에서) Next.js에서는 이 방법을 사용하지 않는 것이 좋습니다.

CSS파일을 import 하는 것보다 각각의 컴포넌트의 스타일을 지정할 수 있는 CSS in Js를 권장합니다

Next.js에는 styled-jsx 라는 CSS 프레임워크가 준비되어 있습니다. 컴포넌트에 CSS 규칙을 사용할 수 있으며, 다른 컴포넌트에 영항을 주지 않습니다.


(개인적으로는 styled-component를 주로 사용합니다. 

styled-component 적용 방법은 https://jcon.tistory.com/118?category=798379 에서 확인 할 수 있습니다)

Setup

아래의 예제를 다운로드 해주세요
git clone https://github.com/zeit/next-learn-demo.git
cd next-learn-demo
cd 7-styling-components

npm install
npm run dev


Styling our home page

'pages/index.js'에 스타일을 추가해 봅시다
아래의 코드를 추가해 주세요

import Layout from '../components/MyLayout'
import Link from 'next/link'

function getPosts() {
  return [
    { id: 'hello-nextjs'title: 'Hello Next.js' },
    { id: 'learn-nextjs'title: 'Learn Next.js is awesome' },
    { id: 'deploy-nextjs'title: 'Deploy apps with ZEIT' }
  ]
}

export default function Blog() {
  return (
    <Layout>
      <h1>My Blog</h1>
      <ul>
        {getPosts().map(post => (
          <li key={post.id}>
            <Link href="/p/[id]" as={`/p/${post.id}`}>
              <a>{post.title}</a>
            </Link>
          </li>
        ))}
      </ul>
      <style jsx>{`
        h1,
        a {
          font-family: 'Arial';
        }

        ul {
          padding: 0;
        }

        li {
          list-style: none;
          margin: 5px 0;
        }

        a {
          text-decoration: none;
          color: blue;
        }

        a:hover {
          opacity: 0.6;
        }
      `}</style>
    </Layout>
  )
}


<style jsx>요소를 살펴 봅시다. 이곳에 우리는 css규칙을 사용했습니다

저장 후 home 페이지를 확인 해보면 css가 적용된 것을 확인 할 수 있습니다.


style 태그의 안에 직접적으로 css를 사용하지 않고, template string( `{` `}` )의 안쪽에 작성하였습니다

template string을 사용하지 않는다면 작동하지 않습니다


Styling Components

Styled jsx는 바벨 플러그인으로 작동합니다. css의 모드 것을 파싱하고 빌드 할 때 적용이 됩니다.
CSS가 template string안에 들어가야 하는 이유는 동적인 변수 또한 지원하기 때문입니다

Styles and Nested Components

home 페이지에 작은 변화를 줍시다. 아래의 코드를 pages/index.js에 작성하세요

import Layout from '../components/MyLayout'
import Link from 'next/link'

function getPosts() {
  return [
    { id: 'hello-nextjs'title: 'Hello Next.js' },
    { id: 'learn-nextjs'title: 'Learn Next.js is awesome' },
    { id: 'deploy-nextjs'title: 'Deploy apps with ZEIT' }
  ]
}

const PostLink = ({ post }) => (
  <li>
    <Link href="/p/[id]" as={`/p/${post.id}`}>
      <a>{post.title}</a>
    </Link>
  </li>
)

export default function Blog() {
  return (
    <Layout>
      <h1>My Blog</h1>
      <ul>
        {getPosts().map(post => (
          <PostLink key={post.id} post={post} />
        ))}
      </ul>
      <style jsx>{`
        h1,
        a {
          font-family: 'Arial';
        }

        ul {
          padding: 0;
        }

        li {
          list-style: none;
          margin: 5px 0;
        }

        a {
          text-decoration: none;
          color: blue;
        }

        a:hover {
          opacity: 0.6;
        }
      `}</style>
    </Layout>
  )
}


ul 태그 안의 내용을 함수형 컴포넌트로 빼서 작성했습니다. 저장 후 확인 해보면 함수형 컴포넌트(PostLink)에 css가 적용되지 않는 것을 확인 할 수 있습니다. 즉, style-jsx는 하위 컴포넌트에 영향을 주지 않습니다. 이 기능은 큰 사이즈의 앱을 관리할 때 도움이 됩니다


이렇게 컴포넌트가 분리되어 있으면 PostLink에도 아래와 같이 스타일을 지정해 주어야 합니다


const PostLink = ({ post }) => (
  <li>
    <Link href="/p/[id]" as={`/p/${post.id}`}>
      <a>{post.title}</a>
    </Link>
    <style jsx>{`
      li {
        list-style: none;
        margin: 5px 0;
      }

      a {
        text-decoration: none;
        color: blue;
        font-family: 'Arial';
      }

      a:hover {
        opacity: 0.6;
      }
    `}</style>
  </li>
);


또는 global selectors를 사용할 수 있습니다


Global Styles

가끔은 자식 컴포넌트의 안에서 스타일을 바꿔야 할 때가 있습니다. 특히 리엑트에서 마크다운을 사용해야 할 때 그렇습니다. 
'pages/p/p[id].js'에 아래의 코드를 작성해 주세요
다음으로 진행하기 전에 react-markdown 를 설치해주세요
npm install --save react-markdown

import { useRouter } from 'next/router'
import Markdown from 'react-markdown'
import Layout from '../../components/MyLayout'

export default () => {
  const router = useRouter()
  return (
    <Layout>
      <h1>{router.query.id}</h1>
      <div className="markdown">
        <Markdown
          source={`
This is our blog post.
Yes. We can have a [link](/link).
And we can have a title as well.

### This is a title

And here's the content.
      `}
        />
      </div>
      <style jsx global>{`
        .markdown {
          font-family: 'Arial';
        }

        .markdown a {
          text-decoration: none;
          color: blue;
        }

        .markdown a:hover {
          opacity: 0.6;
        }

        .markdown h3 {
          margin: 0;
          padding: 0;
          text-transform: uppercase;
        }
      `}</style>
    </Layout>
  )
}

저장 후 확인 해보면 markdown 아래의 a 태그 등에 스타일이 적용된 것을 확인 할 수 있습니다


Global Styles Work

이는 global로 스타일을 지정했기 때문에 작동합니다. 
이 기능은 유용할 수는 있지만 global스타일 보단 scoped 스타일을 사용하는 것을 권장합니다

평범한 스타일 태그를 사용하는 것보다는 좋은 방법입니다. sryled-jsx를 사용하면 바벨 플러그인 안에서 필요한 브라우저 prefixing과 css가 검증이 완료 됨으로 추가적인 overhead시간이 들어 가지 않습니다

What Next

우리는 styled-jsx까지 Next.js의 기초적인 내용을 학습했습니다. 

styled-jsx에 대해 자세히 알고 싶다면  styled-jsx 깃허브 repo를 참고하세요

other styling solutions와 같은 다른 방법도 있습니다. 한번 확인해 보면 좋을 것 같습니다


다음 장에는 Next.js App을 배포하는 방법에 대해 배워보겠습니다




Next js 튜토리얼 7편 : 컴포넌트 스타일링  - 현재 글

Next js 튜토리얼 8편 : 배포 

반응형
댓글