🔗 Blob URL vs Presigned URL
웹 개발자를 위한 완전 가이드
파일 관리의 두 가지 핵심 기술을 마스터하고, 실제 프로젝트에서 발생하는 문제들을 해결해보세요!
웹 개발에서 파일 관리는 항상 중요한 과제입니다. 특히 사용자가 업로드한 이미지를 미리보기로 표시하거나, 클라우드 저장소에 저장된 파일에 접근할 때 Blob URL과 Presigned URL을 올바르게 이해하고 사용하는 것이 핵심입니다.
🎯 개요 및 핵심 차이점
🔵 Blob URL
브라우저 메모리에 있는 파일을 참조하는 임시 URL
🟢 Presigned URL
클라우드 저장소에 있는 파일에 임시 접근 권한을 주는 보안 URL
🔵 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을 아는 모든 곳 |
| 지속 시간 | 🔄 세션 종료 시까지 | ⏰ 설정된 만료 시간까지 |
| 네트워크 의존성 | ❌ 없음 | ✅ 있음 |
| 메모리 사용 | 📈 파일 크기만큼 사용 | 📉 거의 없음 |
| 비용 | 💚 무료 | 💰 저장 및 전송 비용 |
🚀 실제 사용 시나리오
📋 일반적인 파일 업로드 프로세스
📁 파일 선택
사용자가 input[type="file"]로 이미지 파일을 선택합니다.
👁️ 즉시 미리보기
Blob URL을 생성하여 업로드 전에 즉시 미리보기를 표시합니다.
☁️ 백그라운드 업로드
사용자가 미리보기를 확인하는 동안 백그라운드에서 S3에 파일을 업로드합니다.
🔄 URL 교체
업로드 완료 후 Presigned 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 사용 고려
🏆 모범 사례
🎯 상황별 최적 선택 가이드
| 🎮 상황 | 🛠️ 권장 방법 | 💡 이유 | |||||||||
| 파일 선택 직후 미리보기 | 🔵 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 |