QR코드를 일반 script 에서 type="module"로 바꾸니 문제가 생겼다.
갑자기 undefined에서 값을 불러오려고 한다는 것이다.
에러난 부분의 코드는 아래와 같다.
if (this._android && this._android <= 2.1) {
var factor = 1 / window.devicePixelRatio;
var drawImage = CanvasRenderingContext2D.prototype.drawImage;
CanvasRenderingContext2D.prototype.drawImage = function (image, sx, sy, sw, sh, dx, dy, dw, dh) {
if (("nodeName" in image) && /img/i.test(image.nodeName)) {
for (var i = arguments.length - 1; i >= 1; i--) {
arguments[i] = arguments[i] * factor;
}
} else if (typeof dw == "undefined") {
arguments[1] *= factor;
arguments[2] *= factor;
arguments[3] *= factor;
arguments[4] *= factor;
}
drawImage.apply(this, arguments);
};
}
왜 갑자기 이전에는 window에 잘 바인딩되던 this가 이번에는 undefined로 바인딩 되어 에러가 발생한 것이다.
자세히 알아보니 모듈 방식은 strict모드를 사용한다는 것
을 알게 되었고
strict모드에서는 전역에서 this가 window로 바인딩되지 않는다는 것을 깨달았다.
즉, 순서대로 생각하면 이 new QRCode()
를 실행하는 곳은 모듈이었기 때문에 this는 undefined로 바인딩된다. 여기서 생성자를 호출해 QRCode 인스턴스를 생성했다면, 그 인스턴스는 호출한 곳의 this에 바인딩되고, 그 인스턴스의 this도 undefined가 된다.
const printCode = (url) => {
const qrCode = new QRCode("qrcode", qrOption);
qrCode.makeCode(url);
};
그러면 해결책은
1. 인스턴스의 this를 window로 바인딩
2. strict모드를 취소
3. 코드를 수정
이렇게 세가지 방법이 있을 수 있다.
하지만 1번의 경우, new를 통해 객체의 인스턴스를 생성하는 작업에 call함수를 통해 this를 바인딩하는 것은 불가능했다.
또한 2번도 찾아본 결과 불가능했다.
결국 this에러가 발생하는 코드를 window로 직접 수정해보기로 하였고, 일단 한 줄만 수정해서 해결이 되었다.
하지만 현재 상황에서만 잘 동작하지, 다른 상황에서는 어떻게 동작할지 모르므로 코드를 직접 읽고 이해해서 고치거나, 모듈 방식이 아니라 script방식을 그대로 사용하는 것이 좋을 것 같다.