emotion에서 타이포그래피와 컬러같은 디자인시스템 변수들을 어떻게 정의하는 게 좋을까

1. GlobalStyles

GlobalStyles는 애플리케이션 전역에 영향을 미치는 스타일을 정의할 때 사용됨. 이를 통해 특정 HTML 요소(예: body, h1, p)의 기본 스타일을 지정하거나, 리셋 스타일(CSS Reset)을 적용할 수 있다. GlobalStyles는 한 번 설정하면 애플리케이션 전체에서 적용되며, 주로 전역적인 리셋이나 기본 레이아웃을 설정하는 데 적합하다.

여기에 css 변수로서 디자인 토큰을 정의하면 IDE의 자동완성 도움을 받기가 어려웠다.

예시

import { Global, css } from '@emotion/react';

const globalStyles = css({
	* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
  }
  
  ':root' : {
    '--display-bold24': `700 24px 'Pretendard-Variable'`,
    '--display-bold16': `700 16px 'Pretendard-Variable'`,

    '--text-strong': '#888888',
    '--text-bold': '#666666',
  },
})

export function GlobalStyles(){
  return(
    <Global styles={globalStyles} />
  )
}

2. Variable 객체 만들어서 사용하기

styles/Variables.ts 파일에 객체로 정의해서 Variables.typography.font_bold_24 과 같은 형태로 자동완성의 도움을 도움을 받으면서 활용하는 방법도 있다. 무난한 방법이나 버튼 하나만 눌러서 라이트/다크 모드를 전환하게 하는 데에는 썩 좋은 방법은 아닐수도 있겠다.

export const Variables = {
  colors: {
    primary: '#fe4902',
    surface_default: '#F8F8F8',
    surface_strong: '#434343',
    // ...
  },
  typography: {
    font_medium_20: '500 20px "Pretendard-Variable", sans-serif',
    font_medium_16: '500 16px "Pretendard-Variable", sans-serif',
    font_bold_72: '700 72px "Pretendard-Variable", sans-serif',
    font_bold_56: '700 56px "Pretendard-Variable", sans-serif',
    // ...
  },
  shadow: {
    shadow_floating: '0px 4px 8px #00000040'
  }
};
import { Variables } from '../styles/Variables';
import { css } from '@emotion/react';

const startButtonStyle = css({
  font: Variables.typography.font_bold_24,
  color: Variables.colors.text_white,
  backgroundColor: Variables.colors.surface_point,
  padding: '24px 48px',
  borderRadius: 32,
  ':hover': {
    opacity: 0.8
  }
});

3. Theme

Theme는 Emotion의 ThemeProvider를 통해 구성되며, 디자인 시스템의 일관성을 유지하는 데 유용하다. Theme에 정의된 값은 컴포넌트에서 사용할 수 있으며, 주로 색상, 타이포그래피, 간격, 그림자 등 일관된 디자인 요소를 제공하는 데 사용된다. Theme를 사용하면 디자인 시스템을 재사용 가능하고 유지 관리하기 쉽게 만들 수 있다.

단, 타입스크립트 환경에서는 emotion에서 theme을 사용하기 위해서는 emotion.d.ts라는 별도의 type 정의 파일을 만들어야 한다.

예시

// theme.ts
const theme = {
  colors: {
    primary: '#3498db',
    secondary: '#2ecc71',
    text: '#333',
  },
  typography: {
    fontSizeLarge: '2rem',
    fontWeightBold: 700,
  },
};

export default theme;

// emotion.d.ts
import '@emotion/react'
import {theme} from './theme'

type ThemeTpye = typeof theme

declare module '@emotion/react' {
  export interface Theme extends ThemeTpye {}
}

// ThemeProvider 사용
import { ThemeProvider } from '@emotion/react'

const theme = {
  colors: {
    primary: 'hotpink'
  }
}

render(
  <ThemeProvider theme={theme}>
    <div css={theme => ({ color: theme.colors.primary })}>some other text</div>
  </ThemeProvider>
)

참고자료

https://velog.io/@2ast/React-emotion으로-theme-적용하기

https://emotion.sh/docs/theming