혼자서 디자인 시스템을 만들면서 가장 어려운 점은 '디자인'이다.
그래서 Figma에서 잘 만들어진 디자인 시안을 참고해서 코드로 구현하는 방식을 활용하는데, 이 과정에서 디자인 시안을 실제 React 컴포넌트 코드로 정확하고 일관성 있게 구현하는 것이 생각보다 어려웠다.
Figma Dev Mode나 플러그인을 통해 CSS, 라이브러리 문법에 맞는 스타일 코드를 추출할 수 있지만, 이것만으로는 충분하지 않다.
복잡한 컴포넌트 구조를 반영하거나, Figma에 적용된 디자인 토큰을 실제 코드에서 사용하는 디자인 토큰으로 변환하는 등 수작업이 많이 필요하다.
Figma의 Component Set은 Variant별로 스타일을 적용한 컴포넌트를 관리할 수 있는 기능이다

코드에서는 cva 같은 유틸리티로 공통 스타일(base)과 Variant별 스타일을 분리하여 정의하는 것이 일반적인데,
// 예시: tailwind+cva를 사용한 shadcn 코드
const buttonVariants = cva(
"inline-flex items-center justify-center ...", // 공통 Base 스타일
{
variants: { /* ... Variant 스타일 정의 ... */ },
// ...
}
);
Figma에서 정의한 Variant를 기반으로 이런 base + variant 형태의 코드를 자동으로 생성할 수 있다면 시간을 매우 단축할 수 있을 것 같아 여러 방법을 찾아보았지만,
Figma에서는 아직 이러한 기능을 자체적으로 제공하고 있지 않다(plugin도 딱히 없는 것 같다)
Figma에서 추출한 스타일은 각 Variant가 적용된 결과물일 뿐, Base 스타일과 Variant별 스타일이 분리되어 있지 않다. 이를 코드에서 재사용 가능한 base + variant 구조로 만들려면, 각 Variant 스타일을 추출하고, 비교 분석하여 수동으로 분리해야 하는 복잡함이 있다.
컴포넌트 구조가 복잡하거나(합성 컴포넌트) Figma 파일마다 컴포넌트를 작성하는 방식이 다르기 때문에, 일관된 로직 적용이 어렵다.
어떤 스타일을 공통(Base) 으로 정의할지에 대한 주관적인 판단 문제도 있다.
사실 이 Base/Variant 스타일 분리 문제는 복잡한 로직이 필요하다기보다는, 여러 스타일 속성들을 보고 '공통적인 것'과 '개별적인 것'을 구분하는 '판단' 이 필요한 부분이다. 그렇다면 이를 AI한테 맡기면 어떨까? 라는 생각을 했다.
따라서, AI를 활용하여 이 분류 작업을 자동화하는 접근법을 구상했다.
사실 이 AI 기반 분류 작업은 MCP가 활성화되기 전부터 시도해오던 작업이었다. 당시에는 자체 제작한 Figma 플러그인을 로컬에서 실행해서 콘솔로 결과물을 출력하고, 이 결과물을 복사해서 Claude 같은 LLM에게 전달하는 방식으로 진행했다. 이 과정에서 수작업이 너무 많았다.
이후 MCP(Model Context Protocol)와 Figma MCP 구현체에 대한 소개를 보고, 이 번거로운 작업 과정을 개선하는 데 MCP를 이용할 수 있지 않을까 생각했다.
사용한 MCP 구현체는 cursor-talk-to-figma-mcp이다. 이 방식은 Figma 플러그인을 실행해야 MCP 서버와 통신이 가능한 약간의 불편함은 있지만, Figma 노드 정보 접근 등 다양한 API를 제공하고 있어 활용하기로 했다.
MCP의 상세한 동작 원리까지는 모르지만, cursor-talk-to-figma의 server.ts 코드를 보면 다음과 같은 구조로 동작한다.
server.tool(
"get_nodes_info", // 도구(명령어) 이름
"Get detailed information about multiple nodes in Figma", // 설명
{ /* 입력 스키마 정의 */ },
async ({ nodeIds }) => { // 실제 로직
// ... nodeIds를 받아 Figma에 명령 전달 ...
const result = await sendCommandToFigma("get_node_info", { nodeId });
// ... 결과 반환 ...
}
);
Cursor Agent가 get_nodes_info 같은 명령을 받으면(혹은 유사한 요청 시 자체 판단), sendCommandToFigma 함수를 호출하고, 이 함수는 Figma 플러그인 내부에 정의된 로직을 실행시킨다.
// Figma 플러그인 코드 예시 (plugin.ts)
async function handleCommand(command, params) {
switch (command) {
case "get_node_info":
// ... params에서 nodeId 추출 ...
return await getNodeInfo(params.nodeId); // 플러그인 내부 함수 호출
// ...
}
}
async function getNodeInfo(nodeId) {
// ... figma.getNodeByIdAsync(nodeId) 등 figma plugin API를 활용
return extractedInfo;
}
이 구조를 보고, AI에게 스타일 분류를 요청하는 로직을 MCP의 커스텀 명령어로 만들 수 있지 않을까 생각했다.
(기존 cursor-talk-to-figma에 있던 명령어들이 Component Set의 Variant와 관련된 정보를 잘 못가져오는 것 같아서 직접 만들기로 했다.)
그래서 기존 플러그인에서 사용하던 로직을 옮겨와 MCP 서버에 새로운 Command를 추가하는 방식으로 구현을 시도했다.
결과물과, 개선 사항은 다음 포스트에서...
그전에 느낀 점