μžλ°”μŠ€ν¬λ¦½νŠΈUI

πŸŒ— 운영체제 ν…Œλ§ˆμ— 따라 μžλ™μœΌλ‘œ λ³€ν•˜λŠ” μ›Ή UI – prefers-color-scheme ν™œμš© κ°€μ΄λ“œ

πŸ―κΏ€μƒμ΄πŸ 2025. 7. 25. 12:17

운영체제 ν…Œλ§ˆμ— 따라 μžλ™μœΌλ‘œ λ³€ν•˜λŠ” μ›Ή UI

 

 

닀크 λͺ¨λ“œ ν† κΈ€ κΈ°λŠ₯은

μ‚¬μš©μž 맞좀 UX의 μ‹œμž‘μ μž…λ‹ˆλ‹€.

 

ν•˜μ§€λ§Œ μ‚¬μš©μžκ°€ λ³„λ„μ˜ μ„€μ • 없이도

운영체제의 ν…Œλ§ˆμ— 맞좰 μ›Ήμ‚¬μ΄νŠΈκ°€ μžμ—°μŠ€λŸ½κ²Œ λ°˜μ‘ν•œλ‹€λ©΄

훨씬 더 직관적인 κ²½ν—˜μ„ μ œκ³΅ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

 

λ°”λ‘œ μ—¬κΈ°μ„œ μ‹œμŠ€ν…œ ν…Œλ§ˆ 감지 κΈ°λŠ₯이 λ“±μž₯ν•©λ‹ˆλ‹€.

 

이번 ν¬μŠ€νŠΈμ—μ„œλŠ”

prefers-color-scheme λ―Έλ””μ–΄ 쿼리λ₯Ό ν™œμš©ν•˜μ—¬

운영체제의 라이트/닀크 섀정을 μžλ™μœΌλ‘œ κ°μ§€ν•˜κ³ ,

 

이λ₯Ό μ‚¬μš©μž μ„€μ •κ³Ό μ‘°ν•©ν•΄

μžμ—°μŠ€λŸ½κ²Œ μ „ν™˜ν•˜λŠ” λ‘œμ§μ„

κ΅¬ν˜„ν•΄λ³Ό κ±°μ˜ˆμš”.

 

βœ… κ΅¬ν˜„ λͺ©ν‘œ

  • OS의 라이트/닀크 λͺ¨λ“œ μƒνƒœ 감지
  • μ‚¬μš©μž μ„€μ •κ³Ό μ‹œμŠ€ν…œ μ„€μ •μ˜ μš°μ„ μˆœμœ„ 처리
  • CSS λ³€μˆ˜μ™€ data-theme 속성을 ν™œμš©ν•œ μŠ€νƒ€μΌ λ³€κ²½
  • 둜컬 μŠ€ν† λ¦¬μ§€ μ €μž₯을 ν†΅ν•œ μ‚¬μš©μž μ»€μŠ€ν„°λ§ˆμ΄μ§•

 

🧠 CSSμ—μ„œ μ‹œμŠ€ν…œ ν…Œλ§ˆ κ°μ§€ν•˜κΈ°

 

μš΄μ˜μ²΄μ œκ°€ 닀크 λͺ¨λ“œλ‘œ μ„€μ •λ˜μ–΄ μžˆμ„ λ•Œλ₯Ό κ°μ§€ν•˜λ €λ©΄ prefers-color-scheme을 μ‚¬μš©ν•˜λ©΄ λ©λ‹ˆλ‹€:

 
@media (prefers-color-scheme: dark) {
  :root {
    --bg-color: #121212;
    --text-color: #ffffff;
  }
}

@media (prefers-color-scheme: light) {
  :root {
    --bg-color: #ffffff;
    --text-color: #000000;
  }
}

 

πŸ’‘ 이 방식은 JS 없이도 κΈ°λ³Έ μŠ€νƒ€μΌμ„ μžλ™μœΌλ‘œ μ μš©ν•  수 μžˆμ–΄

초기 λ‘œλ”©μ—μ„œ λΆ€λ“œλŸ¬μš΄ μ‚¬μš©μž κ²½ν—˜μ„ μœ λ„ν•©λ‹ˆλ‹€.

 

