@emotion/react와 @emotion/styled를 사용하여 CSS-in-JS 방식으로 스타일을 관리함1. @emotion/react
@emotion/react는 CSS-in-JS 스타일링을 위한 핵심 라이브러리이를 통해 스타일을 JavaScript에서 직접 정의하고, 동적으로 조작
설치된 버전
패키지 | 설명 |
@emotion/react | React에서 CSS-in-JS 스타일 관리 |
사용
/** @jsxImportSource @emotion/react */ import { css } from "@emotion/react"; const boxStyle = css` padding: 20px; background-color: #f5f5f5; border-radius: 5px; `; const EmotionComponent = () => { return <div css={boxStyle}>Emotion 스타일 적용</div>; };
동적 스타일 적용
const dynamicStyle = (isActive: boolean) => css` background-color: ${isActive ? "blue" : "gray"}; color: white; padding: 10px; `; const DynamicStyledComponent = ({ isActive }: { isActive: boolean }) => { return <div css={dynamicStyle(isActive)}>테마 변경</div>; };
2. @emotion/styled
패키지 | 설명 |
@emotion/styled | Styled Components 스타일 관리 |
@emotion/styled는 styled-components와 유사한 방식 으로 컴포넌트 스타일링사용
import styled from "@emotion/styled"; const Button = styled.button` background-color: #007bff; color: white; padding: 10px; border-radius: 5px; &:hover { background-color: #0056b3; } `; const EmotionStyledComponent = () => { return <Button>Emotion Styled 버튼</Button>; };
Props를 활용한 동적 스타일링
const StyledButton = styled.button<{ primary: boolean }>` background-color: ${(props) => (props.primary ? "blue" : "gray")}; color: white; padding: 10px; `; const App = () => { return ( <> <StyledButton primary={true}>Primary</StyledButton> <StyledButton primary={false}>Default</StyledButton> </> ); };
호텔 키오스크에서 활용
Emotion을 활용한 글로벌 테마 관리
ThemeProvider와recoil을 조합하여 테마 변경 기능을 구현
components/layouts/ThemeContainer.tsx에서 Recoil 상태를 활용하여 동적 테마 적용
ThemeContainer.tsximport { useLowVisionState, useLowScreenState } from '@/recoil/theme'; import { ThemeProvider } from '@emotion/react'; import React, { useMemo } from 'react'; import { useRecoilValue } from 'recoil'; export interface EmotionTheme { useLowVision: boolean; useLowScreen: boolean; } const ThemeContainer = ({ children }: { children: React.ReactElement }) => { const useLowVision = useRecoilValue(useLowVisionState); const useLowScreen = useRecoilValue(useLowScreenState); // 의존성 배열(useLowVision, useLowScreen)이 변경될 때만 새로운 객체를 생성 const theme = useMemo<EmotionTheme>(() => { return { useLowVision, useLowScreen }; }, [useLowVision, useLowScreen]); // theme 객체를 리액트 컴포넌트 트리에 전달 // 이 테마는 하위 컴포넌트에서 Emotion의 useTheme() 훅을 통해 접근가능 return <ThemeProvider theme={theme}>{children}</ThemeProvider>; }; export default ThemeContainer;
레이아웃 컴포넌트에서
ThemeProvider로 감싸면, useTheme() 훅을 통해, 테마 정보 가져올 수 있음
→ 하위 컴포넌트에서
useTheme()를 통해 테마 상태를 참조컴포넌트에서
ThemeProvider 사용import styled from "@emotion/styled"; const ThemedBox = styled.div` background: ${(props) => props.theme.background}; color: ${(props) => props.theme.text}; padding: 20px; `; const ThemedComponent = () => { return <ThemedBox>테마 적용</ThemedBox>; };

@emotion/react는 CSS를 동적으로 적용할 때 사용
@emotion/styled는 컴포넌트 단위로 스타일을 관리할 때 사용 (스타일드 컴포넌트 대체)
({ theme })값은ThemeProvider를 통해 전역 테마 설정된 값을 가져와 사용.
- Recoil과 함께 테마 변경 및 UI 스타일링을 담당