※ 체크리스트
① Emotion 라이브러리의 개념과 CSS-in-JS 방식의 장점을 이해하기
② Emotion을 활용해 React 프로젝트에 스타일링을 적용하는 방법을 학습하기
③ Emotion의 고급기능(동적 스타일링, 테마, 애니메이션) 익히기
1. Emotion
1-1. Emotion 정의
Emotion : CSS-in-JS 방식의 강력한 스타일링 라이브러리, JavaScript 코드 내에서 스타일을 작성하고 컴포넌트 별로 적용할 수 있다
1-2. Emotion의 특징
1) CSS와 JavaScript의 통합 :
스타일과 로직을 한 파일에 작성 가능하다
2) 동적 스타일링 지원 :
props와 상태에 따라 스타일 변경이 가능하다
3) 높은 성능 :
스타일이 필요한 시점에만 동적으로 생성과 적용이 가능하다
4) 다양한 스타일링 방식 지원 :
css 함수, styled API, 객체 스타일링 방식을 지원한다
2. Emotion 기본 사용법
2-1. 설치
npm install @emotion/react @emotion/styled
2-2. 사용법
css 함수를 사용한 스타일 적용, styled API를 사용하는 스타일링 방식 두 가지가 있다
1) css 함수 사용
css 함수는 Emotion의 기본 스타일링 방식 중 하나로,
CSS-in-JS 방식으로 스타일을 작성해 해당 스타일을 컴포넌트의 css prop에 직접 전달한다
① 사용법 예시
/** @jsxImportSource @emotion/react */
import { css } from '@emotion/react';
const buttonStyle = css`
background-color: blue;
color: white;
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
&:hover {
background-color: darkblue;
}
`;
function App() {
return <button css={buttonStyle}>Click Me</button>
}
export default App;
● css 스타일 코드를 템플릿 리터럴(' ') 안에 작성한다
● Emotion은 css prop을 사용해 스타일을 전달할 수 있다
② 장점 :
특정 스타일을 여러 컴포넌트에 재사용하기 쉽고 기존 스타일 객체와 결합하기도 용이하다
2) styled API 사용
HTML 요소 또는 React 컴포넌트를 기반으로 새로운 스타일 컴포넌트를 생성한다
① 사용법 예시
import styled from '@emotion/styled';
const Button = styled.button'
background-color: blue;
color: white;
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
&:hover {
background-color: darkblue;
}
';
function App() {
return <Button>Click Me</Button>
}
export default App;
특정 HTML 태그(button, div, p 등)을 래핑하여 스타일을 가진 새로운 컴포넌트를 만든다
② 장점 :
HTML 태그가 아닌 React 컴포넌트를 래핑하여 더 높은 재사용성을 제공한다
코드가 깔끔하고 가독성이 좋다
3) css 함수와 styled API의 차이점과 활용
특징 | css 함수 | styled API |
스타일 재사용 | 재사용 가능(스타일 변수를 여러 곳에 전달) | 재사용 가능(컴포넌트를 여러 곳에서 사용) |
가독성 | JSX 코드가 스타일과 함께 섞일 수 있다 | 스타일 코드와 컴포넌트 구조가 더 명확하다 |
동적 스타일링 | 스타일 내부에서 props를 사용할 때 약간 복잡할 수 있다 | props를 통해 동적 스타일링이 간편하다 |
추천 사용 사례 | 간단한 컴포넌트 또는 동적 스타일 적용 시 | 재사용 가능한 컴포넌트 스타일링 시 사용 |
3. Emotion의 동적 스타일링과 고급 기능을 한 프로젝트에서 실행해보며 해당 내용을 공부해보겠다
3. Emotion의 동적 스타일링과 고급기능
3-1. 동적 스타일링 적용
1단계 : props 기반 스타일링
styled API에서 props를 사용해 동적으로 스타일 변경
// props 기반 동적 스타일링
const Button = styled.button`
background-color: ${(props) => (props.primary ? 'blue' : 'gray')};
color: white;
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
&:hover {
background-color: ${(props) => (props.primary ? 'darkblue' : 'darkgray')};
}
`;
function App() {
return (
<div>
<Button primary>Primary Button</Button>
<Button>Secondary Button</Button>
</div>
);
}
2단계 : 객체 스타일링
css 함수에서 객체 형태로 스타일 정의
// 객체 스타일링
const buttonStyle = {
background: 'blue',
color: 'white',
padding: '10px 20px',
border: 'none',
borderRadius: '5px',
cursor: 'pointer',
'&:hover': {
},
};
function App() {
return <button css={buttonStyle}>Click Me</button>
}
3-2. 고급 기능 스타일링 적용
1단계 : 글로벌 스타일
Global 컴포넌트를 사용해 전역 스타일 정의
import { Global, css } from '@emotion/react';
const globalStyle = css`
body {
margin: 0;
font-family: Arial, sans-serif;
background-color: #f0f0f0;
}
`;
function App() {
return (
<Global styles={globalStyle} />
<h1>Emotion</h1>
);
}
export default App;
2단계 : 테마 기반 스타일링
ThemeProvider를 사용해 테마 적용
import { ThemeProvider } from '@emotion/react';
const theme = {
primary: 'blue',
secondary: 'gray',
};
const Button = styled.button`
background-color: ${(props) => props.theme.primary};
color: white;
padding: 10px 20px;
`;
function App() {
return (
<ThemeProvider theme={theme}>
<Button>Styled Button</Button>
</ThemeProvider>
);
}
export default App;
3단계 : 애니메이션
keyframes를 사용해 애니메이션 적용
import { keyframes } from '@emotion/react';
import styled from '@emotion/styled';
const fadeIn = keyframes`
from {
opacity: 0;
}
to {
opacity: 1;
}
`;
const AnimatedDiv = styled.div`
animation: ${fadeIn} 2s ease-in-out;
`;
function App() {
return <AnimatedDiv>Fading In</AnimatedDiv>;
}
3-3. 전체 코드 및 실행
1) 프로젝트 생성
npx create-react-app react-emotion-styling
2) Emotion 라이브러리 설치
npm install @emotion/react @emotion/styled
3) App.js 코드 수정
* 전체 코드
/** @jsxImportSource @emotion/react */
import { css, Global, keyframes } from '@emotion/react';
import styled from '@emotion/styled';
import { ThemeProvider } from '@emotion/react';
// 1. 고급 기능 스타일링 적용 - 1단계 : 글로벌 스타일 정의
const globalStyle = css`
body {
margin: 0;
font-family: Arial, sans-serif;
background-color: #f0f0f0;
}
`;
// 2. 고급 기능 스타일링 적용 - 2단계 : 테마 정의
const theme = {
primary: 'blue',
secondary: 'gray',
};
// 3. Emotion의 동적 스타일링 적용 - 1단계 : props 기반 동적 스타일링
const Button = styled.button`
background-color: ${(props) => (props.primary ? props.theme.primary : props.theme.secondary)};
color: white;
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
&:hover {
background-color: ${(props) => (props.primary ? 'darkblue' : 'darkgray')};
}
`;
// 4. Emotion의 동적 스타일링 적용 - 2단계 : 객체 스타일링
const buttonStyle = {
backgroundColor: 'blue',
color: 'white',
padding: '10px 20px',
border: 'none',
borderRadius: '5px',
cursor: 'pointer',
'&:hover': {
backgroundColor: 'skyblue',
},
};
// 5. 고급 기능 스타일링 적용 - 3단계 : 애니메이션 적용
const fadeIn = keyframes`
from {
opacity: 0;
}
to {
opacity: 1;
}
`;
const AnimatedDiv = styled.div`
animation: ${fadeIn} 2s ease-in-out;
margin: 20px 0;
`;
function App() {
return (
// 테마 기반 스타일 적용
<ThemeProvider theme={theme}>
{/* 글로벌 스타일 적용*/}
<Global styles={globalStyle} />
<h1 css={{ textAlign: 'center' }}>Emotion Demo</h1>
{/* 동적 스타일링 적용 - 1단계 : props 기반 스타일링 */}
<div css={{ textAlign: 'center', marginBottom: '20px' }}>
<Button primary>Primary Button</Button>
<Button style={{ marginLeft: '10px' }}>Secondary Button</Button>
</div>
{/* 동적 스타일링 적용 - 2단계 : 객체 스타일링 */}
<div css={{ textAlign: 'center' }}>
<button css={buttonStyle}>Click Me</button>
</div>
{/* 애니메이션 */}
<AnimatedDiv css={{ textAlign: 'center' }}>Fading In Animation</AnimatedDiv>
</ThemeProvider>
);
}
export default App;
4) 실행
npm start
5) 화면 및 결과
① 글로벌 스타일 : Global 컴포넌트를 사용해 전역 스타일(body 배경 컬러, 폰트 등) 설정해주었다
② 테마 기반 동적 스타일링 : ThemeProvider를 사용해 primary와 secondary 색상을 전달하며 props를 활용해 버튼 스타일이 동적으로 변경된다
③ 객체 스타일링 : css 함수 대신 객체 형태로 스타일을 정의하여 버튼에 적용한다
④ 애니메이션 : keyframes로 정의한 페이드 인 애니메이션을 AnimatedDiv 컴포넌트에 적용한다
● 페이지 상단에 Emotion Demo 표시
● 두 개의 버튼 : Primary Button, Secondary Button(props 기반 스타일링)
● 객체 스타일로 만든 버튼 : Styled with Object
● 페이드 인 애니메이션 효과를 가진 텍스트 Fading In Animation
4. 실습 과제
4-1. 실습 목표
① Emotion을 사용해 Card 컴포넌트를 생성하고 제목과 내용을 스타일링하기
② props를 활용해 primary 및 secondary 버튼 스타일을 동적으로 변경하기
③ 테마를 정의하여 컬러, 폰트 스타일을 중앙에서 관리하기
4-2. React 프로젝트 준비
1) 프로젝트 생성
npx create-react-app react-emotion-practice
2) Emotion 라이브러리 설치
npm install @emotion/react @emotion/styled
4-3. 코드 구현
* 사용 프로그램 : VSCode
1) 계획 : App.js만 수정할 예정
2) App.js에서 모든 구현이 가능한 이유 :
ⓘ Emotion의 유연성 : styled와 css를 활용해 한 파일에서 모든 스타일을 작성할 수 있음
ⓙ ThemeProvider : 테마를 최상위에서 정의하여 모든 하위 컴포넌트에 스타일을 쉽게 전달할 수 있음
ⓚ 글로벌 스타일 : Global로 공통 스타일을 설정해, 추가적인 CSS 파일이 필요하지 않음
3) 코드 작성
> App.js 수정
* 전체 코드
// App.js
/** @jsxImportSource @emotion/react */
import { css, Global } from '@emotion/react';
import styled from '@emotion/styled';
import { ThemeProvider } from '@emotion/react';
// 1. 글로벌 스타일 정의
const globalStyle = css`
body {
margin: 0;
font-family: 'Arial', sans-serif;
background-color: #f9f9f9;
}
`;
// 2. 테마 정의
const theme = {
colors: {
primary: '#007bff',
secondary: '#6c757d',
text: '#212529',
background: '#ffffff',
},
fonts: {
main: 'Arial, sans-serif',
},
};
// 3. Card 컴포넌트 스타일
const Card = styled.div`
background-color: ${(props) => props.theme.colors.background};
border: 1px solid ${(props) => props.theme.colors.secondary};
border-radius: 8px;
padding: 16px;
margin: 16px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
text-align: center;
h2 {
color: ${(props) => props.theme.colors.primary};
margin-bottom: 8px;
}
p {
color: ${(props) => props.theme.colors.text};
font-size: 16px;
}
`;
// 4. Button 컴포넌트 스타일
const Button = styled.button`
background-color: ${(props) => (props.primary ? props.theme.colors.primary : props.theme.colors.secondary)};
color: #fff;
padding 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 14px;
margin: 0 8px;
&:hover {
background-color: ${(props) => (props.primary ? '#0066b3' : 'skyblue')};
}
`;
// 5. App 컴포넌트
function App() {
return (
<ThemeProvider theme={theme}>
{/* 글로벌 스타일 적용 */}
<Global styles={globalStyle} />
{/* Card 컴포넌트 */}
<Card>
<h2>Emotion Card</h2>
<p>This is a card styled with Emotion and theming</p>
<div>
{/* 동적 버튼 스타일링 */}
<Button primary>Primary Button</Button>
<Button>Secondary Button</Button>
</div>
</Card>
</ThemeProvider>
);
}
export default App;
4-4. 실행
npm start
1) 화면
2) 설명
① Card 컴포넌트 :
제목 : 파란색(primary color)
배경 : 흰색
② Buttons
● Primary 버튼 : blue background
● Secondary 버튼 : 회색 background
+ git에 REACT-EMOTION-STYLING과 REACT-EMOTION-PRACTICE로 업로드!
※ 정리
① Emotion과 styled Components의 공통점과 차이점은 ?
→ Emotion과 styled Components는 CSS-in-JS 라이브러리로, JavaScript 코드 내에서 CSS 스타일을 작성할 수 있다
→ 공통점
▶ CSS-in-JS 방식 : 컴포넌트 단위로 스타일을 작성
▶ 스타일 동적 처리 : props를 사용해 스타일을 동적으로 변경할 수 있다
▶ 지원 브라우저 : 최신 브라우저와 IE11 이상을 지원한다
▶ SSR 지원 : 서버사이드 렌더링(SSR) 지원한다
→ 차이점
특징 | Emotion | Styled Components |
유연성 | 다양한 스타일링 접근법을 지원 (css, styled, Global, keyframes 등) |
styled 기반 API만 제공 |
퍼포먼스 | Emotion은 런타임 최적화 및 정적 추출 기능이 존재 > 퍼포먼스가 우수함 | 런타임이 빠르지만 Emotion의 정적 추출에는 뒤처질 수 있음 |
파일 크기 | 더 작은 패키지 크기를 가지고 있으며 필요에 따라 모듈만 설치 가능함 (@emotion/react , @emotion/styled) |
styled Components는 Emotion보다 상대적으로 패키지 크기가 더 큼 |
스타일링 방식 | css 함수를 통해 객체 스타일링과 클래식 CSS 문자열 스타일링을 지원함 | CSS 문자열 스타일링 방식만 제공함 |
테마 사용 | 테마 지원(ThemeProvider) 과 사용자 정의가 유연함 | 테마 지원은 있지만 Emotion처럼 다양한 방식으로 접근하지 못함 |
커뮤니티 및 에코시스템 | styled Components보다 상대적으로 작은 사용자 기반을 가지고 있지만, 최근 들어 빠르게 성장 중 | 넓은 커뮤니티와 오래된 에코시스템을 가지고 있음 |
② Emotion은 대규모 프로젝트에서 어떻게 사용할 수 있을까?
→ 성능 최적화와 유연한 설정이 필요한 대규모 프로젝트에서 관리성과 재사용성을 극대화할 수 있다
→ 사용 방법
▶ 1. 글로벌 스타일과 테마 관리 (Global 스타일 정의, ThemeProvider 활용)
const theme = {
colors: {
primary : '#007bff',
secondary: '#6c757d',
},
spacing: {
small : '8px',
medium : '16px',
large : '24px',
},
};
<ThemeProvider theme={theme}>
<App />
</ThemeProvider>
▶ 2. 컴포넌트 기반 스타일링 : Emotion의 styled를 사용해 기본 컴포넌트를 만들어 재사용한다
const PrimaryButton = styled.button`
background-color : ${(props) => props.theme.colors.primary};
padding : ${(props) => props.theme.spacing.medium};
color : white;
`;
▶ 3. 동적 스타일링 : 컴포넌트에 props를 전달해 스타일을 동적으로 변경
const Button = styled.button`
background-color: ${(props) => (props.primary ? props.theme.colors.primary : props.theme.colors.secondary)};
`;
▶ 4. 모듈화된 스타일링 : 각 컴포넌트의 스타일을 별도의 파일에 저장하고 컴포넌트에 필요할 때만 로드
// styles/button.js
export const buttonStyle = css`
background-color: blue;
color: white;
`;
// Button.jsx
import { buttonStyle } from './styles/button';
function Button() {
return <button css={buttonStyle}>Click Me</button>;
}
▶ 5. 코드 스플리팅
- Emotion은 코드 스플리팅을 지원하여, 필요한 스타일만 번들에 포함되도록 최적화함
- 정적 CSS 추출을 사용해 런타임에서 스타일 생성 비용을 줄일 수 있음
▶ 6. SSR(Server-Side-Rendering)
- Emotion은 서버사이드 렌더링을 지원하며 Next.js 같은 프레임워크와 쉽게 통합이 가능함
☞ Emotion은 CSS와 JavaScript를 통합해 강력한 스타일링 도구를 제공한다
☞ css 함수, styled API, 글로벌 스타일 및 테마 등 다양한 기능을 활용해 스타일을 관리할 수 있다
☞ 동적 스타일링과 성능 최적화에 강점을 가지며, React 프로젝트에 적합한 CSS-in-Js 솔루션이다
'개발 기록 > front - react' 카테고리의 다른 글
React Context API로 상태 관리하기 : Props Drilling 해결 (0) | 2024.12.27 |
---|---|
React에서 Hook이란? (공부 + 면접 답변용) (3) | 2024.12.18 |
React Query로 서버 상태 관리하기 : 데이터 패칭과 캐싱 (0) | 2024.12.17 |
[React] 함수형 컴포넌트 (1) | 2024.11.27 |
[React] React 컴포넌트 생명주기, 생명주기 메소드 (0) | 2024.11.26 |