βš™οΈ JavaScript둜 μ‚¬μš©μž μ„€μ •κ³Ό μ‹œμŠ€ν…œ 섀정을 λ³‘ν•©ν•˜κΈ°

 

κΈ°λ³Έ CSS에 더해, JavaScriptλ₯Ό 톡해 둜컬 섀정을 μš°μ„  μ μš©ν•˜κ³ ,

없을 경우 μ‹œμŠ€ν…œ ν…Œλ§ˆλ₯Ό κ°μ§€ν•˜μ—¬ μ μš©ν•˜λŠ” 방식이 UX적으둜 더 μžμ—°μŠ€λŸ½μŠ΅λ‹ˆλ‹€.

 
window.addEventListener("DOMContentLoaded", () => {
  const toggle = document.getElementById("toggle");
  const savedTheme = localStorage.getItem("theme");

  if (savedTheme) {
    document.documentElement.setAttribute("data-theme", savedTheme);
    toggle.checked = savedTheme === "dark";
  } else {
    const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
    const theme = prefersDark ? "dark" : "light";
    document.documentElement.setAttribute("data-theme", theme);
    toggle.checked = prefersDark;
  }
});
  • βœ… μ‚¬μš©μž 섀정이 μš°μ„ 
  • βœ… 섀정이 없을 경우 μ‹œμŠ€ν…œ ν…Œλ§ˆ 반영

 

🧩 ν™•μž₯ 포인트

  • μ•„μ΄μ½˜λ„ ν•¨κ»˜ μ „ν™˜: 🌞 → 🌚
  • μ „ν™˜ μ‹œ fade μ• λ‹ˆλ©”μ΄μ…˜ μΆ”κ°€λ‘œ λΆ€λ“œλŸ¬μš΄ UX
  • matchMedia에 λ³€ν™” 감지 이벀트λ₯Ό 달아 μ‹€μ‹œκ°„μœΌλ‘œ ν…Œλ§ˆ λ³€κ²½ 감지 κ°€λŠ₯
window.matchMedia("(prefers-color-scheme: dark)")
  .addEventListener("change", e => {
    if (!localStorage.getItem("theme")) {
      const newTheme = e.matches ? "dark" : "light";
      document.documentElement.setAttribute("data-theme", newTheme);
      toggle.checked = e.matches;
    }
  });

 

🧡 λ§ˆλ¬΄λ¦¬ν•˜λ©°

 

μ‚¬μš©μž 쀑심 μ›Ή UI 개발의 핡심은 선택지λ₯Ό 주되,

μžλ™ν™”λœ λ°°λ €λ₯Ό λ‹΄λŠ” κ²ƒμž…λ‹ˆλ‹€.

 

μ‹œμŠ€ν…œ ν…Œλ§ˆ 감지 κΈ°λŠ₯은

μž‘μ€ κΈ°λŠ₯처럼 보일 수 μžˆμ§€λ§Œ,

μ‚¬μš©μž λ§Œμ‘±λ„μ™€ 기술적 완성도λ₯Ό λ†’μ΄λŠ”

결정적인 μš”μ†Œκ°€ λ©λ‹ˆλ‹€.

 

λ‹€μŒ ν¬μŠ€νŠΈμ—μ„œλŠ”

μ‚¬μš©μžμ˜ ν…Œλ§ˆ μ„€μ • 변경을

μ‹œκ°μ μœΌλ‘œ μ–΄λ–»κ²Œ 더 λ§€λ„λŸ½κ²Œ ν‘œν˜„ν•  수 μžˆμ„μ§€μ— λŒ€ν•΄

닀뀄볼 μ˜ˆμ •μž…λ‹ˆλ‹€.

 

UI Code Labμ—μ„œ

더 λ˜‘λ˜‘ν•œ ν”„λŸ°νŠΈμ—”λ“œ μΈν„°λž™μ…˜μ„ ν•¨κ»˜

κ³ λ―Όν•΄λ΄μš”! πŸ§ͺ