본문 바로가기
React

Emotion, CSS-in-JS 라이브러리 - 커스터마이징 가능한 테마와 스타일 시스템 구축

by 박_은애 2025. 6. 16.
반응형

Emotion, CSS-in-JS 라이브러리 - 커스터마이징 가능한 테마와 스타일 시스템 구축

오늘날 웹 애플리케이션은 사용자의 다양한 취향과 환경에 맞춰 개인화된 경험을 제공하는 것이 매우 중요합니다. 특히 리액트(React)를 사용하는 프로젝트에서는 일관된 UI/UX를 유지하면서도, 사용자가 자신의 선호에 따라 테마를 동적으로 전환할 수 있는 기능이 필수적입니다.

이 글에서는 CSS-in-JS 기법과 함께 Styled Components, Emotion 등의 라이브러리를 활용해 커스터마이징 가능한 테마와 스타일 시스템을 구축하는 방법을 구체적으로 살펴보고, 실제 코드 예제와 적용 전략을 통해 사용자 맞춤형 UI를 만드는 방법을 소개합니다.


디자인 시스템과 테마의 중요성

디자인 시스템은 색상, 타이포그래피, 간격, 아이콘 등 모든 시각적 요소와 UI 컴포넌트를 하나의 체계로 정리한 것입니다. 이를 통해 전체 애플리케이션에서 일관된 디자인을 유지하고, 개발자와 디자이너 간의 협업 효율성을 극대화할 수 있습니다. 특히, 테마는 사용자에게 다크 모드, 라이트 모드와 같은 다양한 환경 설정을 제공함으로써, 개인화된 경험을 가능하게 합니다.
디자인 시스템과 테마 관리의 주요 장점은 다음과 같습니다.

  • 일관성: 전체 애플리케이션에서 동일한 스타일 가이드라인을 적용하여, 브랜드 일관성을 유지합니다.
  • 재사용성: 공통 컴포넌트와 스타일을 모듈화함으로써, 코드의 중복을 줄이고 신규 기능 개발 시 생산성을 높입니다.
  • 유지보수 효율성: 중앙에서 스타일을 관리하면, 디자인 변경 시 모든 컴포넌트에 일괄적으로 적용할 수 있어 유지보수가 용이합니다.
  • 사용자 맞춤형 경험: 사용자 환경 설정(예: 다크 모드, 라이트 모드) 변경에 따라 동적으로 UI를 전환하여, 개인화된 경험을 제공합니다.

CSS-in-JS와 라이브러리 활용

전통적인 CSS 방식은 전역 스타일로 인해 클래스 충돌이나 유지보수의 어려움이 발생할 수 있습니다. 반면, CSS-in-JS 기법은 각 컴포넌트에 독립적인 스타일을 적용할 수 있도록 도와주며, JavaScript 코드 안에서 직접 스타일을 관리할 수 있는 장점을 제공합니다. 대표적인 CSS-in-JS 라이브러리로는 Styled ComponentsEmotion이 있으며, 이들은 모두 동적 테마 전환 및 사용자 맞춤형 UI 구현에 최적화되어 있습니다.

Styled Components

Styled Components는 리액트 컴포넌트와 CSS를 결합하여, 컴포넌트 단위로 스타일을 캡슐화할 수 있는 라이브러리입니다. 이를 활용하면, 스타일이 컴포넌트와 함께 관리되므로 클래스 네임 충돌이나 전역 스타일 문제를 해결할 수 있습니다.

예를 들어, 다음과 같이 기본 버튼 컴포넌트를 작성할 수 있습니다.

import React from 'react';
import styled from 'styled-components';

const StyledButton = styled.button`
  background-color: ${({ theme }) => theme.primaryColor};
  color: #fff;
  font-family: ${({ theme }) => theme.fontFamily};
  padding: ${({ theme }) => theme.basePadding};
  border: none;
  border-radius: 4px;
  cursor: pointer;
  transition: background-color 0.3s ease, transform 0.2s ease;

  &:hover {
    background-color: ${({ theme }) => theme.hoverPrimaryColor};
    transform: scale(1.05);
  }

  &:active {
    transform: scale(0.95);
  }
`;

const Button = ({ label, onClick }) => {
  return <StyledButton onClick={onClick}>{label}</StyledButton>;
};

export default Button;

위 코드는 테마 객체에 정의된 값(예: primaryColor, fontFamily, basePadding 등)을 활용하여, 버튼의 스타일을 동적으로 관리할 수 있습니다.

Emotion

Emotion 역시 Styled Components와 유사하게 CSS-in-JS 기법을 제공하지만, 보다 가볍고 빠른 퍼포먼스를 자랑합니다. Emotion을 활용하면 스타일을 객체 형태나 템플릿 리터럴 형태로 작성할 수 있어, 개발자가 선호하는 방식에 맞춰 유연하게 적용할 수 있습니다.

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

const buttonStyle = (theme) => css`
  background-color: ${theme.primaryColor};
  color: #fff;
  padding: ${theme.basePadding};
  border: none;
  border-radius: 4px;
  cursor: pointer;
  transition: background-color 0.3s ease, transform 0.2s ease;

  &:hover {
    background-color: ${theme.hoverPrimaryColor};
    transform: scale(1.05);
  }

  &:active {
    transform: scale(0.95);
  }
`;

const EmotionButton = ({ label, onClick }) => {
  return (
    <button css={buttonStyle} onClick={onClick}>
      {label}
    </button>
  );
};

export default EmotionButton;

Emotion은 Styled Components와 달리 css 함수를 활용하여 간결하게 스타일을 적용할 수 있으며, ThemeProvider를 통해 전역 테마를 손쉽게 주입할 수 있습니다.


