디자인 투 코드 #2: 하나의 JSON, 열한 개 출력

발행: (2026년 4월 17일 AM 10:55 GMT+9)
7 분 소요
원문: Dev.to

Source: Dev.to

번역을 진행하려면 번역이 필요한 원본 텍스트(마크다운 형식 포함)를 제공해 주시겠어요?
코드 블록, URL 및 기술 용어는 그대로 유지하면서 본문만 한국어로 번역해 드리겠습니다.

개요

전체 7onic 디자인 시스템은 1,847줄 길이의 단일 JSON 파일(figma‑tokens.json)에서 실행됩니다. 이 파일은 다음을 저장합니다:

  • 색상은 16진수 값으로 저장됩니다(예: #6B21A8)
  • 간격은 일반 숫자로 저장됩니다(예: 16)
  • 테두리 반경도 같은 형식으로 저장됩니다
  • 애니메이션은 키프레임 객체로 저장됩니다

이 파일은 디자인 값이 존재할 수 있는 코드베이스 내 유일한 장소이며, 그 외 모든 것은 이 파일에서 생성됩니다.

단일 명령으로 이 파일을 읽어 약 200 ms 안에 11개의 배포 파일을 생성합니다. 색상을 변경하고, 스크립트를 실행하고, 배포하면—이것이 전체 파이프라인입니다.

PathDescription
css/variables.css기본 CSS 변수
css/themes/light.css시맨틱 라이트 테마
css/themes/dark.css시맨틱 다크 테마
css/all.css번들된 CSS
tailwind/v3-preset.jsTailwind v3 프리셋
tailwind/v4-theme.cssTailwind v4 테마 파일
tailwind/v4.cssTailwind v4 CSS
js/index.jsCommonJS 진입점
js/index.mjsESM 진입점
types/index.d.tsTypeScript 선언
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에만 의존하면 이런 상황이 번거로워집니다.

최종 결합 전략

  1. 기본적으로 OS 환경설정을 따름
  2. 명시적인 data-theme="dark"를 우선 적용
  3. 레거시 .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;

이들은 선택 사항이지만 토큰을 차트, 런타임 테마 또는 기타 동적 시스템에 연결할 때 편리합니다.

실제 승리

BeforeAfter
디자인 값은 Figma에 존재했습니다.값은 하나의 JSON 파일에 저장됩니다.
코드 값은 코드베이스에 존재했습니다.그 외 모든 것은 자동으로 파생됩니다.
정렬에는 인간의 규율이 필요했습니다.드리프트가 구조적으로 불가능해집니다.

11개의 출력, RGB 채널, 다크 모드 로직, 그리고 Tailwind 특성은 구현 세부 사항에 불과합니다. 핵심 성과는 디자인과 코드가 더 이상 현실을 놓고 논쟁하지 않는 시스템입니다.

Resources

  • 7onic – 오픈‑소스 React 디자인 시스템 (MIT 라이선스). 문서와 인터랙티브 플레이그라운드.
  • Source code: (별표에 감사)
  • 이 시리즈의 더 많은 포스트.
  • X에서 업데이트 팔로우: @7onicHQ
0 조회
Back to Blog

관련 글

더 보기 »

cubic-bezier로 CSS 전환을 레벨업하기

플랫해 보이는 CSS 전환은 왜 그런가요? 기본 ease 타이밍 함수는 작동하지만 일반적입니다. 실제 움직임은 개성이 있습니다—튕기고, 과도하게 움직이며…