피그마 플러그인에 리액트 세팅하기(0)

김형태·2024년 1월 11일

Figma

목록 보기
1/1

피그마 플러그인에 관심이 생겨서 플러그인 개발 환경을 세팅하는 중이다.

피그마 공식 홈페이지의 피그마 플러그인 퀵 스타트 가이드를 따라하면 최소한의 셋팅이 된다.

바닐라 자바스크립트도 좋지만 익숙한 리액트로 개발하는 게 좋으니 세팅을 해야하는데.. 맨날 vite나 cra로 폴더를 만들고 시작했더니 어디서부터 시작해야 할지 모르겠다.

tsconfig.json 설정은 어떻게 해야하는지, 번들러는 뭘 써야하고 config 설정은 어떻게 해야하는지 제대로 아는 게 하나도 없다는 걸 뼈저리게 느끼고, 여기에 모든 과정을 세세하게 적어야겠다. 아무것도 모른다는 게 낱낱이 드러날 테지만..


막연하게 리액트와 리액트 타입 패키지들을 설치했다.

리액트 공식 홈페이지

그리고 빌드를 하면, 바로 에러가 발생한다.

node_modules/@types/react/index.d.ts:7:22 - error TS2792: Cannot find module 'csstype'. Did you mean to set the 'moduleResolution' option to 'nodenext', or to add aliases to the 'paths' option?

피그마 플러그인 퀵 스타트 가이드에서 제공하는 보일러플레이트의 package.json을 보면, build 커맨드에서 tsc(타입스크립트 컴파일러)를 사용한다.

항상 vite나 cra CLI에서 제공하는 보일러 플레이트를 사용해왔으니 tsconfig.json을 건드릴 일이 많이 없었는데, 타입스크립트 컴파일러 옵션을 스스로 설정할 때가 왔다. 에러로 돌아가보면 moduleResolution과 관련이 있으니, 검색했다.

타입스크립트 공식 홈페이지: module-resolution

TS 컴파일러가 어떤 과정을 따를지 이해하기 위해서는, Node.js 모듈을 이해하는 것이 중요합니다.

자바스크립트 공부를 하든, 프론트엔드 면접 준비를 했든 어디서든 접해봤을 모듈과 관련된 이야기가 나왔다. 벌써부터 왜 면접에서 타입스크립트 컴파일러나 번들러에 질문했는지 다시 생각해보게 됐다.

다음의 설정을 추가해서 타입스크립트에게 어떤 모듈 시스템을 사용할지 알려줬다.

{
  "compilerOptions": {
    "target": "es6",
    "lib": ["es6"],
    "strict": true,
    "typeRoots": [
      "./node_modules/@types",
      "./node_modules/@figma"
    ],
    // 추가!
    "moduleResolution": "node"
  },
}

npm run build 커맨드에서 에러를 뱉지 않는다.

이제 타입스크립트 + 리액트를 사용할 것이니, .tsx.js로 바꿔주는 과정이 필요하다.

여기서 또 내가 아래의 과정이 어떻게 일어나는지에 대해 정말 아는 게 없다는 걸 알았다.

.tsx -> (???) -> .js

아는 게 없으니 무작정 번들러들을 검색했다. cra는 webpack을 사용하고 vite는 사전 번들링 시에는 esbuild를, 번들링 시에는 rollup을 사용한다고 한다.

검색하다보니 각각의 번들러들을 검색할 게 아니라 번들러 자체에 대해 제대로 알아야했다는 걸 깨달았다. 그래서 번들러가 무엇인지를 검색했다.

알고 보니 tsc, babel, webpack, esbuild 등등을 모두 짬뽕해서 대충 알고 있었다는 걸 알았다.

그리고 스택오버플로우에서 그렇게 봤던, tsconfig.json의 compilerOptionsjsx 옵션에 대해서도 찾아보게 됐다.

타입스크립트 공식 홈페이지: JSX

개발을 하면서 가끔 봤던 다음 에러에 대해 구글링하면,
'React' refers to a UMD global, but the current file is a module

항상 compilerOptions"jsx": "react-jsx"를 추가하라고 했었는데 바보같이 jsx 옵션이 뭔지는 찾아볼 생각도 하지 않았다.

막연하게 알고 있던 프로세스는(각 프로세스에서 어떤 작업이 이뤄지는지는 모르지만) 아래와 같았는데,

.tsx -> .jsx -> .js

"jsx": "preserve".tsx.jsx로 바꾼 뒤에 Babel과 같은 트랜스파일러를 통해 .jsx.js로 바꾸거나 "jsx": "react-jsx"를 통해 .tsx.js로 바꿀 수 있다는 걸 알게 되면서, tsc와 바벨이 어떻게 다른지에 대해서 알게 됐다.

