피그마

피그마 Dev mode 플러그인을 만들어서 웹 프론트엔드팀 생산성 높여보기

송동훈 프로필 이미지

송동훈

2023.12.18

9 min read

피그마 Dev mode 플러그인을 만들어서 웹 프론트엔드팀 생산성 높여보기

안녕하세요. 코멘토에서 웹 프론트엔드를 개발하고 있는 송동훈입니다. 코멘토 프론트엔드팀은 코멘토 디자인 시스템(comento-ui)과 피그마를 활용해 디자이너분들과 효율적으로 협업하고 있습니다.

기존 작업 플로우

텍스트 기반 서비스를 개발하다보니 텍스트 작업을 할 때가 많습니다. 작업할 때는 피그마의 Typography 속성을 참고해 comento-ui의 c-typography 코드를 작성합니다. IDE가 자동 완성으로 도와주기는 하지만 매번 텍스트와 속성을 적거나 붙여넣기해야하는 번거로운 작업입니다. 이 작업을 더 단순화해서 생산성을 높일 수 있는 방법은 없을까 고민하다가 피그마 플러그인을 활용하면 어떨까 하는 생각이 들었습니다.

이 글에서는 피그마에서 디자인 시스템 컴포넌트를 활용한 부분을 코드로 손쉽게 변환할 수 있는 피그마 플러그인을 개발해 생산성을 높인 배경과 방법을 소개합니다.


피그마 플러그인

피그마 플러그인은 피그마 에디터의 기능을 확장한 애플리케이션입니다. 웹 친화적으로 로직 부분은 Javascript, UI는 HTML로 작성할 수 있고 피그마 컨텐츠에 접근해서 데이터를 이용하거나 컨텐츠를 생성하거나 수정할 수 있습니다. 인기가 많은 대표적인 플러그인으로는 피그마 파일을 HTML, React 코드로 변환해주는 Figma to Code가 있습니다.

저는 작업할 때 피그마의 Dev mode를 주로 사용합니다. 이 모드는 개발자 도구로 요소를 확인하는 것처럼 개발자 친화적인 UI, UX를 제공해서 작업하기 편하게 해줍니다.

출처: https://www.figma.com/dev-mode/

Dev mode에서 동작하는 플러그인의 Code Generation(오른쪽 패널에 코드를 출력하는 기능)을 활용하면 번거로운 작업을 줄일 수 있을 것이라 생각했습니다.

만들고 싶은 플러그인

타이핑 단계를 없앤 작업 플로우

플러그인이 텍스트의 속성을 참고해 바로 c-typography 코드로 만들어서 타이핑 단계를 없애준다면 생산성이 향상될 것이라고 생각했습니다. 그렇다면 플러그인은 다음과 같은 로직으로 동작할 것이라고 생각했습니다.

  1. 유저가 피그마의 text를 선택합니다.
  2. 플러그인이 text의 property를 조사합니다.
  3. 플러그인이 property들을 c-typography의 props로 넘겨준 코드를 생성합니다.

개발을 시작하기 전에 ChatGPT에게 제가 원하는 기능의 플러그인을 만들 수 있는지 물어봤는데 답변을 보니 만들 수 있겠다는 생각이 들어서 플러그인 API 문서를 찾기 시작했습니다.

ChatGPT를 활용한 아이디어 실현 가능성 판단

플러그인 생성

플러그인은 피그마 데스크톱 앱에서 생성할 수 있습니다. 데스크톱 앱을 켜고 가이드를 따라가면 기본 예제 코드가 포함된 프로젝트를 생성할 수 있습니다.

기본 예제가 포함되어 생성된 피그마 플러그인 프로젝트

플러그인 실행

플러그인을 로컬에서 실행하고 피그마에서 바로 확인할 수 있습니다. 코드가 바뀔때마다 결과를 바로 반영하기 위해 watch 모드로 실행했습니다.

yarn && yarn run watch

피그마에서 Dev mode에서 동작하는 플러그인은 오른쪽 패널에 실행됩니다. 피그마 파일에서 오른쪽 마우스 버튼을 클릭해 "Manage plugins in development" 메뉴에 들어가면 방금 만든 플러그인의 목록을 확인할 수 있습니다.

피그마 앱에서 오른쪽 마우스 버튼을 클릭해 plugin 관리 메뉴에 들어가는 방법
피그마 앱의 오른쪽 패널

초기 예제 코드의 빨간 부분이 피그마의 Inspect 패널에 나오는 것을 확인할 수 있습니다.

기본 예제 코드
Inspect 패널에 플러그인 정보가 출력된 모습

코드 작성

코드를 보면 피그마 요소를 클릭하면 codegen의 generate event가 발생합니다. callback으로 넘어오는 CodegenEvent는 SceneNode type인 node를 넘겨주고 있었고, 여기에는 TextNode도 포함되어 있습니다.

