styled-components 사용 및 Next.js 에서 SSR

IT공부중·2020년 2월 22일
6

Next

목록 보기
6/11
post-thumbnail
post-custom-banner

styled-components란 ?

react로 개발을 하면 SPA이기 때문에 class나 id를 제대로 구분하지 않으면 css가 겹쳐버리는 현상이 발생한다.

그래서 styled-components를 사용하면 알아서 임의의 id 또는 class로 구분시켜주기 때문에 css가 겹치지 않고 사용이 가능하다.

styled-components 설치

npm install styled-components

사용법

import React from 'react';

const Test = () => {
  return (
    <div>
      <div>
        반갑습니다.
        <div>
          <span>안녕하세요</span>
        </div>
      </div>
    </div>
  );
};

export default Test;

이런식으로 있다고 가정했을 때 원래는 새로운 css를 만들어서 맨 위에서 import를 해와야 했을 것이다. 하지만 styled-components를 쓰면 다른 방식으로 할 수 있다.

import React from 'react';
import styled from 'styled-components'; // stlyed-components를 불러온다
// styled. 뒤에 자신이 사용하고 싶은 jsx tag를 입력한다. 현재 코드에서 TestDiv라는 변수로 div처럼 이용 가능하다. 그 밑에 css 코드를 적는다.

const TestDiv = styled.div`
    background : yellow;
    & div {
        color : red;
        & span {
            color : blue;
        }
    }
`;
const Test = () => {
  return (
    <TestDiv>
      <div>
        반갑습니다.
        <div>
          <span>안녕하세요</span>
        </div>
      </div>
    </TestDiv>
  );
};

export default Test;

React Component 만들듯이 대문자로 시작하는 변수명으로 만들어주고 styled.div 뒤에 backtick을 붙여주고 그 안에 css 코드를 적는다. 그냥 적으면 TestDiv의 css를 수정하는 것이다. &은 자기 자신을 뜻하고 & div를 하면 자신 자식, 손자 등 모든 div의 css를 수정하는 것이다. 그리고 &은 자기 자신을 가리키는데 블록 scope를 갖기 때문에 {} 마다 가리키는 태그가 바뀐다. 잘 보고 사용해야한다!!


위 코드를 실행하게 되면 이런식으로 나오게 된다. 만약에 jsx 태그 말고 antd 같은 ui framework의 css를 덮어 씌우고 싶다면

import styled from 'styled-components';
import { Button } from 'antd';

const TestDiv = styled(Button)`
    background : yellow;
`;

이런식으로 사용해야한다.

styled-components 사용시 문제점??

문제: 처음에 css가 적용하지 않은 채로 잠시 나왔다가 css가 적용된다. 뭔가 보기가 안 좋다.

해결 : styled-components에 ssr을 적용하면 처음부터 css가 적용 된 상태로 나오게 된다.

Next.js에서 styled-components ssr 적용 방법

/pages/_document.js

import React from "react";
import Document, { Main, NextScript, Head } from "next/document"; //next의 html과 나머지 기타 기능들을 넣어주는 Main과 NextScript
import Helmet from "react-helmet"; // head태그에 넣을 정보를 jsx로 작성할 수 있게 도와준다.
import { ServerStyleSheet, createGlobalStyle } from "styled-components";
// _document.js는 index.html을 꾸며주는거다라고 생각하면 된다.
// class형으로 밖에 못 하는게 조금 아쉽다.
// ServerStyleSheet을 사용하여 서버사이드렌더링을 하게 할 수 있다.
// 전체적으로 css를 주고 싶은 부분은 createGlobalStyle을 사용하여 가능하다.
const GlobalStyles = createGlobalStyle`
       html, body {
            height: 100%;
            overflow: auto;
          }
          #__next {
            height: 100%;
          }
`;
class MyDocument extends Document {
  static getInitialProps(context) {
    const sheet = new ServerStyleSheet(); // 서버사이드 렌더링 할 수 있게함.
    const page = context.renderPage(App => props =>
      sheet.collectStyles(
        <>
          <GlobalStyles />
          <App {...props} />
        </>
      )
    ); // 아래의 스타일들을 모아서 페이지를 그려준다. 원래는 <GlobalStyles/> 없이 하는데 글로벌 스타일을 지정해주기 위해 저렇게 적었다.
    const styleTags = sheet.getStyleElement();
    return { ...page, helmet: Helmet.renderStatic(), styleTags };
  }
  render() {
    const { htmlAttributes, bodyAttributes, ...helmet } = this.props.helmet; // helmet으로 부터 받아온다.
    const htmlAttrs = htmlAttributes.toComponent();
    const bodyAttrs = bodyAttributes.toComponent();
    return (
      //html이랑 head, body 부분에 각각 props들을 넣어준다
      <html {...htmlAttrs}> 
        <Head> 
          {this.props.styleTags}
          {Object.values(helmet).map(el => el.toComponent())} 
        </Head>
        <body {...bodyAttrs}>
          <Main />
          <NextScript />
        </body>
      </html>
    );
  }
}

export default MyDocument;

이런식으로 작성을 하게 되면 페이지들이 서버로부터 그려져 나와서 처음부터 css가 적용이 된 페이지를 볼 수 있을 것이다!!

결론

  • styled-components는 css-in-js 스타일로 작성할 수 있게 한다. css를 컴포넌트처럼 만들 수 있다.
  • 그냥 사용하면 첫 렌더링시 css가 적용이 안 된 화면이 보이게 되어 불편하다.
  • Next의 _document.js를 수정함으로써 ssr로 페이지를 그릴 수 있게 하여 해결 할 수 있다.
profile
4년차 프론트엔드 개발자 문건우입니다.
post-custom-banner

0개의 댓글