ํ”„๋กœ๊ทธ๋ž˜๋ฐ/React JS

[React] ํ™”๋ฉด(DOM) ์บก์ณ ๋ฐ ์ €์žฅ ๊ธฐ๋Šฅ ๊ตฌํ˜„ํ•˜๊ธฐ (feat. html2canvas, file-saver)

์šฉ๋‡ฝ 2023. 5. 19. 19:47
๋ฐ˜์‘ํ˜•

[React] ํ™”๋ฉด(DOM) ์บก์ณ,์ €์žฅ ๊ธฐ๋Šฅ ๊ตฌํ˜„ํ•˜๊ธฐ (feat. html2canvas, file-saver)

๐Ÿ“– ๋“ค์–ด๊ฐ€๋ฉฐ

React์—์„œ ํ™”๋ฉด (DOM)๋ฅผ ์บก์ฒ˜, ์ €์žฅํ•˜๋Š” ๊ธฐ๋Šฅ์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด๋ ค ํ•ฉ๋‹ˆ๋‹ค.

์ž‘์€ ํ† ์ด ํ”„๋กœ์ ํŠธ๋ฅผ ํ•˜๋ฉด์„œ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ๋ฌธ์ œ๋ฅผ ๋งž์ด ํ–ˆ์—ˆ๋Š”๋ฐ, ๊ฒฐ๊ณผ์ ์œผ๋กœ ์„ฑ๊ณตํ•œ ๋ฐฉ๋ฒ•๋“ค๋กœ ํฌ์ŠคํŒ…ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์บก์ณ(์Šคํฌ๋ฆฐ์ƒท)์„ ๋„์™€์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค

๋Œ€ํ‘œ์ ์œผ๋กœ html2canvas, dom-to-image, html-to-image ๋“ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๋ฉด์„œ html2canvas์™€ dom-to-image๋ฅผ ๋ชจ๋‘ ์‚ฌ์šฉํ•ด ๋ดค์Šต๋‹ˆ๋‹ค.

 

์ œ๊ฐ€ ์‚ฌ์šฉํ•ด ๋ณธ ๋‘ ๊ฐ€์ง€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๋Œ€ํ•ด์„œ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ๋‘ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ชจ๋‘ ์˜์—ญ์„ ์ •ํ™•ํ•˜๊ฒŒ ์บก์ฒ˜ํ•˜๊ณ  DOM ์š”์†Œ์— ์ ์šฉ๋œ CSS ์Šคํƒ€์ผ์„ ์บก์ฒ˜ํ•˜๋Š” ๋ฐ ํฐ ๋ฌธ์ œ๋Š” ์—†์—ˆ์Šต๋‹ˆ๋‹ค.

 

๊ทธ๋Ÿฌ๋‚˜ dom-to-image๊ฐ€ html2canvas๋ณด๋‹ค ๋” ๋น ๋ฅด๊ณ  ์•ˆ์ •์ ์ด๋ผ๊ณ  ํ•˜๋Š” ์‚ฌ์šฉ์ž๋„ ์žˆ๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

๋˜ํ•œ, dom-to-image๋Š” ๋” ์ž‘์€ ๋ฒˆ๋“ค ํฌ๊ธฐ(์•ฝ 14kb)๋ฅผ ๊ฐ–๋Š” ๋ฐ˜๋ฉด html2canvas๋Š” ๋” ํฐ ๋ฒˆ๋“ค ํฌ๊ธฐ(์•ฝ 140kb)๋ฅผ ๊ฐ–๋Š”๋‹ค๋Š” ๊ฒƒ์„ ๊ณ ๋ คํ•ด ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

๋”ฐ๋ผ์„œ ๋ฒˆ๋“ค ํฌ๊ธฐ๊ฐ€ ์ค‘์š”ํ•œ ๊ฒฝ์šฐ dom-to-image๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ์ข‹์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ๋‘ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ํฐ ์ฐจ์ด์  ์ค‘ ํ•˜๋‚˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ธฐ๋Šฅ์˜ ๋ฒ”์œ„์ž…๋‹ˆ๋‹ค.

