Emotion 정리: @emotion/react 제대로 이해하기

김진아·2026년 5월 1일
post-thumbnail

스타일링 방식에는 어떤 것들이 있을까?

React에서 스타일을 적용하는 방식은 여러 가지가 있다.

방식특징
CSS 파일가장 기본적인 방식. 별도의 .css 파일에서 스타일을 관리한다.
CSS Module클래스명이 자동으로 고유해져서 스타일 충돌을 줄일 수 있다.
Sass/SCSS변수, 중첩, mixin 등을 사용할 수 있는 CSS 확장 문법이다.
styled-components컴포넌트 단위로 스타일을 작성할 수 있는 CSS-in-JS 라이브러리다.
Emotionstyled 방식과 css prop 방식을 모두 지원하는 CSS-in-JS 라이브러리다.
Tailwind CSS미리 정의된 유틸리티 클래스를 조합해서 스타일을 작성한다.

이 중에서 내가 Emotion을 선택한 이유는 다음과 같다.

  1. 컴포넌트 단위로 스타일을 관리할 수 있다.
  2. props를 이용한 동적 스타일링이 쉽다.
  3. styled 방식과 css prop 방식을 모두 지원한다.
  4. Global, ThemeProvider 같은 React 스타일링 기능을 통해 전역 스타일과 테마 관리가 가능하다.
  5. styled-components와 문법이 비슷해서 진입 장벽이 낮다.

기존에는 styled-components를 주로 사용했지만, 최근 maintenance mode로 전환되면서 새 프로젝트에서는 사용을 지양하고 있다.
이에 익숙한 사용 방식은 유지하면서도 더 유연한 스타일링이 가능한 Emotion을 선택하게 되었고, 특히 헷갈렸던 @emotion/react 부분을 중심으로 정리해보려고 한다.

Emotion이란?

Emotion은 CSS 파일을 따로 분리하지 않고, JavaScript 안에서 스타일을 작성할 수 있게 해주는 CSS-in-JS 라이브러리다.

일반 CSS 방식에서는 보통 이렇게 작성한다.

<button className="button">버튼</button>
.button {
  padding: 10px 16px;
  background-color: black;
  color: white;
}

Emotion을 사용하면 스타일을 JavaScript 코드 안에서 작성할 수 있다.

import styled from "@emotion/styled";

const Button = styled.button`
  padding: 10px 16px;
  background-color: black;
  color: white;
`;

function App() {
  return <Button>버튼</Button>;
}

즉, Emotion은 컴포넌트와 스타일을 가까운 위치에서 관리할 수 있게 해준다.

이러한 방식은 styled-components를 사용해봤다면 익숙하게 느껴질 것이다.

Emotion 설치하기

Emotion을 사용하려면 보통 아래 두 패키지를 함께 설치한다.

npm install @emotion/react @emotion/styled

pnpm을 사용한다면 이렇게 설치할 수 있다.

pnpm add @emotion/react @emotion/styled

@emotion/styled@emotion/react는 무슨 차이가 있을까?

@emotion/styled와 @emotion/react

Emotion에는 대표적으로 두 패키지가 있다.

import styled from "@emotion/styled";
import { css } from "@emotion/react";

둘 다 Emotion이지만 역할이 조금 다르다.

패키지역할
@emotion/styledstyled-components처럼 styled.div, styled.button 형태로 스타일 컴포넌트를 만들 때 사용한다.
@emotion/reactcss prop, Global, ThemeProvider, keyframes 같은 React 전용 기능을 제공한다.

쉽게 말하면 다음과 같다.

@emotion/styled는 styled-components와 거의 비슷하게 사용하는 패키지다.
@emotion/react는 Emotion의 React 전용 핵심 기능을 제공하는 패키지다.

styled 방식은 styled-components와 매우 유사하기 때문에, 이번 글에서는 따로 설명하지 않겠다.

@emotion/react에서 제공하는 기능들

@emotion/react는 Emotion의 React 전용 기능을 제공한다.

대표적으로 다음 기능들이 있다.

  1. css
  2. Global
  3. ThemeProvider
  4. keyframes

1. css

css는 Emotion 스타일을 만들 때 사용하는 함수다.

import { css } from "@emotion/react";

const containerStyle = css`
  padding: 20px;
  background-color: #f5f5f5;
`;

이렇게 만든 스타일은 JSX의 css prop에 넣어서 사용할 수 있다.

function App() {
  return <div css={containerStyle}>내용</div>;
}

객체 형태로도 작성할 수 있다.

import { css } from "@emotion/react";

const containerStyle = css({
  padding: "20px",
  backgroundColor: "#f5f5f5",
});

문자열 방식은 일반 CSS를 쓰는 느낌이고, 객체 방식은 JavaScript 객체로 스타일을 작성하는 느낌이다.

2. Global

Global은 전역 스타일을 지정할 때 사용한다.

컴포넌트 스타일은 보통 특정 컴포넌트에만 적용된다.

하지만 body, html, * 같은 전역 스타일은 특정 컴포넌트에만 묶기 어렵다.

이럴 때 Global을 사용할 수 있다.

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

function App() {
  return (
    <>
      <Global
        styles={css`
          * {
            box-sizing: border-box;
          }

          body {
            margin: 0;
            font-family: sans-serif;
          }

          button {
            font-family: inherit;
          }
        `}
      />

      <div>Emotion Global 스타일</div>
    </>
  );
}

