ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 새 탭 열림 없이 파일 다운로드: Blob으로 해결하기
    개발 여정/FrontEnd 2025. 5. 6. 22:04

     

    예전에 실무에서 일을 했을 때, pdf나 jpg 파일 링크를 클릭하면 사용자가 다운받게 하는 기능을 만든 적이 있다. 이렇게 보면 매우 간단하지만, PM이 요구한 다음과 같은 조건이 나를 난감하게 했다.

     

    1. 새 탭 열기 없이
    2. 지정된 파일명으로 다운받아지게 할 것...

    특히 새 탭 열기 없이 << 이 부분이 나에게 많은 물음표를 뜨게 했다. 대부분의 브라우저는 pdf나 jpg 링크를 클릭했을 때 새 탭을 열어서 보여주기 때문에.

     

    그래서 열심히 서치를 하던 중 Blob의 존재를 알게 됐고, 위 문제를 손쉽게 해결할 수 있게 해주었다.

    그럼 저 까다로운 조건을 가능하게 해준 고마운 Blob이란 건 뭘까?

     

    Blob이란?

    Blob은 Binary Large Object의 준말로, 이미지, 사운드, 비디오와 같은 멀티미디어 데이터를 이진(Binary) 형태로 임시 저장할 수 있는 객체다.

     

    Blob을 비유하자면 택배 상자와 같다.

    • 상자 안에 어떤 물건(데이터)가 들었는지는 중요하지 않음.
    • 중요한 건 '이 상자 안에 어떤 데이터가 들어있다'라는 것.
    • 이 상자를 이용해서 다운로드, 업로드, 파일 미리보기, url 생성 등을 할 수 있음.

    즉 Blob은 데이터를 포장해서, 브라우저가 파일처럼 취급하게 만드는 기술이라고 이해할 수 있다.

     

    자바스크립트로 '파일'을 만들어주는 도구

     

    실제 파일이 아니더라도 blob을 거치면 파일 형태로 변환되어 사용할 수 있다. 예를 들어, 일반 'Hello, World!' 문자열도 Blob 생성자를 통해 text 파일로 거듭날 수 있다.

    const blob = new Blob(["Hello, World!"], {type: 'text/plain'})

     

    파일을 다운로드할 수 있게 도와주는 도구

     

    일단 파일 링크는 브라우저의 영향을 받는다.

    다음과 같이 a 링크가 있다고 가정해보자.

    <a href="https://myFile.pdf" />

     

    브라우저는 이를 보고

    • 새 탭에서 열지
    • 다운로드를 할지
    • 무시할지

    를 판단하고, 이는 브라우저마다 기준도 다르다.

     

     

    따라서 같은 링크라도 브라우저마다 반응이 다르다. 현재 탭에서 열릴 수도 있고, 새 탭에서 열릴 수도 있고, 새 탭에서 열리면서 파일이 다운로드될 수도 있고, 이 모든 게 작동하지 않을 수도 있다.

     

    그러면 a 태그에 download 속성을 추가하면 되는 거 아냐? 라고 할 수 있지만, 쉽게 사용하기엔 또 다른 제약들이 있다.

     

    CORS 이슈

     

    일단 download 속성은 같은 origin일 때만 작동한다.

    // 파일을 여는 사이트 도메인이 myWolrld.com일 때
    <a href="https://myWolrd.com/file.pdf" download />✅ 잘 됨 
    <a href="https://otherWorld.com/file.pdf" download /> ❌ CORS 이슈 발생 가능

     

    파일 링크가 두번째처럼 다른 도메인이라면, 보안 때문에 CORS(Cross-Origin Resource Sharing) 이슈가 발생하면서 다운로드가 동작하지 않을 수 있다.

     

    서버 헤더 응답

     

    서버 응답 헤더에도 영향을 받는다.
    서버 응답 헤더에서 다음과 같이 설정되어 있다면,

    Content-Disposition: inline

     

    다운로드는 작동되지 않고 브라우저는 그냥 파일을 열어버린다.

    즉, 서버가 통제권을 가지기 때문에 프론트에서 download 속성을 강제할 수 없는 경우가 많다.

     

    Blob을 사용한다면?

    Blob을 사용한다면 다음과 같은 장점을 통해 위 이슈들을 해결할 수 있다.

    1. 새 탭 열기 이슈: Blob URL은 브라우저를 위한 임시 url이기 때문에, 브라우저가 '외부 자원'으로 간주하지 않아 새 탭 열기 동작을 실행하지 않음.
    2. CORS 이슈: Blob URL은 브라우저 내부 리소스이기 때문에, CORS 요청을 거치지 않음.
    3. 다운로드 이슈: 마찬가지로 Blob URL이 브라우저 내부 리소스이기 때문에 서버 응답에 통제를 받지 않음. 따라서 다운로드를 강제할 수 있음.

    그리고 Blob URL은 브라우저 내부에서만 유효한 임시 주소이기 때문에 보안적 측면에서도 강점이 있다.

    • 외부에서 접근 불가능
    • 세션 종료되면 자동 폐기됨
    • 서버에 저장하지 않아도 되므로 개인정보 보호에 유리

     

    실제 코드 예시: Blob으로 새탭열기 없이 파일 저장하기

    위에서처럼 Blob을 통하면 브라우저 설정에도, 서버에도 영향을 받지 않기 때문에 내가 원하는 방식인

    1. 새 탭 열기 없이
    2. 바로 다운로드 (지정된 파일명과 함께)
      를 실현할 수 있었다.
    const handleDownloadOnWeb = async (url: string) => {
    
      const response = await fetch(url);                     // 파일 데이터를 비동기 fetch
      
      const blob = await response.blob();                   // 응답을 Blob으로 변환
      
      const binary = new Blob([blob], { type: blob.type }); // Blob 재포장
    
      const windowUrl = window.URL.createObjectURL(binary); // 가짜 주소(URL) 생성
      
      const link = document.createElement('a');             // <a> 태그 동적으로 생성
      
      link.href = windowUrl;
      
      link.setAttribute('download', 'report.pdf');          // 저장할 파일명 지정
      
      document.body.appendChild(link);                      // DOM에 추가
      
      link.click();                                         // 클릭 이벤트 발생시켜 다운로드 실행
      
      link.remove();                                        // DOM에서 제거
      
      window.URL.revokeObjectURL(windowUrl);               // 메모리에서 URL 해제
      
    };

     

    비교: 일반 다운로드 방식과의 차이

    기능 Blob 방식 일반 방식
    새 탭 없이 저장 ✅ 가능 ❌ 서버 헤더/브라우저 영향 받음
    파일명 지정 ✅ 가능 (download) ❌ 외부 링크는 불가능
    클라이언트에서 만든 데이터 저장 ✅ 가능 ❌ 불가
    다른 origin 파일 다운로드 ✅ 대부분 가능 ❌ 브라우저 제약 많음

     

    Blob URL 사용 시 주의해야 할 점

    • URL.createObjectURL 로 만든 url은 브라우저 메모리를 사용하기 때문에,
      • 사용 후 URL.revokeObjectURL() 로 꼭 해제해야 한다.
    • 일부 오래된 브라우저(ex. IE11)는 Blob 지원이 잘 안 될 수도 있다.
Designed by Tistory.