html2canvas๋Š” SVG ๋ฐ Canvas ์š”์†Œ๋„ ์บก์ฒ˜ํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ๋” ๋‹ค์–‘ํ•œ ์š”์†Œ์— ๋Œ€ํ•œ ์บก์ฒ˜ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

๋ฐ˜์‘ํ˜•

์‹ค์ œ๋กœ, ๊ฐœ๋ฐœํ•˜๋ฉด์„œ DOM์š”์†Œ ์•ˆ์— img ํŒŒ์ผ์ด ํฌํ•จ๋˜์–ด ์žˆ๋Š” ์ƒํ™ฉ์—์„œ dom-to-image๋Š” imgํŒŒ์ผ์„ ์ธ์‹ํ•˜์ง€ ๋ชปํ•˜์—ฌ imgํŒŒ์ผ์ด ๊นจ์ ธ์„œ ์บก์ฒ˜๋˜๋Š” ๊ฒฐ๊ณผ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์–ด์„œ dom-to-image์—์„œ html2canvas๋กœ ๋ณ€๊ฒฝํ–ˆ์Šต๋‹ˆ๋‹ค.

 

SVG ๋ฐ Canvas๋ฅผ ํฌํ•จํ•œ ๋‹ค์–‘ํ•œ ์š”์†Œ์— ๋Œ€ํ•œ ์บก์ฒ˜๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ html2canvas๋ฅผ ์„ ํƒํ•˜๋Š” ๊ฒƒ์ด ์ตœ์„ ์ด๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๊ฒƒ์ด ์•„๋‹ˆ๋ผ๋ฉด ๊ฐ€๋ณ๊ณ  ๋น ๋ฅธ dom-to-image๋ฅผ ์„ ํƒํ•˜๋Š” ๊ฒƒ์ด ์ตœ์„ ์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

html2canvas์™€ dom-to-image๋กœ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋ถ€๋ถ„์€ ๋งค์šฐ ์œ ์‚ฌํ•˜๊ณ  ์‰ฝ๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค๋ฅธ ๊ฑฑ์ •์€ ํ•˜์ง€ ์•Š์•„๋„ ๋ฉ๋‹ˆ๋‹ค.

 

๊ทธ๋ž˜๋„ html2canvas๊ฐ€ ํ˜„์žฌ๋Š” ์••๋„์ ์œผ๋กœ ๋งŽ์ด ์‚ฌ์šฉ๋˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

NPM ๋‹ค์šด๋กœ๋“œ ์ˆœ์œ„ ๋น„๊ต

html2canvas

์‚ฌ์šฉ์ž ๋ธŒ๋ผ์šฐ์ €์—์„œ ์ง์ ‘ ์›น ํŽ˜์ด์ง€ ๋˜๋Š” ๊ทธ ์ผ๋ถ€์˜ "์Šคํฌ๋ฆฐ์ƒท"์„ ์ฐ์„ ์ˆ˜ ์žˆ๋‹ค. ์Šคํฌ๋ฆฐ์ƒท์€ DOM์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ๋‹ค.

์บก์ฒ˜ํ•  ์˜์—ญ (DOM)์„ ์ง€์ •ํ•˜๊ณ  ํ•ด๋‹น ์˜์—ญ์— ๋Œ€ํ•œ ์Šคํฌ๋ฆฐ์ƒท์„ ์ฐ์„ ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค.

https://html2canvas.hertzen.com/

 

html2canvas - Screenshots with JavaScript

Try out html2canvas Test out html2canvas by rendering the viewport from the current page. Capture

html2canvas.hertzen.com

์„ค์น˜ ๋ฐฉ๋ฒ•

npm install html2canvas
or
yarn add html2canvas

๊ธฐ๋ณธ์ ์ธ ์‚ฌ์šฉ ๋ฐฉ๋ฒ• ์˜ˆ์‹œ

