푸터 콘텐츠로 바로가기
노드 도움말

Dropzone npm (개발자를 위한 작동 방식)

파일 업로드는 웹 애플리케이션에서 흔히 볼 수 있는 기능이며, 사용자 친화적인 인터페이스를 제공하는 것은 좋은 사용자 경험을 위해 매우 중요합니다. 이 과정을 간소화하는 데 널리 사용되는 라이브러리 중 하나는 Dropzone.js 입니다. Dropzone은 React 와 결합될 때 드래그 앤 드롭 방식의 파일 업로드를 구현하는 데 강력한 도구가 될 수 있습니다. react-dropzone 은 최소한의 개발 노력으로 완벽하고 매끄럽게 통합됩니다. 이 글에서는 Dropzone.js 라이브러리를 훌륭하게 감싸는 react-dropzone 패키지를 사용하여 React 애플리케이션에 Dropzone을 통합하는 방법을 안내합니다.

이 글에서는 PDF 문서를 생성, 편집 및 관리하는 데 사용되는 IronPDF NPM 패키지에 대해서도 살펴보겠습니다.

React에서 Dropzone을 사용하는 이유는 무엇일까요?

Dropzone은 파일 업로드를 원활하게 해주는 다양한 기능을 제공합니다.

1. 드래그 앤 드롭 인터페이스

사용자가 파일을 드래그 앤 드롭하여 선택할 수 있도록 하고, 프로그램적으로 파일 대화 상자를 추가합니다.

2. 미리보기

드롭된 파일에서 기본 이미지 썸네일 미리보기를 표시하여 사용자 인터페이스의 가독성을 향상시킵니다.

3. 여러 파일 업로드

여러 파일을 한 번에 업로드할 수 있습니다.

4. 맞춤 설정 가능

다양한 옵션과 콜백을 통해 높은 수준의 맞춤 설정이 가능합니다. 파일 대화 상자 열기 또는 파일 선택 대화 상자를 사용자 지정할 수 있습니다.

5. 대용량 파일 분할 업로드

파일 크기를 분할하여 업로드하세요.

6. 이벤트 처리

파일 대화 상자 취소 콜백 및 브라우저 이미지 크기 조정 이벤트를 처리할 수 있습니다.

React 애플리케이션 설정하기

Dropzone을 통합하기 전에 React 애플리케이션이 설정되어 있는지 확인하십시오. React 애플리케이션이 없다면 Create React App을 사용하여 새 React 프로젝트를 생성할 수 있습니다.

npx create-react-app dropzone-demo
cd dropzone-demo
npx create-react-app dropzone-demo
cd dropzone-demo
SHELL

react-dropzone 설치 중

React 프로젝트에서 Dropzone을 사용하려면 react-dropzone 패키지를 설치해야 합니다.

npm install react-dropzone
# or
yarn add react-dropzone
npm install react-dropzone
# or
yarn add react-dropzone
SHELL

react-dropzone의 기본 사용법

다음은 React 컴포넌트에서 react-dropzone을 사용하는 간단한 예입니다.

import React, { useCallback } from 'react';
import { useDropzone } from 'react-dropzone';

// DropzoneComponent is a React component demonstrating basic usage of react-dropzone
const DropzoneComponent = () => {
  // Callback to handle file drops
  const onDrop = useCallback((acceptedFiles) => {
    console.log(acceptedFiles); // Log the accepted files
  }, []);

  // Extracted properties from useDropzone hook
  const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop });

  return (
    <div {...getRootProps()} style={dropzoneStyle}>
      <input {...getInputProps()} />
      {
        isDragActive ? 
          <p>Drop the files here ...</p> : 
          <p>Drag 'n' drop some files here, or click to select files</p>
      }
    </div>
  );
};

// Styles for the dropzone area
const dropzoneStyle = {
  border: '2px dashed #0087F7',
  borderRadius: '5px',
  padding: '20px',
  textAlign: 'center',
  cursor: 'pointer'
};

export default DropzoneComponent;
import React, { useCallback } from 'react';
import { useDropzone } from 'react-dropzone';

