코샵
끄적끄적 코딩 공방
코샵

인기 글

  • 분류 전체보기 (474) N
    • MongoDB (4)
    • 일기장 (4)
    • Unity (138)
      • Tip (41)
      • Project (1)
      • Design Pattern (8)
      • Firebase (6)
      • Asset (2)
    • 파이썬 (127)
      • Basic (40)
      • OpenCV (8)
      • Pandas (15)
      • PyQT (3)
      • SBC(Single Board Computer) (1)
      • 크롤링 (14)
      • Fast API (29)
      • Package (6)
    • Linux (4)
    • C# (97)
      • Algorithm (11)
      • Window (7)
    • TypeScript (43) N
      • CSS (5) N
    • Git (11)
    • SQL (5)
    • Flutter (10)
      • Tip (1)
    • System (1)
    • BaekJoon (6)
    • Portfolio (2)
    • MacOS (1)
    • 유틸리티 (1)
    • 서비스 (6) N
    • 자동화 (3)
    • Hobby (10)
      • 물생활 (10)
      • 식집사 (0)
전체 방문자
오늘
어제

최근 댓글

최근 글

반응형
hELLO · Designed By 정상우.
코샵

끄적끄적 코딩 공방

TypeScript/CSS

CSS 변수(Custom Properties)로 코드 유지보수 시간 절반으로 줄이기

2025. 5. 11. 11:55
반응형

웹 개발자라면 큰 프로젝트에서 동일한 색상값이나 크기를 CSS 파일 전체에 반복해서 사용한 경험이 있을 겁니다. 그리고 나중에 디자인이 변경되면? 전체 파일을 검색하여 모든 값을 수동으로 변경해야 했죠. 바로 이런 문제를 CSS 변수(Custom Properties)가 해결해 줍니다. 이 글에서는 CSS 변수를 효과적으로 활용하여 유지보수성을 높이고 작업 시간을 획기적으로 줄이는 방법을 알아보겠습니다.

CSS 변수란 무엇인가?

CSS 변수(또는 CSS Custom Properties)는 문서 전체에서 재사용할 수 있는 값을 저장하는 사용자 정의 속성입니다. 이름 앞에 두 개의 대시(--)를 붙여 정의하고, var() 함수를 사용하여 참조합니다.

:root {
  --primary-color: #3498db;
  --secondary-color: #2ecc71;
  --font-size-base: 16px;
  --spacing-unit: 8px;
}

.button {
  background-color: var(--primary-color);
  padding: var(--spacing-unit) calc(var(--spacing-unit) * 2);
  font-size: var(--font-size-base);
}

이 간단한 예시에서 보듯이, CSS 변수를 사용하면 중요한 값들을 한 곳에서 정의하고 필요할 때마다 참조할 수 있습니다.

CSS 변수의 장점

중앙 집중식 관리

모든 주요 값(색상, 글꼴 크기, 여백 등)을 한 곳에서 정의하면 전체 디자인 시스템의 일관성을 유지하기 쉽습니다. 브랜드 색상이 변경되었나요? 한 곳만 수정하면 됩니다!

유지보수 시간 단축

큰 프로젝트에서 색상 팔레트를 변경해야 한다고 상상해보세요. CSS 변수 없이는 수백 개의 선택자를 찾아 변경해야 할 수 있습니다. CSS 변수를 사용하면 변수 정의 부분만 수정하면 됩니다.

테마 구현 용이성

라이트/다크 테마나 다중 색상 테마를 구현하기가 매우 쉬워집니다. 단순히 변수 값만 변경하면 됩니다.

:root {
  --bg-color: white;
  --text-color: black;
}

[data-theme="dark"] {
  --bg-color: #333;
  --text-color: white;
}

body {
  background-color: var(--bg-color);
  color: var(--text-color);
}

계산 및 조합 가능

CSS 변수는 calc() 함수와 결합하여 동적 값을 생성할 수 있습니다.

:root {
  --spacing-unit: 8px;
}

.container {
  padding: var(--spacing-unit);
  margin-bottom: calc(var(--spacing-unit) * 2);
}

반응형 디자인 개선

미디어 쿼리 내에서 변수 값을 재정의할 수 있어 반응형 디자인을 구현하기 쉽습니다.

:root {
  --container-width: 1200px;
}

@media (max-width: 768px) {
  :root {
    --container-width: 100%;
  }
}

.container {
  width: var(--container-width);
}

CSS 변수의 실용적인 구조화 방법

글로벌 변수 설정

:root 선택자를 사용하여 전체 문서에서 사용할 수 있는 글로벌 변수를 설정합니다.

