이번 글에서는 Style Dictionary가 무엇인지와 사용 방법을 간단히 정리하고자 한다
1. 디자인 시스템과 Style Dictionary
Style Dictionary가 무엇인지 알기 전에, 디자인 시스템이 무엇인지 알 필요성이 있다.
쉽게 설명하자면, 디자인 시스템은 디자인과 개발을 좀 더 쉽게, 일관되게, 효율적으로 만들고 관리하는 방법이라고 할 수 있다.
그러면 Style Dictionary와 디자인 시스템이 무슨 상관이 있는 걸까?
Style Dictionary는 디자인 시스템에서 사용되는 디자인 토큰을 관리하고 적용하는 오픈 소스이다.
* 디자인 토큰: 디자인에서 사용되는 요소(글꼴, 색상, 그림자 등)을 표준화 한 요소
그럼 디자인 토큰이 왜 필요한 걸까?
디자인 토큰은 css변수를 설정하는 것과 같은 이치라고 볼 수 있다.
예를 들어, 본문의 color를 #f5f5f5라고 정해놨다고 하자.
만약 우리가 본문이 있는 곳마다 color: #f5f5f5라고 작성을 해놓았는데
맙소사, 갑자기 본문의 color가 #f6f6f6으로 바뀌어버리면 우리는 #f5f5f5가 있는 곳마다 일일이 다 바꿔줘야 할 것이다.
하지만 우리가 mainColor: #f5f5f5 라고 정해놓고 color를 mainColor라고 지정해놨으면
mainColor 색상만 바꾸면 쉽게 전체 색상을 바꿀 수 있을 것이다.
2. 피그마의 디자인 토큰 추출
https://www.figma.com/community/file/876022745968684318
부트스트랩의 figma를 보며 디자인 토큰을 추출하고, style Dictionary로 가공해보자
피그마에서 디자인 토큰을 추출할 수 있는 곳은 styles와 variables 두 종류가 있다.
보통은 Local styles 많이 이용한다. (위 Bootstrap도 styles를 이용하고 있다)
피그마를 열어서 우측 패널을 보면 Local styles라고 Text style, color 등을 정의해 둔 부분이 있다.
우리는 저 요소를 json으로 추출하여 style dictionary로 가공 할 것이다.
styles를 json형태로 추출하는 방법은 플러그인을 이용하는 방법이 제일 간단하다 !
좌측 상단 패널에서 저 아이콘을 클릭하면 플러그인을 검색하고, 사용할 수 있다.
token이라고 검색하면 여러 플러그인들이 많이 나오는데, 우리는 저 노란색 아이콘을 가진 Design Tokens를 이용할 것이다.
클릭해서 export design token files를 누르면 아래 창이 뜬다
여기서 Figma Variables(BETA)를 제외하고는 styles에 정의한 부분들이다.
추출해서 json 파일을 보면 아래와 같다.
{
"color": {
"primary": {
"color": {
"description": "",
"type": "color",
"value": "#7749f8ff",
"blendMode": "normal",
"extensions": {
"org.lukasoppermann.figmaDesignTokens": {
"styleId": "S:a4a48d4ec66ef0f05bfa6d36fcb36361ca79ab4c,",
"exportKey": "color"
}
}
},
"color dark": {
"description": "",
"type": "color",
"value": "#5227ccff",
"blendMode": "normal",
"extensions": {
"org.lukasoppermann.figmaDesignTokens": {
"styleId": "S:0a2a37c25b70236776ff632aa7ff581a98b60a02,",
"exportKey": "color"
}
}
},
...
}
}
color를 살펴보면 ...
primary라고 정의한 color가 value에 #7749f8ff 형태로 들어가 있는 것을 볼 수 있다.
3. Style Dictionary로 디자인 토큰을 CSS 변수 형태로 변환
사실 피그마 플러그인을 잘 찾아보면, styles -> css variables 로 바꿔주는 플러그인이 많이 있다.
하지만 해당 플러그인의 단점은 변수 이름이나 나오는 포맷을 커스텀하기 힘들다는 점이다.
style dictionary를 사용하면, 우리가 원하는 형태로 filter하고, format을 정하여 원하는 형태로 변환할 수 있다.
자! 새 프로젝트를 만들어서 style dictionary를 설치해 주자
$ npm install -D style-dictionary
설치한 후, 우리가 직접 config 파일을 만들어서 가공할 형태를 정의해줘야 한다
transformToken.js를 만들어서(파일 이름 자유) 아래 코드를 복붙 해주자 !
const StyleDictionary = require('style-dictionary').extend({
source: ['tokens/**/*.json'],
platforms: {
scss: {
transformGroup: 'scss',
buildPath: 'build/',
files: [{
destination: 'variables.scss',
format: 'scss/variables'
}]
}
// ...
}
});
StyleDictionary.buildAllPlatforms();
위 코드가 node에서 가장 기본적인 형태다. (https://amzn.github.io/style-dictionary/#/quick_start?id=node)
위 코드를 간략하게 설명하자면,,,
- source : 디자인 토큰이 저장된 장소
- platforms : 디자인 토큰을 변환할 형태를 정의한 부분 (플랫폼 이름: 객체 형태)
- 위 코드에선 scss라는 이름을 가지고 내부 속성에 따라 변환한다.
- transformGroup : color, size, time 등 해당 속성들을 어떻게 변환할 껀지 한꺼번에 정의한 형태
- buildPath : 어디에 변환되어 저장될 건지
- files
- destination : 변환될 파일 이름
- format: 변환될 형태를 정의한 포맷
Style Dictionary 공식 문서를 살펴보면 모든 속성에 대해 아주 자세하게 설명되어 있으니 참고하시길..
https://amzn.github.io/style-dictionary/#/
우리는 bootstrap token을 css변수 형태로 변환할 꺼니까 아래처럼 코드를 수정해준다.
const StyleDictionaryExtended = require('style-dictionary').extend({
source: ['./bootstrap-token.json'],
platforms: {
css: {
transformGroup: 'css',
buildPath: 'build/',
files: [{
destination: 'variables.css',
format: 'css/variables'
}]
}
// ...
}
});
StyleDictionaryExtended.buildAllPlatforms();
transformToken.js을 실행해주면 ! ($ node transformToken.js)
build/css/variables.css파일이 생성된다.
/**
* Do not edit directly
* Generated on Sat, 23 Sep 2023 08:47:51 GMT
*/
:root {
--color-primary-color: #7749f8;
--color-primary-color-dark: #5227cc;
--color-primary-light: #ebe5fc;
--color-secondary-color: #6c757d;
--color-secondary-dark-color: #54595e;
--color-secondary-light-color: #abb5be;
--color-status-color-success: #28a745;
--color-status-color-danger: #dc3545;
--color-status-color-warning: #ffc107;
--color-status-color-info: #17a2b8;
--color-gray-100: #f8f9fa;
...
}
style dictionary가 정의해둔 포맷으로 변환되어 나온다.
하지만 우리는 이 포맷이 아니라, 우리가 원하는 형태로 포맷팅하여 변환할 것이다.
4. 실습) 변수이름 바꾸기 (RegisterFormat)
변수 이름을 바꿀려면 Styledictionary.registerFormat 메서드를 이용을 해야한다.
https://amzn.github.io/style-dictionary/#/api?id=registerformat
StyleDictionary.registerFormat({
name: 'json',
formatter: function({dictionary, platform, options, file}) {
return JSON.stringify(dictionary.tokens, null, 2);
}
})
위 형태는 style dictionary의 registerFormat 사용 예제이다.
- name : config에 작성한 format 값에 들어갈 이름 (해당 이름을 참조하게 됨)
- formatter: 우리가 변환할 형태를 커스텀할 수 있는 부분, return하는 내용으로 결과물에 보이게 된다.
그러면 이제 대충 사용법을 알았으니, CSS 변수 이름을 바꿔보자!
--color-primary-color 를 primary로 보일 수 있게 formatter을 정의할 것이다.
그러면, 우리의 customFormatter을 작성해보자
const StyleDictionary = require('style-dictionary');
StyleDictionary.registerFormat({
name: 'customCss',
formatter: ({dictionary, options}) => {
console.log(dictionary);
return "";
},
});
위 형태로 작성해주고, 우리가 아까 작성한 StyleDictionaryExtended의 format 이름을 customCss로 바꿔주자
(css/variables -> customCss)
그리고, 다시 TransformToken.js를 실행시켜주면?
styleDictionary가 파싱한 형태의 dictionary를 볼 수 있다.
styledictionary.allProperties의 내용을 보면, styledictionary가 변수이름을 어떻게 설정했는지 알 수 있다.
{
description: '',
type: 'color',
value: '#7749f8',
blendMode: 'normal',
extensions: { 'org.lukasoppermann.figmaDesignTokens': [Object] },
filePath: './bootstrap-token.json',
isSource: true,
original: {
description: '',
type: 'color',
value: '#7749f8ff',
blendMode: 'normal',
extensions: [Object]
},
name: 'color-primary-color',
attributes: { category: 'color', type: 'primary', item: 'color' },
path: [ 'color', 'primary', 'color' ]
},
name과 path 속성을 보면, styledictionary에서는 단순히 변수이름을 path를 케밥케이스로 이어준 것이라는 걸 확인할 수 있다.
그러면, 우리가 primary라는 key 이름을 얻을려면, path 배열에서 color를 제외하고 케밥 케이스로 이어주면 되겠다.
그리고 value는 StyleDictionary가 잘 파싱하여 value라는 속성에 color값을 잘 넣어주었기에 해당 값을 활용하면 된다.
위 내용 바탕으로, registerFormat을 정의해주자.
StyleDictionary.registerFormat({
name: 'customCss',
formatter: function({dictionary, platform, options, file}) {
const variablesObject = dictionary.allProperties.reduce((acc,{value,type, path}) => {
// type에 따라 어떻게 파싱할 껀지 처리 해주면 됨 ! (현재는 color에 대해서만 파싱)
if(type === 'color') {
const key = path
.map((name) => name.replace('color', '').trim())
.filter((name) => name.length !== 0).join("-");
acc[key] = value;
}
return acc;
}, {});
const cssString = Object.entries(variablesObject)
.map(([key, value]) => ` --${key}: ${value};`)
.join("\n");
return `:root {\n${cssString}\n}`;
}
})
사실 파싱로직을 작성하는 건 알고리즘?문제 푸는거랑 비슷한거라...
자신이 알아서 어떤 형태로 나오게 할건지 정의하면 된다.
위 형태로 정의한 registerFormat을 이용해 styleDictionary를 실행시켜주면,
:root {
--primary: #7749f8;
--primary-dark: #5227cc;
--primary-light: #ebe5fc;
--secondary: #6c757d;
--secondary-dark: #54595e;
--secondary-light: #abb5be;
--status-success: #28a745;
...
}
이런 형태로 파싱되어 나오게 된다. !
registerFormat외에도,
https://amzn.github.io/style-dictionary/#/api
해당 api 문서를 보면, 파일 헤더를 정의하거나 템플릿을 정의한다던가 등의 action이 가능하다.
그리고 우리가 처음 bootStrap 피그마에서 디자인 토큰을 추출한 플러그인 깃헙에 가보면
https://github.com/lukasoppermann/design-tokens/blob/main/examples/build.js
StyleDictionary를 이용한 예제 코드들이 있다.
코드들을 참고해서, 어떤 형태로 파싱코드를 작성하는지 참고 할 수있다!
이번 글은 여기 까지 !!!!
궁금한 점 있으면 언제든지 댓글 달아주세요 :)
'Frontend > Article' 카테고리의 다른 글
Rollup을 이용하여 컴포넌트 라이브러리 만들기 ! (React, Ts, Sass, Storybook) (5) | 2023.11.26 |
---|---|
rollup-plugin-postcss의 SASS 파일 내 custom alias 처리 문제 (0) | 2023.10.14 |
Storybook path alias 설정 (0) | 2023.09.09 |
자바스크립트의 숫자(Number)형 (Feat. 부동 소수점 vs 고정 소수점) (0) | 2023.05.07 |
VanillaJs로 무한 스크롤 구현하기(feat: Intersection Observer) (0) | 2023.02.12 |