
SOPT 1주차 과제를 진행하면서 CSS 변수를 사용해 스타일을 관리했습니다! 처음에는 색상을 변수로 빼면 편하겠다는 생각으로 글로벌 CSS를 정의하기 시작했지만, 이전에 진행했던 TSX + Vite 프로젝트를 다시 보니 훨씬 체계적인 디자인 시스템이 구축되어 있었어서, 이 구조를 이번 과제에도 적용할 수 있지 않을까?! 싶어서 적용해본 과정을 공유하려고 합니다.
디자인 시스템은 일관된 사용자 경험을 제공하기 위한 설계 원칙, 컴포넌트, 가이드라인들 입니다!
디자인 토큰과 컴포넌트 라이브러리로 나뉩니다.
/* 디자인 시스템 없을 경우 */
.button-1 { color: #FF8A00; }
.button-2 { color: #ff8900; } /* 미묘하게 다른 색상 !! */
.button-3 { color: orange; }
/* 디자인 시스템이 있는 경우 */
.button { color: var(--color-main); }
작은 프로젝트에 디자인이 없는 경우, 색상/폰트/간격을 매번 고민해야 하는데, 이때 디자인 시스템이 있으면 디자인 토큰만 조합해서 새로운 UI를 빠르게 구성할 수 있음!
/* 메인 컬러를 변경하고 싶을 때 */
:root {
/* --main-color: #FF8A00; 기존 */
--main-color: #2c2c2c; /* 변경 */
}
/* 이 한 줄만 수정하면 전체 사이트의 색상이 전부 변경됨! */
이전 프로젝트는 Tailwind CSS v4의 @theme 블록을 사용하여 디자인 토큰을 정의했습니다.
@theme {
/* Green */
--color-green-light: oklch(0.98 0.01 134);
--color-green-light-hover: oklch(0.96 0.02 134);
--color-green: oklch(0.75 0.21 134);
--color-green-hover: oklch(0.69 0.2 134);
--color-green-dark: oklch(0.56 0.16 134);
/* Orange */
--color-orange-light: oklch(0.97 0.01 45);
--color-orange: oklch(0.75 0.27 45);
--color-orange-dark: oklch(0.61 0.22 45);
}
OKLCH는 밝기/채도/색상 세 가지 값으로 색을 표현하는 시스템입니다.
그렇다면 왜 RGB/HEX가 아닌 OKLCH를 사용할까요?
1. 균일함
RGB/HEX는 같은 밝기 값을 주어도 색상에 따라 실제 밝기가 다르게 보입니다.
/* RGB는 노란색이 파란색보다 훨씬 밝게 보임 */
color: rgb(255, 255, 0); /* 노란색 */
color: rgb(0, 0, 255); /* 파란색 */
/* 그러나 OKLCH는 같은 L값이면 실제로도 비슷한 밝기 */
color: oklch(0.75 0.21 60); /* 노란색 */
color: oklch(0.75 0.21 240); /* 파란색 */
2. 색상 변형이 쉬움
/* 기본 컬러에서 밝기만 조절 */
--color-green: oklch(0.75 0.21 134);
--color-green-light: oklch(0.85 0.21 134); /* L만 증가 */
--color-green-dark: oklch(0.65 0.21 134); /* L만 감소 */
3. 더 넓은 색 범위
OKLCH는 RGB보다 훨씬 많은 색을 표현할 수 있으며, 특히 비비드한 컬러 표현에 강합니다.
프로젝트 협업시에는 체계적인 네이밍 규칙으로 색상의 용도를 명확히 해야합니다!
--color-{색상}-{밝기}-{상태}
/* 예시 */
--color-green-light /* 밝은 초록 */
--color-green-light-hover /* 밝은 초록 (ex. hover 상태) */
--color-green /* 기본 초록 */
--color-green-hover /* 기본 초록 (ex. hover 상태) */
--color-green-dark /* 어두운 초록 */
이런 규칙을 통해, 색상의 용도를 변수명만 봐도 파악이 가능합니다. 또한 인터랙션 상태(hover, active)를 위한 색상을 미리 정의해서 빠른 UI 구성에 도움이 되고, 역시 디자인에 일관성이 보장이 되어 협업에 유리합니다.
@layer utilities {
/* Title */
.text-title-semibold {
font-size: clamp(1.375rem, 1.1vw + 1rem, 1.5rem);
font-weight: 600;
line-height: 2rem;
}
/* Body */
.text-body-regular {
font-size: clamp(0.9375rem, 0.5vw + 0.5rem, 0.9375rem);
font-weight: 400;
line-height: 1.25rem;
}
}
.font-pretendard {
font-family:
BlinkMacSystemFont,
-apple-system,
Roboto,
Pretendard,
'Noto Sans KR',
'Segoe UI',
sans-serif;
}
폰트 스택의 의미는
BlinkMacSystemFont, -apple-system: macOS의 시스템 폰트
Roboto: Android 기본 폰트
Pretendard: 프로젝트의 주 폰트
Noto Sans KR: 한글 대체 폰트
sans-serif: 최종 대체 폰트
→ 사용자 환경에 따라 최적의 폰트를 자동으로 선택하는 것입니다!
font-size: clamp(최소값, 선호값, 최대값);
이 때의 선호값이란, 뷰 포트 크기에 따라 유동적으로 변하는 값입니다.
실제 예시:
.text-title-semibold {
/* 모바일(320px): 22px
태블릿(768px): 약 23.4px
데스크톱(1440px): 24px (최대값) */
font-size: clamp(1.375rem, 1.1vw + 1rem, 1.5rem);
}
아래처럼 계층적 구조로 텍스트 크기를 정의하는 시스템입니다.
Title (24px) - 페이지 제목
Subtitle (20px) - 섹션 제목
Body (15px) - 본문
Small (12px) - 보조 정보
Tiny (10px) - 캡션
이때 각 크기마다 여러 weight를 제공합니다
ex.
semibold (600)
medium (500)
regular (400)
저는 이번 프로젝트에서 tailwind CSS가 아닌 Styled-Component를 사용했습니다.
그래서 Tailwind의 @theme 블록을 CSS 변수로 변환해서 사용했고, HEX 컬러와 조합해서 사용했습니다.
간단한 과제였기 때문에 프로젝트 규모에 맞게 네이밍도 단순화해서 사용했습니다.
/*CSS Variables + HEX*/
:root {
--main-color: #2c2c2c;
--point-color: #00c8ff;
--text-color: #000000;
--bg-color: #ffffff;
--border-color: #e0e0e0;
}
또한 Tailwind의 타이포그래피 클래스인 @layer utilities를 일반 CSS 클래스로 변환했습니다.
/* 타이포그래피 유틸리티 */
.text-title-semibold {
font-size: clamp(1.375rem, 1.1vw + 1rem, 1.5rem);
font-weight: 600;
line-height: 2rem;
}
.text-body-regular {
font-size: clamp(0.9375rem, 0.5vw + 0.5rem, 0.9375rem);
font-weight: 400;
line-height: 1.25rem;
}
아래는 제가 1주차 과제에 적용한 최종 styles.css의 일부입니다.
/* CSS Reset */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Noto Sans KR', sans-serif;
}
/* 글로벌 스타일 - 디자인 토큰 */
:root {
/* 색상 */
--main-color: #2c2c2c;
--point-color: #00c8ff;
--text-color: #000000;
--bg-color: #ffffff;
--border-color: #e0e0e0;
/* 폰트 크기 */
--text-small: 12px;
--text-medium: 16px;
--text-large: 20px;
--text-xlarge: 24px;
/* 기타 */
--border-radius: 4px;
--header-height: 80px;
--max-width: 375px;
}
body {
min-height: 100vh;
background-color: var(--bg-color);
color: var(--text-color);
}
활용 예시:
/* 헤더 */
.header {
position: fixed;
height: var(--header-height);
background-color: var(--bg-color);
border-bottom: 1px solid var(--border-color);
}
/* 버튼 */
.btn-primary {
background-color: var(--main-color);
color: white;
border-radius: var(--border-radius);
}
/* 타이틀 */
.introduce-title {
font-size: var(--text-xlarge);
font-weight: bold;
color: var(--text-color);
}
아쉬운 부분은 CSS에서 OKLCH를 직접 사용하지 못한 부분입니다
요즘 대부분의 프로젝트에서 Tailwind를 사용하는 걸로 알지만, CSS로 디자인 시스템을 구현해보면서 도구보단 그 안의 원칙에 집중해서 디자인 시스템 설계를 고민해볼 수 있었습니다!
Tailwind 없이 CSS로만 디자인 시스템을 구현하면서
중요한 건 Tailwind를 사용하든, CSS 변수를 사용하든,
라는 걸 느꼈습니다. 좋은 설계에 더 가까워진 기분이었습니다!