// DropzoneComponent is a React component demonstrating basic usage of react-dropzone
const DropzoneComponent = () => {
  // Callback to handle file drops
  const onDrop = useCallback((acceptedFiles) => {
    console.log(acceptedFiles); // Log the accepted files
  }, []);

  // Extracted properties from useDropzone hook
  const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop });

  return (
    <div {...getRootProps()} style={dropzoneStyle}>
      <input {...getInputProps()} />
      {
        isDragActive ? 
          <p>Drop the files here ...</p> : 
          <p>Drag 'n' drop some files here, or click to select files</p>
      }
    </div>
  );
};

// Styles for the dropzone area
const dropzoneStyle = {
  border: '2px dashed #0087F7',
  borderRadius: '5px',
  padding: '20px',
  textAlign: 'center',
  cursor: 'pointer'
};

export default DropzoneComponent;
JAVASCRIPT

파일 업로드 처리

파일을 드롭하거나 선택하면 onDrop 콜백 함수는 허용된 파일 배열을 받습니다. 그런 다음 파일을 서버에 업로드하는 등의 작업을 수행할 수 있습니다. 다음은 fetch를 사용하여 파일을 업로드하도록 onDrop 콜백을 확장하는 방법입니다.

// onDrop callback to handle file uploads
const onDrop = useCallback((acceptedFiles) => {
  const formData = new FormData();
  // Append each file to the formData
  acceptedFiles.forEach((file) => {
    formData.append('files', file);
  });

  // Send a POST request to upload the files
  fetch('https://your-upload-endpoint', {
    method: 'POST',
    body: formData,
  })
  .then(response => response.json()) // Parse the JSON from the response
  .then(data => console.log(data)) // Log the response data
  .catch(error => console.error('Error:', error)); // Handle errors
}, []);
// onDrop callback to handle file uploads
const onDrop = useCallback((acceptedFiles) => {
  const formData = new FormData();
  // Append each file to the formData
  acceptedFiles.forEach((file) => {
    formData.append('files', file);
  });

  // Send a POST request to upload the files
  fetch('https://your-upload-endpoint', {
    method: 'POST',
    body: formData,
  })
  .then(response => response.json()) // Parse the JSON from the response
  .then(data => console.log(data)) // Log the response data
  .catch(error => console.error('Error:', error)); // Handle errors
}, []);
JAVASCRIPT

미리보기 표시

업로드된 파일의 미리보기를 표시할 수도 있습니다. 다음은 그 방법을 보여주는 예시입니다.

import React, { useCallback, useState } from 'react';
import { useDropzone } from 'react-dropzone';

const DropzoneComponent = () => {
  const [files, setFiles] = useState([]);

  // onDrop callback to handle file drops and generate previews
  const onDrop = useCallback((acceptedFiles) => {
    setFiles(acceptedFiles.map(file => Object.assign(file, {
      preview: URL.createObjectURL(file)
    })));
  }, []);

  const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop });

  // Generate thumbnails for each file
  const thumbs = files.map(file => (
    <div key={file.name}>
      <img
        src={file.preview}
        style={{ width: '100px', height: '100px' }}
        alt={file.name}
      />
    </div>
  ));

  return (
    <div>
      <div {...getRootProps()} style={dropzoneStyle}>
        <input {...getInputProps()} />
        {
          isDragActive ? 
            <p>Drop the files here ...</p> : 
            <p>Drag 'n' drop some files here, or click to select files</p>
        }
      </div>
      <div>
        {thumbs}
      </div>
    </div>
  );
};

// Styles for the dropzone area
const dropzoneStyle = {
  border: '2px dashed #0087F7',
  borderRadius: '5px',
  padding: '20px',
  textAlign: 'center',
  cursor: 'pointer'
};

export default DropzoneComponent;
import React, { useCallback, useState } from 'react';
import { useDropzone } from 'react-dropzone';

const DropzoneComponent = () => {
  const [files, setFiles] = useState([]);

  // onDrop callback to handle file drops and generate previews
  const onDrop = useCallback((acceptedFiles) => {
    setFiles(acceptedFiles.map(file => Object.assign(file, {
      preview: URL.createObjectURL(file)
    })));
  }, []);

  const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop });

  // Generate thumbnails for each file
  const thumbs = files.map(file => (
    <div key={file.name}>
      <img
        src={file.preview}
        style={{ width: '100px', height: '100px' }}
        alt={file.name}
      />
    </div>
  ));

  return (
    <div>
      <div {...getRootProps()} style={dropzoneStyle}>
        <input {...getInputProps()} />
        {
          isDragActive ? 
            <p>Drop the files here ...</p> : 
            <p>Drag 'n' drop some files here, or click to select files</p>
        }
      </div>
      <div>
        {thumbs}
      </div>
    </div>
  );
};

