AX 노트 · 측정

안드로이드 한글 뷰어 만들기: rhwp + WebView를 문서 222개로 실측한 기록

오픈소스 엔진 rhwp를 WebView에 올려 HWP·HWPX 222개를 열어 보니 221개가 열렸고, 첫 쪽까지 중앙값 1.2~1.5초가 걸렸습니다.

작성 SugarMount Android 개발 읽는 시간 8분 최종 업데이트

한글 문서 222개 중 221개가 열렸습니다. 한글뷰어 슈가독을 만들기 전, "이 엔진으로 앱이 되는가"부터 보려고 2026년 10월 3일 Galaxy S21(Android 15, WebView 153)에서 문서를 하나씩 콜드 스타트로 열어 본 결과입니다. 엔진은 그대로 채택했습니다. 다만 384쪽 문서를 한꺼번에 그리자 렌더러 메모리가 2.8GB까지 올라갔고, 처음 보고서가 "공문서 24개"라고 적은 묶음에서 실제 정책브리핑 첨부는 17파일뿐이었습니다.

숫자는 SugarMount 앱 저장소(sugar-utils)의 엔진 실측 문서(측정 2026-10-03, 커밋 7b0e567), 후속 검증 문서(2026-10-05), 그리고 이 글을 쓰며 원자료 JSON에서 다시 계산한 값입니다. 기준일은 2026년 10월 19일입니다.

목차 (7)
  1. 측정 조건: S21 한 대, 문서 222개, 매번 콜드 스타트
  2. 측정표: 221/222 열림, 첫 쪽까지 중앙값 1.2~1.5초
  3. 384쪽 문서는 보이는 쪽만 그려야 버팁니다
  4. 글꼴은 144MB에서 9.2MB로 줄였습니다
  5. AI가 틀린 숫자와 검증 에이전트가 고친 값
  6. 남은 일
  7. 자주 묻는 질문

측정 조건: S21 한 대, 문서 222개, 매번 콜드 스타트

rhwp는 Rust로 짠 HWP·HWPX 파서를 WebAssembly(WASM)로 빌드한 오픈소스 엔진입니다. 문서의 쪽을 SVG로 그려 주고, 라이선스는 MIT입니다. 측정에는 npm 패키지 @rhwp/core 0.8.6을 썼고, 지금 출시된 앱도 같은 버전에 고정돼 있습니다.

테스트 앱은 WebView 하나에 rhwp와 rhwp가 제공하는 글꼴 CSS(글꼴 규칙 153개)를 넣었습니다. 문서마다 앱을 강제 종료한 뒤 다시 띄웠고, 앞 3쪽만 화면에 그리고 나머지 쪽은 렌더링 시간만 쟀습니다.

저사양 기기는 없었습니다.

측정표: 221/222 열림, 첫 쪽까지 중앙값 1.2~1.5초

"탭→첫 쪽"은 콜드 스타트를 포함해 앱 실행 시간과 첫 쪽 렌더링 시간을 더한 값입니다. p90은 느린 쪽 10%가 시작되는 값입니다. 렌더러 메모리는 WebView 렌더러 프로세스의 PSS(공유 메모리를 나눠 계산한 실사용량)로 쟀습니다.

항목정책브리핑 17파일처음 보고서의 "공문서 24"rhwp 샘플 198
열기 성공17/1724/24197/198
탭→첫 쪽 중앙값1.4초1.5초1.2초
탭→첫 쪽 p901.6초2.1초1.9초
탭→첫 쪽 최대1.8초3.0초3.3초
쪽당 렌더링 중앙값-10ms6ms
렌더러 메모리(PSS) 최대286MB391MB422MB

못 연 1개는 issue2063_huge_cellbreak_table.hwp입니다. 쪽 나눔이 걸린 초대형 표로 성능을 시험하려고 일부러 만든 문서라서, 120초 제한을 넘겼습니다. 실측 보고서는 이런 문서를 위한 대체 경로를 채택 조건으로 걸었습니다. 지금 앱은 10초가 넘으면 계속 기다릴지, 다른 앱으로 넘길지 고르게 합니다.