callback의 CodegenEvent
declare type CodegenEvent = {
  node: SceneNode
  language: string
}

declare type SceneNode =
  | SliceNode
  | FrameNode
  | GroupNode
  | ComponentSetNode
  | ComponentNode
  | InstanceNode
  | BooleanOperationNode
  | VectorNode
  | StarNode
  | LineNode
  | EllipseNode
  | PolygonNode
  | RectangleNode
  | TextNode
  | StickyNode
  | ConnectorNode
  | ShapeWithTextNode
  | CodeBlockNode
  | StampNode
  | WidgetNode
  | EmbedNode
  | LinkUnfurlNode
  | MediaNode
  | SectionNode
  | HighlightNode
  | WashiTapeNode
  | TableNode
SceneNode type의 한 종류인 TextNode type

TextNode의 API 문서를 참고하여 어떤 API를 쓰면 원하는 값을 얻을지 console에 찍어보면서 파악했습니다. 아래 방법으로 console을 열어 볼 수 있었습니다.

피그마 앱에서 오른쪽 마우스 버튼을 클릭해 console을 보는 방법
정상적으로 출력되는 console

type props는 comento-ui에서 정의한 각 typography의 종류를 나타내는 값입니다. figma 객체의 getStyleById를 활용하여 값을 가져올 수 있었습니다.

c-typography의 type props

또한 필요한 font-weight, color값은 getCSSAsync method를 이용해 가져온 css object에서 가져올 수 있었습니다.

c-typography의 color, fontWeight props

아래는 getCSSAsync 메서드를 호출한 결과값입니다.

// getCSSAsync 결과값
{
    "color": "var(--Primary-blue800, #1B5192)",
    "font-family": "Pretendard",
    "font-size": "12px",
    "font-style": "normal",
    "font-weight": "400",
    "line-height": "122% /* 14.64px */"
}

마지막으로 텍스트 내용은 characters property를 가져왔습니다.

이를 종합하여 코드로 작성하면 다음과 같습니다.

figma.codegen.on('generate', async (event) => {
  // TEXT_NODE 일때
  if(event.node.type === 'TEXT') {
    /*
      mixed(여러개의 스타일이 적용된 텍스트)일때는 textStyleId가 figma.mixed이기 때문.
      <https://www.figma.com/plugin-docs/api/TextNode/#textstyleid>
    */
    if (typeof event.node.textStyleId === "string") {
      const css = await event.node.getCSSAsync();
      /*
       예시
         ex) extract 'body1' from 'body/body1(600)'
         ex) extract 'caption1' from 'caption/caption1(600)'
       */
      const fontType = figma.getStyleById(event.node.textStyleId)?.name.split('/')[1].split('(')[0];
      /*
        예시
          ex) extract 'gray850' from 'var(--Gray-gray850, #202325)'
          ex) extract 'red600' from 'var(--Error-red600, #E92525)'
      */
      const fontColor = css.color.match(/var\\(--(.+),/)?.[1].split('-')[1];
      const fontWeight = css['font-weight'];
      const content = event.node.characters;

      const code = `<c-typography type="${fontType}" color="${fontColor}" :font-weight="${fontWeight}">${content}</c-typography>`
      return [
        {
          language: "HTML",
          code: code,
          title: "c-typography-converter",
        },
      ];
    }
  }

  return [
    {
      language: "PLAINTEXT",
      code: "코드를 생성하려면 노드를 선택해주세요.",
      title: "c-typography-converter",
    },
  ];
});

피그마로 돌아가 이 플러그인을 실행해보면 아래와 같이 잘 동작하는 걸 볼 수 있습니다.

0:00
/
잘 동작하는 c-typography-converter 플러그인

마치며

이렇게 피그마 플러그인을 만들어 생산성을 높였던 경험을 살펴보았습니다. 플러그인 API가 잘 구현되어 있어서 원하는 기능을 어렵지 않고 빠르게 구현할 수 있었습니다. 간단한 기능을 구현해 보니까 뿌듯했고 시야를 더 넓혀서 다른 컴포넌트에도 적용해보고 싶다는 생각이 들었습니다. 플러그인을 개발하고 실제로 사용하다 보니 텍스트의 중간에 색상이 바뀌는 등 property들이 섞여 있는 예외 상황에는 작동하지 않는 이슈도 발견해 수정하려고 합니다. 이 글이 여러분에게 반복 작업을 줄일 수 있는 영감이 되었으면 합니다. 감사합니다.


커리어의 성장을 돕는 코멘토에서 언제나 함께 성장할 개발자를 기다리고 있습니다. 채용 페이지에서 코멘토가 어떤 회사인지, 어떤 사람을 찾는지 더 자세히 확인해보세요. 😊