// Styles for the dropzone area
const dropzoneStyle = {
  border: '2px dashed #0087F7',
  borderRadius: '5px',
  padding: '20px',
  textAlign: 'center',
  cursor: 'pointer'
};

export default DropzoneComponent;
JAVASCRIPT

청소하기

메모리 누수를 방지하려면 객체 URL을 취소하는 것이 필수적입니다. useEffect 훅을 사용하면 이를 구현할 수 있습니다.

import { useEffect } from 'react';

// useEffect to clean up object URLs to prevent memory leaks
useEffect(() => {
  // Revoke the data URIs
  return () => files.forEach(file => URL.revokeObjectURL(file.preview));
}, [files]);
import { useEffect } from 'react';

// useEffect to clean up object URLs to prevent memory leaks
useEffect(() => {
  // Revoke the data URIs
  return () => files.forEach(file => URL.revokeObjectURL(file.preview));
}, [files]);
JAVASCRIPT

IronPDF 소개합니다

IronPDF 는 Node.js 애플리케이션 내에서 PDF 생성을 용이하게 하도록 설계된 강력한 npm 패키지입니다. 이 도구를 사용하면 HTML 콘텐츠 , URL 또는 기존 PDF 파일에서 PDF 문서를 생성할 수 있습니다. IronPDF 직관적인 API 와 강력한 기능 세트를 통해 송장, 보고서 또는 기타 모든 유형의 문서를 생성하는 과정을 간소화합니다.

IronPDF 의 주요 기능은 다음과 같습니다.

1. HTML을 PDF로 변환

HTML 콘텐츠를 PDF 문서로 손쉽게 변환하세요. 이 기능은 웹 콘텐츠에서 동적 PDF를 생성하는 데 특히 유용합니다.

2. URL을 PDF로 변환

URL에서 바로 PDF 파일을 생성합니다. 이 기능을 사용하면 웹 페이지의 콘텐츠를 캡처하여 프로그램적으로 PDF 파일로 저장할 수 있습니다.

3. PDF 조작

기존 PDF 문서를 손쉽게 병합, 분할 및 편집하세요. IronPDF 페이지 추가, 문서 분할 등 PDF 파일을 조작할 수 있는 기능을 제공합니다.

4. PDF 보안

PDF 문서를 암호로 암호화하거나 디지털 서명을 적용하여 보안을 강화하세요. IronPDF 무단 접근으로부터 중요한 문서를 보호할 수 있는 다양한 옵션을 제공합니다.

5. 고품질 출력

텍스트, 이미지 및 서식이 정확하게 표현된 고품질 PDF 문서를 제작하세요. IronPDF 생성된 PDF 파일이 원본 콘텐츠와 동일한 품질을 유지하도록 보장합니다.

6. 크로스 플랫폼 호환성

IronPDF 는 Windows, Linux, macOS를 비롯한 다양한 플랫폼과 호환되므로 폭넓은 개발 환경에 적합합니다.

7. 간단한 적분

IronPDF의 npm 패키지를 사용하면 IronPDF Node.js 애플리케이션에 쉽게 통합할 수 있습니다. API 문서가 잘 되어 있어 프로젝트에 PDF 생성 기능을 쉽게 통합할 수 있습니다.

웹 애플리케이션, 서버 측 스크립트 또는 명령줄 도구를 개발하든 IronPDF 사용하면 전문가 수준의 PDF 문서를 효율적이고 안정적으로 생성할 수 있습니다.

IronPDF 사용하여 PDF 문서를 생성하고 Dropzone NPM 패키지를 사용합니다.

필수 구성 요소 설치: 먼저 다음 명령어를 사용하여 새 Next.js 프로젝트를 생성합니다(아직 생성하지 않은 경우). 설정 페이지를 참조하세요.

