본문 바로가기
Tech Notes

WebView 이미지 캡처 & 저장

by miracle-tech 2026. 2. 24.
320x100
반응형
WebView 이미지 캡처 & 저장 완전 정복
dev.note / WebView / image-capture
2025-02-24 | WebView · Mobile
html2canvas modern-screenshot iOS WebView android saveBase64Data 앱인토스

WebView 이미지 캡처 & 저장 완전 정복

html2canvas vs modern-screenshot 비교, canvas 태그 호환성, 폰트 CORS, iOS 권한 처리까지 — WebView 환경에서 이미지를 저장하는 과정에서 마주치는 모든 함정을 정리했습니다.

1. 전체 흐름 — 3단계로 이해하기

WebView에서 화면을 이미지로 저장하는 과정은 크게 3단계로 나뉩니다. 각 단계마다 별개의 기술적 문제가 존재하기 때문에, 어느 단계에서 오류가 났는지를 먼저 파악하는 것이 중요합니다.

STEP 01
화면 캡처
HTML → Canvas
STEP 02
이미지 데이터
Base64 / Blob
STEP 03
기기에 저장
Native Bridge
01
캡처 라이브러리 선택
canvas 태그 포함 여부에 따라 라이브러리가 달라집니다. 잘못 선택하면 iOS에서 빈 화면이 나옵니다.
02
폰트 CORS 처리
외부 CDN 폰트는 캡처 시 CORS 오류로 기본 글꼴로 대체됩니다. 로컬 폰트가 유일한 해결책입니다.
03
플랫폼별 저장 처리
iOS는 권한 요청이 먼저 필요합니다. Android는 브리지 함수를 바로 호출해도 됩니다.

2. 캡처 라이브러리 비교 — html2canvas vs modern-screenshot

브라우저는 "화면을 스크린샷으로 찍는" 네이티브 API를 제공하지 않습니다. 때문에 라이브러리가 HTML 구조를 읽어 직접 이미지로 변환합니다. 방식의 차이가 iOS 호환성을 크게 좌우합니다.

라이브러리 변환 방식 장점 주의사항
html2canvas HTML을 읽어서 <canvas>에 직접 재드로우 레퍼런스 풍부 내부 iframe 생성 방식 사용. 기존 <canvas> 태그(rough.js 등)가 있으면 iOS에서 빈 화면 렌더링
modern-screenshot HTML → SVG → 이미지 변환 iframe 미사용 canvas 호환 외부 폰트(Google Fonts) CORS로 읽기 실패. 로컬 폰트 필수

// 어떤 라이브러리를 선택해야 하나

프로젝트에 <canvas> 태그가 존재하는가?
(rough.js, chart.js, Three.js 등 포함)
YES
modern-screenshot 사용
NO
html2canvas 사용 가능
CAUTION
html2canvas는 내부적으로 대상 DOM을 iframe에 복제한 뒤 캔버스로 그립니다. 이 과정에서 이미 존재하는 <canvas> 요소의 픽셀 데이터를 iOS 보안 정책상 읽지 못하는 경우가 발생합니다. 결과는 해당 영역이 완전히 비어있는 이미지입니다.

3. 폰트 CORS 문제 — 글씨체가 캡처에서 깨지는 이유

캡처 라이브러리는 HTML 구조와 함께 CSS에 지정된 폰트도 이미지에 포함시키려 합니다. 이때 폰트 파일의 출처(origin)가 결정적입니다.

CASE 1 — Google Fonts (실패)
@import url(fonts.googleapis.com)
캡처 라이브러리: 외부 서버 요청 시도
CORS 오류: 폰트 파일 로드 실패
결과: 기본 글꼴(serif/sans-serif)로 대체
CASE 2 — 로컬 폰트 (성공)
@font-face { src: /fonts/xxx.woff2 }
캡처 라이브러리: 같은 origin 요청
CORS 제한 없음: 파일 정상 로드
결과: 지정 글꼴 정상 렌더링
KEY POINT
이미지 캡처 기능이 있는 프로젝트는 폰트 파일을 반드시 public/fonts/ 디렉토리에 직접 포함시키세요. 런타임에 CDN에서 로드하는 방식은 캡처 시 동작하지 않습니다.

4. 저장 처리 — iOS와 Android가 다른 이유

웹 페이지는 보안 정책상 사용자 기기의 파일 시스템에 직접 접근할 수 없습니다. 앱인토스 같은 네이티브 WebView 환경은 JavaScript Bridge를 통해 이 제약을 우회합니다. 그러나 iOS와 Android의 권한 모델이 달라 처리 순서가 다릅니다.

Android — 바로 저장 가능
1 saveBase64Data() 호출
 
2 사진첩 저장 완료
iOS — 권한 요청 선행 필수
1 requestPermission('photos') 호출
 
2 시스템 권한 다이얼로그 표시
 
3 사용자 허용
 
4 saveBase64Data() → 저장 완료
CAUTION
iOS에서 권한 요청 없이 saveBase64Data()를 바로 호출하면 저장이 무음 실패합니다. 에러도 없이 아무 일도 일어나지 않는 것처럼 보여 디버깅이 어렵습니다. 반드시 권한 획득 후 저장 함수를 호출하세요.

5. 핵심 체크리스트

WebView 이미지 저장 기능을 구현할 때 놓치기 쉬운 항목들을 단계별로 정리했습니다.

STEP 01
canvas 태그 유무 확인 후 캡처 라이브러리 선택
canvas 있음 → modern-screenshot / canvas 없음 → html2canvas 가능
STEP 02
폰트 파일을 로컬에 직접 배치
public/fonts/ 경로에 woff2 파일 포함. Google Fonts CDN은 캡처 시 동작 안 함
STEP 03
플랫폼 분기 처리로 저장 로직 구현
iOS: requestPermission('photos') 먼저 → 허용 후 saveBase64Data() / Android: 바로 saveBase64Data()
WebView Image Capture Guide — html2canvas · modern-screenshot · iOS · Android
320x100