React + TS | Emotion Theme 세팅하기

dayannne·2024년 3월 24일
0

React

목록 보기
9/13
post-thumbnail

현재 실무 프로젝트에서 emotion을 사용하고 있는데,
기존의 styled components와 비슷해서 어려울 건 없지만 theme 세팅 방법에 대해 정리해두려 한다. (설치부터의 사용법은 다음에!)

Emotion 설치

npm install @emotion/react @emotion/styled

React 프로젝트에서 emotion을 사용할 수 있는 @emotion/react 패키지와 styled-components처럼 스타일링 컴포넌트 생성을 위한 @emotion/styled를 설치해 준다.

Theme 객체 생성하기

emotion에서는 아래와 같이 테마에 포함될 스타일 속성들을 객체 형태로 정의할 수 있다.

// theme.ts
export const theme = {
  fontSizes: {
    sm: "13px",
    base: "14px",
    md: "18px",
  },
  lineHeight: {
    sm: "13px",
    base: "14px",
    md: "18px ",
  },
  letterSpacing: "-2%",
  colors: {
    main: "#2F3438",
    red: "#FF0000",
    white: "#FFFFFF",
    gray: "#999999",
    blueGray2: "#505B6D",
    blueGray3: "#505B6D",
    blueGray4: "#9DA8B6",
    border01: "#E7EDF6",
    border02: "#8899B6",
    bg01: "#F9FAFC",
  },
};

theme.js 파일을 생성해서, fontSizes, lineHeight, letterSpacing, colors 등 필요에 따라 테마를 설정해 준다.

  • 아래는 이전까지 프로젝트에서의 GlobalStyle css -> :root 세팅 방식인데, 비교해서 보니 emotion의 theme 설정이 조금 더 스타일을 세분화해서 사용할 수 있는 장점이 있는 것 같다.
:root{
   --main-color:#724FFF;
   --font-color:#191919; 
   --sub-font-color:#767676;
   --extra-font-color: #909090;
   --tertiary-font-color: #575757;
   --border-color:#DBDBDB;
   --modal-border-color: #EDEDED;
   --input-background-color:#F1F1F5;
   --btn-border-color:#724FFF;
   --btn-background-color:#724FFF;
   --btn-point-color: #7D4FFF;
   --playlist-info-bg-color: #8969FF;
   --playlist-info-sub-color: #DBDBDB;
   --error-color: #FF003E;
   --font-xl : 22px;
   --font-l: 18px;
   --font-lg: 16px;
   --font-md: 14px; 
   --font-sm : 12px;
   letter-spacing: -0.02em;
     }

TypeScript에서 Theme 인터페이스 확장하기

이건 TypeScript를 사용한다면 emotion을 사용하기 좋은 큰 이유이자 이점이라고 생각한다.
TypeScript를 사용하는 경우, @emotion/react 모듈의 Theme 인터페이스를 확장하여 테마 객체에 정의된 속성들에 대한 타입을 선언 및 지정해 줄 수 있다(!)

/// theme.ts
import "@emotion/react";

declare module "@emotion/react" {
  export interface Theme {
    fontSizes: {
      sm: string;
      base: string;
      md: string;
    };
    lineHeight: {
      sm: string;
      base: string;
      md: string;
    };
    letterSpacing: string;
    colors: {
      wb500: string;
      red: string;
      white: string;
      gray: string;
      blueGray2: string;
      blueGray3: string;
      blueGray4: string;
      border01: string;
      border02: string;
      bg0: string;
    };
  }
}

이렇게 테마를 정의한 theme.ts 파일 내에 Theme에 대한 타입을 함께 지정해 두면,
테마 내 스타일 속성을 사용할 때의 타입 체킹까지 가능하게 된다.
(물론 타입 선언이 theme 세팅에서의 필수가 아니라 세팅하지 않아도 작동에 문제는 없다.)

theme 타입 세팅 시 주의⚠️
declare로 정의해 준다고 해서 타입 선언을 다른 파일에 분리해 정의를 하게 될 경우 Typescript compiler가 type을 감지하지 못하는 버그가 발생할 수 있다고 한다.

Property 'colors' does not exist on type 'Theme'.

다음과 같은 에러를 만날 수 있으니 꼭 타입을 한 파일 같이 내에 넣어 줄 것!
(나도 작업 중 만난 에러인데, 해당 원인 외에도 theme 내에 설정한 스타일이 타입 내에 누락 될 경우에도 에러 문구를 만날 수 있으니 꼼꼼한 타입체킹하기)

ThemeProvider로 애플리케이션 감싸기

// index.ts
import React from "react";
import ReactDOM from "react-dom/client";
import { ThemeProvider } from "@emotion/react";
import App from "./App";

import "./index.css";
import "./fonts/Font.css";
import { theme } from "./styles/theme";

ReactDOM.createRoot(document.getElementById("root")!).render(
      <React.StrictMode>
        <ThemeProvider theme={theme}>
          <App />
        </ThemeProvider>
      </React.StrictMode>
);

index.ts 파일에 theme.ts 파일을 불러온 다음, ThemeProvider로 App 컴포넌트를 감싸주면 세팅이 끝난다.

세팅 끝, Theme 사용하기

import styled from "@emotion/styled";

export const Wrapper = styled.div`
  color: ${({ theme }) => theme.colors.main};
  font-size : ${({ theme }) => theme.fontSizes.sm};
  background-color : ${({ theme }) => theme.colors.bg};
`;

작업하게 될 컴포넌트 스타일 적용 시 다음과 같이 theme을 가져와 사용하면 된다.
ThemeProvider 덕분에 theme을 import하는 등의 과정은 불필요하다!

마무리하며

emtion의 theme 세팅 및 사용 방법은 스타일 컴포넌트와 비슷한 방법으로,
emotion 하면 또 다른 가장 유명한 방법은 태그에서 css props로 스타일을 지정하고 접근할 수 있는 방법이 있다. 이 부분은 다음에 한 번더 포스팅으로 정리해 보고 싶다!

profile
☁️

0개의 댓글