본문 바로가기
Tech Notes

Blob URL vs Presigned URL: 웹 개발자를 위한 완전 가이드

by miracle-tech 2025. 9. 11.
728x90
반응형
Blob URL vs Presigned URL: 웹 개발자를 위한 완전 가이드

🔗 Blob URL vs Presigned URL

웹 개발자를 위한 완전 가이드

파일 관리의 두 가지 핵심 기술을 마스터하고, 실제 프로젝트에서 발생하는 문제들을 해결해보세요!

웹 개발에서 파일 관리는 항상 중요한 과제입니다. 특히 사용자가 업로드한 이미지를 미리보기로 표시하거나, 클라우드 저장소에 저장된 파일에 접근할 때 Blob URLPresigned URL을 올바르게 이해하고 사용하는 것이 핵심입니다.

🎯 개요 및 핵심 차이점

🔵 Blob URL

브라우저 메모리에 있는 파일을 참조하는 임시 URL

blob:https://example.com/550e8400-e29b-41d4-a716-446655440000

🟢 Presigned URL

클라우드 저장소에 있는 파일에 임시 접근 권한을 주는 보안 URL

https://bucket.s3.amazonaws.com/file.jpg?X-Amz-Expires=3600...

🔵 Blob URL 완전 분석

💡 Blob URL이란?

Blob URL은 사용자가 파일을 선택했을 때 브라우저에서 즉시 생성되는 임시 URL입니다. 서버 업로드 없이도 파일을 미리볼 수 있게 해주는 강력한 도구입니다.

✅ 장점

  • 즉시 생성 - 네트워크 요청 0ms
  • 🚀 초고속 로딩 - 메모리에서 직접 로드
  • 🔒 서버 독립적 - 오프라인에서도 동작
  • 💡 구현 간단 - 한 줄 코드로 생성

⚠️ 단점

  • 일시적 - 새로고침 시 사라짐
  • 💾 메모리 점유 - 파일 크기만큼 RAM 사용
  • 🚫 로컬 전용 - 다른 기기에서 접근 불가
  • 🧹 수동 정리 - 메모리 해제 필요
// Blob URL 생성 및 사용 const fileInput = document.getElementById('fileInput'); const preview = document.getElementById('preview'); fileInput.addEventListener('change', function(event) { const file = event.target.files[0]; if (file) { // Blob URL 생성 const blobUrl = URL.createObjectURL(file); preview.src = blobUrl; // 메모리 해제 (중요!) preview.onload = () => URL.revokeObjectURL(blobUrl); } });

🟢 Presigned URL 완전 분석

🛡️ Presigned URL이란?

Presigned URL은 AWS S3 같은 클라우드 저장소의 파일에 임시 접근 권한을 부여하는 보안 URL입니다. 파일을 공개하지 않으면서도 특정 시간 동안 접근을 허용합니다.

✅ 장점

  • 🌍 전역 접근 - 어디서든 동일한 URL
  • 💾 영구 보관 - 클라우드에 안전 저장
  • 🔄 지속성 - 세션과 무관하게 유지
  • 📱 크로스 플랫폼 - 모든 기기에서 동작

⚠️ 단점

  • 🕐 생성 지연 - API 호출 시간 필요
  • 만료 제한 - 설정된 시간 후 무효
  • 🌐 네트워크 의존 - 인터넷 연결 필수
  • 💰 비용 발생 - 저장 및 전송 요금
// Presigned URL 생성 (서버 측 - Node.js) const AWS = require('aws-sdk'); const s3 = new AWS.S3(); function generatePresignedUrl(bucketName, objectKey) { const params = { Bucket: bucketName, Key: objectKey, Expires: 3600, // 1시간 ResponseContentDisposition: 'inline' }; return s3.getSignedUrl('getObject', params); } // 클라이언트에서 사용 const presignedUrl = await fetch('/api/get-presigned-url').then(r => r.json()); document.getElementById('image').src = presignedUrl.url;

📊 상세 비교표

🔍 구분 🔵 Blob URL 🟢 Presigned URL
생성 위치 🖥️ 클라이언트 (브라우저) ⚙️ 서버
생성 시간 ⚡ 즉시 (0ms) 🕐 API 호출 시간 (100-500ms)
파일 위치 💾 브라우저 메모리 ☁️ 클라우드 저장소
접근 범위 📱 현재 탭에서만 🌍 URL을 아는 모든 곳
지속 시간 🔄 세션 종료 시까지 ⏰ 설정된 만료 시간까지
네트워크 의존성 ❌ 없음 ✅ 있음
메모리 사용 📈 파일 크기만큼 사용 📉 거의 없음
비용 💚 무료 💰 저장 및 전송 비용

🚀 실제 사용 시나리오

📋 일반적인 파일 업로드 프로세스

1

📁 파일 선택

