Kage로 웹사이트를 13MiB 단일 바이너리로 박제하기 — 오프라인 아카이브 가이드

본 가이드는 Kage v0.1.1을 사용해 임의의 웹사이트를 자바스크립트가 제거된 정적 미러로 복제하고, ZIM 아카이브 또는 13 MiB 단일 실행 파일로 묶는 절차를 다룹니다. 사내 폐쇄망 이전, 외부 API 문서 백업, 컴플라이언스 감사 자료 보존 같은 백엔드 팀의 실무 시나리오를 염두에 둡니다.

Kage로 웹사이트를 오프라인 아카이브로 박제하는 백엔드 개발자 워크스페이스 이미지
Photo by Christopher Gower on Unsplash

테스트 환경: Ubuntu 22.04.4 LTS, Go 1.22, Chromium 126 기준. macOS·Windows에서도 동일한 명령으로 동작하며 컨테이너 이미지(ghcr.io/tamnd/kage)에는 Chromium이 번들로 포함되어 있습니다.

1. Kage가 해결하는 문제

Kage(影, 그림자)는 헤드리스 Chrome으로 페이지를 실제 렌더링한 뒤 DOM 스냅샷을 떠서 모든 <script>·on* 핸들러·javascript: URL을 제거하고, CSS·이미지·폰트를 로컬 경로로 재작성해 디스크에 저장하는 Go 95.6% 순수 도구입니다. 공식 README에 따르면 결과물은 “네트워크 호출이 전혀 없는 정적 HTML”이며, MIT 라이선스로 배포됩니다.

전통적 “다른 이름으로 저장”은 SPA에서 빈 셸만 캡처하거나, 6개월 뒤 트래커 호출 실패로 무한 스피너에 빠지는 회귀를 자주 일으킵니다. Kage는 렌더링 후 코드를 제거하는 순서를 채택해 이 문제를 우회합니다.

2. 설치와 전제 조건

Kage는 호스트의 Chrome 또는 Chromium을 호출합니다. 공식 README 기준 자동 탐지가 실패하면 --chrome 플래그나 KAGE_CHROME 환경 변수로 경로를 지정합니다.

# Go 1.22 이상 환경
go install github.com/tamnd/kage/cmd/kage@latest

# 또는 Docker 컨테이너 (Chromium 번들)
docker run --rm -v "$PWD/out:/out" ghcr.io/tamnd/kage clone example.com

Release 페이지에는 .deb, .rpm, .apk 패키지와 체크섬·SBOM·cosign 서명이 함께 제공됩니다. 사내 정책상 외부 바이너리 실행이 제한되면 컨테이너 이미지로 우회하는 편이 안전합니다.

3. 기본 사용 흐름 (clone → serve → pack)

Kage CLI clone serve pack 명령 흐름을 보여주는 터미널 작업 이미지
Photo by Mohammad Rahmani on Unsplash

Kage는 4개 서브커맨드로 동작합니다. clone이 미러를 만들고, serve가 로컬 HTTP로 검수용 미리보기를 제공하고, pack이 단일 아티팩트로 묶고, open이 ZIM을 다시 펼칩니다.

# 1. 사이트 미러 ($HOME/data/kage/example.com/)
kage clone example.com --max-pages 50 --max-depth 2

# 2. 로컬 검수
kage serve $HOME/data/kage/example.com   # http://127.0.0.1:8800

# 3. ZIM 아카이브로 압축
kage pack example.com                    # example.com.zim

# 4. 단일 실행 파일로 배포
kage pack example.com --format binary -o example
./example                                # 의존성 없이 자체 서빙

크롤은 robots.txt를 읽고 sitemap.xml을 시드로 사용하는 정중한 BFS이며 기본 워커 수는 4입니다. Ctrl-C로 중단해도 state.json에 진행 상태를 저장하고 재실행 시 이어서 받습니다.

4. 단일 바이너리 패킹의 의미

--format binary는 ZIM 아카이브를 Kage 본체 뒤에 이어 붙여 자체 서빙 가능한 실행 파일을 만듭니다. 공식 문서 기준 베이스 바이너리는 약 13 MiB이며, 여기에 미러 크기가 더해집니다. 수신자는 Kage·ZIM 리더·압축 해제 도구가 전혀 필요 없습니다.

크로스 컴파일도 지원합니다. --base kage-windows-amd64.exe처럼 다른 OS용 베이스 바이너리를 지정하면 macOS에서 Windows용 뷰어를 생성할 수 있습니다. 헤더를 읽어 자동으로 .exe 확장자를 붙입니다.

