๐ก ์ด ํฌ์คํ ์ styled-components์ ๋ํด ํผ์ ๊ณต๋ถํ๋ฉฐ ์ ๋ฆฌํ ๋ด์ฉ์ ๋๋ค. ํน์ฌ๋ ์ผ๋ถ ์ฌ๋ฐ๋ฅด์ง ์์ ์ ๋ณด๊ฐ ์์ ์์ ์ง์ ํด์ฃผ์๋ฉด ์ ์ ํ ๋กํ๊ฒ ์ต๋๋ค.
styled-components ์ฌ์ฉ๋ฒ ์ ๋ฆฌ์ ํ๋ก์ ํธ ์ฝ๋ ๋ฆฌํฉํ ๋ง์ ํตํ ์ค์ต์ ๋ชฉํ๋ก ํฉ๋๋ค.
React์์๋ ๋ณดํต CSS-in-JS์ ํตํด ์คํ์ผ ์์ ์ ์งํํ๋ค.
๋ํ์ ์ผ๋ก ์ฌ์ฉ๋๋ CSS-in-JS ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ emotion
๊ณผ styled-components
๊ฐ ์๋ค.
์ด๋ฒ ํฌ์คํ
์์๋ styled-components
์ ํน์ง๊ณผ ์ฅ/๋จ์ ๊ทธ๋ฆฌ๊ณ ์ฌ์ฉ ๋ฐฉ๋ฒ์ ๋ํด ๋ค๋ค๋ณด๊ณ ์ ํ๋ค.
stlyed-components๋ CSS-in-JS์ ๋ํ์ ์ธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ด๊ธฐ ๋๋ฌธ์ ์ด๋ฅผ ์๊ธฐ์ ์ CSS-in-JS์ ๋ํด ์์์ผํ๋ค.
์ ์ปดํฌ๋ํธ ์คํ์ผ ๋ฐฉ์์ ๊ธฐ์กด CSS์ ์๋
๋จ์ ์ ๊ทน๋ณตํ๊ณ ์ ๊ฐ๋ฐ๋์๋ค.
CSS ๋ฌธ์ ์ (Vjeux)
- Global namespace: ๋ชจ๋ ์คํ์ผ์ด global์ ์ ์ธ๋์ด ์ค๋ณต๋์ง ์๋ class ์ด๋ฆ์ ์ ์ฉํด์ผ ํ๋ ๋ฌธ์
- Dependencies: css ๊ฐ์ ์์กด๊ด๊ณ๋ฅผ ๊ด๋ฆฌํ๊ธฐ ํ๋ ๋ฌธ์
- Dead Code Elimination: ๊ธฐ๋ฅ ์ถ๊ฐ, ๋ณ๊ฒฝ, ์ญ์ ๊ณผ์ ์์ ๋ถํ์ํ CSS๋ฅผ ์ ๊ฑฐํ๊ธฐ ์ด๋ ค์ด ๋ฌธ์
- Minification: ํด๋์ค ์ด๋ฆ์ ์ต์ํ ๋ฌธ์
- Sharing Constants: JS ์ฝ๋์ ์ํ ๊ฐ์ ๊ณต์ ํ ์ ์๋ ๋ฌธ์
- Non-deterministic Resolution: CSS ๋ก๋ ์์์ ๋ฐ๋ผ ์คํ์ผ ์ฐ์ ์์๊ฐ ๋ฌ๋ผ์ง๋ ๋ฌธ์
- Isolation: CSS์ JS๊ฐ ๋ถ๋ฆฌ๋ ํ์ ์์์ ๋ฐ๋ฅธ ๊ฒฉ๋ฆฌ๊ฐ ์ด๋ ค์ด ๋ฌธ์
๊ฐ๋จํ๊ฒ ์ค๋ช ํ์๋ฉด ๊ธฐ์กด CSS ์คํ์ผ๋ง ๋ฐฉ์์ ํ๋ก์ ํธ๊ฐ ์ปค์ง์๋ก ๋ชจ๋ html ์์์ ํด๋์ค ๋ค์ด๋ฐ์ ๋ช ์ํด์ผํ๊ณ ,
์ปดํฌ๋ํธ ์คํ์ผ์ ๋ณ๊ฒฝํ ๋ ํด๋์ค์ ๋ง๋ CSS Selector์ ์ผ์ผํ ์ฐพ์ ๋ณ๊ฒฝํด์ผํ๊ธฐ ๋๋ฌธ์ ๋ฒ๊ฑฐ๋ก์ธ ์ ๋ฐ์ ์๋ค.
๊ทธ๋์ ๊ธฐ์กด์ CSS ํ์ผ์ ์์ฑ, ๊ด๋ฆฌํ๋ ๊ณผ์ ์ CSS-in-JS์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ์ปดํฌ๋ํธ ๋จ์๋ก ๊ฐ๋ฐ๋ JSํ์ผ์ CSS ์คํ์ผ๋ง์ ํ๊ฒ ๋๋ค.
ํ์ง๋ง, ๋ฌด์กฐ๊ฑด CSS-in-JS๊ฐ ์ข์ ๊ฒ ๋ง์ ์๋๋ค.
runtime overhead๊ฐ ์ผ์ด๋ ์ ์๋ค. ์ฌ์ฉ์์์ interaction์์ ์ ๋๋ฉ์ด์
๋ฑ๊ณผ ๊ฐ์ ์ฐ์ฐ์ด ํ์ํ ํ์ด์ง์ ๊ฒฝ์ฐ (๋ฐํ์์์ ๋์ ์ผ๋ก ์คํ์ผ์ ์์ฑํ๊ธฐ ๋๋ฌธ์) ์ฑ๋ฅ ์ด์๊ฐ ๋ฐ์ํ ์ ์๋ค.
์กฐ๊ธ ๋ ๊น์ด ์ดํดํ๊ธฐ ์ํด์๋ CSS-in-JS์ ๋์๋ฐฉ์์ธ runtime, zero-runtime ๋ฑ์ ์ฐพ์๋ณด๊ธธ ๋ฐ๋๋ค.
๊ธฐ์กด CSS-in-CSS ๋ฐฉ์์ ์ฒซ ํ์ด์ง๊ฐ ๋ก๋๋ ๋ ์ ์ฉ ๊ฐ๋ฅํ ๋ชจ๋ ์คํ์ผ๋ค์ ๋ง๋ค์ด๋๊ธฐ ๋๋ฌธ์ ์ปดํฌ๋ํธ์ ์ํ๊ฐ ๋ณ๊ฒฝ๋๋ค ํ๋๋ผ๋ ๋ฐ๋ก๋ฐ๋ก ์ ์ฉ์ด ๊ฐ๋ฅํ๋ค.
ํ์ง๋ง CSS-in-JS์ ๊ฒฝ์ฐ, ์ํ๊ฐ ๋ณ๊ฒฝ๋๋ฉด ์ฐ์ JS์ CSS ์ฝ๋๋ฅผ ์ฝ์ด์์ ํ์ฑํ๋ ๋จ๊ณ๋ถํฐ ์์ํ๊ธฐ ๋๋ฌธ์ ์๋ฌด๋๋ ๋ฆ์ด์ง ์ ๋ฐ์ ์๋ ๋ฌธ์ ๊ฐ ์๋ค.
์ถ๊ฐ์ ์ธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค์น๊ฐ ํ์ํ๊ธฐ ๋๋ฌธ์ JS์ ๋ฒ๋ค ํฌ๊ธฐ๊ฐ ์ปค์ง๋ ์ , ์ด์ ๋ฐ๋ผ ์ต์ด ๋ ๋๋ง์ ์๋์ ์ผ๋ก ์๊ฐ์ด ๋ ์ค๋ ๊ฑธ๋ฆฐ๋ค๋ ๊ฒ ๋ํ ๋จ์ ์ผ๋ก ๋ณผ ์ ์๋ค.
์ ์ฅ/๋จ์ ์ ๊ณ ๋ คํ๋ค ์คํ์ ์ฑ์ฉํ๋ ๊ฒ๋ ์ค์ํ์ง๋ง
๊ฐ์ธ์ ์ผ๋ก ์ ์๋ฏธํ ํผํฌ๋จผ์ค์ ์ฐจ์ด๊ฐ ๋์ง ์๋๋ค๋ฉด ๊ฐ๋ฐ ๋ฌธํ์ ๋ง๋์ง,๊ฐ๋ฐ ์นํ์
์ธ์ง๊ฐ ๊ฐ์ฅ ์ค์ํ ์ด์๋ผ๊ณ ์๊ฐ์ด ๋ ๋ค..
CSS-in-JS ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค styled-components๋ก ๋์์ธ ์์คํ ์ ๊ตฌ์ถํ๊ธฐ๋ก ํ๋ค๊ณ ๊ฐ์ ํ์. emotion์ ์ถํ์ ๋ค๋ค๋ณด๊ฒ ๋ค.
๋ด๊ฐ CSS-in-JS ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค ์ค์์ emotion
๋ฑ ๋ค์ํ ๊ฒ๋ค์ ์ ์ธํ๊ณ styled-components
๋ฅผ ๋จผ์ ๊ณต๋ถํ๋ ์ด์ ๋
์์ง๊น์ง ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋๋น ์ฌ์ฉ๋์ด ๋๊ธฐ ๋๋ฌธ์ด๋ค. (reference๊ฐ ๋ง๊ฒ ์ฃต?) ์ถํ์๋ emotion
stylex
stitches.js
๊ณผ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์ฌ์ฉํด๋ณด๊ณ ์ํ๋ค.
stlyed-conponents
์ ์ฅ์ ์ ์๋์ ๊ฐ๋ค. ๋๋ถ๋ถ CSS-in-JS์ ์ฅ ๋จ์ ์ ์์๋ฐ๊ณ ์๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
vendor prefix
๋จ์ ์ ์๋์ ๊ฐ๋ค.
์ฅ ๋จ์ ์ ์ ๋ฆฌํ๋ฉด์ ํ๋ฒ ๋
๊ฐ๋ฐ ์นํ์
์ธ ์ ์ด ์ค์ํ๋ค๋ ์๊ฐ์ด ๋ ๋ค.
์ค์น๋ถํฐ ์์ ๊น์ง ์์ฑํด๋ณด์.
์๋ ๋ช ๋ น์ด๋ฅผ ์์ฑํด ์๋ก์ด CRA ์ฑ์ ์์ฑํ๊ณ , styled-components๋ฅผ ์ค์นํด์ค๋ค.
$ npx create-react-app project-name
$ npm i styled-components
App.js
์ปดํฌ๋ํธ์ ์๋์ ๊ฐ์ด ์์ฑํ๋ค.
import React from 'react';
import styled from 'styled-components';
const Wrapper = styled.div`
display: flex;
height: 100px;
width: 100px;
justify-content: center;
align-items: center;
background-color: black;
`;
function App() {
return <Wrapper>
</Wrapper>;
}
export default App;
styled-components ๋ฅผ ์ฌ์ฉํ๋ฉด ์ด๋ ๊ฒ ์คํ์ผ์ ์ ๋ ฅํจ๊ณผ ๋์์ ํด๋น ์คํ์ผ์ ๊ฐ์ง ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค ์ ์๋ค.
์ ์์ ์ฒ๋ผ div ๋ฅผ ์คํ์ผ๋ง ํ๊ณ ์ถ์ผ๋ฉด styled.div + ๋ฐฑํฑ์ ์ฌ์ฉํ๋ฉด ๋๊ณ , span์ด๋ button ์ ์คํ์ผ๋ง ํ๊ณ ์ถ์ผ๋ฉด styled.tag-name ์ผ๋ก ์ฌ์ฉํ๋ฉด ๋๋ค.
์ผ๊ด์ ์ธ ์คํ์ผ ๊ด๋ฆฌ๋ฅผ ์ํด ์์ฃผ ์ฌ์ฉํ๊ฒ ๋ ์์ ์ฝ๋, ์ฌ์ด์ฆ ๋ฑ์ ์ ๋ณด๋ฅผ ์์ฑํด ์์ ์ปดํฌ๋ํธ์ ์ ์ํ ์ ์๋ค.
styled-component์์ ์ด๋ฐ ๋ณ์ ๊ฐ์ฒด๋ฅผ theme
์ด๋ผ๊ณ ๋ถ๋ฅธ๋ค.
์์ ์ปดํฌ๋ํธ index.js
import React from 'react';
import { ThemeProvider } from 'styled-components';
import App from './App';
const darkTheme = {
textColor: "whitesmoke",
backgroundColor: "#111"
};
const lightTheme = {
textColor: "#111",
backgroundColor: "whitesmoke"
};
ReactDOM.render(
<React.StrictMode>
<ThemeProvider theme={darkTheme}>
<App />
</ThemeProvider>
</React.StrictMode>,
document.getElementById('root')
);
์ต์์ ์ปจํ
์ด๋์์ ThemeProvider
ํ๊ทธ์ theme ๊ฐ์ฒด๋ฅผ ๋ณด๋ด์ค๋ค.
ํ์ ์ปดํฌ๋ํธ App.js
import React from 'react';
import styled from 'styled-components';
const Title = styled.h1`
color: ${props => props.theme.textColor};
`;
const Wrapper = styled.div`
display: flex;
height: 100vh;
width: 100vw;
justify-content: center;
align-items: center;
background-color: ${props => props.theme.backgroundColor};
`;
function App() {
return <Wrapper>
<Title>Title</Title>
</Wrapper>;
}
export default App;
theme ๊ฐ์ฒด๋ ํ
ํ๋ฆฟ ๋ฆฌํฐ๋ด ๋ด๋ถ์ props.theme.value
๋ก ๊ฐ์ ์ ๊ทผํ ์ ์๋ค.
๋ฐ๋ก ํ์ ์ปดํฌ๋ํธ ์ธ์๋ ๋ชจ๋ ์ปดํฌ๋ํธ์์ theme ๊ฐ์ฒด์ ์ ๊ทผํ ์ ์๋ค.
CSS module๋ก ์์ฑ๋ ๋ฆฌ์กํธ ํ๋ก์ ํธ๋ฅผ styled-components๋ก ๋ฆฌํฉํ ๋งํด๋ณธ๋ค.
github link: movie-app-react-frontend