:root {
  /* 색상 */
  --color-primary: #3498db;
  --color-secondary: #2ecc71;
  --color-accent: #e74c3c;
  --color-text: #333333;
  --color-text-light: #666666;
  --color-bg: #ffffff;
  --color-bg-alt: #f9f9f9;
  
  /* 타이포그래피 */
  --font-family-base: 'Roboto', sans-serif;
  --font-family-heading: 'Montserrat', sans-serif;
  --font-size-xs: 12px;
  --font-size-sm: 14px;
  --font-size-md: 16px;
  --font-size-lg: 18px;
  --font-size-xl: 24px;
  --font-size-xxl: 32px;
  
  /* 간격 */
  --spacing-xs: 4px;
  --spacing-sm: 8px;
  --spacing-md: 16px;
  --spacing-lg: 24px;
  --spacing-xl: 32px;
  --spacing-xxl: 48px;
  
  /* 레이아웃 */
  --container-width: 1200px;
  --border-radius-sm: 4px;
  --border-radius-md: 8px;
  --border-radius-lg: 12px;
  
  /* 애니메이션 */
  --transition-speed: 0.3s;
}

변수 이름 지정 규칙

명확하고 일관된 이름 지정 규칙을 사용하여 변수의 목적을 쉽게 이해할 수 있게 합니다:

  • --category-name-variant 형식 사용 (예: --color-primary-light)
  • 목적이 명확한 이름 사용 (예: --spacing-button-horizontal)
  • 접두사를 사용하여 관련 변수 그룹화 (예: --btn-, --card-)

컴포넌트별 변수

각 컴포넌트에 대한 특정 변수를 해당 컴포넌트 선택자 내에 정의합니다.

.button {
  --button-padding-x: 16px;
  --button-padding-y: 8px;
  
  padding: var(--button-padding-y) var(--button-padding-x);
}

.button-primary {
  --button-bg-color: var(--color-primary);
  --button-text-color: white;
  
  background-color: var(--button-bg-color);
  color: var(--button-text-color);
}

실전 활용 사례

테마 전환 시스템

사용자가 라이트/다크 모드를 전환할 수 있는 시스템을 구현해 봅시다:

:root {
  --color-bg: #ffffff;
  --color-text: #333333;
  --color-border: #dddddd;
  --color-primary: #3498db;
}

[data-theme="dark"] {
  --color-bg: #222222;
  --color-text: #f5f5f5;
  --color-border: #444444;
  --color-primary: #5dade2;
}

body {
  background-color: var(--color-bg);
  color: var(--color-text);
  transition: background-color 0.3s, color 0.3s;
}

JavaScript로 테마 전환

const themeToggle = document.getElementById('theme-toggle');
themeToggle.addEventListener('click', () => {
  const currentTheme = document.documentElement.getAttribute('data-theme') || 'light';
  const newTheme = currentTheme === 'light' ? 'dark' : 'light';
  document.documentElement.setAttribute('data-theme', newTheme);
  localStorage.setItem('theme', newTheme);
});

// 사용자 선호 테마 로드
const savedTheme = localStorage.getItem('theme');
if (savedTheme) {
  document.documentElement.setAttribute('data-theme', savedTheme);
}

상태 기반 스타일링

CSS 변수를 사용하여 요소의 상태에 따라 스타일을 변경할 수 있습니다:

.button {
  --button-bg: var(--color-primary);
  --button-text: white;
  --button-border: transparent;
  
  background-color: var(--button-bg);
  color: var(--button-text);
  border: 1px solid var(--button-border);
  transition: all var(--transition-speed);
}

.button:hover {
  --button-bg: transparent;
  --button-text: var(--color-primary);
  --button-border: var(--color-primary);
}

.button:disabled {
  --button-bg: #cccccc;
  --button-text: #666666;
}

반응형 타이포그래피 시스템

:root {
  --font-size-base: 16px;
  --line-height: 1.5;
  --scale-ratio: 1.25;
  
  --font-size-sm: calc(var(--font-size-base) / var(--scale-ratio));
  --font-size-md: var(--font-size-base);
  --font-size-lg: calc(var(--font-size-base) * var(--scale-ratio));
  --font-size-xl: calc(var(--font-size-lg) * var(--scale-ratio));
  --font-size-xxl: calc(var(--font-size-xl) * var(--scale-ratio));
}

@media (max-width: 768px) {
  :root {
    --font-size-base: 14px;
    --scale-ratio: 1.2;
  }
}

h1 { font-size: var(--font-size-xxl); }
h2 { font-size: var(--font-size-xl); }
h3 { font-size: var(--font-size-lg); }
body { font-size: var(--font-size-md); }
small { font-size: var(--font-size-sm); }

간격 시스템

일관된 간격 시스템을 만들어 디자인의 리듬을 유지하세요:

:root {
  --spacing-unit: 8px;
  
  --space-1: var(--spacing-unit);
  --space-2: calc(var(--spacing-unit) * 2);
  --space-3: calc(var(--spacing-unit) * 3);
  --space-4: calc(var(--spacing-unit) * 4);
  --space-5: calc(var(--spacing-unit) * 6);
  --space-6: calc(var(--spacing-unit) * 8);
}

.card {
  padding: var(--space-3);
  margin-bottom: var(--space-4);
}

.card-header {
  margin-bottom: var(--space-2);
}