npx create-next-app@latest demo-dropzone-ironpdf --use-npm --example "https://github.com/vercel/next-learn/tree/main/basics/learn-starter"
npx create-next-app@latest demo-dropzone-ironpdf --use-npm --example "https://github.com/vercel/next-learn/tree/main/basics/learn-starter"
SHELL

다음으로 프로젝트 디렉토리로 이동하세요.

cd demo-dropzone-ironpdf
cd demo-dropzone-ironpdf
SHELL

필요한 패키지를 설치하세요:

npm install @ironsoftware/ironpdf
npm install react-dropzone
npm install @ironsoftware/ironpdf
npm install react-dropzone
SHELL

PDF 생성: 이제 IronPDF 사용하여 간단한 PDF 생성 예제를 만들어 보겠습니다. Next.js 컴포넌트(예: pages/index.tsx)에 다음 코드를 추가하세요.

import Head from 'next/head';
import styles from '../styles/Home.module.css';
import { ToastContainer, toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import { useState } from "react";
import DropzoneComponent from "../components/mydropzone";

export default function Home() {
    const [textInput, setTextInput] = useState('');

    // Function to display different types of toast messages
    const notify = () => {
        toast.success("Success! This is a success message.", {
            position: "top-right"
        });
        toast.info("Information message", {
            position: "bottom-left"
        });
        toast.warn("Warning message", {
            autoClose: 5000
        });
        toast.error("Error message", {
            className: 'custom-toast',
            style: { background: 'red', color: 'white' }
        });
    };

    // Function to generate and download a PDF
    const generatePdf = async () => {
        try {
            const response = await fetch('/api/pdf?url=' + textInput);
            const blob = await response.blob();
            const url = window.URL.createObjectURL(new Blob([blob]));
            const link = document.createElement('a');
            link.href = url;
            link.setAttribute('download', 'awesomeIron.pdf');
            document.body.appendChild(link);
            link.click(); // Trigger the download
            link.parentNode.removeChild(link); // Remove the link
        } catch (error) {
            console.error('Error generating PDF:', error);
        }
    };

    // Handle changes in the text input field
    const handleChange = (event) => {
        setTextInput(event.target.value);
    }

    return (
        <div className={styles.container}>
            <Head>
                <title>Generate PDF Using IronPDF</title>
                <link rel="icon" href="/favicon.ico" />
            </Head>
            <main>
                <h1>Demo Drop Zone and Generate PDF Using IronPDF</h1>
                <DropzoneComponent />
                <p>
                    <span>Enter Url To Convert to PDF:</span>{" "}
                </p>
                <button style={{ margin: 20, padding: 5 }} onClick={generatePdf}>Generate PDF</button>
            </main>
            <style jsx>{`
                main {
                    padding: 5rem 0;
                    flex: 1;
                    display: flex;
                    flex-direction: column;
                    justify-content: center;
                    align-items: center;
                }
                footer {
                    width: 100%;
                    height: 100px;
                    border-top: 1px solid #eaeaea;
                    display: flex;
                    justify-content: center;
                    align-items: center;
                }
                footer img {
                    margin-left: 0.5rem;
                }
                footer a {
                    display: flex;
                    justify-content: center;
                    align-items: center;
                    text-decoration: none;
                    color: inherit;
                }
                code {
                    background: #fafafa;
                    border-radius: 5px;
                    padding: 0.75rem;
                    font-size: 1.1rem;
                    font-family: Menlo,
                    Monaco,
                    Lucida Console,
                    Liberation Mono,
                    DejaVu Sans Mono,
                    Bitstream Vera Sans Mono,
                    Courier New,
                    monospace;
                }
            `}</style>
            <style jsx global>{`
                html,
                body {
                    padding: 0;
                    margin: 0;
                    font-family: -apple-system,
                    BlinkMacSystemFont,
                    Segoe UI,
                    Roboto,
                    Oxygen,
                    Ubuntu,
                    Cantarell,
                    Fira Sans,
                    Droid Sans,
                    Helvetica Neue,
                    sans-serif;
                }
                * {
                    box-sizing: border-box;
                }
            `}</style>
        </div>
    );
}
import Head from 'next/head';
import styles from '../styles/Home.module.css';
import { ToastContainer, toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import { useState } from "react";
import DropzoneComponent from "../components/mydropzone";

export default function Home() {
    const [textInput, setTextInput] = useState('');

    // Function to display different types of toast messages
    const notify = () => {
        toast.success("Success! This is a success message.", {
            position: "top-right"
        });
        toast.info("Information message", {
            position: "bottom-left"
        });
        toast.warn("Warning message", {
            autoClose: 5000
        });
        toast.error("Error message", {
            className: 'custom-toast',
            style: { background: 'red', color: 'white' }
        });
    };

    // Function to generate and download a PDF
    const generatePdf = async () => {
        try {
            const response = await fetch('/api/pdf?url=' + textInput);
            const blob = await response.blob();
            const url = window.URL.createObjectURL(new Blob([blob]));
            const link = document.createElement('a');
            link.href = url;
            link.setAttribute('download', 'awesomeIron.pdf');
            document.body.appendChild(link);
            link.click(); // Trigger the download
            link.parentNode.removeChild(link); // Remove the link
        } catch (error) {
            console.error('Error generating PDF:', error);
        }
    };

    // Handle changes in the text input field
    const handleChange = (event) => {
        setTextInput(event.target.value);
    }

    return (
        <div className={styles.container}>
            <Head>
                <title>Generate PDF Using IronPDF</title>
                <link rel="icon" href="/favicon.ico" />
            </Head>
            <main>
                <h1>Demo Drop Zone and Generate PDF Using IronPDF</h1>
                <DropzoneComponent />
                <p>
                    <span>Enter Url To Convert to PDF:</span>{" "}
                </p>
                <button style={{ margin: 20, padding: 5 }} onClick={generatePdf}>Generate PDF</button>
            </main>
            <style jsx>{`
                main {
                    padding: 5rem 0;
                    flex: 1;
                    display: flex;
                    flex-direction: column;
                    justify-content: center;
                    align-items: center;
                }
                footer {
                    width: 100%;
                    height: 100px;
                    border-top: 1px solid #eaeaea;
                    display: flex;
                    justify-content: center;
                    align-items: center;
                }
                footer img {
                    margin-left: 0.5rem;
                }
                footer a {
                    display: flex;
                    justify-content: center;
                    align-items: center;
                    text-decoration: none;
                    color: inherit;
                }
                code {
                    background: #fafafa;
                    border-radius: 5px;
                    padding: 0.75rem;
                    font-size: 1.1rem;
                    font-family: Menlo,
                    Monaco,
                    Lucida Console,
                    Liberation Mono,
                    DejaVu Sans Mono,
                    Bitstream Vera Sans Mono,
                    Courier New,
                    monospace;
                }
            `}</style>
            <style jsx global>{`
                html,
                body {
                    padding: 0;
                    margin: 0;
                    font-family: -apple-system,
                    BlinkMacSystemFont,
                    Segoe UI,
                    Roboto,
                    Oxygen,
                    Ubuntu,
                    Cantarell,
                    Fira Sans,
                    Droid Sans,
                    Helvetica Neue,
                    sans-serif;
                }
                * {
                    box-sizing: border-box;
                }
            `}</style>
        </div>
    );
}
JAVASCRIPT

IronPDF Node.js에서만 실행되므로, 다음 단계로 Node.js에서 PDF를 생성할 수 있는 앱용 API를 추가해야 합니다.

파일을 pages/api 폴더에 pdf.js으로 생성하고 아래 소스 코드를 추가하십시오:

// pages/api/pdf.js
import { IronPdfGlobalConfig, PdfDocument } from "@ironsoftware/ironpdf";

// Apply your IronPDF license key
IronPdfGlobalConfig.getConfig().licenseKey = "Add Your key here";

export default async function handler(req, res) {
    try {
        const url = req.query.url;
        const pdf = await PdfDocument.fromUrl(url);
        const data = await pdf.saveAsBuffer();
        console.log('PDF data:', data);

        res.setHeader('Content-Type', 'application/pdf');
        res.setHeader('Content-Disposition', 'attachment; filename=awesomeIron.pdf');
        res.send(data);
    } catch (error) {
        console.error('Error generating PDF:', error);
        res.status(500).end();
    }
}
// pages/api/pdf.js
import { IronPdfGlobalConfig, PdfDocument } from "@ironsoftware/ironpdf";

// Apply your IronPDF license key
IronPdfGlobalConfig.getConfig().licenseKey = "Add Your key here";

export default async function handler(req, res) {
    try {
        const url = req.query.url;
        const pdf = await PdfDocument.fromUrl(url);
        const data = await pdf.saveAsBuffer();
        console.log('PDF data:', data);

        res.setHeader('Content-Type', 'application/pdf');
        res.setHeader('Content-Disposition', 'attachment; filename=awesomeIron.pdf');
        res.send(data);
    } catch (error) {
        console.error('Error generating PDF:', error);
        res.status(500).end();
    }
}
JAVASCRIPT

참고: 위 코드에 자신의 라이선스 키를 추가해야 합니다.

앱 실행하기: Next.js 앱을 시작하세요:

npm run dev
# or
yarn dev
npm run dev
# or
yarn dev
SHELL

이제 PDF를 생성할 웹사이트 URL을 입력하고 "PDF 생성"을 클릭하세요. 아래와 같이 awesomeIron.pdf이라는 이름의 파일이 다운로드됩니다.

이제 드롭존을 클릭하고 다운로드한 파일을 선택하십시오. 그러면 파일의 미리보기가 표시되고 이름이 아래에 표시됩니다: awesomeIron.pdf.

IronPDF 라이선스

라이선스 관련 자세한 내용은 IronPDF 페이지를 참조하십시오.

아래 그림과 같이 앱에 라이선스 키를 입력하십시오.

import { IronPdfGlobalConfig, PdfDocument } from "@ironsoftware/ironpdf";

// Apply your IronPDF license key
IronPdfGlobalConfig.getConfig().licenseKey = "Add Your key here";
import { IronPdfGlobalConfig, PdfDocument } from "@ironsoftware/ironpdf";

// Apply your IronPDF license key
IronPdfGlobalConfig.getConfig().licenseKey = "Add Your key here";
JAVASCRIPT

결론

react-dropzone을 사용하여 Dropzone을 React와 통합하는 것은 간단한 과정이며 파일 업로드 환경을 크게 향상시켜 줍니다. 드래그 앤 드롭, 파일 미리보기, 다양한 사용자 지정 옵션과 같은 기능을 갖춘 react-dropzone은 React 프로젝트에 매우 유용한 도구가 될 수 있습니다. 이 도구의 기능을 살펴보고 애플리케이션 요구 사항에 맞게 맞춤 설정해 보세요!

반면 IronPDF 는 다양한 PDF 생성 및 조작 라이브러리로, 애플리케이션에 쉽게 통합할 수 있습니다. IronPDF 개발자가 쉽게 시작할 수 있도록 상세한 문서코드 예제를 제공합니다.

이 문서에 설명된 단계를 따르면 React 애플리케이션에 강력한 파일 업로드 컴포넌트를 만들고 최신 애플리케이션에 PDF 파일 생성 기능도 통합할 수 있습니다.

다리우스 세란트
풀스택 소프트웨어 엔지니어 (웹 운영)

다리우스 세런트는 마이애미 대학교에서 컴퓨터 과학 학사 학위를 받았으며, Iron Software에서 풀 스택 웹 운영 마케팅 엔지니어로 근무하고 있습니다. 어린 시절부터 코딩에 매료되었던 그는 컴퓨팅이 신비로우면서도 접근하기 쉬운 분야라고 생각했고, 창의력과 문제 해결 능력을 발휘하기에 완벽한 매체라고 여겼습니다.

Iron Software에서 다리우스는 새로운 것을 만들고 복잡한 개념을 단순화하여 더 쉽게 이해할 수 있도록 하는 것을 즐깁니다. 그는 사내 개발자로서 학생들을 가르치는 데에도 자원하여 차세대 인재들과 전문 지식을 공유하고 있습니다.

다리우스에게 있어 그의 일은 가치 있고 실질적인 영향을 미치기 때문에 보람 있는 일입니다.

아이언 서포트 팀

저희는 주 5일, 24시간 온라인으로 운영합니다.
채팅
이메일
전화해