디자인 투 코드 #2: 하나의 JSON, 열한 개 출력
Source: Dev.to
번역을 진행하려면 번역이 필요한 원본 텍스트(마크다운 형식 포함)를 제공해 주시겠어요?
코드 블록, URL 및 기술 용어는 그대로 유지하면서 본문만 한국어로 번역해 드리겠습니다.
개요
전체 7onic 디자인 시스템은 1,847줄 길이의 단일 JSON 파일(figma‑tokens.json)에서 실행됩니다. 이 파일은 다음을 저장합니다:
- 색상은 16진수 값으로 저장됩니다(예:
#6B21A8) - 간격은 일반 숫자로 저장됩니다(예:
16) - 테두리 반경도 같은 형식으로 저장됩니다
- 애니메이션은 키프레임 객체로 저장됩니다
이 파일은 디자인 값이 존재할 수 있는 코드베이스 내 유일한 장소이며, 그 외 모든 것은 이 파일에서 생성됩니다.
단일 명령으로 이 파일을 읽어 약 200 ms 안에 11개의 배포 파일을 생성합니다. 색상을 변경하고, 스크립트를 실행하고, 배포하면—이것이 전체 파이프라인입니다.
| Path | Description |
|---|---|
css/variables.css | 기본 CSS 변수 |
css/themes/light.css | 시맨틱 라이트 테마 |
css/themes/dark.css | 시맨틱 다크 테마 |
css/all.css | 번들된 CSS |
tailwind/v3-preset.js | Tailwind v3 프리셋 |
tailwind/v4-theme.css | Tailwind v4 테마 파일 |
tailwind/v4.css | Tailwind v4 CSS |
js/index.js | CommonJS 진입점 |
js/index.mjs | ESM 진입점 |
types/index.d.ts | TypeScript 선언 |
json/tokens.json | 처리된 토큰 출력 |
대부분의 파일은 생성이 간단하지만, 몇몇은 특수한 처리가 필요했습니다.
Tailwind 불투명도 수정자 다루기
문제
다음과 같은 클래스를 사용했을 때:
작동하지 않았습니다. Tailwind의 불투명도 수정자는 실제 색상 채널에 접근해야 하기 때문입니다. 16진수 값이면 Tailwind가 알파 컴포넌트를 삽입할 수 있지만, CSS 변수(var(--color-primary))는 Tailwind에게 단순 문자열에 불과해 불투명도를 계산할 수 없습니다.
해결책
각 색상 토큰에 RGB 채널을 노출하는 두 번째 버전을 생성합니다:
/* figma‑tokens.json → generated CSS */
--color-primary: #6B21A8;
--color-primary-rgb: 107, 33, 168;
Tailwind v3은 이제 다음과 같이 사용할 수 있습니다:
rgb(var(--color-primary-rgb) / <alpha>)
이를 통해 bg-primary/50, border-border/40, text-foreground/80와 같은 클래스를 사용할 수 있습니다.
결과: 모든 색상이 두 번 제공됩니다—한 번은 16진수 형태로, 또 한 번은 RGB 채널 형태로. 우아한가요? 논란의 여지가 있습니다. 효과적인가요? 확실히 그렇습니다. Tailwind v4에서는 이후 네이티브
color-mix()를 사용해 이 과정을 간소화했습니다.
다크‑모드 전략
클래식 접근법 (Tailwind v3)
/* light values */
:root { /* … */ }
/* dark values */
.dark { /* … */ }
.dark 클래스를 “에 토글합니다.
시스템 환경설정 접근법 (Tailwind v4)
@media (prefers-color-scheme: dark) {
/* dark styles */
}
실제 상황에서의 충돌
사용자는 OS 환경설정을 무시하고 싶을 수 있습니다. 예를 들어 “내 OS는 다크 모드인데, 사이트는 라이트 모드로 보고 싶다.”와 같은 경우입니다. prefers-color-scheme에만 의존하면 이런 상황이 번거로워집니다.
최종 결합 전략
- 기본적으로 OS 환경설정을 따름
- 명시적인
data-theme="dark"를 우선 적용 - 레거시
.dark클래스 토글도 지원
예외 처리 방법:
위 코드는 OS 설정과 관계없이 라이트 모드를 강제합니다.
@theme 함정
@theme inline을 사용하면 토큰 값이 직접 생성된 유틸리티에 삽입됩니다:
/* before */
background-color: var(--color-primary);
/* after (incorrect) */
background-color: #6B21A8;
하드코딩된 16진수 색상은 CSS 변수는 변경될 수 있지만 정적 값은 변경되지 않기 때문에 다크 모드 업데이트를 방해했습니다. 해결 방법은 inline 키워드를 제거하는 것뿐이었습니다:
@theme
이제 유틸리티가 다시 CSS 변수를 참조하므로 다크 모드가 정상적으로 작동합니다.
TypeScript 선언
파이프라인은 다음과 같은 선언도 내보냅니다:
export declare const colorPrimary: string;
export declare const spacingMd: string;
이들은 선택 사항이지만 토큰을 차트, 런타임 테마 또는 기타 동적 시스템에 연결할 때 편리합니다.
실제 승리
| Before | After |
|---|---|
| 디자인 값은 Figma에 존재했습니다. | 값은 하나의 JSON 파일에 저장됩니다. |
| 코드 값은 코드베이스에 존재했습니다. | 그 외 모든 것은 자동으로 파생됩니다. |
| 정렬에는 인간의 규율이 필요했습니다. | 드리프트가 구조적으로 불가능해집니다. |
11개의 출력, RGB 채널, 다크 모드 로직, 그리고 Tailwind 특성은 구현 세부 사항에 불과합니다. 핵심 성과는 디자인과 코드가 더 이상 현실을 놓고 논쟁하지 않는 시스템입니다.
Resources
- 7onic – 오픈‑소스 React 디자인 시스템 (MIT 라이선스). 문서와 인터랙티브 플레이그라운드.
- Source code: (별표에 감사)
- 이 시리즈의 더 많은 포스트.
- X에서 업데이트 팔로우: @7onicHQ