끄적끄적

V-Gesture 제작기 - 4. 번들링

개발가락 2024. 6. 7. 21:49

가장 당황스러웠던 Rollup...

개발 자체는 vite 템플릿 기반으로 개발하였으나, 프로덕션용 번들링은 rollup으로 했다.

 

물론 vite가 내부적으로 rollup을 이용하긴 하나, entry가 여럿일 경우, 각 entry에 맞는 설정파일을 만들어 여러번 번들링을 수행해줘야하는 단점이 있기에, rollup으로 번들러를 재구성 하였다.

 

여기까진 문제가 없었는데, 빌드 후 실행을 시키니, tfjs의 의존성인 @mediapipe/hand 모듈에서 다음과 같은 에러를 뿜기 시작했다.

 

 

개발 서버에서는 잘되는데 번들 후 에러가 뜨니, 이건 100% 번들러 에러였다.

 

 

 

번들된 파일 상에서 위 코드에서 발생하는 에러였기에, 별다른 선택지가 없이 @mediapipe/hand  모듈을 다운받아 로컬에서 빌드해봤다.

 

 

어..? 여기는 멀쩡해보이는데..? 그러면 @tfjs/hand-pose-detector에서 번들링이 잘못된건가? 

 

이렇게 생각하고 이번엔 tfjs에서 빌드를 해보았다.

 

 

 

놀랍게도 문제가 없었다!

 

분명 Hands 클래스가 잘 번들링 되고 있는데 왜 에러는 Hands 객체가 없다 판단하는 것일까?

 

이러쿵 저러쿵 열심히 삽질하다가 정말 우연하게 발견했는데, 바로 @rollup/commonjs 과 @mediapipe간 환장의 콜라보 때문이었다.

 

@mediapipe 모듈 자체가 오픈소스가 아니기에, rollup이 번들링 할 시, @mediapipe가 export하는 모듈들에 대한 참조를 얻지 못하여 모듈이라고 인지를 못하는 문제였다.

 

이를 위해 좀 hacky한 방법이지만 해당 모듈을 번들링을 위한 플러그인을 하나 만드는 것이다.

 

여기서 주객전도라고 느낄 수 있는데, 생각보다 쉽다. 결국 참조를 찾지 못해 export를 안해주는것이니, 직접 export 구문을 삽입하면된다.

 

내가만든 플러그인은 다음과 같다.

 

function rollupMediapipeObfuscationPolyfill() {
  return {
    name: "mediapipe-obfuscation-polyfill",
    load(id) {
      if (path.basename(id) === "hands.js") {
        let handSourceCode = fs.readFileSync(id, "utf-8");
        handSourceCode += "exports.Hands = Hands;";
        return { code: handSourceCode };
      } else {
        return null;
      }
    },
  };
}