๐ŸŒ— Styled Components๋กœ ๋ผ์ดํŠธ/๋‹คํฌ ๋ชจ๋“œ ์ „ํ™˜ํ•˜๊ธฐ

    ์‹ค์ œ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ์‚ฌ์šฉ์ž์—๊ฒŒ ๋‹คํฌ ๋ชจ๋“œ์™€ ๋ผ์ดํŠธ ๋ชจ๋“œ๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•œ UX ์š”์†Œ ์ค‘ ํ•˜๋‚˜์ด๋‹ค.

    styled-components์™€ ThemeProvider๋ฅผ ํ™œ์šฉํ•˜๋ฉด ์ „์—ญ ํ…Œ๋งˆ ์ „ํ™˜์„ ๋งค์šฐ ๊ฐ„๋‹จํ•˜๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.


    โœ… 1. ํ…Œ๋งˆ ๊ฐ์ฒด ์ •์˜ํ•˜๊ธฐ

    // themes.js
    export const lightTheme = {
      textColor: "#111",
      backgroundColor: "whitesmoke",
    };
    
    export const darkTheme = {
      textColor: "whitesmoke",
      backgroundColor: "#111",
    };
    

    โœ… 2. App์—์„œ ํ…Œ๋งˆ ์ƒํƒœ ๊ด€๋ฆฌ

    ์—ฌ๋Ÿฌ๊ฐœ์˜ property๋ฅผ ๊ฐ€์ง„ ๊ฐ์ฒด๋ฅผ ๋‘๊ฐœ (๋‹คํฌ/๋ผ์ดํŠธ) ์„ค์ •ํ•จ์œผ๋กœ์จ ๊ฐ„ํŽธํ•˜๊ฒŒ theme์„ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋‹ค. 

     

    // App.js
    import React, { useState } from "react";
    import styled, { ThemeProvider } from "styled-components";
    import { lightTheme, darkTheme } from "./themes";
    
    const Title = styled.h1`
      color: ${(props) => props.theme.textColor};
    `;
    
    const Wrapper = styled.div`
      display: flex;
      flex-direction: column;
      gap: 20px;
      height: 100vh;
      width: 100vw;
      justify-content: center;
      align-items: center;
      background-color: ${(props) => props.theme.backgroundColor};
      transition: all 0.3s ease-in-out;
    `;
    
    const ToggleButton = styled.button`
      padding: 10px 20px;
      font-weight: bold;
      border: none;
      cursor: pointer;
      background-color: ${(props) => props.theme.textColor};
      color: ${(props) => props.theme.backgroundColor};
      border-radius: 8px;
    `;
    
    function App() {
      const [isDark, setIsDark] = useState(true);
      const toggleTheme = () => setIsDark((prev) => !prev);
    
      return (
        <ThemeProvider theme={isDark ? darkTheme : lightTheme}>
          <Wrapper>
            <Title>{isDark ? "Dark Mode" : "Light Mode"}</Title>
            <ToggleButton onClick={toggleTheme}>
              Toggle Theme
            </ToggleButton>
          </Wrapper>
        </ThemeProvider>
      );
    }
    
    export default App;

    โœ… ๊ฒฐ๊ณผ ํ™”๋ฉด

    • ๊ธฐ๋ณธ์€ ๋‹คํฌ ๋ชจ๋“œ (isDark = true)
    • ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ๋ผ์ดํŠธ ๋ชจ๋“œ๋กœ ์ „ํ™˜๋จ
    • ThemeProvider๋Š” ์ƒํƒœ์— ๋”ฐ๋ผ lightTheme ๋˜๋Š” darkTheme์„ ์ „๋‹ฌ


    ๐Ÿ”ง ThemeProvider ์ž‘๋™ ์›๋ฆฌ

    โœ… 1. React Context๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋™์ž‘ํ•œ๋‹ค

    styled-components์˜ ThemeProvider๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ React Context API๋ฅผ ์‚ฌ์šฉํ•ด ํ…Œ๋งˆ๋ฅผ ๊ด€๋ฆฌํ•œ๋‹ค.

     
    <ThemeProvider theme={currentTheme}> 
    	<App /> 
    </ThemeProvider>
     

    ์ด๋ ‡๊ฒŒ ๊ฐ์‹ธ๋ฉด ThemeProvider๋Š” theme ๊ฐ์ฒด๋ฅผ Context๋กœ ์ €์žฅํ•˜๊ณ , ํ•˜์œ„์˜ ๋ชจ๋“  styled component๋Š” ๊ทธ ๊ฐ’์„ props.theme์„ ํ†ตํ•ด ์ž๋™์œผ๋กœ ์ฃผ์ž…๋ฐ›๋Š”๋‹ค.


    โœ… 2. styled-components๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ ThemeContext๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค

    styled-components๋Š” ThemeContext๋ผ๋Š” ๋‚ด๋ถ€ ์ปจํ…์ŠคํŠธ๋ฅผ ๋งŒ๋“ค๊ณ , ThemeProvider๋กœ ์ „๋‹ฌ๋ฐ›์€ theme์„ ์—ฌ๊ธฐ์— ์ €์žฅํ•œ๋‹ค.

    // (๋‚ด๋ถ€์ ์œผ๋กœ๋Š” ๋Œ€๋žต ์ด๋Ÿฐ ํ˜•ํƒœ) 
    const ThemeContext = React.createContext(defaultTheme); 
    export const ThemeProvider = ({ theme, children }) => { 
    	return <ThemeContext.Provider value={theme}>{children}</ThemeContext.Provider>; 
    };
     

    โœ… 3. styled component๋Š” theme context์— ์ ‘๊ทผํ•˜์—ฌ props.theme์œผ๋กœ ๋„ฃ์–ด์ค€๋‹ค

    ๋ชจ๋“  styled ์ปดํฌ๋„ŒํŠธ๋Š” ์ƒ์„ฑ๋  ๋•Œ ThemeContext๋ฅผ ์ž๋™์œผ๋กœ ๊ตฌ๋…ํ•˜๊ณ , ๋ Œ๋”๋ง ์‹œ theme ๊ฐ’์„ props.theme์œผ๋กœ ๋„ฃ์–ด์ค€๋‹ค.

    const Title = styled.h1` 
    	color: ${(props) => props.theme.textColor}; 
    `;

    → ์—ฌ๊ธฐ์„œ props.theme.textColor๋Š” ThemeProvider๋ฅผ ํ†ตํ•ด ์ „๋‹ฌ๋œ ๊ฐ’์ด๋‹ค.
    → ๋งŒ์•ฝ ThemeProvider๊ฐ€ ์—†์œผ๋ฉด props.theme๋Š” undefined๋‹ค.

     

    โœ… ์ผ๋‹จ styled-component ๋กœ ํ•œ๋ฒˆ ๋งŒ๋“ค์–ด๋ณด๊ธด ํ–ˆ์ง€๋งŒ.. 

    • localStorage์— ์‚ฌ์šฉ์ž์˜ ํ…Œ๋งˆ ์„ ํ˜ธ ์ €์žฅํ•˜์—ฌ ์œ ์ง€ํ•˜๊ธฐ
    • ์‹œ์Šคํ…œ ์„ค์ •์— ๋”ฐ๋ฅธ ๋‹คํฌ๋ชจ๋“œ ์ž๋™ ์ ์šฉ (window.matchMedia)

    ์‹ค์œ ์ €๊ฐ€ ์žˆ๋Š” ์„œ๋น„์Šค์—์„œ๋Š” ์œ„์˜ ๋‘๊ฐ€์ง€ ๋ฐฉ๋ฒ•์œผ๋กœ ๊ตฌํ˜„ํ•˜๋Š”๊ฒŒ ์ข‹์„๋“ฏ. 


    React + Styled-components๋กœ ๊ตฌํ˜„ํ•œ ํ…Œ๋งˆ ์‹œ์Šคํ…œ์€ ํ™•์žฅ์„ฑ๋„ ์ข‹๊ณ , ์œ ์ง€๋ณด์ˆ˜๋„ ์‰ฝ๋‹ค.
    ๋‹คํฌ๋ชจ๋“œ ๋ฒ„ํŠผ์„ ๋„ฃ๊ณ  ์‹ถ๋‹ค๋ฉด ์ด ๊ตฌ์กฐ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์‹œ์ž‘ํ•ด๋ณด์ž!

     

    ๋ฐ˜์‘ํ˜•

    ๋Œ“๊ธ€