지금까지는 CSS-in-JS 인, styled-components 를 사용해왔었다. 최근에 emotion 으로 사용하는 분들이 점점 늘어가는 추세인 것 같아서 나도 이번 기회에 emotion에 대하여 알아보려한다.
styled-components와 매우 비슷하여 배움에 있어서는 큰 어려움이 없어보였으나, 직접 부딪혀 봐야 알 것 같다.
기존에 styled-components로 반응형 레이아웃
을 구현해놓은 것이 있었는데, 이것을 emotion 으로 볼 것이고, 전역적으로 사용될 css 인 globalStyles
와 theme
역시 emotion 으로 대체하여 볼 것이다.
아래와 같은 순서로 글을 작성해보려 한다.
- styled-components 와 emotion 의 차이점
- styled-components 를 emotion 으로 변환하기
- global styles
- theme
- 반응형 레이아웃
https://blog.songc.io/react/react-js-in-css/
https://velog.io/@bepyan/styled-components-%EA%B3%BC-emotion-%EB%8F%84%EB%8C%80%EC%B2%B4-%EC%B0%A8%EC%9D%B4%EA%B0%80-%EB%AD%94%EA%B0%80
세계 인지도는 emotion 이 높고, 국내에서는 아직 styled-component 가 우위에 있다.
번들 크기
로는 emotion
이 styled-components 보다 작다
. 성능
상으로는 유의미하게 차이가 나지는 않는다
.
또한, emotion
에서는 서버 사이드 렌더링
에 따로 서버쪽에 설정을 하지 않아도 된다
는 장점이 있다. 서버 사이드 렌더링 설정 시, emotion에서는 별도의 설정 없이 작동되는 반면, styled-components
는 설정이 필요
하는 번거로움이 있다.
import { createGlobalStyle } from 'styled-components';
import reset from 'styled-reset';
const GlobalStyle = createGlobalStyle`
${reset}
html {
font-size: 16px;
};
body {
font-family: 'Noto Sans KR', sans-serif;
}
select,
input,
button,
textarea {
border: 0;
outline: 0 !important;
}
`;
export default GlobalStyle;
// src/styles/global
import React from 'react';
import { Global, css } from '@emotion/react';
const style = css`
html {
font-size: 16px;
}
body {
font-family: 'Noto Sans KR', sans-serif;
}
select,
input,
button,
textarea {
border: 0;
outline: 0 !important;
}
`;
const GlobalStyle = () => {
return <Global styles={style} />;
};
export default GlobalStyle;
import React from 'react';
import { render } from 'react-dom';
import GlobalStyle from '@src/styles/global';
import theme from '@src/styles/theme';
import { ThemeProvider } from '@emotion/react';
render(
<ThemeProvider theme={theme}>
<GlobalStyle />
</ThemeProvider>,
document.querySelector('#app'),
);
import styled, { css } from 'styled-components';
const fontSizes = {
xxs: '12px',
xs: '13px',
sm: '14px',
base: '16px',
md: '18px',
lg: '24px',
};
const colors = {
black: '#000',
dark: '#191a20',
primary: '#3f4150',
secondary: '#8c8d96',
};
const theme = {
fontSizes,
colors,
};
export default theme;
type
을 지정해주어야 한다.// theme.ts
import { DefaultTheme } from '@emotion/react';
const theme: DefaultTheme = {
fontSizes: {
xxs: '12px',
xs: '13px',
sm: '14px',
base: '16px',
md: '18px',
lg: '24px',
},
colors: {
black: '#000',
dark: '#191a20',
primary: '#3f4150',
secondary: '#8c8d96',
},
};
export default theme;
// theme.d.ts
import '@emotion/react';
declare module '@emotion/react' {
export interface DefaultTheme {
fontSizes: {
xxs: string;
xs: string;
sm: string;
base: string;
md: string;
lg: string;
};
colors: {
black: string;
dark: string;
primary: string;
secondary: string;
};
}
}
styled-media-query
라이브러리를 사용하여 tablet, desktop 사이즈를 나누었다.
import { generateMedia } from 'styled-media-query'
import { theme } from '../index'
export const media = generateMedia({
...theme.breakpoints,
})
Emotion 문서를 참고하여, tablet, desktop breakpoints 를 설정하였다.
const breakpoints = [768, 1200];
export const media = breakpoints.map((bp) => `@media (min-width: ${bp}px)`);
위에서 styled-media-query
를 사용하여 media를 구현하였던 것을 사용하였다. tablet 과 desktop 으로 나누어 css 를 적용할 수 있다.
export const StyledContainer = styled.div`
width: 100%;
padding: 0 5px;
margin: 0 auto;
${media.greaterThan('tablet')`
max-width: 1020px;
padding: 0 30px;
`}
${media.greaterThan('desktop')`
max-width: 1140px;
padding: 0;
`}
`;
export const StyledContainer = styled.div`
width: 100%;
padding: 0 5px;
margin: 0 auto;
${media[0]} {
max-width: 1020px;
padding: 0 30px;
}
${media[1]} {
max-width: 1140px;
padding: 0;
}
`;
emotion 을 아직 제대로 학습하지 않아, 코드 구현이 미숙하지만 포트폴리오를 진행하며 꾸준히 배울 생각이다. styled-components, emotion 둘다 장점과 단점이 각각 존재하는 것 같다. 그래서 아직까지는 어떤 것이 더 좋은지는 잘 모르겠으나, 회사에 입사하였을 때 만약 emotion 을 사용한다고 할 수도 있으니 코드 구현시에 거부감이 들지않게 미리 배워놓는 것이 좋을 것 같다.