[html2canvas, domtoImage] 화면 캡쳐가능한 라이브러리

iamsummer__·2022년 2월 23일
0

얼마전 화면 캡쳐가능한 라이브러리에 대해서 검토를 해보았습니다.

간단하게 정리하면 dom-to-image가 html2canvas보다는 속도측면에서는 빠릅니다.
그러나 캡쳐하는 화면에 이미지가 있는 경우, cors에러가 발생할 수 있기 때문에 proxy기능을 지원하는 html2canvas라이브러리 사용을 권장드립니다.

화면 캡쳐 관련 라이브러리 검토하다가 발생한 몇가지 이슈들에 대해서 정리해보겠습니다.

브라우저 메인스레드 부하

화면캡쳐하는 기능을 브라우저단에서 적용하려다보니, 메인 스레드 부하가 엄청났습니다.
그래서 web worker에서 화면 캡쳐하는 작업을 진행하고, 메세지로 변환된 이미지만 받으려고 했으나,,
web worker는 dom에 직접 접근이 불가능하며, 편법으로 dom을 넘기더라도 이미지 변환하는 과정에서 dom에 접근이 무조건적으로 필요하다보니 사용이 불가했습니다.😂

이미지 cors이슈

캡쳐하려는 화면에 이미지가 있는 경우, cors에러가 발생하며 캡쳐기능이 정상적으로 되지 않았습니다.

라이브러리쪽 소스코드를 확인해보니, img 파일의 url을 읽어오는 부분에서 cors에러가 발생하고 있었습니다.

다행히도, html2canvas에서는 proxy라는 옵션을 제공해주고 있습니다.
proxy옵션을 사용하게 되면, proxy를 통해 받아온 url을 통해 동작합니다.

🧐 proxy 서버에는 어떤 내용이?

브라우저단에서 이미지 url을 호출하면 cors에러가 발생하니, 서버에서 이미지 url을 호출하는 방식을 사용하는 것입니다.
proxy서버에서는 이미지 url -> base64로 변환시켜줍니다.

const express = require('express');
const url = require('url');
const cors = require('cors');
const request = require('request');

function validUrl(req, res, next) {
    if (!req.query.url) {
        next(new Error('No url specified'));
    } else if (typeof req.query.url !== 'string' || url.parse(req.query.url).host === null) {
        next(new Error(`Invalid url specified: ${req.query.url}`));
    } else {
        next();
    }
}

module.exports = () => {
    const app = express.Router();
    app.get('/', cors(), validUrl, (req, res, next) => {
        switch (req.query.responseType) {
    case 'blob':
        req.pipe(request(req.query.url).on('error', next)).pipe(res);
        break;
    case 'text':
    default:
        request({url: req.query.url, encoding: 'binary'}, (error, response, body) => {
            if (error) {
                return next(error);
            }
            res.send(
            `data:${response.headers['content-type']};base64,${Buffer.from(
                body,
                'binary'
            ).toString('base64')}`
        );
    });
    }
});

    return app;
};

html2canvas-proxy-~~ 이 api가 제가 구축한 proxy서버이고 쿼리스트링으로 이미지 url을 보냅니다.
cors이슈 없이 이미지 잘 불러옵니다 👍

html2canvas(document.body, {
	proxy: 'proxy서버 url',
}).then(function(canvas) {
    document.body.appendChild(canvas);
});
profile
개발하는 프론트엔드개발자

1개의 댓글

감사합니다 👍 잘읽었어요. "dom-to-image-improved"를 사용해보니 렉은 사라졌습니다만 아이폰기종에서 찍히지 않는 문제가 있더라구요

답글 달기