[CSS] Vanila-extract
์นดํ
๊ณ ๋ฆฌ : ํ๋ก๊ทธ๋๋ฐ ์ธ์ด
ํ๊ทธ: CSS · css · Vanila-extract · CSS-in-CSS · CSS-in-JS · Vanila-extract ์ฐ๋ ์ด์
ํ๊ทธ: CSS · css · Vanila-extract · CSS-in-CSS · CSS-in-JS · Vanila-extract ์ฐ๋ ์ด์
1. ์คํ์ผ๋ง ์ข ๋ฅ
- CSS-in-CSS(
tailwind,scss...
) - ๊ฐ๋ณ ์คํ์ผ ๋จ์์stylesheet
- ๋ณ๋์ ์๋ฐ์คํฌ๋ฆฝํธ ์ ํ์ด ํ์์์ด์ ์๋๊ฐ ๋น ๋ฆ
- ํด๋์ค๋ค์ ๋ค๋ฅธ ์ปดํฌ๋ํธ๋ฅผ ์คํ์ผ๋งํ ๋ ์ฌ์ฌ์ฉ ๊ฐ๋ฅ
- ๋ชจ๋์ฑ์ด ์ข์ง ์๋ค
- ๋๋ฌด ๋ง์ ์คํ์ผ ์ฝ๋๋ฅผ ์์ฑํ๊ฑฐ๋ ์คํ์ผ ํด๋์ค๊ฐ ํผ์ฉ๋๋ฉด ์คํ๋ฅผ ํํฐ๋งํ๊ธฐ ๊น๋ค๋กญ๋ค
- CSS-in-JS(
styled-components, emotionโฆ
) - ์ปดํฌ๋ํธ ๋ณ ์คํ์ผ ๋จ์์stylesheet
- ์คํ์ผ๋ง์
JavaScript
๋ด์์ ์ฒ๋ฆฌํ ์ ์๋ค - ์กฐ๊ฑด๋ถ ์คํ์ผ๋ง์ด๋ ๋์ ์คํ์ผ ๋ณ๊ฒฝ์ด ์ฝ๋ค
- ์บก์ํํ์ฌ ์ฌ์ฌ์ฉ์ฑ๊ณผ ์ ์ง๋ณด์์ฑ์ด ๋๋ค
- CSS-in-CSS์ ๋นํด ๋๋ฆผ (์์๋ก ํ์
์ถ๋ก ์ ์ํด ์ถ๊ฐ์ ์ผ๋ก ํ์
์ ์๋ฅผ ํด์ค์ผํ๋ค,
d.ts
ํ์ผ์ ๋ณ๋๋ก ์์ฑํด์ผ๋ ์ผ์ด ์๊น (styled
๋ฅผ ๋ช ์์ ์ผ๋ก ๋ค๋ฅธ ํ์ ์ผ๋ก ๊ฐ์ ๋ก ๋ณํ) - ๋ณ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค์น๋ก ๋ฒ๋ค ํฌ๊ธฐ๊ฐ ์ฆ๊ฐํจ ,
d.ts
์ ๊ฐ์ ๋ณ๋์ ํ์ผ๋ ์ถ๊ฐ๋ก ํ์ํด์ง
์์ฝ
- ๋น ๋ฅธ ์๋ , ๋๋๋ง ์๋ , ์ธํฐ๋ ํฐ๋ธํ ํ๋ก์ ํธ โ CSS-in-CSS
- ๊ฐ๋ฐ ํจ์จ์ฑ , ์ปดํฌ๋ํธ ๊ธฐ๋ฐ์ ํ๋ก์ ํธ โ CSS-in-JS
2. Vanila-extract ์ ํฉ
- CSS-in-CSS - ์ง๊ธ ์ปดํฌ๋ํธ ๊ธฐ๋ฐ์ ํ๋ก์ ํธ ๊ฐ๋ฐ์ด ํ์ํ๋ค. tailwind๋ ๊ฐ๋ ์ฑ์ด ๋๋ฌด ์์ข์
Styled-components , Emotion js ๋ฑ - Next13 ๋ฒ์ ์ดํ ๋ถํฐ SSR์์ ํ์ด์ง์ ์คํ์ผ์ํธ ์ ๋ณด๊ฐ ๋ก๋ ์์ ์ ํฌํจ์ด ์๋์ ์คํ์ผ ์ ์ฉ์ด ์๋๋ ์ด์๊ฐ ์์
- Next13 ๋ฒ์ ๋ถํฐ app ๋๋ ํ ๋ฆฌ์ _app.tsx , _documents.tsx๋ฅผ ์์ฐ๊ธฐ ๋๋ฌธ์ ์ด ์ฝ๋๋ฅผ ์ฌ์ฉํ์ง ๋ชปํจ
// _document.tsx export default class MyDocument extends Document { static async getInitialProps(ctx: DocumentContext) { const sheet = new ServerStyleSheet(); const originalRenderPage = ctx.renderPage; try { ctx.renderPage = () => originalRenderPage({ enhanceApp: (App) => (props) => sheet.collectStyles(<App {...props} />), }); const initialProps = await Document.getInitialProps(ctx); return { ...initialProps, styles: [initialProps.styles, sheet.getStyleElement()], }; } finally { sheet.seal(); } } }
- ๋์์ผ๋ก ์๋์ ๊ฐ์ ๋ณ๋์ ์ฝ๋๊ฐ ํ์ํจ
// /app/page.tsx import styled from "styled-components"; function HomePage() { return <Container>Client Components</Container>; } export default HomePage; const Container = styled.div` padding: 0 2rem; `;
import React from "react"; import { ServerStyleSheet, StyleSheetManager } from "styled-components"; export function useStyledComponentsRegistry() { const [styledComponentsStyleSheet] = React.useState( () => new ServerStyleSheet() ); const styledComponentsFlushEffect = () => { const styles = styledComponentsStyleSheet.getStyleElement(); styledComponentsStyleSheet.instance.clearTag(); return <>{styles}</>; }; const StyledComponentsRegistry = ({ children, }: { children: React.ReactNode; }) => ( <StyleSheetManager sheet={styledComponentsStyleSheet.instance}> {children as React.ReactElement} </StyleSheetManager> ); return [StyledComponentsRegistry, styledComponentsFlushEffect] as const; }
(1) Vanila-extract ์ฅ์
- ์ฒซ๋ฒ์งธ๋ก CSS-in-TS
- All the styling APIs in Vanilla Extract take a style object as input.
- style object ์ฌ์ฉ
- Zero-runtime in TypeScript
- TypeScript์์ ์คํ์ผ์ํธ๋ฅผ ์์ฑํ๊ณ ์ฌ์ฉํ ๋, ๋ฐํ์์ ์ถ๊ฐ์ ์ธ ์ฒ๋ฆฌ๋ ๊ณ์ฐ ์์ด ์๋
- styles.css.ts๋ .css.ts์ ๊ฐ์ postfix ํ์ผ์ ์์ฑํ๊ธฐ ๋๋ฌธ์ ์์ฑํ๋ ๋ชจ๋ ์คํ์ผ์ ๋ํ ํ์ ์ถ๋ก ์ด ๊ฐ๋ฅ
- Use TypeScript as your preprocessor
- TypeScript๋ฅผ ์ ์ฒ๋ฆฌ๊ธฐ ์ฒ๋ผ ์ฌ์ฉ ๊ฐ๋ฅํจ
- Zero-runtime in TypeScript
- TypeScript์์ ์คํ์ผ์ํธ๋ฅผ ์์ฑํ๊ณ ์ฌ์ฉํ ๋, ๋ฐํ์์ ์ถ๊ฐ์ ์ธ ์ฒ๋ฆฌ๋ ๊ณ์ฐ ์์ด ์๋
- CSS-in-JS ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฐํ์์ ์คํ์ผ์ ๋์ ์ผ๋ก ์์ฑํ๊ณ ์ ์ฉํ๋ ๊ณผ์ ์ด ํ์ํจ
(2) Vanila-extract ๊ณง ๋ง์ฃผํ๊ฒ ๋ ๋จ์
-์จ๋ณด๋ฉด์ ์ฅ๋จ์ ์ ๋ฆฌ