[Figma 플러그인] 플러그인 개발 시작하기(Dev Mode Codegen)

bluejoy·2023년 7월 25일
1

Figma 플러그인

목록 보기
1/2
post-thumbnail

간단한 설명

Figma

웹 기반의 UI/UX 디지인 프로토타이핑, 협업툴이다. 과거부터 무척 애용해왔는데, 최근 추가하고 싶은 기능이 생겨서 플러그인 개발을 시도해보기로 했다.

플러그인


이미 상당 수의 플러그인들이 피그마의 기능을 확장해주고 있다. 앞에서 피그마가 웹 기반이라고 했는데, 이 덕에 플러그인 개발 또한 기존 웹 개발과 비슷하게 개발이 가능하다.

공식 문서에서는 다음과 같이 설명하고 있다.

플러그인은 커뮤니티에서 만든 프로그램 또는 애플리케이션으로, Figma 편집기의 기능을 확장합니다. 플러그인은 파일에서 실행되고 하나 이상의 사용자 작업을 수행하며 사용자가 경험을 사용자 지정하거나 보다 효율적인 워크플로를 만들 수 있도록 합니다.
플러그인은 웹 기술로 구동됩니다. 플러그인을 개발하려면 이러한 기술에 대한 이해가 필요합니다. JavaScript 로 플러그인을 작성 하고 HTML을 사용하여 UI를 빌드합니다.

Figma Dev Mode

피그마에 새로 추가된 기능. 현재 베타이며, 디자인을 코드로 빠르게 변환하는데에 도움이 되는 여러 기능을 포함하고 있다.

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

나는 Dev 모드의 코드 변환에 기능을 추가하고자 했으므로 그 부분을 중점으로 살펴볼 것이다.

시작하기

플러그인 API

공식 문서는 플러그인 API 공식 문서
플러그인 API는 현재 열려있는 파일에 대해 읽기 및 쓰기 기능을 모두 지원한다. 즉 플러그인을 통해 파일 내용을 수정 및 조회 가능하다.

figma 전역 개체를 통해 파일에 접근 가능한데, 해당 객체는 피그마 내부에서만 주입되므로 개발 시에서는 타입만 설치 후 개발한다.

웹 버전

Figma 플러그인 개발을 위해서는 반드시 데스크톱 앱이 필요하다. 없다면 다운로드 하자.

새 플러그인 만들기


아무 파일이나 열어서 상단 메뉴의 Plugin > Developement > New Plugin을 누르자


FigJam은 의사소통에 포커스한 서비스인데, 이번에는 필요가 없으므로 Figma용 플러그인을 선택한다.


Run once에서 시작한다. 이후 Save As를 눌러서 편한 폴더에 저장하자. Default로 하면 타입스크립트 설정을 수동으로 해줘야 한다.

처음 구조

├── README.md # 설명
├── code.js # code.ts가 tsc에 의해 컴파일
├── code.ts # 실제 개발 파일
├── manifest.json # figma에서 읽어 api 접근 권한 및 플러그인의 정보를 알아냄.
├── package.json # 패키지 괸리자
└── tsconfig.json # code.ts를 컴파일 하기 위한 설명

처음 열었을 때의 폴더 구조는 다음과 같다.

package.json 수정

패키지 설치 전에 패키지들의 버전을 수정해주자.

{
  "name": "css-object",
  "version": "1.0.0",
  "description": "Your Figma Plugin",
  "main": "code.js",
  "scripts": {
    "build": "tsc -p tsconfig.json",
    "watch": "npm run build -- --watch"
  },
  "author": "",
  "license": "",
  "devDependencies": {
    "@figma/plugin-typings": "^1.71.1", // 수정
    "typescript": "^5.1.6" // 수정
  }
}

기존에는 *로 되어 있어 구버전이 설치되는 경우가 있었다. 최신 버전으로 설치해주자.

이후 의존성을 설치하자

pnpm install # or yarn, npm

최초 실행

pnpm watch

개발 모드로 code.ts를 실행 해주자.
이후 피그마로 이동한다.

상단의 피그마 메뉴바에서 플러그인 버튼을 눌러 Development 탭을 선택하면 내가 생성한 플러그인이 보인다.
(만약 못찾는다면 이전의 메뉴를 통해 매니페스트 파일을 불러오면 된다)

눌러서 실행해보면

짜잔 주황색 사각형이 5개 나타났다.

Figma Dev 모드 개발

그러나 나는 문서를 수정하고 싶은게 아니기에 매니페스트를 수정해야한다.

// manifest.json
{
  "name": "css-object",
  "id": "숫자",
  "api": "1.0.0",
  "main": "code.js",
  "capabilities": [
    "codegen" // 수정
  ],
  "enableProposedApi": false,
  "editorType": [
    "dev" // 수정
  ],
  "networkAccess": {
    "allowedDomains": [
      "none"
    ]
  }
}
  • editorTypefigma에서 dev
  • capabilitiesinspect를 추가했다.