5. ZIM 포맷과 Kiwix 생태계 호환

ZIM은 openZIM 프로젝트가 2009년부터 관리하는 개방 포맷입니다. Kage가 만든 *.zim 파일은 kiwix-serve, Kiwix 데스크톱 앱, Android·iOS 앱에서 동일하게 열립니다. 다만 공식 README 기준 Kage는 구조적으로 유효한 아카이브를 작성하지만 Kiwix의 자체 팩이 포함하는 풀텍스트 검색 인덱스는 빌드하지 않으므로, 리더 내 검색 기능은 제한적입니다.

패킹은 결정적(deterministic)입니다. 같은 미러는 항상 바이트 동일한 파일을 생성하며 아카이브 UUID도 콘텐츠에서 파생됩니다. 따라서 체크섬 캐시·CI 재현성·감사 추적에 적합합니다.

6. 백엔드 팀의 활용 시나리오

사내 폐쇄망과 외부 API 문서 백업 시나리오에서의 오프라인 아카이브 보관 개념 이미지
Photo by Tyler on Unsplash

6-1. 외부 API 문서 스냅샷

벤더가 문서를 갑자기 개편하거나 EOL 시키는 사례는 잦습니다. 의존 중인 SDK 문서를 분기마다 kage clone --refresh로 갱신해두면, 이슈 분석 시점의 문서 버전을 정확히 재현할 수 있습니다.

6-2. 폐쇄망 이전

망 분리 환경에 공개 문서를 반입할 때 ZIM 파일 1개를 보안 검사하는 편이 수천 개 정적 파일을 검사하는 것보다 운영 부담이 작습니다. 결정적 빌드라 보안팀이 사전 검증한 체크섬과 일치 여부를 자동화할 수 있습니다.

6-3. 컴플라이언스 증거 보존

약관·공지·릴리즈 노트 페이지를 클론해 보관하면 분쟁 시 “해당 시점의 화면”을 재현할 수 있습니다. 스크립트가 제거되므로 캡처 당시 트래커·광고 호출에 영향받지 않은 정적 증거가 남습니다.

7. 주의사항과 한계

  • 로그인 후에만 접근 가능한 SaaS 콘솔, 동적 폼 제출이 필요한 페이지는 정상 캡처되지 않을 수 있습니다.
  • --no-robots로 robots.txt를 무시하면 법적·윤리적 책임이 따릅니다. 공식 문서도 “be nice”라고 명시합니다.
  • WebView 빌드(-tags webview)는 cgo가 필요하며 플랫폼별 WebView 라이브러리(WKWebView/WebView2/WebKitGTK)에 의존합니다.
  • 풀텍스트 검색이 필요한 사내 위키 대체용으로는 Kiwix의 표준 팩 도구(zimit 등)를 함께 검토하는 편이 안전합니다.
  • 30 stars 규모의 초기 프로젝트(v0.1.1 기준)이므로 프로덕션 의존 전 자체 테스트 환경에서 회귀 확인이 필요합니다.

8. 도입 판단 체크리스트

  • 대상 사이트가 공개 콘텐츠인가? (인증 필요 시 효용 급감)
  • 아카이브 결과의 활용처가 “읽기 전용 보관”인가? (검색·편집 필요 시 다른 도구 검토)
  • 배포 대상이 사내 네트워크가 막혀 단일 파일이 유리한가?
  • 크롤링 정책상 외부 사이트 대량 미러링이 허용되는가?
  • 장기 보존 시 ZIM 포맷의 개방성과 Kiwix 호환성을 신뢰할 수 있는가?

9. 관련 글

Kage는 로컬에서 헤드리스 Chrome 프로세스를 띄우므로 자원 사용량 관리가 필요합니다. 유사한 데스크톱 도구의 리소스 누수 사례는 다음 글을 참고하시기 바랍니다.


📌 함께 보시면 좋은 글

※ 본 글은 AI(Claude)의 초안을 기반으로 편집자 검수를 거쳐 발행되었습니다. (한국 AI기본법 대응 고지)

이직·퇴사, 지금 움직여도 될지 헷갈리시나요?

막연히 불안한 건지, 정말 시점이 온 건지 판단이 어려울 때가 있습니다.

5분 체크리스트로 지금 상태를 먼저 정리해보세요.
결론을 대신 내리기보다, 스스로 판단할 기준을 잡는 데 도움을 드립니다.

무료 체크리스트 보기

아직 확신이 없다면, 지금이 ‘고민 단계’인지부터 먼저 점검해보세요