DEV/CSS

CSS와 JS 사이에 변수 공유하기

young.gratia 2021. 5. 3. 15:21

프론트엔드 개발을 하다 보면 각종 스타일 변수(대표적으로 컬러와 여백값)를 JS 코드에서 끌어다 써야 할 때가 있다. 생각나는 방법으로는 세가지 정도가 있다.

  1. styled-component 등 CSS-in-JS 라이브러리를 사용하는 경우: JS 코드로 정의하기
  2. CSS 커스텀 프로퍼티로 정의해 두고 DOM API를 사용해 접근하기
  3. css-modules 사용하는 경우: :export 사용하여 스타일 파일에서 변수 내보내기

각각의 방법을 하나씩 살펴보자!

JS 코드에 객체 등으로 정리

스타일과 스크립트 코드가 섞이는 것에 그닥 불만이 없다면 적극 활용을 권장하고 싶다. 나는 그 둘 사이의 명확한 구분이 꼭 필요하다고 생각하는 타입이 아니고, 객체로 상수값 정리하는 것을 좋아해서 예전에 네이버 스마트 플레이스 모바일 버전 개발할 때 이 방법을 택했다. 정말 간단하게 예를 들자면 아래와 같다.

// styleVars.js
const COLORS = {
  white: '#fff',
  black: '#000',
  ...
}

export default {
  COLORS,
  ...
}

// Button.jsx
import { COLORS } from 'src/styleVars'

const Button = () => {
  return (
    <button type="button"
        style={{ backgroundColor: COLORS.white }}>
    Simple Button</button>)
}

CSS 커스텀 프로퍼티로 정의한 후 DOM API로 접근하기

부끄럽지만 CSS 커스텀 프로퍼티는 아직 실무에서 써 본 적이 없다. 이거 잘 정의하면 나중에 Theme 설정할 때 컬러 팔레트를 통째로 손쉽게 바꿀 수 있을 것 같다. 커스텀 프로퍼티는 스코프를 정할 수 있다. 보통 전역으로 두고 사용하기 때문에 :root 선택자를 사용한다.

:root {
  --my-theme-color: rebeccapurple;
}
getComputedStyle(document.documentElement).getPropertyValue('--my-theme-color')

// 혹은

document.documentElement.style.getPropertyValue("--my-theme-color'");

커스텀 프로퍼티는 CSS Houdini와 연관지어 생각할 수 있다. 브라우저 실험 기간이 끝나고 본격적으로 벤더들이 지원하기 시작하면 다양한 활용법이 나오리라 기대한다. 나중에 Houdini도 한번 공부해 봐야겠다.

그러나 이 방법은 JS 코드가 이쁘게 나오지 않아서 안 땡긴다. (넘 길어! 😔 타이핑 하다가 시간 다 보낼 것 같다.)

css-modules 사용하는 경우: :export 사용하여 스타일 파일에서 변수 내보내기

이 방법은 모르고 있었는데, 이번에 Woven Planet에서 작업하게 된 UI 라이브러리에 이미 적용이 되어 새로 알게 되었다. 커스텀 프로퍼티 가져다 쓰는 것보다 코드도 깔끔하고 1번 방법 느낌도 나기 때문에 CSS와 JS의 철저한 분리를 지향하면서 코드도 깔끔했으면 하는 사람들에게 추천한다.

:export {
  someVar: $some-var;
  thisIsAlsoSomeVar: $this-is-also-some-var;
  ...
}
import { someVar, thisIsAlsoSomeVar } from 'styles/exports'

⚠️ 주의할 점은, :export를 한 파일에 몰아서 해야 한다는 것이다. 그렇지 않고 스타일 파일 여기저기서 :export 한다면, 그 파일을 다른 스타일 파일에서 사용할 때마다 매번 :export 되기 때문에 스타일 코드량이 불어나게 된다.

예를 들어, colors.scss, font.scss 두 파일이 있는데, 각각의 파일마다 변수를 내보내고 있다고 하자.

// colors.scss

$white: '#fff';

:export {
  white: $white;
}

// font.scss

$font-size: 48px;

:export {
  fontSize: 48px;
}

그러면 만약 Button.scss에서 이 두 파일을 불러와서 사용한다면,

@use 'colors';
@use 'font';

.button {
  ...
}

브라우저 개발자 도구에서 보는 경우, 코드가 아래처럼 나온다.

// 이거는 여기서 필요 없는데!
:export {
  white: '#fff';
  fontSize: '48px';
}

.button {
  ...
}

export.scss 같은 변수 내보내기 전용 파일을 하나 만들고 그것만 JS에서 가져다 사용하는 것이 좋다.

// exports.scss
@use 'colors';
@use 'font';

:export {
    white: $colors.white;
    fontSize: $font.font-size;
}

참고