const saveAsImageHandler = () => {
    const target = document.getElementById('content');
    if (!target) {
      return alert('๊ฒฐ๊ณผ ์ €์žฅ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.');
    }
    html2canvas(target).then((canvas) => {
      const link = document.createElement('a');
      document.body.appendChild(link);
      link.href = canvas.toDataURL('image/png');
      link.download = 'result.png';
      link.click();
      document.body.removeChild(link);
    });
  };

html2canvas์— ๋Œ€ํ•œ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์„ ์ฐพ์•„๋ณด๋ฉด ๋ณดํ†ต ์ด๋Ÿฐ ์‹์œผ๋กœ ๋งŽ์ด ๊ธฐ๋Šฅ์„ ์ž‘์„ฑํ•˜๋Š” ์˜ˆ์ œ๋ฅผ ๋งŽ์ด ์ฐพ์•„๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

ํ•˜์ง€๋งŒ ์ด๋ ‡๊ฒŒ a tag๋ฅผ ํ†ตํ•ด์„œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ–ˆ์„ ๋•Œ PC์—์„œ๋Š” ์ „ํ˜€ ๋ฌธ์ œ๊ฐ€ ์—†์—ˆ์œผ๋‚˜, IPhone ๊ธฐ์ค€ Safari ๋ธŒ๋ผ์šฐ์ € ์™ธ์— ๋ชจ๋‘ ์ž‘๋™ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

 

Android์—์„œ๋Š” ํ…Œ์ŠคํŠธ๋ฅผ ํ•ด๋ณผ ์ˆ˜๊ฐ€ ์—†์–ด์„œ ๋น„์Šทํ•œ ์ƒํ™ฉ์œผ๋กœ ๊ตฌ๊ธ€๋ง์„ ํ•ด๋ณธ ๊ฒฐ๊ณผ Samsung Phone์—์„œ ์ž๋™ ๋‹ค์šด๋กœ๋“œ๋ฅผ ์ฐจ๋‹จํ•ด ๋†“์€ ๊ฒƒ์œผ๋กœ ํ™•์ธ ๋์Šต๋‹ˆ๋‹ค.

file-saver

์œ„์—์„œ ๋งํ•œ ๋ฌธ์ œ์ ์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ํด๋ผ์ด์–ธํŠธ์—์„œ ํŒŒ์ผ ์ €์žฅ์„ ๋„์™€์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ file-saver๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

 

file-saver๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด PC, Mobile ๊ฐ ํ™˜๊ฒฝ๊ณผ ์›ฌ๋งŒํ•œ ๋ธŒ๋ผ์šฐ์ € ๋ชจ๋‘ ํ˜ธํ™˜์ด ๋˜๋„๋ก ํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ์„ ํ•ด์ฃผ๊ณ  ์žˆ๊ณ , ๊ฐ„๋‹จํ•œ ์ฝ”๋“œ๋กœ ํŒŒ์ผ์„ blob, file, url ํ˜•์‹์— ๋Œ€ํ•œ ํŒŒ์ผ๋กœ ์ €์žฅํ•˜๋Š” ๊ฒƒ์„ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

 

https://www.npmjs.com/package/file-saver

 

file-saver

An HTML5 saveAs() FileSaver implementation. Latest version: 2.0.5, last published: 2 years ago. Start using file-saver in your project by running `npm i file-saver`. There are 3981 other projects in the npm registry using file-saver.

www.npmjs.com

์„ค์น˜ ๋ฐฉ๋ฒ•

npm install file-saver --save
or
yarn add file-saver

ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ํ™˜๊ฒฝ์—์„œ๋Š” ํƒ€์ž… ์ •์˜๋„ ๋”ฐ๋กœ ์„ค์น˜๋ฅผ ํ•ด์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.

npm install @types/file-saver --save-dev
or
yarn add @types/file-saver -D

 

์ถœ์ฒ˜: https://github.com/eligrey/FileSaver.js#readme

html2canvas + file-saver

๊ทธ๋Ÿผ ์ด์ œ html2canvas์™€ file-saver๋ฅผ ํ†ตํ•ด์„œ ์–ด๋–ป๊ฒŒ ์ €์žฅ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ• ์ง€ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๋จผ์ € ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์€ React + TypeScript ํ™˜๊ฒฝ์ž…๋‹ˆ๋‹ค.