모양도 확인했습니다. 정답 PDF가 있는 샘플은 쪽 수가 197개 중 195개에서 맞았고(2개는 1쪽 차이), 첫 쪽 이미지 유사도 중앙값은 0.997이었습니다. 문서 7개(보도자료 2, 샘플 5)는 한컴 출력과 나란히 놓고 눈으로 봤습니다. 보도자료의 표·로고·굵은 글씨, 수능 모의고사의 수식과 2단 편집이 거의 같았고, 시험지 첫 문항 번호 "문1)" 하나만 빠져 있었습니다.

384쪽 문서는 보이는 쪽만 그려야 버팁니다

rhwp 샘플에는 384쪽짜리 행정 편람(파일 10.7MB)이 있습니다. 모든 쪽의 SVG를 한꺼번에 DOM에 넣자 WebView 렌더러 프로세스가 2.8GB까지 커졌습니다. 같은 문서를 보이는 쪽만 그리는 방식으로 열었을 때는 255MB였습니다. 같은 날 다른 회차에서는 366MB가 나왔습니다.

비교 그림: 384쪽 문서의 모든 쪽을 그리면 WebView 렌더러가 2.8GB였고, 보이는 쪽만 그리면 255MB(다른 회차 366MB)였다.
보이는 쪽만 그리자 렌더러 메모리의 자릿수가 달라졌습니다.

HWP 뷰어를 WebView로 만든다면 가상 스크롤(보이는 쪽과 그 앞뒤만 DOM에 두는 방식)을 처음부터 넣으십시오.

출시한 앱은 모든 쪽에 크기만 잡힌 빈 칸을 두고, 화면에 보이는 쪽 앞뒤로만 SVG를 둡니다. 메모리가 넉넉한 기기는 앞뒤 2쪽, 적은 기기는 1쪽입니다. 그려 둔 SVG 문자열은 바이트 한도가 있는 LRU 캐시에 넣고, 한도를 넘으면 가장 오래 안 본 쪽부터 버립니다.

글꼴은 144MB에서 9.2MB로 줄였습니다

rhwp가 함께 배포하는 글꼴 폴더는 파일 87개, 144,327,972바이트입니다. 실측 문서에는 이 값이 "138MB"로 적혀 있는데, 1MB를 1,048,576바이트로 센 값입니다. 222개 문서가 실제로 쓴 글꼴은 17개 파일, 약 37MB였습니다.

앱에는 10개 파일, 9,207,952바이트(원래의 약 6%)만 넣었습니다. 기준은 라이선스와 모양 두 가지였습니다. 함초롬체는 앱 탑재 조건이 한컴 페이지에 명확히 적혀 있지 않아 빼고, 함초롬바탕은 Noto Serif KR, 함초롬돋움은 나눔고딕 같은 OFL 글꼴로 바꿔 그립니다. rhwp에 들어 있던 나눔고딕은 예약 이름을 그대로 둔 서브셋이어서, google/fonts의 원본 TTF로 바꿨습니다.

막대그래프: rhwp가 함께 배포하는 글꼴 87개 파일은 144MB, 문서 222개가 실제로 쓴 17개는 약 37MB, 앱에 넣은 10개는 9.2MB다.
앱에는 라이선스와 모양을 확인한 글꼴 10개, 원래의 약 6%만 넣었습니다.

바꾼 글꼴로 모양이 얼마나 달라지는지는 2026-10-05에 같은 S21에서 다시 쟀습니다. 첫 쪽의 잉크 일치도(F1)가 정답 대비 얼마나 떨어지는지를 봤고, 미리 정한 기준은 중앙값 0.02 이하였습니다. 결과는 0.0071로 통과했습니다. 기준을 넘은 문서가 하나 있었습니다. 제목이 한자인 수능 문서로 0.0336이었고, 차이는 제목 한자와 원문자(①~⑤)에 몰려 있었습니다. 번들 글꼴에 한자가 없어 시스템 글꼴이 그린 부분입니다.

