[React] CSS를 작성하는 방법들, css-module, sass, css-in-js

권준혁·2020년 11월 1일
13

React

목록 보기
3/20
post-thumbnail

안녕하세요~
오늘은 CSS를 작성하는 방법들을 알아보겠습니다.

전통적인 방법으로는 CSS를 별도의 파일로 저장하고 HTML의 link태그를 이용해 적용합니다.

리액트에서는 컴포넌트 아키텍쳐를 이용하기때문에 컴포넌트 간의 의존성을 최소화하고 내부 응집도를 높히는게 좋습니다.
따라서 css-module과 css-in-js로 자바스크립트를 이용해 CSS를 만드는게 좋습니다.

하지만 그렇게 하지 못하는 경우에는 scss를 이용하거나, 전통적인 방법을 따라야 하는 수도 있습니다.

정리하면 이렇습니다.

  • 일반적인 CSS파일
  • css-module
  • SCSS
  • css-in-js

일반적인 CSS

Box와 Button컴포넌트를 만들고 css를 적용해보겠습니다.

// Box1.css
.big {width : 200px;}
.small {width : 100px;}
.box {
    height : 50px;
    background-color: #aaaaaa;
}

// Box1.js
import React from 'react'
import './Box1.css'
export default function ({size}) {
    if (size === 'big'){
        return <div className='box big'>큰 박스</div>
    }else {
        return <div className='box small'>작은 박스</div>
    }
}

// Button1.css
.big {width : 100px;}
.small {width : 50px;}
.button {
    height:30px;
    background-color: #aaaaaa;
}

// Button1.js
import React from 'react'
import './Button1.css'
export default function Button({size}) {
    if (size==='big') {
        return <button className='button big'>큰 버튼</button>
    } else {
        return <button className='button small'>작은 버튼</button>
    }
}

각각 4개의 파일, 2개의 컴포넌트를 생성했습니다.
App.js를 수정하고 실행해주세요

// App.js
function App() {
  return (
    <div className="App">
      <Button size='big'></Button>
      <Button size='small'></Button>
      <Box size='big'></Box>
      <Box size='small'></Box>
    </div>
  );
}

실행해보겠습니다.

npm start

잘 작동 되는 모습이지만, 박스와 버튼의 넓이가 같은 걸 알 수 있습니다.

npm run build

패키징 해보겠습니다.

build폴더의 static폴더를 보면 파일들이 빌드되면서 css파일들이 각각 갖고있던 big과 small클래스가 덮어 씌워지는 걸 알 수 있습니다.
클래스명이 서로 갖기 때문에 클래스명이 충돌되며 덮어씌워집니다.

일반적인 css의 단점입니다.


css-module

css-module을 이용하면 클래스명이 충돌하는 단점을 극복할 수 있습니다.
css-module은 간결한 클래스명을 이용해서 컴포넌트 단위로 스타일을 적용할 때 좋습니다.

{이름}.module.css

CRA에서는 라고 작성하면 css-module이 됩니다.
방금 사용한 Button1.css를 Button1.module.css로 바꿔줍니다.
다음은 js파일을 변경합니다.

import React from 'react'
import style from './Button1.module.css'

export default function Button({size}) {
    if (size==='big') {
        return <button className={`${style.button} ${style.big}`}>큰 버튼</button>
    } else {
        return <button className={`${style.button} ${style.big}`}> 작은 버튼</button>
    }
}

Box1.css와 Box1.js도 동일한 방법으로 변경합니다.

npm start

실행해보겠습니다.

css가 덮어 씌워지지않고 잘 적용된 걸 볼 수 있습니다.

npm run build

크롬 개발자 도구에서 elements탭을 보면 클래스명을 보세요

클래스 이름에 hash값이 붙어 고유한 값으로 인식됩니다. 따라서 클래스명이 같더라도 덮어씌워지지 않습니다.


SASS

Sass는 CSS와 비슷하지만, 별도의 문법 변수,믹스인(mixin)등의 개념이 있습니다. 이런 문법을 이용해 재사용성을 높힐 수 있습니다.
Sass문법으로 작성한 파일은 별도의 빌드단계를 거쳐 CSS파일로 변환됩니다. CRA에서 Scss를 사용하고싶다면 node-sass패키지를 설치합니다.

npm i node-sass

node-sass 패키지는 Sass를 CSS로 빌드할 때 사용됩니다.
CRA에는 Sass를 위한 빌드 시스템이 구축되어 있습니다.
자바스크립트에서 scss확장자를 갖는 파일을 불러오면 자동으로 Sass파일이 CSS파일로 컴파일됩니다.

먼저 shared.scss라는 파일을 만들겠습니다.

// shared.scss
$infoColor:#aaaaaa;

Button3.module.scss, Button3.js 파일을 만듭니다.

// Button3.js
import React from 'react'
import style from './Button3.module.scss'

export default function Button({size}) {
    if (size==='big') {
        return <button className={`${style.button} ${style.big}`}>큰 버튼</button>
    } else {
        return <button className={`${style.button} ${style.big}`}> 작은 버튼</button>
    }
}

//Button3.module.scss
@import './shared.scss';
.big {
    width:100px;
}
.small{
    width:50px;
}
.button{
    height:30px;
    background-color: $infoColor;
}

ESM문법처럼 import문을 사용해 변수처럼 사용할 수 있습니다.


css-in-js

이름처럼 CSS코드를 자바스크립트 파일안에서 작성합니다.
자바스크립트 내에서 관리하기 때문에 내부응집도가 올라가고, 동적으로 CSS를 변경하기도 쉽습니다.

styled-components 패키지를 사용해보겠습니다.

npm i styled-components

Box4.js를 생성합니다.

// Box4.js
import React from 'react';
import styled from 'styled-components'

const BoxCommon = styled.div`
    width : ${props=> (props.isBig? 200:100)}px;    // (1)
    height : 50px;
    background-color:#aaaaaa;
`;
export default function Box({size}) {    //(2)
    const isBig = size==='big';
    const label = isBig? '큰 박스' : '작은 박스'
    return <BoxCommon isBig={isBig}>{label}</BoxCommon>
}

App.js에서 Box4.js를 import하고 코드를 수정합니다.
(1)부분을 보면 isBig이라는 props를 받아 삼항식으로 판별합니다.
(2) Box컴포넌트는 size를 props로 받고 'big'인지 판별합니다.
big일 경우 isBig은 true, 아닐경우 false입니다.
결과적으로 BoxCommon의 width값이 size에 따라 변경됩니다.
템플릿 리터럴를 이용해 표현됩니다.

App컴포넌트에서 Box4를 생성할 때 입력하는 props.size에 따라 컴포넌트의 크기가 동적으로 변합니다. 재사용성이 높은 걸 알 수 있습니다.

// App.js
// size값이 big일경우 width가 200인 컴포넌트가 생성
// 아닐경우 width가 100인 컴포넌트가 생성

import React from 'react';
import Box from './CSSPractice/Box4'

function App() {
  return (
    <div className="App">
      <Box size='big'></Box>
      <Box size='small'></Box>
    </div>
  );
}
export default App;

이상으로 React에서 CSS를 사용하는 방법들에대해 알아봤습니다.
읽어주셔서 감사합니다!

코드인용 및 내용 참고 : 실전 리액트 프로그래밍 : 이재승님 지음

profile
웹 프론트엔드, RN앱 개발자입니다.

2개의 댓글

comment-user-thumbnail
2021년 1월 22일

주로 어떤 걸 사용하는 것을 선호하시나요?

1개의 답글