디자인 시스템 팀이 토큰을 DTCG 형식의 JSON 파일로 관리한다고 해 봅시다. 여기에 AI 코딩 에이전트가 읽을 DESIGN.md를 추가하면 같은 색과 간격이 두 파일에 들어갑니다. 두 파일은 같은 값을 다른 문법으로 적습니다. 어느 필드가 어디에 대응하는지 모르면 한쪽만 고쳐져 값이 어긋납니다.
토큰 파일을 이미 쓰면서 에이전트용 DESIGN.md를 만들려는 프론트엔드 개발자라면 아래 예제로 두 파일의 필드를 하나씩 맞출 수 있습니다. 값의 원본은 한 파일에만 둡니다. 다른 파일은 원본에서 만들거나 검사로 맞춥니다. DESIGN.md를 DTCG로 내보내는 공식 명령은 줄 높이·반투명 색·컴포넌트 값을 잃거나 바꾸므로, 내보낸 파일은 검사한 뒤에 씁니다.
기준: 2026-10-24 · DTCG Format Module 2025.10 ↗·Color Module 2025.10 ↗(커뮤니티 그룹 최종 보고서) · DESIGN.md 형식 ↗
alpha,@google/design.md0.4.0 · Style Dictionary 5.7.0
두 파일은 읽는 쪽이 다릅니다
DTCG(Design Tokens Community Group)는 디자인 토큰을 도구 사이에서 주고받는 JSON 형식을 정합니다. 2025년 10월 28일 첫 안정 버전 2025.10 ↗을 공개했습니다. 2025.10은 형식(Format)·색(Color)·리졸버(Resolver) 모듈로 나뉩니다. 문서의 지위는 W3C 커뮤니티 그룹의 최종 보고서입니다. 스펙은 스스로 W3C 표준이 아니며 표준화 과정에 있지도 않다고 밝힙니다.
Format Module ↗이 염두에 둔 독자는 도구입니다. 디자인 툴은 토큰을 내보내고, 번역 도구(translation tool)는 토큰을 플랫폼별 코드로 바꾸고, 문서 도구는 토큰 이름과 값을 보여 줍니다. W3C 커뮤니티 그룹 공지는 Style Dictionary, Tokens Studio, Terrazzo를 참조 구현으로 소개합니다. 파일 확장자로는 .tokens나 .tokens.json을 권장합니다.
DESIGN.md는 Google Labs의 design.md ↗ 저장소가 정한 형식입니다. 코딩 에이전트에게 제품의 시각적 정체성을 설명하는 Markdown 파일입니다. 파일 위쪽 YAML frontmatter에 토큰을 적고, 아래 Markdown 본문에 값을 쓰는 이유와 적용 규칙을 적습니다. 형식 스펙 ↗은 토큰을 규범 값으로, 본문을 그 값을 적용하는 문맥으로 정합니다. 형식 버전은 아직 alpha입니다.
flowchart TD
T["design.tokens.json<br/>DTCG 2025.10"] --> SD["번역 도구<br/>Style Dictionary 등"]
SD --> CSS["CSS 변수·플랫폼별 코드"]
M["DESIGN.md<br/>YAML 토큰 + Markdown 본문"] --> AG["코딩 에이전트"]
CSS --> UI["화면 코드"]
AG --> UI
두 경로는 화면 코드에서 만납니다. 에이전트는 DESIGN.md의 값을 보고 코드를 쓰고, 그 코드는 토큰 파일에서 만든 CSS 변수와 함께 쓰입니다. 두 파일의 값이 다르면 에이전트가 쓴 색과 CSS 변수의 색이 달라집니다.
Atlassian이 이 형식으로 자사 디자인 시스템을 공개하고 MCP·스킬과 비교한 실험은 Atlassian DESIGN.md 공개에서 다뤘습니다. 그 실험에서 DESIGN.md는 프로토타입에서 효과를 보였습니다. 프로덕션 코드에서는 MCP·스킬보다 디자인 시스템 반영도가 낮았습니다.
같은 값을 두 형식으로 적은 예
아래 두 파일은 작성자가 만든 설명용 예제입니다. 업무용 관리 화면의 주요 색 두 개, 간격 하나, 모서리 반경 하나, 글자 스타일 하나, 버튼 하나를 같은 값으로 적었습니다.
DESIGN.md
---
version: alpha
name: Sample Console
colors:
primary: "#0B57D0"
on-primary: "#FFFFFF"
typography:
label-md:
fontFamily: Pretendard
fontSize: 14px
fontWeight: 600
lineHeight: 1.4
letterSpacing: 0px
rounded:
md: 8px
spacing:
md: 16px
components:
button-primary:
backgroundColor: "{colors.primary}"
textColor: "{colors.on-primary}"
typography: "{typography.label-md}"
rounded: "{rounded.md}"
padding: "{spacing.md}"
---
## Overview
업무용 관리 화면입니다. 정보 밀도를 높게 유지하고 장식을 줄입니다.
## Colors
- **Primary (#0B57D0):** 화면마다 주요 행동 하나에만 씁니다. 링크와 보조 버튼에는 쓰지 않습니다.
## Components
버튼은 화면당 primary 하나만 둡니다. 나머지는 테두리만 있는 보조 버튼으로 만듭니다.design.tokens.json
{
"color": {
"$type": "color",
"primary": {
"$value": {
"colorSpace": "srgb",
"components": [0.043, 0.341, 0.816],
"hex": "#0b57d0"
},
"$description": "화면마다 주요 행동 하나에만 쓴다."
},
"on-primary": {
"$value": {
"colorSpace": "srgb",
"components": [1, 1, 1],
"hex": "#ffffff"
}
}
},
"spacing": {
"md": { "$type": "dimension", "$value": { "value": 16, "unit": "px" } }
},
"rounded": {
"md": { "$type": "dimension", "$value": { "value": 8, "unit": "px" } }
},
"typography": {
"label-md": {
"$type": "typography",
"$value": {
"fontFamily": "Pretendard",
"fontSize": { "value": 14, "unit": "px" },
"fontWeight": 600,
"letterSpacing": { "value": 0, "unit": "px" },
"lineHeight": 1.4
}
}
},
"button-primary": {
"background": { "$type": "color", "$value": "{color.primary}" },
"text": { "$type": "color", "$value": "{color.on-primary}" },
"typography": { "$type": "typography", "$value": "{typography.label-md}" },
"radius": { "$type": "dimension", "$value": "{rounded.md}" },
"padding": { "$type": "dimension", "$value": "{spacing.md}" }
}
}DTCG 파일은 다음 규칙을 따릅니다.
$value가 있는 객체가 토큰이고, 없는 객체는 그룹입니다. 토큰과 그룹의 이름은$로 시작할 수 없고{,},.을 포함할 수 없습니다.$type은 토큰이나 상위 그룹에 적습니다. 위color그룹의$type은 안쪽 토큰 두 개에 상속됩니다. 스펙은 도구가 값의 모양을 보고 타입을 추측하지 못하게 합니다.- 색은 문자열이 아닌 객체입니다. Color Module ↗에서
colorSpace와components는 필수입니다.hex는 6자리 대체 값이고,alpha를 생략하면 불투명(1)으로 봅니다. - 간격과 반경은
dimension타입입니다. 값은{ "value": 16, "unit": "px" }같은 객체이고 단위는px와rem만 씁니다. typography는fontFamily,fontSize,fontWeight,letterSpacing,lineHeight다섯 속성을 모두 적습니다.lineHeight는 글자 크기에 곱하는 숫자입니다."{color.primary}"처럼 중괄호로 다른 토큰을 참조(alias)합니다. 버튼의 값은 이 참조로 만든 토큰 묶음입니다.
필드는 이렇게 대응합니다
| 항목 | DESIGN.md | DTCG 2025.10 |
|---|---|---|
| 타입 | 섹션 이름(colors, spacing 등)으로 정함 | $type을 토큰이나 그룹에 적음 |
| 색 | CSS 색 문자열(#RRGGBB, oklch() 등) | colorSpace·components 객체, hex·alpha는 선택 |
| 간격·반경 | 16px 같은 문자열, 단위는 px·em·rem | {value, unit} 객체, 단위는 px·rem |
| 타이포그래피 | 속성을 골라 적음, lineHeight는 길이나 숫자 | 다섯 속성 모두 필수, lineHeight는 숫자 배수 |
| 참조 | {colors.primary} | {color.primary}, JSON Pointer를 쓰는 $ref |
| 컴포넌트 | components 아래 정해진 속성 8개 | 정해진 구조 없음, 참조 토큰 묶음으로 표현 |
| 의도와 설명 | Markdown 본문 | 토큰마다 $description 문자열 |
두 형식을 맞출 때 어긋나는 곳은 단위, 줄 높이, 색 표현, 컴포넌트입니다.
DESIGN.md는-0.02em같은em단위를 받지만 DTCGdimension에는em이 없습니다. 글자 간격을em으로 적었다면 글자 크기를 곱해px나rem으로 바꿔야 합니다.DESIGN.md의lineHeight는24px같은 길이와1.5같은 숫자를 모두 받습니다. DTCG는 숫자 배수만 받습니다.DESIGN.md는 CSS 색 문자열을 그대로 씁니다. DTCG는 색 공간과 성분 값으로 적고, 반투명은alpha필드로 적습니다.DESIGN.md의 컴포넌트 속성은backgroundColor,textColor,typography,rounded,padding,size,height,width8개입니다. 테두리 색 같은 다른 속성은 lint 경고를 받습니다. DTCG는 컴포넌트 구조를 정하지 않지만border,shadow같은 합성 타입으로 이런 값도 적을 수 있습니다.
DESIGN.md를 DTCG로 내보내면 빠지는 값
@google/design.md ↗ CLI는 DESIGN.md를 DTCG 형식으로 내보냅니다. 반대 방향 명령은 없습니다. 0.4.0의 명령은 lint, diff, export, spec 네 가지입니다(README ↗).
npx @google/design.md lint DESIGN.md
npx @google/design.md export --format dtcg DESIGN.md > exported.tokens.json위 DESIGN.md를 내보내면 색·간격·반경은 손으로 쓴 design.tokens.json과 같은 값이 나옵니다. 내보내기는 색 성분을 소수점 셋째 자리에서 반올림합니다. 차이는 세 곳입니다.
typography.label-md에lineHeight가 없습니다. 숫자로 적은lineHeight: 1.4가 출력에서 빠집니다.components전체가 빠집니다. 버튼의 참조 토큰이 출력에 없습니다.- Markdown 본문은 옮겨지지 않습니다. 파일 맨 위
$description에는name값이 들어갑니다.
exported.tokens.json의 타이포그래피 부분
{
"typography": {
"label-md": {
"$type": "typography",
"$value": {
"fontFamily": "Pretendard",
"fontSize": { "value": 14, "unit": "px" },
"fontWeight": 600,
"letterSpacing": { "value": 0, "unit": "px" }
}
}
}
}다른 값도 내보내면서 바뀝니다. 아래 표는 @google/design.md 0.4.0의 내보내기 결과와 DTCG JSON Schema 검사 결과입니다.
| DESIGN.md 값 | 내보낸 DTCG 값 | 결과 |
|---|---|---|
lineHeight: 1.4 | 속성 없음 | 스키마 오류: 필수 속성 lineHeight 없음 |
lineHeight: 24px | "lineHeight": 24 | 스키마 통과, 뜻은 글자 크기의 24배 |
letterSpacing: -0.02em | "unit": "em" | 스키마 오류: 단위는 px·rem만 |
"#0B57D080"(반투명) | 성분 3개와 8자리 hex, alpha 없음 | 스키마 오류: hex는 6자리 |
"oklch(62% 0.18 250)" | "colorSpace": "srgb", "hex": "#0089ed" | 스키마 통과, 원래 색 공간은 사라짐 |
components 아래 모든 값 | 출력 없음 | 참조 토큰을 직접 추가해야 함 |
실제 파일에서도 같은 일이 생깁니다. Atlassian이 공개한 DESIGN.md ↗(revision 0.0.7)를 같은 명령으로 내보내면 반투명 색 25개가 8자리 hex로 나옵니다. 타이포그래피 토큰 23개에는 letterSpacing이 없어 모두 스키마 검사를 통과하지 못합니다. heading-xxlarge의 lineHeight: '2.25rem'은 글자 크기의 2.25배를 뜻하는 2.25로 바뀝니다.
내보낸 파일을 빌드 도구에 넣으려면 다음을 고칩니다.
- 숫자 배수로 된
lineHeight를 추가하고, 길이로 적은 줄 높이는 글자 크기로 나눈 배수로 바꿉니다. em단위 값은 글자 크기를 곱해px나rem으로 바꿉니다.- 반투명 색은
hex를 6자리로 줄이고alpha를 따로 적습니다. - 컴포넌트 값은
button-primary예처럼 참조 토큰으로 추가합니다.
두 파일을 각각 검사합니다
DESIGN.md: design.md lint
lint는 결과를 JSON으로 출력하고 오류가 있으면 종료 코드 1을 돌려줍니다. 위 예제의 {colors.primary}를 {colors.primay}로 잘못 적으면 다음 오류가 나옵니다.
{
"severity": "error",
"path": "components.button-primary",
"message": "Reference {colors.primay} does not resolve to any defined token.",
"rule": "broken-ref"
}버튼 글자색 on-primary를 #8AB4F8로 바꾸면 대비 경고가 나옵니다.
textColor (#8ab4f8) on backgroundColor (#0b57d0) has contrast ratio 3.03:1, below WCAG AA minimum of 4.5:1.lint는 DESIGN.md 형식의 규칙 11개를 검사합니다. DTCG 형식에 맞는지는 검사하지 않습니다.
design.tokens.json: DTCG JSON Schema
DTCG 저장소는 2025.10 형식의 JSON Schema를 https://www.designtokens.org/schemas/2025.10/format.json ↗에 공개합니다. 스펙 본문에는 JSON Schema 추가를 검토 중이라는 편집자 메모만 있습니다. 스키마는 DTCG 저장소의 schemas 패키지 ↗에서 관리합니다. 형식은 JSON Schema draft-07이므로 Ajv로 검사할 수 있습니다.
validate-tokens.mjs(설명용 예제)
import Ajv from "ajv";
import { readFile } from "node:fs/promises";
const schemaUrl = "https://www.designtokens.org/schemas/2025.10/format.json";
const schema = await (await fetch(schemaUrl)).json();
const validate = new Ajv({
allErrors: true,
strict: false,
validateFormats: false,
}).compile(schema);
const tokens = JSON.parse(await readFile(process.argv[2], "utf8"));
if (validate(tokens)) {
console.log("valid");
} else {
for (const e of validate.errors) console.log(e.instancePath, e.message);
process.exitCode = 1;
}npm install ajv
node validate-tokens.mjs design.tokens.json
node validate-tokens.mjs exported.tokens.json손으로 쓴 design.tokens.json은 valid를 출력합니다. 내보낸 파일은 오류 목록 안에 다음 줄을 출력합니다. 같이 나오는 다른 줄은 같은 값이 다른 타입 후보와도 맞지 않았다는 기록입니다.
/typography/label-md/$value must have required property 'lineHeight'스키마는 토큰에 직접 적은 $type만 보고 값을 검사합니다. color 그룹에 $type을 두고 안쪽 토큰에 "$value": 5를 넣으면 통과합니다. 5가 number 타입으로는 맞는 값이기 때문입니다. 그룹에서 상속한 타입까지 확인하려면 토큰 파서의 검사 규칙을 함께 씁니다. Terrazzo 2.10.0의 tz check는 설정 파일이 있을 때 core/valid-color, core/valid-typography 같은 권장 규칙을 실행해 이 경우를 오류로 보고합니다. 설정 파일 없이 실행하면 규칙 없이 파싱만 합니다.
빌드 도구가 읽는지 확인
토큰 파일의 독자는 번역 도구입니다. Style Dictionary 5.7.0으로 design.tokens.json을 CSS 변수로 바꾸면 결과를 바로 확인할 수 있습니다. Style Dictionary 문서 ↗는 2025.10 지원을 v5에서 진행 중인 작업이라고 밝힙니다. 이 예제의 색·크기 객체와 참조는 CSS 변수로 바뀝니다.
sd.config.json
{
"source": ["design.tokens.json"],
"platforms": {
"css": {
"transformGroup": "css",
"buildPath": "build/",
"files": [{ "destination": "tokens.css", "format": "css/variables" }]
}
}
}npx style-dictionary build --config sd.config.jsonbuild/tokens.css
/**
* Do not edit directly, this file was auto-generated.
*/
:root {
--color-primary: #0b57d0; /** 화면마다 주요 행동 하나에만 쓴다. */
--color-on-primary: #ffffff;
--spacing-md: 16px;
--rounded-md: 8px;
--typography-label-md: 600 14px/1.4 Pretendard;
--button-primary-background: #0b57d0;
--button-primary-text: #ffffff;
--button-primary-typography: 600 14px/1.4 Pretendard;
--button-primary-radius: 8px;
--button-primary-padding: 16px;
}참조 토큰은 원래 값으로 풀려 들어갑니다. $description은 CSS 주석이 됩니다. CSS font 단축 속성에는 글자 간격이 없으므로 letterSpacing은 빠지고, 빌드 로그에 이를 알리는 경고가 나옵니다.
어느 파일을 원본으로 둘까
두 파일에 같은 값을 손으로 적으면 언젠가 어긋납니다. 값의 원본은 하나로 정하고 다른 파일은 그 원본에서 만듭니다.
- DTCG 토큰 파이프라인이 이미 있는 경우: 디자인 툴에서 내보낸 토큰 파일을 Style Dictionary 같은 빌드 도구가 읽고 있다면 토큰 파일을 원본으로 둡니다.
DESIGN.md의 frontmatter는 위 대응 표대로 토큰 파일에서 만들고, 의도는 Markdown 본문에 직접 씁니다. design.md CLI에는 DTCG를 읽는 명령이 없으므로 변환 스크립트는 팀이 작성합니다. 만든 파일은design.md lint로 검사하고, 이전 버전과design.md diff로 비교해 바뀐 토큰을 확인합니다. - 토큰 파이프라인 없이 에이전트용 문맥부터 필요한 경우:
DESIGN.md로 시작합니다. 빌드 도구가 필요해지면export --format dtcg로 토큰 파일을 만들고, 앞 절의 빠진 값을 채운 뒤 JSON Schema로 검사합니다. - 두 파일을 모두 손으로 고치는 경우: 둘 중 하나를 원본으로 정할 때까지 변경할 때마다 내보낸 값과 토큰 파일을 비교합니다. 비교할 범위는 색·간격·반경·타이포그래피입니다. 컴포넌트와 본문은 내보내기 대상이 아닙니다.
DESIGN.md 본문에는 토큰 값으로 표현되지 않는 규칙을 적습니다. 예제의 “화면마다 primary 버튼 하나”처럼 언제 어떤 값을 쓰는지가 여기에 해당합니다. DTCG의 $description에도 짧은 설명을 넣을 수 있습니다. 이 문자열은 토큰 하나에 붙는 설명이고, Style Dictionary의 CSS 출력에서는 주석이 됩니다.
다음에 확인할 것
DESIGN.md형식이alpha를 벗어나는지, 내보내기가 숫자lineHeight·alpha·components를 옮기는지- DTCG JSON Schema가 스펙 본문에 정식으로 포함되는지
- Style Dictionary가 2025.10 지원을 마쳤다고 밝히는지
참고 자료
- Design Tokens Format Module 2025.10 ↗, Color Module 2025.10 ↗
- DTCG 첫 안정 버전 공지(W3C 커뮤니티 그룹) ↗
- DTCG JSON Schema 2025.10 ↗, schemas 패키지 ↗
- google-labs-code/design.md ↗, DESIGN.md 형식 스펙 ↗
- Style Dictionary DTCG 지원 ↗, Terrazzo 문서 ↗
- Atlassian 공식 글: Atlassian’s DESIGN.md is here ↗, Atlassian DESIGN.md ↗
2026년 10월 24일 수정: 같은 색·간격·타이포그래피를 DTCG 2025.10 토큰 JSON과 DESIGN.md로 적은 예제, 필드 대응 표, design.md CLI 내보내기에서 빠지는 값과 검사 방법을 새로 썼습니다. 이전 글은 두 형식의 구체적인 예 없이 같은 결론을 반복했고, DTCG 2025.10을 W3C 표준처럼 설명했습니다.