한 문장으로 이 프로젝트가 뭘 하는지부터.
Pake = "웹사이트를 → 네이티브 데스크탑 앱으로 한 줄에 포장하는 도구." 우리가 매일 쓰는 서비스는 대부분 웹(브라우저 탭)에 산다. 트위터, 위챗 리딩, ChatGPT, DeepSeek… 그런데 탭으로 열어 두면 다른 탭에 묻히고, 단축키도 없고, 독립 창처럼 못 쓴다. Pake는 터미널에서 pake https://원하는주소 한 줄을 치면, 그 사이트를 독 아이콘으로 띄울 수 있는 진짜 앱으로 만들어 준다. 결과물은 macOS면 .dmg, 윈도우면 .msi, 리눅스면 .deb.
브라우저 탭은 큰 냉장고(크롬) 안에 음식이 뒤섞여 있는 상태다. 탭이 수십 개면 어디 있는지 찾기도 힘들고, 브라우저를 닫으면 같이 사라진다.
Pake는 좋아하는 사이트 하나를 작은 진공팩(독립 앱)으로 포장해 준다. 게다가 이 진공팩은 통째로 새 냉장고(Electron=크롬 전체)를 사 오는 게 아니라, 집에 이미 있는 그릇(OS 내장 웹뷰)을 빌려 담기 때문에 부피가 1/20로 작다. 포장하면서 라벨(아이콘)·여는 방법(단축키)·내용물 손질(광고 제거·스타일)까지 같이 해 줄 수 있다.
pake라는 CLI다. pake https://x.com --name X처럼 "주소 + 옵션"을 한 줄로 주면 앱이 구워져 나온다. GUI(클릭형)가 아니라 한 줄 명령이라, 똑같은 작업을 스크립트로 반복·자동화하기 쉽다.정리하면 Pake의 핵심 약속은 세 가지다. ① 한 줄 명령(또는 GitHub Actions 온라인 빌드)으로 누구나 웹사이트를 앱으로 만든다. ② Tauri 덕에 결과물이 극도로 가볍다(≈5MB). ③ 단축키·창 스타일·드래그앤드롭·광고 제거 등 "브라우저 탭보다 나은 경험"을 옵션으로 얹는다. README가 직접 강조하는 표현 그대로, "Turn any webpage into a desktop app with one command."
"가볍다 + 한 줄이다 + 즉시 쓸 앱이 이미 있다"의 삼박자.
"웹사이트를 앱으로 감싼다"는 아이디어 자체는 새롭지 않다(브라우저의 'PWA 설치', Nativefier 등 선례가 있다). 그런데 Pake가 유독 인기를 끄는 이유는 결과물의 가벼움과 진입장벽 0, 그리고 바로 받아 쓸 완성 앱 목록을 동시에 갖췄기 때문이다. 다섯 가지로 본다.
Electron 앱이 디스크·메모리를 많이 먹는다는 불만은 오래된 주제다. Pake는 같은 "웹을 앱으로" 목적을 Rust/Tauri로 다시 써서 보통 5MB 안팎으로 끝낸다. README가 "Electron 패키지보다 거의 20배 작다"고 못 박는다. 설치도 실행도 가볍다는 건 사용자에게 즉시 와닿는 가치다.
개발자는 npm install -g pake-cli 후 pake <url> 한 줄이면 된다. 개발 환경이 없는 사람도 GitHub Actions 기반 온라인 빌드(docs/github-actions-usage.md)로 클릭만으로 앱을 받을 수 있다. "Rust를 모르고 빌드 도구가 없어도 된다"는 점이 사용자층을 크게 넓혔다.
레포에는 WeRead·Twitter·Grok·DeepSeek·ChatGPT 등 인기 사이트를 미리 구워 둔 완성 앱 다운로드 표가 있다(default_app_list.json). "도구를 배우기 전에 결과물을 먼저 맛보게" 하는 구성이라, 처음 온 사람도 5초 만에 가치를 체감한다.
단순 래핑을 넘어, 단축키·몰입형(타이틀바 숨김) 창·드래그앤드롭·커스텀 CSS/JS 주입·광고 제거를 옵션으로 제공한다. 즉 "그냥 웹"이 아니라 "데스크탑에 최적화된 전용 앱"을 만들 수 있다. 이 주입 기능이 Pake를 단순 포장지 이상으로 만든다.
Tauri 2.x, Rust edition 2021(MSRV 1.85), Node 18+, pnpm 10, Rollup 4 등 최신 도구 위에서 꾸준히 업데이트된다(버전 3.11.x). 커밋·릴리스가 활발하고 다국어 문서(영/중)와 기여자 그래프까지 갖춰, "살아 있는 프로젝트"라는 신뢰를 준다.
| 방법 | 웹사이트를 앱으로 만드는 방식 | Pake와의 차이 |
|---|---|---|
| Electron 직접 | 크롬+Node를 앱마다 번들 | 100~200MB로 무겁고 설정 복잡. Pake는 Tauri로 ≈5MB. |
| Nativefier | Electron 기반 자동 래퍼 | 같은 "한 줄 래핑"이지만 결과물이 Electron이라 무겁다. Pake는 Rust/Tauri. |
| 브라우저 PWA 설치 | 크롬의 "앱으로 설치" | 브라우저·정책에 종속, 커스텀 한계. Pake는 독립 설치파일 + 주입·단축키. |
| Pake | pake <url> → Tauri 빌드 → 네이티브 설치파일 | 가볍고, 한 줄이고, 기능 주입까지. 온라인 빌드로 환경 없이도 가능. |
핵심 가치가 명확하다. 결과물은 5MB로 가볍고, 만드는 법은 한 줄이며, 당장 받아 쓸 완성 앱까지 있다. Rust를 몰라도 온라인 빌드로 끝낼 수 있어, 개발자가 아니어도 자기만의 앱을 가질 수 있다.
Pake 앱은 본질적으로 지정 URL을 띄우는 웹뷰다. 그 사이트가 오프라인을 지원 안 하면 앱도 인터넷이 필요하고, 사이트 구조가 바뀌면 주입했던 광고 제거 CSS가 깨질 수 있다. 또 렌더링 엔진이 OS마다 다르다(WKWebView/WebView2/WebKitGTK) — 한 곳에서 멀쩡한 화면이 다른 OS에선 미세하게 다를 수 있다. 로컬에서 직접 빌드하려면 결국 Rust 툴체인 + 플랫폼 SDK가 필요하다(그래서 온라인 빌드가 존재한다). 마지막으로 라이선스가 GPL-3.0이라, 코드를 가져다 쓸 땐 예외 조항(LICENSE-EXCEPTION)을 확인해야 한다.
package.json · src-tauri/Cargo.toml · bin/ CLI 소스에서 실제로 확인한 구성.
Pake는 두 개의 다른 세계가 맞물려 돈다. ① 사용자가 만지는 CLI(TypeScript로 작성, Rollup으로 dist/cli.js로 번들) 와, ② 실제 앱이 되는 Tauri 셸(Rust로 작성, src-tauri/). CLI가 "설계도와 옵션"을 준비하면, Tauri가 그걸 받아 진짜 네이티브 앱으로 컴파일한다. 계층별로 본다.
| 구성요소 | 무엇 | 역할 |
|---|---|---|
| commander | CLI 인자 파서 | pake <url> --name --icon … 옵션을 해석. helpers/cli-program.ts. |
| prompts / ora / chalk | 대화형 입력·스피너·색 출력 | 옵션 누락 시 되묻고, 빌드 진행을 예쁘게 표시. |
| icon-gen / sharp | 아이콘 생성·이미지 처리 | 준 이미지를 .icns/.ico/png 세트로 변환(utils/icon-source.ts). |
| execa / fs-extra | 외부 명령 실행·파일 조작 | tauri build를 호출하고 설정 파일을 써 넣는다. |
| Rollup + TS | CLI 번들러 | TypeScript bin/을 단일 dist/cli.js로 묶어 npm에 배포. |
| 구성요소 | 무엇 | 역할 |
|---|---|---|
| Tauri 2.10 | 웹→데스크탑 프레임워크 | OS 웹뷰를 띄우고 창·메뉴·트레이·IPC를 관리. Pake 앱의 뼈대. |
| tauri-plugin-* | 공식 플러그인 묶음 | window-state(창 위치 기억)·global-shortcut(단축키)·shell·http·opener·single-instance(중복 실행 방지)·notification·oauth. |
| serde / serde_json | 직렬화 | pake.json 같은 설정을 Rust 구조체로 읽어들임(app/config.rs). |
| tokio | 비동기 런타임 | 타이머·비동기 작업 처리. |
| objc2 (macOS) | 맥 네이티브 연동 | 독 타일·NSApplication 등 맥 전용 동작(조건부 컴파일). |
로컬 빌드는 tauri build가 Rust를 컴파일해 플랫폼별 설치파일을 만든다(release 프로필은 opt-level="z"·lto·strip으로 바이너리 크기를 최소화). 환경이 없는 사용자를 위해 GitHub Actions 온라인 빌드(action.yml·.github/)가 있어, 폼에 URL만 넣으면 클라우드에서 세 OS용 앱을 구워 준다. Docker 빌드(Dockerfile)도 제공.
먼저 전체 그림을 한 장으로 본 뒤, "pake 명령 한 줄이 앱이 되기까지"를 끝까지 따라간다.
Pake의 일은 "URL + 옵션 → 네이티브 설치파일" 이라는 변환이다. 이걸 두 단계로 나눠 보면 머리에 잘 들어온다. (1) CLI 단계: 사용자 입력을 받아 아이콘을 만들고, Tauri가 읽을 설정 파일(tauri.conf.json·pake.json)을 채운다. (2) 빌드 단계: 그 설정을 박은 src-tauri/를 tauri build로 컴파일해 설치파일을 뽑는다. 실행된 앱은 OS 웹뷰로 URL을 띄우고, Rust 셸이 단축키·창·주입을 관리한다. 부품 이름보다 숲을 먼저 보자.
url을 띄울지, 타이틀바를 숨길지(hide_title_bar), 활성화 단축키(activation_shortcut), 트레이 표시, JS/CSS inject 목록 등을 담는다. CLI가 사용자 옵션을 이 파일들에 써 넣으면, Rust가 시작할 때 읽어 그대로 창을 만든다 — "설정이 곧 앱의 성격"이다.pake https://x.com --name X 한 줄 뒤에서 벌어지는 일을 순서대로 풀면(실제 bin/cli.ts → BuilderProvider 흐름):
// CLI가 URL과 옵션을 받은 뒤
1. 옵션 해석 cli.ts → options/index → URL·이름·아이콘·창설정 정리(commander)
2. 아이콘 준비 utils/icon : 준 이미지 → .icns/.ico/png (없으면 기본 아이콘)
3. 설정 주입 helpers/tauriConfig : 옵션을 pake.json + tauri.conf.json 에 병합
4. 빌더 선택 BuilderProvider.create() → 현재 OS에 맞는 Mac/Win/LinuxBuilder
5. 빌드 실행 builder.prepare()(rust 점검) → builder.build(url)(execa로 tauri build)
6. 산출물 target/ 아래 .dmg/.msi/.deb 설치파일 생성 → 경로 안내
핵심 관례 하나 — Pake는 src-tauri 프로젝트를 매번 새로 만들지 않는다. 레포에 이미 있는 src-tauri/ 템플릿에 설정값만 갈아 끼워 빌드한다. 그래서 "여러 사이트를 각각 다른 앱으로" 만들 때도, 바뀌는 건 pake.json의 URL·창 옵션·주입 목록뿐이다. 빌더(BaseBuilder → 플랫폼별 서브클래스)는 이 공통 흐름을 정의하고, OS별 차이(서명·번들 포맷)만 각자 처리한다 — 전형적인 전략 패턴(Strategy Pattern)이다.
설치한 앱을 켜면 Rust 진입점(src-tauri/src/lib.rs, 332줄)이 돈다. 여기서 ① 창을 만들고(app/window.rs), ② 단축키를 등록하고(set_global_shortcut), ③ 트레이 아이콘을 올리고(set_system_tray), ④ 플러그인들(창 위치 기억·중복 실행 방지 등)을 붙인 뒤, ⑤ OS 웹뷰에 URL을 띄운다. 그리고 pake.json의 inject 목록에 있던 JS/CSS를 페이지에 주입해 광고를 가리거나 단축키를 덧붙인다. "겉은 웹, 속은 네이티브 셸"이 협력하는 구조다.
둘 다 "웹을 앱으로"지만 작동 원리가 다르다. Electron은 크롬을 앱에 넣어 어디서나 똑같이 렌더한다. Pake(Tauri)는 OS 웹뷰를 빌려 가벼운 대신, 렌더링이 OS마다 미묘하게 다를 수 있다. "내 맥에선 완벽한데 친구 윈도우에선 폰트가 다르다" 같은 일이 생길 수 있으니, 배포 전 각 OS에서 한 번씩 확인하는 게 안전하다.
크게 두 덩어리 — CLI(bin/)와 Tauri 앱(src-tauri/). 큰 것만 본다.
레포를 열면 압도될 수 있지만, 실은 "명령을 받는 곳(bin)"과 "앱이 되는 곳(src-tauri)" 두 축만 잡으면 된다. 나머지(docs·tests·icons)는 보조다.
| 위치 | 한 줄 역할 |
|---|---|
| bin/cli.ts | 모든 것의 시작점. URL·옵션을 받아 빌더에 넘긴다. 여기부터 읽으면 흐름이 보인다. |
| bin/builders/BaseBuilder.ts | 빌드 공통 절차(prepare→build). OS별 빌더가 이걸 상속. |
| bin/helpers/tauriConfig.ts | 사용자 옵션을 tauri.conf.json/pake.json에 병합하는 다리. |
| src-tauri/src/lib.rs | 실행된 앱의 본체. 창·트레이·단축키·플러그인을 세팅하고 웹뷰를 띄움. |
| src-tauri/pake.json | 앱의 성격을 정하는 파일. URL·타이틀바·단축키·JS/CSS 주입 목록. |
| docs/cli-usage.md | 옵션 전체 레퍼런스. "무엇을 커스터마이즈할 수 있나"의 정답지. |
| action.yml | 환경 없이 클라우드에서 앱을 굽는 온라인 빌드 정의. |
이 레포 한 채로 "CLI 설계 + Tauri 데스크탑 + 크로스플랫폼 빌드"를 한 번에 본다.
Pake는 규모가 크지 않으면서도, 실무에서 자주 만나는 주제들이 깔끔하게 모여 있어 공부 소재로 좋다. 기술별로 무엇을 건질지 짚는다.
Tauri 앱이 어떻게 창을 만들고, 시스템 트레이를 올리고, 전역 단축키를 잡고, 플러그인을 붙이는지 src-tauri/src/lib.rs 한 파일에서 다 볼 수 있다. Electron 대안으로서 Tauri를 배우기에 살아 있는 최고의 예제다.
실습: pake.json의 hide_title_bar·activation_shortcut을 바꿔 빌드하고, 창 동작이 어떻게 달라지는지 관찰.
bin/cli.ts가 옵션을 받고, BuilderProvider가 현재 OS에 맞는 Mac/Win/LinuxBuilder를 골라 주는 구조는 전략 패턴의 교과서적 사례다. "공통 흐름은 부모(BaseBuilder), 차이는 자식"이라는 객체지향 설계를 실코드로 익힌다.
실습: --help 출력을 분석해 옵션이 어디서 정의되는지(options/) 따라가 보기.
같은 소스가 .dmg/.msi/.deb로 나뉘는 과정, 그리고 Cargo.toml의 [profile.release]에서 opt-level="z"·lto·strip으로 바이너리를 어떻게 줄이는지를 본다. 배포·최적화의 실전 감각을 키운다.
실습: release 프로필 옵션을 바꿔 빌드하고 결과 바이너리 크기를 비교(pnpm analyze = cargo bloat).
광고 제거·단축키·스타일 커스터마이징은 모두 페이지에 스크립트/스타일을 주입해 구현된다(pake.json의 inject). 브라우저 확장 프로그램이 동작하는 원리와 같아서, "콘텐츠 스크립트" 개념을 자연스럽게 배운다.
실습: 간단한 CSS 파일로 특정 사이트의 배너를 display:none 처리해 주입해 보기.
action.yml과 워크플로가 어떻게 매트릭스 빌드(맥·윈·리눅스 러너)를 돌려 산출물을 만드는지 본다. CI/CD와 릴리스 자동화의 실전 템플릿으로 그대로 활용 가능하다.
실습: 레포를 포크해 Actions 탭에서 온라인 빌드를 직접 돌려 보고 산출물(아티팩트)을 내려받기.
"앱을 쓰는 것"과 "앱을 만드는 것(로컬 빌드)"의 요구가 다르다.
Pake는 추론 모델이 아니라 빌드 도구라 GPU·고사양이 필요 없다. 다만 "이미 구워진 앱을 쓰는 사람"과 "직접 빌드하는 사람"의 요구사항이 갈린다. 직접 빌드는 Rust 툴체인 + 플랫폼 SDK가 필요하고, 그게 부담이면 온라인 빌드로 우회하면 된다.
| 항목 | 요구사항 |
|---|---|
| 완성 앱 실행 | 해당 OS만 있으면 됨. 맥은 시스템 WKWebView, 윈도우는 WebView2 런타임(최신 윈도우는 기본 포함), 리눅스는 WebKitGTK. |
| CLI 설치 | Node.js 18 이상 + npm/pnpm. npm install -g pake-cli. |
| 로컬 빌드 | Rust 툴체인(MSRV 1.85) + Tauri 사전요구(플랫폼 SDK). 맥=Xcode CLT, 윈도=MSVC/WebView2, 리눅스=webkit2gtk 등. |
| 패키지 매니저 | pnpm 10.x 권장(레포 개발 시). 일반 사용은 전역 설치 CLI로 충분. |
| 온라인 빌드(대안) | 로컬 환경 불필요 — GitHub 계정 + 포크만 있으면 Actions가 세 OS 앱을 빌드. |
| 결과물 크기 | 보통 ≈5MB(Electron 대비 ~20배 작음). 네트워크는 대상 사이트가 온라인을 요구하면 필요. |
| GPU | 불필요. |
가장 빠른 출발점은 빌드를 건너뛰고 README의 "Popular Packages"에서 완성 앱 하나를 받아 실행해 보는 것이다. 그다음 npm install -g pake-cli로 CLI를 깔고 좋아하는 사이트 하나를 직접 구워 보면, 도구의 가치가 단번에 와닿는다.
"완성 앱 받기"는 1분, "내 앱 굽기·주입"은 한나절. 난이도 순으로.
README 표에서 Twitter나 DeepSeek 앱을 받아 설치한다. 독에 뜨는 아이콘, 단축키, 창 동작을 브라우저 탭과 비교해 본다. "웹을 앱으로"가 어떤 느낌인지 먼저 체감.
npm install -g pake-cli 후 pake https://news.ycombinator.com --name HN처럼 한 줄로 앱을 만든다. --icon으로 아이콘도 바꿔 본다. 생성된 설치파일을 실행해 확인.
--hide-title-bar(몰입형)와 --activation-shortcut(전역 단축키)을 줘서 앱을 다시 굽는다. docs/cli-usage.md의 옵션 표를 참고해 창 크기·항상 위 등을 조합해 본다.
pake.json 설정이 실행 시 창 동작으로 어떻게 이어지는지 이해. "설정이 곧 앱 성격"을 체감.대상 사이트의 거슬리는 요소를 개발자도구로 찾아, 그걸 숨기는 CSS를 작성해 주입(inject)한다. 앱을 다시 빌드해 배너가 사라졌는지 확인. 브라우저 확장과 같은 원리를 직접 구현.
레포를 포크하고 Actions에서 빌드 워크플로를 돌려 맥·윈·리눅스 산출물을 한 번에 뽑는다. action.yml과 워크플로 YAML을 읽어 매트릭스 빌드가 어떻게 구성되는지 파악.
레포를 클론해 src-tauri/src/lib.rs의 트레이 메뉴나 단축키 등록 부분을 읽고, 메뉴 항목을 하나 추가하거나 기본 창 크기를 바꿔 로컬 빌드한다. Tauri 앱 내부를 직접 만지는 단계.
Pake를 100% 소화하기 위한 6주 코스(주당 5~7시간 가정).
| 주차 | 주제 | 학습 자료 / 할 일 |
|---|---|---|
| 1주차 | 웹→앱 개념 · Tauri vs Electron | WebView·번들 크기 차이 정리. Popular Package 실행 + CLI로 첫 앱 굽기. 실습 1·2. |
| 2주차 | Pake CLI 옵션 마스터 | docs/cli-usage.md 정독. 창·아이콘·단축키 옵션 조합 빌드. 실습 3. |
| 3주차 | JS/CSS 주입 · 콘텐츠 스크립트 | pake.json의 inject 구조 분석. 광고 제거 CSS 작성. 실습 4. |
| 4주차 | Tauri 앱 내부(Rust) | src-tauri/src/lib.rs·app/ 읽기. 창/트레이/단축키 API 이해. 실습 6 준비. |
| 5주차 | CLI 아키텍처(전략 패턴) | bin/ 전체 흐름 추적: cli.ts → BuilderProvider → 플랫폼 빌더. 옵션→설정 병합 경로. |
| 6주차 | 크로스플랫폼 빌드 · CI/CD | release 프로필 최적화, GitHub Actions 매트릭스 빌드. 세 OS 산출물 만들기. 실습 5. |
이 문서와 레포에 등장한 용어를 한자리에.
| 용어 | 의미 |
|---|---|
| Pake | 웹페이지를 한 줄 명령으로 가벼운 데스크탑 앱으로 만드는 CLI 도구. Tauri 기반. |
| Tauri | OS 내장 웹뷰 + Rust로 데스크탑 앱을 만드는 프레임워크. Electron보다 훨씬 가벼움. |
| Electron | 크롬+Node를 앱마다 번들하는 데스크탑 프레임워크. 무겁지만 어디서나 동일 렌더. |
| WebView | 앱 안에 박는 "브라우저 화면 한 조각". 맥=WKWebView·윈도=WebView2·리눅스=WebKitGTK. |
| CLI | 터미널에서 명령어로 쓰는 프로그램. Pake의 본체(pake <url>). |
| pake.json | Pake 전용 앱 설정. URL·타이틀바·단축키·트레이·JS/CSS 주입 목록. |
| tauri.conf.json | Tauri 표준 설정. 앱 이름·식별자·창 기본값·번들 형식. |
| inject (주입) | 실행 중인 페이지에 JS/CSS를 끼워 넣어 광고 제거·단축키·스타일을 덧입히는 기능. |
| BuilderProvider / BaseBuilder | 현재 OS에 맞는 빌더를 고르는 구조(전략 패턴). 공통 흐름은 BaseBuilder. |
| 전략 패턴(Strategy) | "공통 흐름은 부모, 차이는 자식"으로 분기하는 객체지향 설계. Pake의 OS별 빌더가 예. |
| global-shortcut | 앱이 비활성 상태여도 작동하는 전역 단축키. Tauri 플러그인으로 등록. |
| single-instance | 같은 앱이 중복 실행되지 않게 막는 Tauri 플러그인. |
| online build(온라인 빌드) | 로컬 환경 없이 GitHub Actions로 세 OS 앱을 클라우드에서 굽는 방식. |
| release profile | Cargo의 배포 빌드 설정. opt-level="z"·lto·strip으로 바이너리 최소화. |
| MSRV | Minimum Supported Rust Version. Pake는 Rust 1.85 이상 필요. |
| GPL-3.0 | Pake의 라이선스. 코드 재사용 시 동일 라이선스 의무(생성 앱은 예외 조항 참고). |
원문·문서·관련 기술 더 파기.