CSS 변수와 CSS 전처리기 비교

Sass나 Less와 같은 CSS 전처리기도 변수를 제공하지만, CSS 변수에는 몇 가지 중요한 차이점이 있습니다:

  1. 런타임 vs 컴파일 타임: CSS 변수는 런타임에 작동하여 JavaScript로 동적으로 변경할 수 있습니다. 전처리기 변수는 컴파일 시점에 평가됩니다.
  2. 상속 및 범위: CSS 변수는 DOM 트리를 통해 상속되고 범위가 지정됩니다. 전처리기 변수는 파일 내에서만 존재합니다.
  3. 미디어 쿼리 및 상태 변경: CSS 변수는 미디어 쿼리 내에서 재정의하거나 상태(예: 호버, 포커스)에 따라 변경할 수 있습니다. 전처리기 변수는 이러한 동적 상황에 대응할 수 없습니다.

이상적인 접근 방식은 두 기술을 함께 사용하는 것입니다. 전처리기는 믹스인, 중첩 등 다른 유용한 기능을 제공하고, CSS 변수는 런타임 유연성을 추가합니다.

브라우저 호환성 및 대체 방법

CSS 변수는 대부분의 현대 브라우저에서 잘 지원되지만, IE11과 같은 구형 브라우저에서는 지원되지 않습니다. 다음과 같은 대체 방법을 고려해 보세요:

폴백 값 제공

var() 함수는 두 번째 매개변수로 폴백 값을 받을 수 있습니다:

.element {
  color: var(--text-color, #333);
}

PostCSS와 cssnext

postcss-custom-properties와 같은 플러그인을 사용하여 CSS 변수를 정적 값으로 컴파일할 수 있습니다.

@supports 규칙 활용

/* 기본 스타일(레거시 브라우저용) */
.element {
  color: #3498db;
}

@supports (--css: variables) {
  .element {
    color: var(--primary-color);
  }
}

실무 팁과 모범 사례

변수 구조화

프로젝트 규모에 따라 변수를 구조화하는 방법:

  • 소규모 프로젝트: 모든 변수를 :root에 정의
  • 중대규모 프로젝트: 카테고리별로 파일 분리 (colors.css, typography.css 등)
  • 대규모 프로젝트: 디자인 시스템 접근 방식 (토큰 기반 시스템)

문서화

주석을 사용하여 변수의 목적과 사용법을 문서화합니다:

:root {
  /* 
   * 주 색상 - 브랜드의 핵심 색상으로 CTA, 링크 등에 사용
   * 접근성 참고: WCAG AAA 수준을 위해 어두운 배경에서만 사용
   */
  --color-primary: #3498db;
}

JavaScript와의 통합

CSS 변수는 JavaScript에서 쉽게 읽고 쓸 수 있습니다:

// CSS 변수 읽기
const rootStyles = getComputedStyle(document.documentElement);
const primaryColor = rootStyles.getPropertyValue('--color-primary').trim();

// CSS 변수 쓰기
document.documentElement.style.setProperty('--color-primary', '#ff0000');

마무리

CSS 변수는 단순한 편의성 이상의 가치를 제공합니다. 유지보수성을 크게 향상시키고, 더 동적이고 적응력 있는 스타일시트를 작성할 수 있게 해줍니다. 작은 프로젝트에서 시작하여 점차 확장해 나가면서 CSS 변수의 강력함을 경험해 보세요.

최소한의 노력으로 코드베이스를 더 관리하기 쉽게 만들고, 변경 요청이 들어왔을 때 한 줄만 수정하는 기쁨을 누려보세요. CSS 변수는 현대 웹 개발의 필수적인 도구이며, 지금 바로 도입하면 유지보수 시간을 획기적으로 줄일 수 있습니다!

저작자표시 비영리 변경금지

'TypeScript > CSS' 카테고리의 다른 글

CSS 애니메이션 마스터하기: 자바스크립트 없이 인터랙티브한 웹 만들기  (0) 2025.05.13
반응형 웹 디자인: 모바일부터 데스크톱까지 완벽하게 대응하는 CSS 기법  (1) 2025.05.12
CSS Grid 완벽 가이드: 복잡한 레이아웃도 쉽게 만드는 방법  (0) 2025.05.10
10분 만에 마스터하는 CSS Flexbox! 복잡한 레이아웃도 쉽게 해결하는 비밀  (1) 2025.05.09
    'TypeScript/CSS' 카테고리의 다른 글
    • CSS 애니메이션 마스터하기: 자바스크립트 없이 인터랙티브한 웹 만들기
    • 반응형 웹 디자인: 모바일부터 데스크톱까지 완벽하게 대응하는 CSS 기법
    • CSS Grid 완벽 가이드: 복잡한 레이아웃도 쉽게 만드는 방법
    • 10분 만에 마스터하는 CSS Flexbox! 복잡한 레이아웃도 쉽게 해결하는 비밀
    코샵
    코샵
    나의 코딩 일기장

    티스토리툴바