즉 개발 모드에서 코드 생성 기능을 제공하는 플러그인이다. 그런 의미인듯.

이렇게 수정하고 다시 피그마로 돌아가면

일반 모드의 플러그인에서는 사라졌다.

개발 모드에서 실행 시키면 Figma Dev Mode에서 허용되지 않은 메소드에 접근해 에러가 난다!.

code.ts 수정

피그마 개발 모드에서 코드 생성시 이벤트에 접근한다.

// code.ts
figma.codegen.on('generate', (e : CodegenEvent) => {
  return [
    {
      title: 'hi',
      code: 'code',
      language: 'JAVASCRIPT'
    }
  ]
});

리턴이 배열인 이유는 여러 코드를 한번에 생성 가능해서이다.

에러 디버깅


매니페스트 수정 이후 다음과 같이 코드 생성 탭에서 새로 추가된 것을 확인 가능하다. 그러나 현재는 선택 하면 에러가 난다.

하단 에러 메세지 혹은 상단 메뉴의 open console을 통해 브라우저 콘솔에 접근 가능하다.

에러는 다음과 같았다. codegen 플러그인의 경우 생성하는 언어에 대한 정보를 매니페스트에 추가해줘야 한다.

수정

// manifest.json
{
  "name": "css-object",
  "id": "1265699568605378644",
  "api": "1.0.0",
  "main": "code.js",
  "capabilities": [
    "codegen"
  ],
  "codegenLanguages": [
    {
      "label": "css object",
      "value": "javascript"
    }
  ], // 추가
  "enableProposedApi": false,
  "editorType": [
    "dev"
  ],
  "networkAccess": {
    "allowedDomains": [
      "none"
    ]
  }
}

확인

위에서 설정해준 codegenLanguages의 label과 value는여러 언어 생성을 지원할 경우에 의미가 있다.

이제 선택 후 결과를 확인하면


짠 다음과 같이 코드가 생성됐다.

더 복잡하게

다시 코드로 돌아와서, codegengenerate 이벤트에서는 CodegenEvent을 파라미터로 받는다.

declare type CodegenEvent = {
  node: SceneNode // 선택한 피그마 레이어
  language: string // 매니페스트에서 설정해준 value. 하나일 경우 유저의 별도 선택 없이 자동 선택.
}

SceneNode

type SceneNode =
  BooleanOperationNode |
  CodeBlockNode |
  ComponentNode |
  ComponentSetNode |
  ConnectorNode |
  EllipseNode |
  EmbedNode |
  FrameNode |
  GroupNode |
  InstanceNode |
  LineNode |
  LinkUnfurlNode |
  MediaNode |
  PolygonNode |
  RectangleNode |
  SectionNode |
  ShapeWithTextNode |
  SliceNode |
  StampNode |
  StarNode |
  StickyNode |
  TableNode |
  TableCellNode |
  TextNode |
  VectorNode |
  WidgetNode |
  MediaNode

이런데... 즉 피그마의 노드 타입들 중 하나라는 뜻이다.

각각에 대해서 전부 처리해줄 수 없으므로 공유 노드 속성을 통해 접근하자.

예제

css 읽어오기

figma.codegen.on('generate', async (e : CodegenEvent) => {
  const node = e.node;
  const css =await node.getCSSAsync();
  
  let result = ''
  for(const key of Object.keys(css)) {
    result += `${key}: ${css[key]};\n`
  }
  return [
    {
      title: 'my css',
      code: `${result}`,
      language: 'JAVASCRIPT'
    },
    {
      title: 'zz',
      code: `123123`,
      language: 'JAVASCRIPT'
    }
  ]
});

자신과 자식의 css 읽어오기

const genCssSr = async (node : SceneNode ) => {
  const css = await node.getCSSAsync();
  let result = ''
  Object.keys(css).forEach((key) => {
    result += `${key}: ${css[key]};\n`
  });
  return result;
}

figma.codegen.on('generate', async (e : CodegenEvent) => {
  const node = e.node;
  if(!('children' in node)) {
    return [];
  }
  const cssPromises= node.children.map(genCssSr);
  const results = await Promise.all(cssPromises);
  const parentCss = await genCssSr(node);

  const result = [
    {
      title: 'parent css',
      code: parentCss,
      language: 'JAVASCRIPT'
    },
    ...results.map((result,idx) => ({
      title: `${idx + 1}번째 child css`,
      code: `${result}`,
      language: 'JAVASCRIPT'
    } ))
  ] as CodegenResult[];
  return result;
});

결과


나의 조그마한 css object 스타일 생성기
emotion object 방식을 쓸 때 이걸 생성해주는게 없어서 정말 귀찮았는데, 이제 복붙하면 된다!!

소스 코드

figma 커뮤니티

현재는 리뷰중이라 접속이 안될 수 있다.

profile
개발자 지망생입니다.

1개의 댓글

comment-user-thumbnail
2023년 7월 25일

좋은 정보 감사합니다

답글 달기