PWA & Tauri Mobile
이 문서가 답하는 질문: “데스크톱 + 모바일을 한 코드로 가려면 PWA와 Tauri 2.0 중 어느 쪽인가?” 한 줄 답 (Pyramid Top): “PWA는 설치 가능한 웹이고 Tauri 2.0은 작은 binary로 모바일까지 확장한다 — 둘 다 Electron보다 가볍지만, OS 깊은 통합에서 갈린다.”
Why — 왜 존재하는가
Electron은 데스크톱만 한다. 모바일이 함께 필요하면 — 다른 패키지(Capacitor·React Native·Flutter)를 별도 운영하거나, 웹 표준 기반으로 통합해야 한다.
| 옵션 | 코드 1벌? | 설치 가능? | OS 통합 깊이 |
|---|---|---|---|
| Electron + Capacitor | No (별도 배포) | Yes (각각) | 깊음 |
| PWA | Yes | Yes (옵션) | 얕음 |
| Tauri 1.x | No (데스크톱만) | Yes | 깊음 |
| Tauri 2.0 | Yes | Yes | 깊음 |
How — 어떻게 동작하는가
PWA
manifest.json으로 설치 가능 선언.Service Worker로 오프라인 캐시.- 브라우저가 호스트 — 설치돼도 브라우저 엔진 위.
Tauri 2.0 Mobile (2024 GA)
- 같은 Rust 백엔드 + 웹 프론트.
- iOS는 WKWebView, Android는 WebView (System WebView).
- 빌드 결과:
.app/.ipa(iOS),.apk/.aab(Android),.dmg/.exe/.AppImage(데스크톱).
What — 구체 사양·수치·예시
PWA Manifest
{
"name": "My App",
"short_name": "MyApp",
"start_url": "/",
"display": "standalone",
"background_color": "#fff",
"theme_color": "#2c3e50",
"icons": [
{ "src": "/icons/192.png", "sizes": "192x192", "type": "image/png" },
{ "src": "/icons/512.png", "sizes": "512x512", "type": "image/png" }
]
}Service Worker — 오프라인
// sw.js
self.addEventListener('install', (e) => {
e.waitUntil(caches.open('v1').then(c => c.addAll([
'/', '/style.css', '/app.js'
])));
});
self.addEventListener('fetch', (e) => {
e.respondWith(
caches.match(e.request).then(r => r || fetch(e.request))
);
});PWA의 OS API 한계 (iOS Safari 기준)
| API | iOS PWA | Android PWA | Electron | Tauri |
|---|---|---|---|---|
| Notification | ✗ (16.4부터 부분) | ✓ | ✓ | ✓ |
| File System Access | ✗ | ✗ (부분) | ✓ (Node fs) | ✓ (rust) |
| Camera | ✓ | ✓ | ✓ | ✓ |
| Background Sync | ✗ | ✓ | ✓ | ✓ |
| Push (FCM/APNs) | 16.4+ | ✓ | ✓ (커스텀) | ✓ |
| 시스템 트레이 | ✗ | ✗ | ✓ | ✓ |
| 키보드 단축키 (전역) | ✗ | ✗ | ✓ | ✓ |
| 자동 시작 (부팅) | ✗ | ✗ | ✓ | ✓ |
Tauri 2.0 Mobile 빌드
# Android
cargo tauri android init
cargo tauri android dev
cargo tauri android build
# iOS
cargo tauri ios init
cargo tauri ios dev
cargo tauri ios buildTauri 2.0 권한 시스템 (mobile-first 설계)
# tauri.conf.json
{
"tauri": {
"allowlist": {
"all": false,
"fs": {
"readFile": true,
"writeFile": true,
"scope": ["$APPDATA/*", "$DOWNLOAD/*"]
},
"shell": { "execute": false },
"dialog": { "open": true }
}
}
}디폴트 deny + 명시적 allow. Electron이 디폴트 allow + 명시적 deny인 것과 반대.
What-if — 잘못 쓰면
- 함정 1: PWA로 가능하다고 시스템 트레이·전역 단축키를 요구 → 불가능. 사용자가 ★1점 리뷰.
- 함정 2: Tauri 2.0 모바일에서 Electron 패턴 그대로 적용 → BrowserWindow가 없고, IPC도 다르다. 마이그레이션이 재작성에 가까움.
- 함정 3: iOS PWA의 Storage 7일 정책 → 사용자가 1주일 안 쓰면 IndexedDB 삭제. 오프라인 앱은 PWA 부적합.
- 함정 4: PWA를 App Store에 못 올림 → 사용자 발견 채널이 공유 URL뿐.
Insight — 흥미로운 이야기
“Twitter Web App이 PWA 시대의 선도자였다가 후퇴했다”
2017년 Twitter Lite는 PWA로 모바일 웹 경험을 네이티브 수준으로 끌어올린 사례로 유명했다 — 200KB shell + Service Worker로 첫 화면 1초 미만. 그 결과 일부 시장에서 네이티브 앱을 대체하기까지 했다.
그러나 — Twitter는 결국 네이티브 앱으로 회귀했다. 이유는 PWA의 플랫폼 신뢰 문제: 푸시 알림 제약, App Store 부재, OAuth 흐름의 어색함. 같은 시기 Starbucks PWA는 유지되며 거꾸로 성공 사례가 되었다 — 카탈로그 조회 같은 얕은 통합만 필요한 도메인이었기 때문.
교훈 — PWA는 제품 깊이에 매우 민감하다. 얕은 통합 + 광범위한 디바이스면 PWA가 압승, 깊은 OS 통합이 필요하면 네이티브(Electron·Tauri·React Native)가 답. Tauri 2.0 모바일이 그 사이를 노리는 베팅이고, 2024~2025년이 그 베팅의 분기점이다.
요약
- PWA = 얕은 통합이 충분한 도메인의 답.
- Tauri 2.0 = 깊은 통합을 작은 binary로 달성하는 새 답.
- iOS PWA는 여전히 제약이 많다 — 푸시·스토리지·자동 시작 등.
- 결정 기준: OS API 깊이 × 제품 코어 가치.