Global은 보통 다음과 같은 경우에 사용한다.

  • reset CSS
  • body 기본 스타일
  • font-family 기본값
  • 전체 box-sizing
  • 기본 버튼, input 스타일 초기화

예를 들어 프로젝트에서 공통 reset 스타일을 관리하고 싶다면 이런 식으로 분리할 수 있다.

// GlobalStyle.jsx
import { Global, css } from "@emotion/react";

const globalStyle = css`
  * {
    box-sizing: border-box;
  }

  body {
    margin: 0;
    font-family: sans-serif;
    background-color: #ffffff;
  }

  button {
    border: none;
    background: none;
    cursor: pointer;
    font-family: inherit;
  }
`;

function GlobalStyle() {
  return <Global styles={globalStyle} />;
}

export default GlobalStyle;

그리고 App에서 불러와 사용한다.

import GlobalStyle from "./GlobalStyle";

function App() {
  return (
    <>
      <GlobalStyle />
      <div>앱 화면</div>
    </>
  );
}

export default App;

3. ThemeProvider

ThemeProvider는 공통 디자인 값을 관리할 때 사용한다.

프로젝트를 하다 보면 색상, 폰트 크기, 간격 같은 값을 여러 곳에서 반복해서 사용하게 된다.

color: #333333;
background-color: #f5f5f5;

이런 값을 컴포넌트마다 직접 작성하면 나중에 수정하기 어렵다.

예를 들어 메인 컬러가 바뀌면 모든 파일을 찾아다니며 수정해야 한다.

이럴 때 theme을 만들어 공통 값을 관리할 수 있다.

const theme = {
  colors: {
    primary: "#2f80ed",
    text: "#333333",
    background: "#f5f5f5",
  },
  fontSize: {
    small: "12px",
    medium: "16px",
    large: "24px",
  },
};

그리고 ThemeProvider로 감싸준다.

import { ThemeProvider } from "@emotion/react";
import styled from "@emotion/styled";

const theme = {
  colors: {
    primary: "#2f80ed",
    text: "#333333",
  },
};

const Title = styled.h1`
  color: ${({ theme }) => theme.colors.primary};
`;

function App() {
  return (
    <ThemeProvider theme={theme}>
      <Title>Emotion ThemeProvider</Title>
    </ThemeProvider>
  );
}

export default App;

이렇게 하면 하위 컴포넌트에서 theme 값을 사용할 수 있다.

css prop 방식에서도 사용할 수 있다.

/** @jsxImportSource @emotion/react */
import { css, ThemeProvider } from "@emotion/react";

const theme = {
  colors: {
    primary: "#2f80ed",
  },
};

const titleStyle = (theme) => css`
  color: ${theme.colors.primary};
`;

function Title() {
  return <h1 css={titleStyle}>Emotion</h1>;
}

function App() {
  return (
    <ThemeProvider theme={theme}>
      <Title />
    </ThemeProvider>
  );
}

ThemeProvider를 사용하면 디자인 값을 한 곳에서 관리할 수 있다는 장점이 있다.

4. keyframes

keyframes는 애니메이션을 만들 때 사용한다.

CSS에서 @keyframes를 작성하는 것처럼, Emotion에서도 애니메이션을 정의할 수 있다.

import { keyframes, css } from "@emotion/react";

const fadeIn = keyframes`
  from {
    opacity: 0;
  }

  to {
    opacity: 1;
  }
`;

const boxStyle = css`
  width: 100px;
  height: 100px;
  background-color: black;
  animation: ${fadeIn} 1s ease-in-out;
`;

function App() {
  return <div css={boxStyle} />;
}

이렇게 하면 컴포넌트 안에서 애니메이션까지 함께 관리할 수 있다.

주의할 점

Emotion을 사용할 때는 styled 방식과 css prop 방식을 상황에 맞게 구분해서 사용하는 것이 중요하다.

css prop은 JSX 요소에 바로 스타일을 작성할 수 있어서 간단한 스타일을 적용할 때 편리하다. 하지만 모든 스타일을 css prop으로 작성하면 JSX 안에 스타일 코드가 많아져 오히려 구조를 파악하기 어려워질 수 있다.

따라서 재사용되는 UI나 스타일 코드가 길어지는 경우에는 styled 방식으로 분리하고, 한 번만 사용하는 간단한 스타일에는 css prop을 사용하는 것이 좋다.

정리하면 다음과 같이 사용할 수 있다.

상황추천 방식
여러 곳에서 재사용되는 버튼, 카드, 모달styled
한 번만 사용하는 간단한 스타일css prop
reset CSS, body 기본 스타일Global
공통 색상, 폰트, 간격 관리ThemeProvider

글을 정리하며

처음 Emotion을 접했을 때는 @emotion/styled@emotion/react가 나뉘어 있어서 구조 자체가 조금 낯설고 헷갈렸다. 특히 css prop 방식은 기존에 사용하던 방식과 달라서 어떻게 활용해야 할지 감이 잘 잡히지 않았다.

이번에 개념을 정리하면서 각각의 역할을 구분해보니, 생각보다 단순한 구조라는 것을 이해할 수 있었다. 상황에 따라 styledcss prop을 선택해서 사용할 수 있다는 점도 Emotion의 큰 장점이라고 느껴졌다.

앞으로는 단순히 사용하는 것을 넘어서, 상황에 맞게 스타일링 방식을 구분하면서 Emotion을 더 적극적으로 활용해볼 수 있을 것 같다.

0개의 댓글