V-Gesture 제작기 - 4. 번들링
가장 당황스러웠던 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;
}
},
};
}