본문 바로가기

Development/Javascript

모던 자바스크립트 입문 - Chapter 19: API 활용 💻

웹 개발을 하다 보면 사용자와의 상호작용을 더욱 풍부하게 만들어 주는 다양한 API들을 접하게 됩니다.

파일을 드래그 앤 드롭으로 업로드하거나, 대용량 데이터를 처리하거나, 무거운 작업을 백그라운드에서 실행하는 것들이 모두 이런 API들 덕분에 가능합니다.

이번 포스트에서는 모던 웹 개발에서 자주 사용되는 세 가지 핵심 API를 살펴보겠습니다.

📌 목차

  • 드래그 앤 드롭 API
  • Blob
  • Web Workers

📝 드래그 앤 드롭 API

드래그 앤 드롭 API는 사용자가 마우스로 요소를 끌어서 다른 위치에 놓을 수 있게 해주는 기능입니다.

파일 업로드나 요소 재정렬에 주로 사용됩니다.

기본 구현

// HTML: <div id="dropArea">여기에 파일을 드롭하세요</div>

const dropArea = document.getElementById('dropArea');

// 드래그 오버 시 기본 동작 방지
dropArea.addEventListener('dragover', (e) => {
    e.preventDefault();
    dropArea.style.backgroundColor = '#f0f0f0';
});

// 드래그 떠날 때
dropArea.addEventListener('dragleave', () => {
    dropArea.style.backgroundColor = '';
});

// 파일 드롭 시
dropArea.addEventListener('drop', (e) => {
    e.preventDefault();
    dropArea.style.backgroundColor = '';
    
    const files = e.dataTransfer.files;
    console.log('드롭된 파일:', files[0].name);
});

요소 간 드래그 앤 드롭

// 드래그 가능한 요소
const draggableItem = document.getElementById('draggable');
draggableItem.draggable = true;

draggableItem.addEventListener('dragstart', (e) => {
    e.dataTransfer.setData('text/plain', '드래그된 데이터');
});

// 드롭 영역
const dropZone = document.getElementById('dropZone');

dropZone.addEventListener('drop', (e) => {
    e.preventDefault();
    const data = e.dataTransfer.getData('text/plain');
    dropZone.textContent = `받은 데이터: ${data}`;
});

 

핵심 포인트: preventDefault()를 반드시 호출해야 하고, dataTransfer 객체를 통해 데이터를 주고받을 수 있습니다.


📝 Blob

Blob(Binary Large Object)은 파일과 같은 바이너리 데이터를 다루는 객체입니다.

파일 다운로드, 이미지 처리, 데이터 저장 등에 활용됩니다.

기본 사용법

// 텍스트로 Blob 생성
const textBlob = new Blob(['안녕하세요!'], { type: 'text/plain' });
console.log(textBlob.size); // 바이트 크기
console.log(textBlob.type); // MIME 타입

// JSON 데이터로 Blob 생성
const data = { name: '홍길동', age: 25 };
const jsonBlob = new Blob([JSON.stringify(data)], { type: 'application/json' });

파일 다운로드 구현

function downloadFile(content, filename) {
    const blob = new Blob([content], { type: 'text/plain' });
    const url = URL.createObjectURL(blob);
    
    const a = document.createElement('a');
    a.href = url;
    a.download = filename;
    a.click();
    
    // 메모리 정리
    URL.revokeObjectURL(url);
}

// 사용 예시
downloadFile('다운로드할 내용입니다.', 'sample.txt');

이미지 미리보기

const fileInput = document.getElementById('fileInput');
const preview = document.getElementById('preview');

fileInput.addEventListener('change', (e) => {
    const file = e.target.files[0];
    if (file && file.type.startsWith('image/')) {
        const imageUrl = URL.createObjectURL(file);
        preview.src = imageUrl;
        
        // 메모리 정리 (이미지 로드 후)
        preview.onload = () => URL.revokeObjectURL(imageUrl);
    }
});

 

핵심 포인트: URL.createObjectURL()로 임시 URL을 생성하고, 사용 후에는 revokeObjectURL()로 메모리를 정리해야 합니다.


📝 Web Workers

Web Workers는 메인 스레드를 블로킹하지 않고 백그라운드에서 스크립트를 실행할 수 있게 해주는 기술입니다.

무거운 계산이나 데이터 처리에 유용합니다.

기본 구현

worker.js 파일:

// 메시지 받기
self.addEventListener('message', (e) => {
    const { numbers } = e.data;
    
    // 무거운 계산 (배열 합계)
    let sum = 0;
    for (let i = 0; i < numbers.length; i++) {
        sum += numbers[i];
    }
    
    // 결과 전송
    self.postMessage({ result: sum });
});

 

메인 스크립트:

const worker = new Worker('worker.js');

// 워커에게 작업 요청
const largeArray = Array.from({ length: 1000000 }, (_, i) => i + 1);
worker.postMessage({ numbers: largeArray });

// 결과 받기
worker.addEventListener('message', (e) => {
    console.log('계산 결과:', e.data.result);
    worker.terminate(); // 워커 종료
});

// 에러 처리
worker.addEventListener('error', (e) => {
    console.error('워커 에러:', e.message);
});

인라인 워커 (파일 없이 사용)

function createInlineWorker(workerFunction) {
    const blob = new Blob([`(${workerFunction.toString()})()`], 
                         { type: 'application/javascript' });
    return new Worker(URL.createObjectURL(blob));
}

// 워커 함수 정의
function workerCode() {
    self.addEventListener('message', (e) => {
        const { start, end } = e.data;
        let result = 0;
        
        for (let i = start; i <= end; i++) {
            result += i * i; // 제곱의 합
        }
        
        self.postMessage({ result });
    });
}

// 사용
const worker = createInlineWorker(workerCode);
worker.postMessage({ start: 1, end: 10000 });

worker.addEventListener('message', (e) => {
    console.log('제곱합:', e.data.result);
});

핵심 포인트: 워커는 DOM에 직접 접근할 수 없고, postMessage()를 통해서만 데이터를 주고받을 수 있습니다.


📝 실전 활용 예시

세 가지 API를 조합한 파일 처리 시스템:

// 드래그 앤 드롭으로 파일 받기
dropArea.addEventListener('drop', (e) => {
    e.preventDefault();
    const file = e.dataTransfer.files[0];
    
    if (file) {
        processFileInWorker(file);
    }
});

function processFileInWorker(file) {
    const worker = new Worker('fileProcessor.js');
    
    // 파일을 ArrayBuffer로 읽기
    file.arrayBuffer().then(buffer => {
        worker.postMessage({ buffer, filename: file.name });
    });
    
    worker.addEventListener('message', (e) => {
        const { processedData } = e.data;
        
        // 처리된 데이터로 새 파일 생성
        const resultBlob = new Blob([processedData], { type: 'text/plain' });
        downloadFile(resultBlob, 'processed_' + file.name);
        
        worker.terminate();
    });
}

📚 마무리 정리

오늘 배운 API들을 정리하면:

 

드래그 앤 드롭 API: 사용자 친화적인 파일 업로드와 요소 조작이 가능합니다. preventDefault()와 dataTransfer 객체가 핵심입니다.

Blob: 바이너리 데이터를 다루며, 파일 다운로드와 이미지 처리에 활용됩니다. 메모리 관리를 위해 revokeObjectURL()을 잊지 말아야 합니다.

Web Workers: 메인 스레드를 블로킹하지 않고 백그라운드에서 무거운 작업을 처리합니다. DOM 접근이 불가능하고 메시지 기반 통신만 가능합니다.

💡 오늘 새롭게 알게 된 것

  • 드래그 앤 드롭에서 dragover 이벤트에 preventDefault()를 호출해야 드롭이 가능해진다는 점입니다.
  • Blob 객체로 메모리상의 데이터를 파일처럼 다룰 수 있다는 점입니다.
  • Web Workers가 완전히 독립된 환경에서 실행되어 DOM 접근이 안 된다는 점입니다.

🤔 어려웠던 점

  • 드래그 앤 드롭의 여러 이벤트들(dragover, dragleave, drop)을 조합하는 것입니다.
  • Web Workers에서 메인 스레드와 데이터를 주고받는 메커니즘 이해하는 것입니다.
  • Blob과 URL.createObjectURL()의 메모리 관리 개념입니다.

🎯 다음 학습 계획

모던 자바스크립트 입문 시리즈가 완료되었습니다!

그동안 함께해 주셔서 감사합니다.

앞으로는 지금까지 배운 내용을 토대로 더욱 중요하고 깊이 있는 자바스크립트 주제들을 다뤄보겠습니다.