AI가 틀린 숫자와 검증 에이전트가 고친 값

엔진 실측은 AI 코딩 에이전트(Claude) 세션이 돌렸고, 보고서도 그 세션이 썼습니다. 이틀 뒤 후속 실험에서는 측정하는 에이전트와 별도로 검증 에이전트를 두고, 증거 파일을 다시 열어 수치를 재계산하게 했습니다. 문서에는 정정된 값만 남겨 둡니다. 처음 보고서의 통계도 이때 다시 세었습니다.

처음 보고검증 뒤
실제 공문서 24개정책브리핑 17파일(보도자료 14건) + 7개. 7개 중 4개는 샘플과 바이트가 같고, 3개는 rhwp 테스트용 문서
샘플 198개 = HWP 177, HWPX 21HWP 180, HWPX 18(그중 HWP 3.0이 9개)
본문 숫자 재현율 약 0.9비교 코드의 버그. 텍스트 조각을 구분자 없이 이어 붙여 11:00과 10. 2.가 11:0010. 2.가 됐습니다. 고친 방식으로는 17파일 모두 1.0(너그러운 상한값)
번들 글꼴 9,700KB(후속 실험 측정 에이전트의 보고)KiB를 KB로 적은 값. 9,933,636바이트 = 9.93MB(최종 9,207,952바이트로 다시 줄임)

가장 크게 틀린 건 첫 줄입니다. "공문서 24/24"는 그럴듯하게 읽히지만, 24개 중 7개는 공문서가 아니었습니다. 17파일만 다시 계산하면 오히려 더 빠르고(중앙값 1.4초) 메모리도 적습니다(최대 286MB). 엔진 판단은 바뀌지 않았지만, 검증 없이 발행했다면 출처가 틀린 숫자를 그대로 인용했을 겁니다.

이 글을 쓰면서 원자료 JSON(s21b.json)으로 중앙값을 한 번 더 냈습니다. 문서에 적힌 1.5초, 2.1초, 3.0초는 그대로 나왔습니다. 384쪽 문서의 366MB 회차는 이때 찾은 것입니다. (원자료 하나는 다른 분석 스크립트가 덮어써서 다시 만들어야 한다는 메모도 검증 문서에 남아 있었습니다.)

남은 일

자주 묻는 질문

rhwp를 상업용 Android 앱에 써도 되나요?

쓸 수 있습니다. rhwp는 MIT 라이선스지만, WASM 안에 함께 빌드된 Rust 크레이트(Apache-2.0, BSD 등)의 고지도 같이 넣어야 합니다. 함께 배포되는 글꼴은 파일마다 라이선스가 달라서 따로 확인해야 합니다. 한글뷰어 슈가독은 OFL 등 라이선스가 확인된 글꼴 파일 10개만 넣고, 함초롬체는 넣지 않았습니다.

WebView로 HWP를 열면 메모리가 왜 그렇게 커지나요?

쪽마다 SVG가 DOM에 계속 남기 때문입니다. 384쪽 문서를 전부 그리자 렌더러가 2.8GB였고, 보이는 쪽만 그리자 255MB였습니다.

HWP와 HWPX를 같은 엔진으로 열 수 있나요?

네. rhwp 0.8.6은 둘 다 엽니다. 이번 측정에서도 두 형식이 섞인 222개 중 221개가 열렸습니다. 두 형식의 차이는 HWP와 HWPX 차이, 휴대폰에서 둘 다 여는 법에 정리했습니다. 카톡으로 받은 HWPX가 휴대폰에서 안 열리면 카톡·휴대폰에서 HWPX 파일이 안 열릴 때를 보세요.

이 글은 SugarMount가 직접 측정한 값으로 쓰고, 초안 작성에 AI 코딩 에이전트를 썼습니다.

Android 개발 글 전체 보기 · AX 노트 전체 보기