์˜ˆ์‹œ ์ฝ”๋“œ

import "./styles.css";
import html2canvas from "html2canvas";
import saveAs from "file-saver";
import { useRef } from "react";

export default function App() {
  const divRef = useRef<HTMLDivElement>(null);

  const handleDownload = async () => {
    if (!divRef.current) return;

    try {
      const div = divRef.current;
      const canvas = await html2canvas(div, { scale: 2 });
      canvas.toBlob((blob) => {
        if (blob !== null) {
          saveAs(blob, "result.png");
        }
      });
    } catch (error) {
      console.error("Error converting div to image:", error);
    }
  };

  return (
    <div className="App">
      <div
        ref={divRef}
        style={{ backgroundColor: "lime", width: "300px", height: "200px" }}
      >
        <h1>Hello CodeSandbox</h1>
        <h2>Start editing to see some magic happen!</h2>
      </div>
      <button onClick={handleDownload}>๋‹ค์šด๋กœ๋“œ</button>
    </div>
  );
}

html2canvas์˜ ๋– ๋Œ์•„๋‹ค๋‹ˆ๋Š” ๊ธฐ๋ณธ ์˜ˆ์ œ์—๋Š” querySelector๋กœ DOM์š”์†Œ๋ฅผ ์žก์•„์ฃผ๋Š”๋ฐ,

React ํ™˜๊ฒฝ์—์„œ๋Š” useRef DOM์š”์†Œ๋ฅผ ๋‹ค๋ฃจ๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ด๊ธฐ ๋•Œ๋ฌธ์— useRef๋กœ ์บก์ฒ˜ ์˜์—ญ์„ ์ง€์ •ํ•ด ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

 

React์—์„œ querySelector ๋Œ€์‹  useRef๋กœ DOM์„ ๋‹ค๋ค„์•ผ ํ•˜๋Š” ์ด์œ 