동적 테마 전환 전략

사용자 맞춤형 UI를 구현하기 위해서는, 다크 모드, 라이트 모드 등 다양한 테마를 동적으로 전환할 수 있어야 합니다. 이를 위해 리액트 컨텍스트와 ThemeProvider를 활용하여 전역 테마 상태를 관리하는 방법이 효과적입니다.

테마 객체 정의

먼저, 다크 모드와 라이트 모드에 해당하는 테마 객체를 정의합니다.

// theme.js
export const lightTheme = {
  primaryColor: '#1976d2',
  hoverPrimaryColor: '#1565c0',
  fontFamily: "'Roboto', sans-serif",
  basePadding: '12px',
  background: '#ffffff',
  textColor: '#333333',
};

export const darkTheme = {
  primaryColor: '#90caf9',
  hoverPrimaryColor: '#64b5f6',
  fontFamily: "'Roboto', sans-serif",
  basePadding: '12px',
  background: '#121212',
  textColor: '#e0e0e0',
};

테마 컨텍스트와 토글 기능

다음으로, 리액트 컨텍스트를 활용하여 테마 상태와 토글 기능을 전역에서 관리합니다.

import React, { createContext, useState, useContext } from 'react';
import { ThemeProvider as StyledThemeProvider } from 'styled-components';
import { lightTheme, darkTheme } from './theme';

const ThemeToggleContext = createContext();

export const useThemeToggle = () => useContext(ThemeToggleContext);

export const CustomThemeProvider = ({ children }) => {
  const [theme, setTheme] = useState('light');

  const toggleTheme = () => {
    setTheme((prev) => (prev === 'light' ? 'dark' : 'light'));
  };

  const currentTheme = theme === 'light' ? lightTheme : darkTheme;

  return (
    <ThemeToggleContext.Provider value={{ theme, toggleTheme }}>
      <StyledThemeProvider theme={currentTheme}>
        {children}
      </StyledThemeProvider>
    </ThemeToggleContext.Provider>
  );
};

이렇게 구성된 CustomThemeProvider를 애플리케이션 최상위에 적용하면, 모든 컴포넌트에서 테마에 접근하고 변경할 수 있게 됩니다.

테마 전환 UI 예제

사용자가 테마를 쉽게 전환할 수 있도록 토글 버튼을 제공하는 컴포넌트를 구현합니다.

import React from 'react';
import styled from 'styled-components';
import { useThemeToggle } from './CustomThemeProvider';

const ToggleButton = styled.button`
  padding: 8px 16px;
  background-color: ${({ theme }) => theme.primaryColor};
  color: #fff;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  transition: background-color 0.3s ease;

  &:hover {
    background-color: ${({ theme }) => theme.hoverPrimaryColor};
  }
`;

const ThemeToggleButton = () => {
  const { theme, toggleTheme } = useThemeToggle();

  return (
    <ToggleButton onClick={toggleTheme}>
      {theme === 'light' ? '다크 모드로 전환' : '라이트 모드로 전환'}
    </ToggleButton>
  );
};

export default ThemeToggleButton;

이 버튼 컴포넌트를 통해 사용자는 원하는 테마로 손쉽게 전환할 수 있으며, 전역 테마 설정에 따라 전체 UI가 즉시 업데이트됩니다.


실제 프로젝트 적용 및 기대 효과

디자인 시스템과 동적 테마 전환은 사용자 맞춤형 경험과 브랜드 일관성을 유지하는 데 매우 중요한 역할을 합니다. 실제 프로젝트에서는 다음과 같은 효과를 기대할 수 있습니다.

  • 개발 생산성 향상: 재사용 가능한 컴포넌트와 중앙 집중식 스타일 관리로, 새로운 기능 추가나 디자인 변경 시 빠른 적용이 가능해집니다.
  • 일관된 사용자 경험: 다크 모드, 라이트 모드 등 다양한 테마를 일관되게 적용하여, 사용자에게 친숙하고 안정적인 UI를 제공합니다.
  • 유지보수 비용 절감: 디자인 토큰과 테마 시스템을 통해, 전체 애플리케이션의 스타일을 한 곳에서 관리할 수 있어 유지보수가 용이합니다.
  • 개인화된 경험: 사용자가 자신의 환경에 맞게 UI를 선택할 수 있어, 보다 만족스러운 사용자 경험을 제공합니다.

또한, Styled Components와 Emotion과 같은 CSS-in-JS 라이브러리를 활용하면, 개발자는 코드 내에서 직접 스타일을 동적으로 제어할 수 있으므로, 유지보수성과 확장성이 극대화됩니다.


결론

리액트 기반 애플리케이션에서 커스터마이징 가능한 테마와 스타일 시스템 구축은, 브랜드 일관성과 사용자 맞춤형 경험을 동시에 제공할 수 있는 강력한 전략입니다.

  • CSS-in-JS 기법을 통해 컴포넌트 단위로 스타일을 캡슐화하고,
  • Styled ComponentsEmotion을 활용하여 동적인 스타일 변경 및 테마 전환을 구현하면,
  • 리액트 컨텍스트ThemeProvider를 결합하여 전역 테마 관리를 손쉽게 처리할 수 있습니다.

이러한 접근 방식을 통해, 개발자는 유지보수가 용이한 모듈화된 코드를 작성할 수 있으며, 사용자는 자신에게 최적화된 맞춤형 UI를 경험할 수 있습니다. 앞으로 리액트 프로젝트에서 디자인 시스템과 테마 전환 기능을 적극 도입하여, 보다 효율적이고 일관된 사용자 경험을 제공하시길 바랍니다.

반응형