피그마 무료 플랜에서도 쉽게 피그마의 컬러 코드를 프로젝트의 root CSS에 import할 수 있는 figmable CLI를 만들었습니다! 🎉
디자인에서 시스템을 구축해주었다면, 프론트엔드 개발자는 피그마에서 핸드오프 문서를 보며 섬세하게 반영하는 역할을 수행합니다. 컬러
, 타이포그래피
, 스페이싱
등, Foundation으로 구축된 값을 그대로 쉽게 재사용할 수 있도록 코드 단에 옮겨오는 작업이 필요하죠.
이것이 꼭 난이도가 높은 작업은 아니더라도, 정보를 틀림없이 잘 반영하는 꼼꼼함이 필요합니다. 또한 처음 반영한 이후, 디자인 시스템이 업데이트가 된다면 또한 누락 없이 잘 반영해야하죠.
하지만 여기서 어떤 점이 변경되었고, 어떤 점이 유지되어야 하는지 잘 파악할 수 있어야합니다. 자칫하다간 누락될 수 있죠.
이번에 저는 휴먼 에러가 발생할 확률이 높은 이 작업의 자동화를 위해, Figmable이라는 이름의 CLI
를 만들어보았습니다!
Figmable은 손쉽게 디자인 시스템의 정보를 프로젝트에 업데이트할 수 있는 CLI입니다. 100% 자동화는 아니라도 필요한 시점에 CLI 한번으로 요소를 가져올 수 있죠.
figmable
이라는 이름은 Figma
와 영어 접미사 -able(~할 수 있는)
의 합성어로, "Figma 데이터를 코드에서 쉽게 활용할 수 있게 만드는 도구"라는 의미를 담았습니다! (마블을 연상시키는 발상이기도 했습니다 🤣)
우선 첫 시작으로 Color 코드
를 가져올 수 있는 기능을 구현하였습니다.
figma.com/file/YOUR_FILE_KEY/...
--
Prefix를 붙여야합니다 (예: --primary-500
, --orange-600
)--orange-600 → #EA580C
--primary-500 → #3B82F6
--neutral-900 → #171717
CSS에 :root
선택자가 필요합니다.
예시:
/* Tailwind 사용 시 */
@layer base {
:root {
/* CSS 변수가 여기에 추가됩니다 */
--primary: #000000;
}
}
/* 또는 일반 CSS도 가능합니다 */
:root {
/* CSS 변수가 여기에 추가됩니다 */
--primary: #000000;
}
npm install -g figmable
먼저 Figma 인증 정보
와 파일 경로
를 저장합니다.
figmable config \
--fileKey YOUR_FIGMA_FILE_KEY \
--token YOUR_FIGMA_API_TOKEN \
--path ./path/to/your/global.css
저장된 설정을 확인합니다.
figmable show
다음 정보가 표시됩니다.
- Figma 파일 키와 URL
- API 토큰
- 파일 경로
- 설정 파일 위치 (직접 수정 가능)
설정 후 간단히 실행:
figmable
실행 시:
figma-variables.json
에 저장합니다.bak
)현대 프론트엔드 개발에서 디자인 시스템의 일관성을 유지하는 것은 중요한 과제입니다. 특히 컬러 시스템은 사용자 경험과 브랜드 아이덴티티의 핵심 요소죠. figmable 개발을 시작하게 된 배경은 다음과 같습니다.
피그마에 디자인 팔레트를 구축하고 이를 스토리북에 반영하는 과정은 순조로웠습니다. 하지만 디자인 변경이 발생할 때마다 매번 수동으로 코드를 업데이트해야 하는 문제가 있었습니다.
디자인팀과 개발팀 사이의 효율적인 협업을 위해서는 이러한 수동 프로세스를 자동화할 필요가 있었습니다.
매번 변경사항을 일일이 global CSS에 반영하는 작업은 단순 반복 작업이라 난이도가 높지는 않지만, 바꾸지 않아야할 요소를 바꾼다거나, 컬러 코드 입력을 실수한다든가 하는 휴먼 에러가 발생할 여지가 큽니다.
논리적 에러가 발생하는 분야가 아니기 때문이죠.
:root {
--primary-100: #E6F7FF;
--primary-200: #BAE7FF;
--primary-300: #91D5FF;
--primary-400: #69C0FF;
--primary-500: #40A9FF;
/* ... 수십 개의 컬러 변수들 */
}
처음에는 특정 프로젝트를 위한 모듈로 시작했지만, 이 기능이 모든 프론트엔드 프로젝트에서 필요할 것이라는 생각이 들었습니다.
'이 로직을 매 프로젝트마다 다시 작성하는 건 비효율적이지 않을까? CLI
로 만들면 재사용성이 높아지지 않을까?'라는 고민이 figmable의 시작점이이었어요!
최근 npm 라이브러리를 만들어 배포한 경험이 곧장 행동할 수 있게끔 만들어준 원동력이었습니다!
처음에는 특정 프로젝트 내에서 피그마 API를 활용해 컬러 코드를 가져오는 간단한 모듈을 만들었습니다. 이 단계에서는 기본적인 HTTP 요청
과 응답 데이터 파싱에 집중했습니다.
// 초기 모듈의 핵심 로직 예시
async function fetchFigmaColors(fileId: string, token: string): Promise<ColorTokens> {
const response = await fetch(`https://api.figma.com/v1/files/${fileId}`, {
headers: {
'Authorization': `Bearer ${token}`
}
});
const data = await response.json();
return parseColorTokens(data);
}
이 기능을 재사용하기 쉽게 만들기 위해 별도의 리포지토리를 생성했습니다. 이 단계에서 코드 구조를 더 모듈화하고, TypeScript
를 사용해 타입 안정성을 강화했습니다.
CLI 도구의 사용성을 높이기 위해 여러 가지 기능을 추가했습니다:
직관적인 로그 메시지: 사용자가 진행 상황을 쉽게 이해할 수 있도록 명확한 메시지를 설계했습니다.
console.log('🎨 피그마에서 컬러 토큰을 가져오는 중...');
로딩 스피너: API 호출 시간 동안 사용자에게 피드백을 제공하기 위해 ora 라이브러리를 활용해 로딩 스피너를 구현했습니다.
import ora from 'ora';
const spinner = ora('피그마 API에서 데이터를 가져오는 중...').start();
try {
const data = await fetchFigmaData(fileId, token);
spinner.succeed('데이터를 성공적으로 가져왔습니다!');
} catch (error) {
spinner.fail('데이터 가져오기 실패');
console.error(error);
}
백업 기능: 기존 CSS 파일이 손상되는 것을 방지하기 위해 자동 백업 기능을 구현했습니다. 동시에 백업이 필요 없는 경우를 위한 -no-backup
옵션도 제공했습니다.
if (!flags.noBackup && fs.existsSync(outputPath)) {
const backupPath = `${outputPath}.backup`;
fs.copyFileSync(outputPath, backupPath);
console.log(`💾 기존 파일의 백업이 생성되었습니다: ${backupPath}`);
}
CLI 도구로서 제대로 기능하기 위해서는 bin
설정이 필수적이라는 점을 알게 되었습니다. 이를 위해 index.ts 최상단에 shebang(#!/usr/bin/env node
)을 추가하고, package.json에 bin 필드를 정의했습니다.
{
"name": "figmable",
"version": "1.0.0",
"bin": {
"figmable": "dist/index.js"
},
"scripts": {
"build": "rollup -c rollup.config.mjs",
"prepare": "npm run build",
}
}
CLI 도구를 개발할 때 사용자 입력을 효과적으로 받기 위해, 라이브러리를 사용한다는 것을 알게되었습니다. 두 가지 주요 npm 라이브러리로, Commander와 Yargs가 있었어요.
조사를 해보니 통상 두 가지 다른 방향성이 있었습니다.
figmable은 Figma의 파일 키
(file-key), API 토큰
(token), 파일 경로
(path) 등 여러 인수를 유연하게 입력 받아야 했습니다.
특히 설정 명령어와 기본 동기화 명령어가 서로 다른 옵션을 가져야 했기 때문에, 저는 Yargs를 선택하였어요.
// 설정 명령어와 기본 명령어의 옵션이 다른 구조
.command("config", "Save configuration", (yargs) => {
return yargs.option("fileKey", {...})
})
.command("$0", "Sync Figma variables", (yargs) => {
// 다른 옵션 구성
})
Yargs는 이런 복잡한 구조를 명확하게 표현할 수 있었고, TypeScript
와의 통합도 자연스러워서 개발 과정이 수월했습니다.
다음 CLI를 만들 때는 Commander를 사용해보려 합니다! 각 도구의 장단점을 직접 경험해보면 더 깊이 이해할 수 있을 것 같아요!
CLI 도구의 사용자 경험은 GUI와는 다른 방식으로 접근해야 합니다
-help
옵션을 통해 모든 기능과 사용 예시를 충분히 제공해야 합니다.npm을 통해 전역 설치될 CLI 도구는 다음 사항을 고려해야 했습니다.
bin
필드 설정figable을 사용하기 위해, 피그마 REST API를 사용하죠. 이때 사용자의 환경변수가 필요합니다.(file key
, token
, path
등) 매번 CLI의 인수로 작성하는 것은 아주 불편하고 실수할 여지가 많은 방식이라 생각했어요.
저는 최초 figable config-
명령어를 이용하여 최초 1번만 설정하면 이후, figable
만 실행하여 쉽게 사용할 수 있도록 만들었습니다.
이를 위해 config에서 받은 인수를 사용자의 환경에 자동으로 .figmablerc
라는 파일을 생성하여 쉽게 관리할 수 있도록 만들었습니다.
개발 과정에서 마주친 주요 문제들과 그 해결책을 공유합니다. 이러한 경험이 비슷한 도구를 개발하시는 분들께 도움이 되길 바랍니다.
피그마에서 디자인 값을 가져올 수 있는 REST API를 제공한다는 것을 알게되었어요. 현재 통상 피그마에서는 Local Variables를 이용하여 간편하게 디자인 토큰을 관리할 수 있습니다.
혹시나 하였는데 역시나! 피그마 REST API에서는 이 기능으로 만들어진 디자인 토큰을 손쉽게 get할 수 있는 엔드포인트를 제공하고 있었어요!
하지만... 무료 플랜에서는 /variables/local 엔드포인트에 접근할 수 없다는 제약이 있다는 것을 알게되었습니다.
이 문제를 해결하기 위해 대체 접근법을 만들었습니다.
- 파일 정보를 가져오는 일반 API를 사용하여 문서 구조를 분석
- 컬러 스타일이 적용된 노드를 찾아 해당 스타일 정보 추출
- CSS 변수명 형식에 맞게 데이터 구조화
조금 번거롭더라도,핸드오프 문서에서 컬러그래피의 Color Object의 이름에 반드시 --
prefix를 붙여서, 디자인 토큰 이름으로 작성해주어야 합니다. 해당 피그마 파일 모든 object의 이름 중에서 위 규칙과 같은 요소들만 가져와 json으로 추출합니다.
이를 통해 자체적으로 디자인 시스템의 컬러 코드를 가져올 수 있는 방법을 만들었습니다!
사용자가 컬러 코드를 추출하기 위해 매번 API 키와 파일 경로를 입력하는 것은 너무 불편합니다. 마치 리포지토리에 .env
파일에 환경변수를 입력하여 보안과 재사용성을 확보하는, 그런 방법을 사용하고 싶었어요.
처음에는 dotenv
를 고려했지만, 전역 설치 CLI에서는 적합하지 않다고 판단했습니다.
❯ figmable config --fileKey YOUR_KEY --token YOUR_TOKEN --path ./src/styles/global.css
✅ Configuration saved: /Users/byungskersmacbook/.figmablerc
대신 사용자 홈 디렉토리에 설정 파일, .figmablerc
를 생성하는 방식을 선택했습니다! 이제 환경변수는 최초 1회만 설치하고 이후에는 figmable
만 실행하여 css에 자동 반영되도록 하였습니다.
또한 이후 figmable show
커맨드를 이용하여 변수들을 확인할 수 있고, 수정이 필요할 경우 로그에 출력된 경로로 이동하여 직접 쉽게 입력할 수 있도록 만들어두었습니다!
디자인 토큰을 손쉽게 가져오는 방법을 고민하고 계시다면, figmable을 한번 경험해보세요! 유용하셨다면, GitHub 저장소에 스타로 응원 해주시면 감사하겠습니다!! 😆
또한, 냉철한 피드백 혹은 이슈를 제보해주시거나 더 좋은 아이디어가 있다면 얼마든지 기여 부탁드려요!
긴 글 읽어주셔서 감사합니다!