사용자가 input[type="file"]로 이미지 파일을 선택합니다.

2

👁️ 즉시 미리보기

Blob URL을 생성하여 업로드 전에 즉시 미리보기를 표시합니다.

3

☁️ 백그라운드 업로드

사용자가 미리보기를 확인하는 동안 백그라운드에서 S3에 파일을 업로드합니다.

4

🔄 URL 교체

업로드 완료 후 Presigned URL로 교체하여 영구 접근이 가능하게 합니다.

⚠️ 주의: 4번 URL 교체 과정에서 앱 환경의 보안 정책이나 네트워크 이슈로 인해 문제가 발생할 수 있습니다!

⚠️ URL 전환 시 발생하는 문제들

🛡️

앱 내 웹뷰 보안 정책

모바일 앱의 웹뷰에서는 외부 URL 접근이 제한될 수 있습니다. 특히 iOS의 ATS(App Transport Security) 정책이 엄격합니다.

🌐

네트워크 연결 문제

Presigned URL은 실제 S3 서버 요청이 필요하므로, 네트워크가 불안정하면 로딩 실패가 발생합니다.

🚫

CORS 정책 충돌

S3 버킷의 CORS 설정이 앱의 도메인을 허용하지 않으면 접근이 차단됩니다.

💾

캐싱 문제

브라우저나 앱의 캐싱 정책으로 인해 이전 Blob URL이 유지되거나 새 URL이 로드되지 않을 수 있습니다.

✅ 해결 방법

🔄 1. 점진적 전환 방식

Presigned URL 로딩 실패 시 Blob URL을 유지하는 안전한 방법입니다.

// 안전한 URL 전환 구현 function safeUrlTransition(blobUrl, presignedUrl, imgElement) { const newImg = new Image(); // 로딩 성공 시 newImg.onload = function() { imgElement.src = presignedUrl; URL.revokeObjectURL(blobUrl); // 메모리 해제 console.log('✅ Presigned URL 로딩 성공'); }; // 로딩 실패 시 Blob URL 유지 newImg.onerror = function() { console.warn('❌ Presigned URL 로딩 실패, Blob URL 유지'); showUserFeedback('네트워크 연결을 확인해주세요.'); }; // 타임아웃 설정 setTimeout(() => { if (!newImg.complete) { newImg.src = ''; // 요청 취소 console.warn('⏰ Presigned URL 로딩 타임아웃'); } }, 5000); newImg.src = presignedUrl; }

🔁 2. 재시도 메커니즘

네트워크 오류 시 자동으로 재시도하는 견고한 시스템입니다.

async function loadPresignedUrlWithRetry(url, maxRetries = 3) { for (let i = 0; i < maxRetries; i++) { try { // HEAD 요청으로 URL 유효성 검사 const response = await fetch(url, { method: 'HEAD', timeout: 3000 }); if (response.ok) { console.log(`✅ ${i + 1}번째 시도 성공`); return url; } } catch (error) { console.log(`❌ 재시도 ${i + 1}/${maxRetries}: ${error.message}`); if (i < maxRetries - 1) { // 지수 백오프: 1초, 2초, 4초 대기 await new Promise(resolve => setTimeout(resolve, 1000 * Math.pow(2, i)) ); } } } throw new Error('Presigned URL 로딩 최종 실패'); }

🛡️ 3. 포괄적 폴백 전략

다양한 상황에 대비한 다단계 폴백 시스템입니다.

📊

Base64 인코딩

작은 이미지(< 1MB)의 경우 Base64로 인코딩하여 데이터베이스에 저장

🚀

CDN 활용

CloudFront 같은 CDN을 통해 더 안정적이고 빠른 URL 제공

🔄

프록시 서버

자체 프록시 서버를 통해 S3 파일을 중계하여 CORS 문제 해결

📱

네이티브 API

앱 환경에서는 네이티브 파일 시스템 API 사용 고려

🏆 모범 사례

🎯 상황별 최적 선택 가이드

728x90

'Tech Notes' 카테고리의 다른 글

🎮 상황 🛠️ 권장 방법 💡 이유
파일 선택 직후 미리보기 🔵 Blob URL 즉시성이 최우선
업로드 완료 후 공유 🟢 Presigned URL 다중 접근 필요
오프라인 환경 🔵 Blob URL 네트워크 독립적
대용량 파일 (>10MB) 🟢 Presigned URL 메모리 효율성
임시 파일 처리 🔵 Blob URL
React에서 무한 루프 발생 원인  (0) 2025.09.11
React Hook은 언제, 왜 사용하는가?  (1) 2025.09.11
Git Cherry-pick 이란?  (0) 2025.09.10
딥링크(Deep Link)란 무엇인가? - 모바일 앱과 웹의 연결고리  (0) 2025.09.09
쿠키, localStorage, SessionStorage 완벽 비교 가이드  (2) 2025.08.25