๋”๋ณด๊ธฐ
๋”๋ณด๊ธฐ
  1. React ์„ ์–ธ์  ๋ฐฉ์‹์— ์ ํ•ฉ: useRef๋Š” React์˜ ์„ ์–ธ์  ๋ฐฉ์‹์— ๋ณด๋‹ค ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค. React์—์„œ๋Š” UI๋ฅผ ์ž‘์„ฑํ•  ๋•Œ ์„ ์–ธ์ ์ธ ์ฝ”๋“œ ์Šคํƒ€์ผ์„ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ, useRef๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ฝ”๋“œ์˜ ์ผ๊ด€์„ฑ์ด ์œ ์ง€๋˜๊ณ  ๋ฆฌ์•กํŠธ์ ์ธ ๊ฐœ๋ฐœ ์Šต๊ด€์„ ์ง€ํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  2. ์ง์ ‘ ์กฐ์ž‘ ์ตœ์†Œํ™”: React๋Š” ์ปดํฌ๋„ŒํŠธ์˜ ์ƒํƒœ์™€ ๋ Œ๋”๋ง์˜ ๊ด€๋ฆฌ๋ฅผ ๋„์™€์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค. querySelector์™€ ๊ฐ™์€ ์ˆœ์ˆ˜ JavaScript ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด, ์ง์ ‘ DOM ์กฐ์ž‘์ด ํ•„์š”ํ•˜๋ฏ€๋กœ ๋ฆฌ์•กํŠธ์˜ ์ฒ ํ•™์— ์–ด๊ธ‹๋‚ฉ๋‹ˆ๋‹ค. useRef๋Š” DOM์— ๋Œ€ํ•œ ์ฐธ์กฐ๋ฅผ ํšจ๊ณผ์ ์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด ์ƒํƒœ ๋ณ€๊ฒฝ ์‹œ React๊ฐ€ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ Œ๋”๋ง ์ตœ์ ํ™”๋ฅผ ๋ฐฉํ•ดํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  3. ๋ฆฌ๋ Œ๋”๋ง์— ์•ˆ์ „: querySelector๋Š” ๋ Œ๋”๋ง ์‹œ๋งˆ๋‹ค ํ˜ธ์ถœ๋˜์–ด์•ผ ํ•˜๋ฉฐ, ๊ฒฐ๊ณผ์ ์œผ๋กœ ์—ฌ๋Ÿฌ ๋ฒˆ DOM์„ ์ฐพ์•„์•ผ ํ•˜๋Š” ๋ฐ˜๋ฉด, useRef๋Š” ํ•œ ๋ฒˆ๋งŒ DOM์„ ์ฐพ์•„์„œ ๊ณ„์† ์ฐธ์กฐํ•˜๋ฏ€๋กœ ๋ฆฌ๋ Œ๋”๋ง์— ์•ˆ์ „ํ•˜๊ณ  ์„ฑ๋Šฅ์— ๋” ์ด์ ์„ ์ค๋‹ˆ๋‹ค.
  4. ์ปดํฌ๋„ŒํŠธ์˜ ์ƒ๋ช…์ฃผ๊ธฐ ์ „๋ฐ˜์— ์‚ฌ์šฉ ๊ฐ€๋Šฅ: useRef๋Š” React์˜ ๋‹ค์–‘ํ•œ ์ƒ๋ช…์ฃผ๊ธฐ์™€ ๊ด€๋ จ Hook๋“ค, ์˜ˆ๋ฅผ ๋“ค์–ด useEffect, useState, useCallback ๋“ฑ๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋กœ ์ธํ•ด ๋” ์œ ์—ฐํ•˜๊ฒŒ ์ฝ”๋“œ๋ฅผ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ปดํฌ๋„ŒํŠธ์˜ ์ƒ๋ช…์ฃผ๊ธฐ์™€ ์ƒํƒœ์— ๋”ฐ๋ผ ์ฐธ์กฐ๊ฐ’์„ ์—…๋ฐ์ดํŠธํ•˜๊ฑฐ๋‚˜ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ์ด์œ ๋กœ ์ธํ•ด, React์—์„œ DOM ์š”์†Œ๋ฅผ ๋‹ค๋ฃฐ ๋•Œ useRef๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ๋ฌผ๋ก  ํ•„์š”ํ•œ ๊ฒฝ์šฐ(ํ™•์ธ ์ „์šฉ ์šฉ๋„ ๋“ฑ) querySelector๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์–ด์ฉ” ์ˆ˜ ์—†์ง€๋งŒ, ๊ฐ€๋Šฅํ•œ ํ•œ React ์ปดํฌ๋„ŒํŠธ์˜ ์ƒํƒœ์™€ ์ƒ๋ช…์ฃผ๊ธฐ๋ฅผ ์ง€ํ‚ฌ ์ˆ˜ ์žˆ๋Š” useRef๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

 

์บก์ฒ˜ํ•  ์˜์—ญ์„ ์ง€์ •ํ•ด ์ฃผ๊ณ  html2canvas์— ๋„˜๊ฒจ์ฃผ๊ณ  html2canvas๊ฐ€ ์บก์ฒ˜ํ•ด ์ค€ ๊ฒƒ blob์œผ๋กœ ๋ณ€ํ™˜ํ•œ ๋‹ค์Œ file-saver๋ฅผ ํ†ตํ•ด์„œ ์ €์žฅ๋˜๋„๋ก ํ•ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

 

๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๋Š” ์ฝ”๋“œ ์ž์ฒด๊ฐ€ ๋งค์šฐ ์ง๊ด€์ ์ธ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ“• ๋งˆ๋ฌด๋ฆฌ

html2canvas์™€ file-saver ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ดค์Šต๋‹ˆ๋‹ค.

 

๊ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์— ๋Œ€ํ•ด ๋‹ค์–‘ํ•œ ์˜ต์…˜๋“ค๋„ ์žˆ์œผ๋‹ˆ ๊ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๋Œ€ํ•œ ๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ  ํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

๋ฐ˜์‘ํ˜•