ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Zero Runtime CSS-in-JS์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์ž
    TECH 2024. 1. 6. 23:02

    ์ตœ๊ทผ์— ์ง„ํ–‰ํ•œ ํ”„๋กœ์ ํŠธ์—์„œ ์š”์ฆˆ์Œ ์ฃผ๋ชฉ๋ฐ›๊ณ  ์žˆ๋Š” Zero Runtime CSS-in-JS ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ, Vanilla Extract๋ฅผ ์‚ฌ์šฉํ•ด ๋ณด์•˜์Šต๋‹ˆ๋‹ค. Vanilla Extract๋Š” ์ปดํŒŒ์ผ ํƒ€์ž„์— CSS ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜์—ฌ ๊ธฐ์กด ๋Ÿฐํƒ€์ž„์— ์ƒ์„ฑ๋˜๋Š” CSS-in-JS๋ณด๋‹ค ์„ฑ๋Šฅ์ƒ์˜ ์ด์ ์„ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์œผ๋กœ ์•Œ๋ ค์ ธ ์žˆ์Šต๋‹ˆ๋‹ค. 

     

    ๊ทธ๋ ‡๋‹ค๋ฉด ๊ธฐ์กด์˜ CSS-in-JS์—๋Š” ์–ด๋–ค ์„ฑ๋Šฅ์ ์ธ ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ๊ธฐ ๋•Œ๋ฌธ์— Zero Runtime CSS-in-JS ๊ธฐ์ˆ ์ด ๋– ์˜ค๋ฅด๊ฒŒ ๋˜์—ˆ์„๊นŒ์š”?

     
    ์ด ํฌ์ŠคํŒ…์—์„œ๋Š” ๋Ÿฐํƒ€์ž„ CSS-in-JS ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ํŠน์ง•๊ณผ ๋ฌธ์ œ๋Š” ๋ฌด์—‡์ธ์ง€, ๊ทธ๋ฆฌ๊ณ  Zero Runtime ์ ‘๊ทผ ๋ฐฉ์‹์ด ๊ทธ ๋ฌธ์ œ๋ฅผ ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ•˜๋Š”์ง€์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.
     
     
     
     

    CSS ์ ์šฉ ๊ณผ์ •

    CSS๊ฐ€ ์›น ํŽ˜์ด์ง€์— ์ ์šฉ๋˜๋Š” ๊ณผ์ •๋ถ€ํ„ฐ ์•Œ์•„๋ด…์‹œ๋‹ค.
     

    1. ๋„คํŠธ์›Œํฌ์—์„œ HTML์„ ๋ฐ›์•„ ๋ธŒ๋ผ์šฐ์ €๋กœ ๋กœ๋”ฉํ•œ๋‹ค.
    2. HTML์„ DOM(Document Object Model)๋กœ ๋ณ€ํ™˜ํ•œ๋‹ค.
    3. ๋ธŒ๋ผ์šฐ์ €๋Š” HTML ๋ฌธ์„œ์— ๋ฆฌ์†Œ์Šค๋“ค์„ ๊ฐ€์ ธ์˜จ๋‹ค. ์ด๋ฏธ์ง€, ๋™์˜์ƒ, CSS ๋“ฑ์ด ํ•ด๋‹น๋œ๋‹ค.
    4. ๋ธŒ๋ผ์šฐ์ €๋Š” ๊ฐ€์ ธ์˜จ CSS๋ฅผ ๋ณ€ํ™˜ํ•˜์—ฌ CSSOM(CSS Object Model)์„ ์ƒ์„ฑํ•œ๋‹ค. 2์—์„œ ๋งŒ๋“ค์–ด์ง„ DOM Tree์™€ CSSOM Tree๋ฅผ ๊ฒฐํ•ฉํ•˜์—ฌ ์Šคํƒ€์ผ์„ DOM ๋…ธ๋“œ์— ์ ์šฉํ•œ๋‹ค. ์ด๋•Œ, CSS Cascading ๊ทœ์น™์— ๋”ฐ๋ผ ์Šคํƒ€์ผ์ด ์ ์šฉ๋œ๋‹ค. ์ด ๊ณผ์ •์„ Render Tree๋ผ๊ณ  ํ•œ๋‹ค.
    5. ํŽ˜์ด์ง€๋ฅผ ํ™”๋ฉด์— ๊ทธ๋ฆฐ๋‹ค. ์ด ๋‹จ๊ณ„๋ฅผ Painting์ด๋ผ๊ณ  ํ•œ๋‹ค.

     
     
    ์œ„ ๊ณผ์ •์„ ๊ทธ๋ฆผ์œผ๋กœ ํ‘œํ˜„ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

    ์ถœ์ฒ˜: MDN web docs

     
     
     
     
     
     

    CSS์˜ ๋ Œ๋”๋ง ๋ฌธ์ œ

    ์œ„์—์„œ ์„ค๋ช…ํ•œ ๊ฒƒ์ฒ˜๋Ÿผ ๋ธŒ๋ผ์šฐ์ €๋Š” HTML์„ ๋จผ์ € ๋ฐ›์•„์˜จ ๋‹ค์Œ CSSOM์„ ์ƒ์„ฑํ•˜์—ฌ HTML์— ์Šคํƒ€์ผ์„ ์ ์šฉ์‹œํ‚ฌ ์ค€๋น„๋ฅผ ํ•ฉ๋‹ˆ๋‹ค.
     
    ์—ฌ๊ธฐ์„œ CSS๋กœ ์ธํ•ด ๋ฐœ์ƒํ•˜๋Š” ๋ Œ๋”๋ง ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. 
    ํ•œ ํŽ˜์ด์ง€์— ์ ์šฉ๋  CSS์— ์ˆ˜๋งŽ์€ ์Šคํƒ€์ผ๊ณผ ์„ ํƒ์ž๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ๋‹ค๋ฉด ์–ด๋–จ๊นŒ์š”? CSS ํŒŒ์ผ์˜ ํฌ๊ธฐ๊ฐ€ ํด์ˆ˜๋ก ๋ธŒ๋ผ์šฐ์ €๊ฐ€ CSSOM์„ ๋งŒ๋“œ๋Š” ๋ฐ ๊ฑธ๋ฆฌ๋Š” ์‹œ๊ฐ„์ด ๊ธธ์–ด์ง‘๋‹ˆ๋‹ค.
     
    ์ด ๊ณผ์ •์—์„œ ๋ Œ๋”๋ง ๋ธ”๋กœํ‚น์ด ๋ฐœ์ƒํ•ด ์š”์ฒญ๋œ ํŽ˜์ด์ง€์˜ ์ฒซ Painting์ด ์ง€์—ฐ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    ์ฒซ Painting์€ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์š”์ฒญ๋œ ํŽ˜์ด์ง€์˜ ์ฒซ ๋ฒˆ์งธ ํ”ฝ์…€์„ ๋ Œ๋”๋งํ•˜๋Š” ์ด๋ฒคํŠธ์ž…๋‹ˆ๋‹ค.

    ์ฒซ Painting์ด 0.5์ดˆ ์ด์ƒ ์ง€์—ฐ๋œ๋‹ค๋ฉด ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์ด ์ €ํ•˜๋˜์–ด ๋ถ€์ •์ ์ธ ์˜ํ–ฅ์„ ๋ฏธ์น  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ CSS๋ฅผ ๋” ๋นจ๋ฆฌ ์ „๋‹ฌํ•˜๊ณ  ์ฒซ Painting ์‹œ๊ฐ„์„ ์ตœ์ ํ™”ํ•˜์—ฌ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ๊ฐœ์„ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

     

     

    โœ”๏ธ CSS-in-JS: ๋ Œ๋”๋ง ๋ธ”๋กœํ‚น ํ•ด๊ฒฐ๊ณผ ํด๋ž˜์Šค ์ค‘๋ณต ๋ฐฉ์ง€

    ๋ Œ๋”๋ง ๋ธ”๋กœํ‚น์„ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด CSS ํŒŒ์ผ์„ ์ปดํฌ๋„ŒํŠธํ™”ํ•˜์—ฌ chunk(์ž‘์€ ๋ฉ์–ด๋ฆฌ)๋กœ ๋ถ„ํ• ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.
    ๊ทธ๋Ÿฌ๋‚˜ ์ด ๋ฐฉ๋ฒ•์€ ๋™์ผํ•œ ํด๋ž˜์Šค ์ด๋ฆ„์„ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ ์ „์—ญ์ ์œผ๋กœ ์Šคํƒ€์ผ์ด ์ค‘๋ณต๋˜์–ด ๋””์ž์ธ ์ƒ์˜ ๋ฒ„๊ทธ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
     
    CSS-in-JS๊ฐ€ ์ด๋Ÿฌํ•œ ํด๋ž˜์Šค ์ค‘๋ณต๊ณผ ๋ฒ”์œ„ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ด ์ค๋‹ˆ๋‹ค. 
     
     
     
     

    CSS-in-JS์˜ ์žฅ์ 

    CSS-in-JS๊ฐ€ ํ•ด๊ฒฐํ•˜๋Š” ๊ฐ€์žฅ ํฐ ๋ฌธ์ œ๋Š” ์œ„์—์„œ ์งง๊ฒŒ ์„ค๋ช…ํ•œ ๊ธ€๋กœ๋ฒŒ ์Šค์ฝ”ํ”„ ๋ฌธ์ œ์ธ๋ฐ,
    ์ด์™ธ์—๋„ CSS-in-JS๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ์žฅ์ ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.
     
     

    1๏ธโƒฃ CSS ํŒŒ์ผ์„ JavaScript์™€ ํ•จ๊ป˜ ๊ด€๋ฆฌ

    ๋™์ผํ•œ ํŒŒ์ผ์— JavaScript ์ฝ”๋“œ์™€ ์Šคํƒ€์ผ ์ฝ”๋“œ๋ฅผ ํ•จ๊ป˜ ์ž‘์„ฑํ•ด ์ปดํฌ๋„ŒํŠธ์˜ ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ๋ณด๋‹ค ๋” ์šฉ์ดํ•ฉ๋‹ˆ๋‹ค.
     
     

    2๏ธโƒฃ ์Šค์ฝ”ํ”„ ๋ฐ ์„ ํƒ์ž ๊ด€๋ จ

    CSS-in-JS๋Š” JavaScript ํŒŒ์ผ๋งˆ๋‹ค ์Šคํƒ€์ผ์„ ์ž‘์„ฑํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ์˜ ์Šคํƒ€์ผ๊ณผ ์ถฉ๋Œํ•˜๋Š” ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ฉ๋‹ˆ๋‹ค.
    ์Šคํƒ€์ผ ์ถฉ๋Œ์„ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด ์–ด๋–ค CSS ๋ฐฉ๋ฒ•๋ก ์„ ์‚ฌ์šฉํ• ์ง€ ๊ฑฑ์ •ํ•  ํ•„์š”๋„ ์—†์Šต๋‹ˆ๋‹ค.

    ๋ณดํ†ต ์Šคํƒ€์ผ์„ ์ž‘์„ฑํ•  ๋•Œ ์„ ํƒ์ž๋ฅผ ์•ž์— ๋ถ™์ด์ง€ ์•Š๊ณ  ํ•˜๋‚˜์˜ ์ปดํฌ๋„ŒํŠธ์— ๋Œ€ํ•ด์„œ๋งŒ ์ž‘์„ฑํ•˜๋ฏ€๋กœ, specificity ๋ฌธ์ œ๋Š” ๊ฑฐ์˜ ๋ฐœ์ƒํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
     
     

    3๏ธโƒฃ ๋™์  ์Šคํƒ€์ผ๋ง

    CSS-in-JS๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์กฐ๊ฑด๋ถ€ CSS๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
     

    import styled from 'styled-components';
    
    const Title = styled.h1<{ highlight?: boolean }>`
      font-size: 1.5em;
      text-align: center;
      color: ${(props) => (props.highlight ? 'black' : '#BF4F74')};
    `;
    
    function App() {
      return (
        <>
          <Title>Hello World</Title>
          <Title highlight>Hello World</Title>
        </>
      );
    }
    
    export default App;

     

    ์ƒ๋‹จ ์ฝ”๋“œ์˜ ๋กœ์ปฌ ํ™˜๊ฒฝ ์‹คํ–‰ ๊ฒฐ๊ณผ

     
     
     

    CSS-in-JS์˜ ๋‹จ์ 

    CSS-in-JS๊ฐ€ ์ปดํฌ๋„ŒํŠธ ๋‹จ์œ„๋กœ CSS๋ฅผ ๋‚˜๋ˆ„์–ด ์ž‘์„ฑํ•  ์ˆ˜๋Š” ์žˆ์ง€๋งŒ, ์œ„์—์„œ ์„ค๋ช…ํ–ˆ๋˜ ๋ Œ๋”๋ง ๋ธ”๋กœํ‚น์„ ์™„์ „ํžˆ ํ•ด๊ฒฐํ•˜์ง€๋Š” ๋ชปํ•ฉ๋‹ˆ๋‹ค.
    ์ด์™ธ์—๋„ ๋ช‡ ๊ฐ€์ง€ ๋‹จ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

     

    1๏ธโƒฃ ๋ Œ๋”๋ง ๋ธ”๋กœํ‚น

    CSS-in-JS ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” *์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ Œ๋”๋ง๋  ๋•Œ ์ƒˆ๋กœ์šด ์Šคํƒ€์ผ์„ ๋™์ ์œผ๋กœ ๊ณ„์‚ฐํ•ด ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ•˜๋ฉฐ, ์ด๋Š” ๊ทผ๋ณธ์ ์œผ๋กœ ์„ฑ๋Šฅ์— ์ข‹์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
    ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋งŽ์„์ˆ˜๋ก ์ฒซ Painting ์‹œ๊ฐ„์ด ๊ธธ์–ด์ ธ ๋ Œ๋”๋ง ๋ธ”๋กœํ‚น์ด ์ƒ๊ธฐ๊ณ  ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ์ €ํ•ดํ•ฉ๋‹ˆ๋‹ค.

     

    *์˜ˆ์‹œ

    import { useState } from 'react';
    import styled from 'styled-components';
    
    const Title = styled.h1<{ $primary?: boolean }>`
      font-size: 1.5em;
      text-align: center;
      color: ${(props) => (props.$primary ? '#000000' : '#BF4F74')};
    `;
    
    function App() {
      const [primary, setPrimary] = useState(false);
    
      const changeColorStyledComponent = () => {
        setPrimary((p) => !p);
      };
      return (
        <>
          <Title $primary={primary}>Hello World</Title>
          <button onClick={changeColorStyledComponent}>change color</button>
        </>
      );
    }
    
    export default App;

    ์ƒ๋‹จ ์ฝ”๋“œ์˜ ๋กœ์ปฌ ํ™˜๊ฒฝ ์‹คํ–‰ ๊ฒฐ๊ณผ

     
    ์‚ฌ์šฉ์ž๊ฐ€ ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ ๋™์ ์œผ๋กœ ์Šคํƒ€์ผ์ด ์ถ”๊ฐ€๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
     
     
     

    2๏ธโƒฃ SSR๊ณผ์˜ ํ˜ธํ™˜์„ฑ

    CSS-in-JS๋Š” ๋Ÿฐํƒ€์ž„์— ์Šคํƒ€์ผ์„ ์ƒ์„ฑํ•˜๊ณ , ์„œ๋ฒ„์—์„œ ํŽ˜์ด์ง€์˜ ์ดˆ๊ธฐ HTML์„ ์ƒ์„ฑํ•˜๋Š” SSR ๋ฐฉ์‹์€ ์„œ๋กœ ์ƒ์ถฉ๋˜๋Š” ์š”๊ตฌ์‚ฌํ•ญ์œผ๋กœ ์ธํ•ด ์ƒ๊ธฐ๋Š” ๋ฌธ์ œ๊ฐ€ ๋งŽ์Šต๋‹ˆ๋‹ค.
    ์„œ๋ฒ„์—์„œ ์ƒ์„ฑ๋œ HTML์ด ์‚ฌ์šฉ์ž์˜ ๋ธŒ๋ผ์šฐ์ €๋กœ ์ „๋‹ฌ๋˜๊ธฐ ์ „๊นŒ์ง€ CSS-in-JS๋กœ ์ƒ์„ฑํ•œ ์Šคํƒ€์ผ์ด ์ ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
    ์ด๋Š” ์ดˆ๊ธฐ ๋กœ๋”ฉ ์‹œ ์Šคํƒ€์ผ์ด ์ ์šฉ๋˜์ง€ ์•Š์€ ์ฝ˜ํ…์ธ ๊ฐ€ ๊นœ๋นก์ด๋ฉฐ ๋ณด์ด๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
     

    Next.js์˜ ๊ณต์‹ ๋ฌธ์„œ์—๋Š” ๋Ÿฐํƒ€์ž„ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๊ฐ€ ํ•„์š”ํ•œ CSS-in-JS ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ํ˜„์žฌ ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ์—์„œ ์ง€์›๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์ฃผ์˜ ๋ฌธ๊ตฌ๊ฐ€ ์จ ์žˆ๊ณ ,
    Emotion GitHub ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์—๋Š” ์ด์™€ ๊ด€๋ จ๋œ ์ˆ˜๋งŽ์€ ๋ฌธ์ œ๊ฐ€ ์ ‘์ˆ˜๋ฉ๋‹ˆ๋‹ค.

     
     
     
     

    Zero Runtime CSS-in-JS

    ์ด๋Ÿฌํ•œ CSS-in-JS์˜ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด, Zero Runtime CSS-in-JS ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ๋งŒ๋“ค์–ด์ง€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
    Zero Runtime ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ๋Š” CSS-in-JS ์ฝ”๋“œ๋ฅผ CSS ํŒŒ์ผ๋กœ ๋จผ์ € ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ํ•ด๋‹น ์Šคํƒ€์ผ์„ ์ฝ๊ณ  ์›น ํŽ˜์ด์ง€์— ์ ์šฉํ•ฉ๋‹ˆ๋‹ค.
    ์ด ๋ฐฉ์‹์œผ๋กœ ๋Ÿฐํƒ€์ž„์— ์Šคํƒ€์ผ ํƒœ๊ทธ๋ฅผ ์ƒ์„ฑํ•จ์œผ๋กœ์จ ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
     
     
     


     
    ์œ„์—์„œ ๋ณด์—ฌ ๋“œ๋ฆฐ ์‚ฌ์šฉ์ž๊ฐ€ ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ ํ…์ŠคํŠธ์˜ ์ƒ‰์ƒ์ด ๋ณ€๊ฒฝ๋˜๋Š” ๋™์ผํ•œ ๊ธฐ๋Šฅ์„ Vanilla Extract๋กœ ์ž‘์„ฑํ•œ ์˜ˆ์ œ์ž…๋‹ˆ๋‹ค. 
     

    import { useState } from 'react';
    import { title } from './test.css';
    
    function App() {
      const [primary, setPrimary] = useState(false);
    
      const changeColor = () => {
        setPrimary((p) => !p);
      };
    
      return (
        <>
          <h1 className={`${title} ${primary ? 'primary' : ''}`}>Hello World</h1>
          <button onClick={changeColor}>change color</button>
        </>
      );
    }
    
    export default App;
    // test.css.ts
    
    import { style } from '@vanilla-extract/css';
    
    export const title = style({
      fontSize: '1.5em',
      textAlign: 'center',
      color: '#BF4F74',
    
      selectors: {
        [`&.primary`]: {
          color: 'black',
        },
      },
    });

    ์ƒ๋‹จ ์ฝ”๋“œ ๋กœ์ปฌ ํ™˜๊ฒฝ ์‹คํ–‰ ๊ฒฐ๊ณผ

     
    ๋นŒ๋“œ ํƒ€์ž„์— ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ์˜ ์Šคํƒ€์ผ๊นŒ์ง€ ๋ชจ๋‘ ๊ณ„์‚ฐ๋˜์–ด HTML๊ณผ CSS์˜ ์ดˆ๊ธฐ ๋กœ๋”ฉ์ด ์™„๋ฃŒ๋˜๋ฉด style ํƒœ๊ทธ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
     


     
     
     
     
    Vanilla Extract ์™ธ์—๋„ Linaria, Astroturf, Reshadow, Panda CSS ๋“ฑ ๋‹ค์–‘ํ•œ Zero Runtime CSS-in-JS ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
     
     
     

    Vanilla Extract

    Vanilla Extract๋Š” GitHub์—์„œ 2024๋…„ 1์›” ๊ธฐ์ค€ 9์ฒœ ๊ฐœ ์ด์ƒ์˜ ์Šคํƒ€๋ฅผ ๋ฐ›์€ ์ธ๊ธฐ ์žˆ๋Š” Zero Runtime CSS-in-JS ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค.
    ํ”„๋ ˆ์ž„์›Œํฌ์— ๊ตฌ์• ๋ฐ›์ง€ ์•Š์•„ ๋ฐ”๋‹๋ผ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋˜๋Š” ๋ชจ๋“  ํ”„๋ก ํŠธ์—”๋“œ ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    Vanilla Extract๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋กœ์ปฌ ๋ฒ”์œ„์˜ ์Šคํƒ€์ผ๊ณผ ๋ณ€์ˆ˜๋ฅผ JavaScript ๋˜๋Š” TypeScript๋กœ ์ž‘์„ฑํ•˜๊ณ  ๋นŒ๋“œ ์‹œ์ ์— CSS ํŒŒ์ผ์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํ…Œ๋งˆ๋ฅผ ๋™์ ์œผ๋กœ ์ง€์ •ํ•˜๊ธฐ ์œ„ํ•œ API๋„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
     
     
     
    Vanilla Extract์˜ ๋‹ค๋ฅธ ํŠน์ง•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.
     

    • ํƒ€์ž… ์•ˆ์ „: ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ง€์›ํ•˜์—ฌ ๊ฐœ๋ฐœ์ž ๊ฒฝํ—˜์„ ๊ฐœ์„ ํ•ฉ๋‹ˆ๋‹ค.
    • ๋ฒˆ๋“ค๋Ÿฌ ์ง€์›: ์›นํŒฉ, Vite, Parcel, Babel๊ณผ ๊ฐ™์€ ๊ฐ€์žฅ ์ธ๊ธฐ ์žˆ๋Š” ํ”„๋ก ํŠธ์—”๋“œ React ํ”„๋ ˆ์ž„์›Œํฌ ๋ฐ ๋„๊ตฌ์™€ ํ†ตํ•ฉ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.
    • ์ž˜ ๋ฌธ์„œํ™”๋จ
    • ์‰ฌ์šด ์„ค์ •
    • ์—ฌ๋Ÿฌ ํŒจํ‚ค์ง€์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ (sprinkles, recipe, dynamic)
      • sprinkles๋ฅผ ํ™œ์šฉํ•ด tailwind์ฒ˜๋Ÿผ Atomic CSS๋ฅผ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์Œ
      • recipe๋ฅผ ํ™œ์šฉํ•˜์—ฌ variant ๊ธฐ๋ฐ˜ ์Šคํƒ€์ผ๋ง์„ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์Œ
      • dynamic์„ ํ™œ์šฉํ•ด ๋™์ ์œผ๋กœ ๊ฐ’์„ ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์žˆ์Œ

     
     
     

    ๊ธ€์„ ๋งˆ์น˜๋ฉฐ

    ์ด ํฌ์ŠคํŒ…์—์„œ, Vanilla Extract์™€ ๊ฐ™์€ Zero Runtime CSS-in-JS ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ๊ธฐ์กด CSS-in-JS ๋ฐฉ์‹์˜ ํ•œ๊ณ„๋ฅผ ์–ด๋–ป๊ฒŒ ๊ทน๋ณตํ•˜๋Š”์ง€ ์•Œ์•„๋ณด์•˜์Šต๋‹ˆ๋‹ค. Zero Runtime CSS-in-JS๋Š” ์ปดํŒŒ์ผ ํƒ€์ž„์— CSS ํŒŒ์ผ์„ ์ƒ์„ฑํ•จ์œผ๋กœ์จ ๋Ÿฐํƒ€์ž„ ๋ Œ๋”๋ง ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ณ , ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์›น ์„œ๋น„์Šค์—์„œ ์ค‘์š”ํ•œ ์ฒซ ํ™”๋ฉด ๋กœ๋”ฉ ์‹œ๊ฐ„์„ ๋‹จ์ถ•ํ•˜์—ฌ ์ข‹์€ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.



     

    ๐Ÿ“Œ ์ฐธ๊ณ 

    ๋Œ“๊ธ€

Designed by Tistory.