Engineering note · Android / Webview

안드로이드 웹뷰에서 다운로드 구현

2026년 05월 21일이현수
태그javascriptandroidwebview

프론트엔드에서 Blob과 Object URL을 이용해 a태그로 파일을 다운로드할 때, 안드로이드 웹뷰 환경에서 겪을 수 있는 한계와 대안을 알아본다.

프론트엔드에서 비동기(Fetch, Axios)로 받아온 파일 데이터를 다운로드할 때, 데이터를 Blob 객체로 만들고 URL.createObjectURL()을 이용해 가상의 URL을 생성한 뒤 <a> 태그의 download 속성으로 파일을 저장하게 하는 방식을 자주 사용한다.

typescript
// 프론트엔드의 일반적인 Blob 다운로드 로직
const blob = new Blob([res.data], { type: res.headers['content-type'] });
const link = document.createElement('a');

link.href = window.URL.createObjectURL(blob);
link.target = '_blank';
link.download = getFileName(res); // 직접 파싱한 파일 이름

document.body.append(link);
link.click();
document.body.removeChild(link);

브라우저 환경에서는 이 방식이 완벽하게 작동한다. 하지만 안드로이드 웹뷰(Android WebView) 기반 앱에서는 파일 다운로드에 제약이 있다. 기본적으로 파일 다운로드를 지원하지 않기 때문에, 네이티브 코드에서 setDownloadListener를 설정해 다운로드 요청을 가로채서 처리해야 한다.

안드로이드 다운로드 실패 알림

그런데 위와 같이 Javascript로 생성한 Blob URL(blob:https://...) 기반 다운로드가 발생할 때, 안드로이드 웹뷰의 DownloadListener로 넘어오는 인자들이 그대로 넘어오지 않는다.

  1. 파일 이름 유실: 프론트엔드에서 link.download 속성에 아무리 정교하게 파일 이름을 지정해 주더라도, 네이티브 웹뷰 콜백에는 그 이름이 넘어오지 않는다.
  2. Content-Disposition 정보 부재: HTTP 응답 헤더의 Content-Disposition 정보를 네이티브에서 알 길이 없다.
  3. MIME 타입 의존: 오직 전달받은 url(blob 주소)과 임의의 mimetype만으로 네이티브에서 파일을 만들어 내야 한다.

결국 네이티브 단에서는 "어떤 이름으로 파일을 저장해야 할지" 알 수 없어서, 알 수 없는 임의의 파일명(bin 파일 등)으로 저장해 버리는 현상이 생긴다.

대안과 해결 방법

안드로이드 웹뷰에서 <a> 태그 클릭을 트리거하는 방식으로는 Blob 데이터를 올바른 이름으로 안전하게 다운로드하기 어렵다. 이를 해결하려면 다운로드 처리를 프론트엔드가 아닌 안드로이드 네이티브로 완전히 위임해야 한다.

Javascript Interface 사용

프론트엔드에서 Blob 다운로드를 발생시키는 대신, 안드로이드 네이티브 브릿지(Javascript Interface) 함수를 직접 호출한다.

javascript
// 프론트엔드
if (window.AndroidBridge && window.AndroidBridge.downloadFile) {
    // 파일 다운로드에 필요한 파라미터(URL, 파일명 등)를 직접 네이티브로 전달
    window.AndroidBridge.downloadFile(fileUrl, fileName);
} else {
    // 브라우저용 일반 Blob 다운로드 실행
}

이 방식을 사용하면 네이티브의 DownloadManager가 주어진 fileUrl로 실제 HTTP 요청을 직접 수행하여 올바른 파일명으로 안정적인 다운로드를 처리할 수 있다. 웹 환경과 앱 환경을 명확히 구분하여 다운로드 방식을 이원화하는 것이 가장 확실한 해결책이다.

좋아요와 댓글

댓글 남기기

댓글 0개

댓글을 불러오는 중입니다.