'React' refers to a UMD global, but the current file is a module

위 에러를 마주했을 때 jsx 옵션에 대해 조금만 더 알아봤다면, 타입스크립트 컴파일러, 트랜스파일러, 번들러에 대해 조금 더 자세히 알 수 있지 않았을까?

타입스크립트 공식 홈페이지: JSX와 함께 스택오버플로우에 올라온 질문 TS Config JSX: ReactJSX vs React를 읽어보며 내 프로젝트의 tsconfig.json에 jsx 옵션을 추가했다.

{
  "compilerOptions": {
    "target": "es6",
    "lib": ["es6"],
    "strict": true,
    "typeRoots": [
      "./node_modules/@types",
      "./node_modules/@figma"
    ],
    "moduleResolution": "node",
    // 추가!
    "jsx":"react-jsx",
  },
}

이제 manifest.json에 설정된 ui.html의 script 안에서 React 코드를 사용해야 한다.

그래서 무지성으로 ui.html에 script 태그를 추가하고 src="/src/main.tsx"를 입력한 다음,

<script type="module" src="/src/main.tsx"></script>

main.tsx에 아래 코드를 쳤다.

import { createRoot } from 'react-dom/client';

// Clear the existing HTML content
document.body.innerHTML = '<div id="app"></div>';

// Render your React component instead
const root = createRoot(document.getElementById('app'));
root.render(<h1>Hello, world</h1>);

그리고 지금까지 설정했던 tsconfig.json으로 main.tsx를 컴파일했는데 에러가 발생했다.

node_modules/@figma/plugin-typings/index.d.ts:10:9 - error TS2451: Cannot redeclare block-scoped variable 'console'.

10   const console: Console
           ~~~~~~~

  node_modules/typescript/lib/lib.dom.d.ts:26471:13
    26471 declare var console: Console;
                      ~~~~~~~
    'console' was also declared here.

node_modules/@figma/plugin-typings/index.d.ts:27:9 - error TS2451: Cannot redeclare block-scoped variable 'fetch'.

27   const fetch: (url: string, init?: FetchOptions) => Promise<FetchResponse>
           ~~~~~

  node_modules/typescript/lib/lib.dom.d.ts:27941:18
    27941 declare function fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
                           ~~~~~
    'fetch' was also declared here.


Found 4 errors in 2 files.

Errors  Files
     2  node_modules/@figma/plugin-typings/index.d.ts:10
     2  node_modules/typescript/lib/lib.dom.d.ts:26471
    

원인은 @figma/plugin-typings/index.d.tstypescript/lib/lib.dom.d.ts에서 선언된 타입들이 충돌하기 때문이었다.

도대체 node_modules 안에 있는 .d.ts 파일을 어떻게 수정해야하지.. 막막했는데, 깃헙의 피그마 조직에 올라온 이슈: unable to use typings with v 1.39.0에서 tsconfig.json 파일을 분리하라고 했다.

As a workaround, you can use two separate tsconfig.json files for UI and for the backend code since you don't need the DOM lib in the plugin backend and that's what causing the conflict.

어찌저찌 tsconfig.json을 분리하고, .tsx -> .js 컴파일까지 마쳤으나.. 기존의(CRA나 vite를 통해 생성된 프로젝트와 같은, index.html에서 번들링된 자바스크립트 파일을 불러오는) 방법은 안 된다는 걸 알았다.

# 이 방법은 안 됨!
<script type="module" src="/src/main.tsx"></script>

깃헙에서 react + figma plugin 레포지토리들을 찾아서 클론 후 빌드해보니, ui.html의 sciprt 태그 안에 빌드한 리액트 코드를 다 박아놨다. 그래서 피그마 문서를 확인해보니..

외부 리소스를 사용하기 위해 제안되는 주요 솔루션은 webpack 섹션에 설명된 임베딩 방법을 사용하는 것입니다. 또는 외부 리소스에 연결할 수도 있습니다.

아무것도 모르는 상태에서 꽤나 시간을 많이 썼다..

생각해보면 피그마가 내 번들링된 js 파일들을 호스팅하는 것도 아닌데!! 바보같았다.

늦게라도 피그마 공식 홈페이지에서 외부 js는 ui.html에 임베딩하라고 했고, 리액트로 플러그인을 만들 때 파일을 여러개로 쪼개서 작성을 할 테니 결국 번들러가 필요해졌다. 이제 웹팩을 볼 시간이다.

공식 문서 한번이라도 훑고 시작할걸!

(1)에 계속..


계속 검색하면서 다른 글들을 찾다보니 다른 곳으로 새는데, 읽어보면 좋겠어서 남기는 블로그들...

다른 피그마 플러그인 보일러 플레이트들

esbuild로 번들링 후 html에 삽입하기

profile
steady

0개의 댓글