본문 바로가기
Tech Notes

Tauri로 웹 개발자도 데스크톱 앱 만들기

by miracle-tech 2026. 1. 31.
728x90
반응형

"Next.js로 만든 웹사이트를 5MB짜리 .exe 파일로 만들 수 있다고?"

 


🤔 왜 데스크톱 앱이 필요한가?

웹 개발자인 나는 평소에 React, Next.js로 웹사이트를 만들었다. 그런데 클라이언트가 이런 요청을 했다:

"이거 웹사이트 말고 프로그램으로 만들어주세요. 더블클릭하면 실행되는 거요!"

아... 데스크톱 앱이라니. C++이나 C# 배워야 하나? 아니면 Python으로 PyQt 써야 하나?

그때 발견한 게 Tauri였다.


🎯 Tauri란 무엇인가?

"웹 기술로 데스크톱 앱을 만드는 프레임워크"

간단히 말하면:

React/Vue/Next.js로 만든 웹사이트
         ↓
    Tauri로 빌드
         ↓
Windows/Mac/Linux 실행 파일 (.exe, .dmg, .AppImage)

Electron 아니야?

맞다. 비슷한 도구로 Electron이 있다. VS Code, Discord, Slack 같은 유명한 앱들이 Electron으로 만들어졌다.

그런데 Tauri는 Electron의 진화형이라고 보면 된다.


⚡ Electron vs Tauri 비교

실제로 "Hello World" 앱을 만들어서 비교해봤다.

파일 크기

Electron "Hello World":  147 MB  📦📦📦📦📦📦📦
Tauri "Hello World":       5 MB  📦

30배 차이!

메모리 사용량

Electron:  ~150 MB
Tauri:     ~30 MB

왜 이렇게 차이가 날까?

Electron:

┌─────────────────────────────────┐
│        Electron App             │
├─────────────────────────────────┤
│  Chromium (브라우저 전체 내장)   │  ← 이게 크다!
│  Node.js (런타임 내장)           │
│  내 앱 코드                      │
└─────────────────────────────────┘

Tauri:

┌─────────────────────────────────┐
│         Tauri App               │
├─────────────────────────────────┤
│  OS 기본 WebView 사용           │  ← 이미 설치되어 있음
│  Rust 런타임 (작음)             │
│  내 앱 코드                      │
└─────────────────────────────────┘

Tauri는 OS에 이미 있는 브라우저를 사용한다!

  • Windows: Edge WebView2
  • macOS: Safari WebKit
  • Linux: WebKitGTK

🏗 Tauri 구조

전체 구조

┌─────────────────────────────────────────┐
│           Tauri Desktop App             │
├─────────────────────────────────────────┤
│                                         │
│  ┌───────────────────────────────┐     │
│  │   Frontend (웹 기술)           │     │
│  │   • HTML, CSS, JavaScript      │     │
│  │   • React, Vue, Svelte...      │     │
│  │   • Next.js도 가능!            │     │
│  └───────────┬───────────────────┘     │
│              │ IPC (Inter-Process      │
│              │      Communication)     │
│  ┌───────────▼───────────────────┐     │
│  │   Backend (Rust)               │     │
│  │   • 파일 시스템 접근           │     │
│  │   • 데이터베이스               │     │
│  │   • 시스템 API                 │     │
│  │   • 네이티브 기능              │     │
│  └───────────────────────────────┘     │
│                                         │
└─────────────────────────────────────────┘

IPC (통신) 방식

Frontend에서 Backend 함수 호출:

// Frontend (TypeScript/React)
import { invoke } from '@tauri-apps/api/core';

async function greet() {
  const response = await invoke<string>('greet', {
    name: 'World'
  });
  console.log(response); // "Hello, World!"
}
// Backend (Rust)
#[tauri::command]
fn greet(name: &str) -> String {
    format!("Hello, {}!", name)
}

마치 API 호출하듯이 사용!


🚀 실제로 만들어보기

1. 설치

# Node.js 필요 (18+)
npm create tauri-app@latest

대화형으로 선택:

✔ Project name · my-tauri-app
✔ Choose which language to use for your frontend · TypeScript
✔ Choose your package manager · npm
✔ Choose your UI template · React
✔ Choose your UI flavor · TypeScript

2. 프로젝트 구조

my-tauri-app/
├── src/              # Frontend (React)
│   ├── App.tsx
│   ├── main.tsx
│   └── ...
│
├── src-tauri/        # Backend (Rust)
│   ├── src/
│   │   └── main.rs   # Rust 진입점
│   ├── Cargo.toml    # Rust 의존성
│   └── tauri.conf.json  # Tauri 설정
│
├── package.json      # Node.js 의존성
└── ...

3. 개발 모드 실행

npm run tauri dev

자동으로 일어나는 일:

  1. Rust 백엔드 컴파일
  2. React dev server 시작 (Vite)
  3. 데스크톱 창 열림
  4. Hot Reload 활성화 (코드 수정 시 자동 새로고침)

4. 간단한 기능 추가

Rust 백엔드 (파일 읽기)

// src-tauri/src/main.rs

use std::fs;

#[tauri::command]
fn read_file(path: String) -> Result<String, String> {
    fs::read_to_string(path)
        .map_err(|e| e.to_string())
}

fn main() {
    tauri::Builder::default()
        .invoke_handler(tauri::generate_handler![read_file])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

React 프론트엔드

// src/App.tsx

import { invoke } from '@tauri-apps/api/core';
import { useState } from 'react';

function App() {
  const [content, setContent] = useState('');

  async function handleReadFile() {
    const fileContent = await invoke<string>('read_file', {
      path: '/path/to/file.txt'
    });
    setContent(fileContent);
  }

  return (
    <div>
      <button onClick={handleReadFile}>파일 읽기</button>
      <pre>{content}</pre>
    </div>
  );
}

5. 빌드

npm run tauri build

결과물:

  • Windows: my-tauri-app.exe, my-tauri-app.msi
  • macOS: my-tauri-app.dmg, my-tauri-app.app
  • Linux: my-tauri-app.AppImage, my-tauri-app.deb

💡 실제 사용 사례

1. Screenpipe

  • 기능: 24/7 화면/오디오 녹화 + AI 분석
  • 이유: 백그라운드 실행 필요, 로컬 파일 접근

2. Cap

  • 기능: Loom 대체 화면 녹화 앱
  • 이유: 화면 캡처 API, 로컬 저장

3. Aptakube

  • 기능: Kubernetes 클러스터 관리 UI
  • 이유: kubectl 명령어 실행, 설정 파일 접근

🎨 Next.js와 통합하기

Tauri는 **Next.js SSG(Static Site Generation)**와 완벽하게 호환된다!

설정 방법

// tauri.conf.json
{
  "build": {
    "beforeDevCommand": "npm run dev",
    "beforeBuildCommand": "npm run build",
    "devPath": "http://localhost:3000",
    "distDir": "../out"  // Next.js 빌드 결과물
  }
}
// next.config.js
module.exports = {
  output: 'export',  // SSG 모드
  images: {
    unoptimized: true  // Tauri에서 필요
  }
}

주의: Next.js SSR은 안 됨! SSG만 가능.


🔒 보안

Tauri의 강력한 보안 기능:

1. Allowlist (권한 시스템)

// tauri.conf.json
{
  "tauri": {
    "allowlist": {
      "all": false,  // 모든 API 기본 차단
      "fs": {
        "readFile": true,  // 파일 읽기만 허용
        "writeFile": false,
        "scope": ["$APPDATA/myapp/*"]  // 특정 디렉토리만
      },
      "shell": {
        "open": true  // URL 열기만 허용
      }
    }
  }
}

2. CSP (Content Security Policy)

{
  "tauri": {
    "security": {
      "csp": "default-src 'self'; script-src 'self'"
    }
  }
}

Electron과의 차이:

  • Electron: 기본적으로 모든 권한 허용 (위험)
  • Tauri: 기본적으로 모든 권한 차단 (안전)

⚠️ 단점과 한계

1. 러닝 커브

  • Rust 문법: 처음엔 어려울 수 있음
  • 하지만 간단한 앱은 Rust 몰라도 됨 (템플릿 복사!)

2. 생태계

  • Electron이 훨씬 오래되어서 자료가 많음
  • Tauri는 2019년 시작 (비교적 최신)

3. 플랫폼 차이

  • OS마다 WebView가 다름 → CSS 미묘한 차이 있을 수 있음
  • 철저한 크로스 플랫폼 테스트 필요

4. Next.js SSR 불가

  • SSG만 가능
  • API Routes도 불가
  • Rust 백엔드로 대체해야 함

🎯 언제 Tauri를 쓸까?

✅ Tauri가 좋은 경우

  • 가벼운 데스크톱 앱
  • 파일 시스템 접근 필요
  • 로컬에서만 동작
  • 개인정보 보호 중요
  • 빠른 성능 필요

❌ Tauri가 적합하지 않은 경우

  • 웹으로 충분한 경우 (그냥 웹사이트가 나음)
  • SSR 필수인 경우
  • Rust 배우기 싫은 경우 (Electron 쓰세요)

📊 성능 벤치마크

실제 프로젝트에서 측정:

지표 Electron Tauri 차이

빌드 크기 147 MB 5 MB 30x
메모리 (유휴) 150 MB 30 MB 5x
시작 시간 2.5초 0.8초 3x
CPU (유휴) 2% 0.5% 4x

🚦 시작하기 전 체크리스트

  • [ ] Node.js 18+ 설치
  • [ ] Rust 설치 (curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh)
  • [ ] 웹 개발 경험 (React, Vue 등)
  • [ ] 데스크톱 앱이 정말 필요한지 확인

🔗 유용한 리소스


🎬 마무리

처음엔 "Rust라니 어렵겠지..."라고 생각했는데, 막상 써보니 생각보다 쉬웠다.

웹 개발자라면:

// 이런 코드만 쓸 줄 알면
const result = await invoke('my_function', { param: 'value' });
// Rust는 복붙하고 약간만 수정
#[tauri::command]
fn my_function(param: String) -> String {
    format!("Hello, {}", param)
}

결론:

  • 가볍고 빠른 데스크톱 앱이 필요하다면? → Tauri
  • 기존 Electron 앱이 너무 무겁다면? → Tauri로 마이그레이션 고려
  • 웹 개발자인데 데스크톱 앱 만들고 싶다면? → Tauri부터 시작

5MB짜리 .exe 파일의 매력, 한번 느껴보시길! 🚀


📝 다음 글 예고

다음엔 실제로 "Screenpipe + Tauri로 AI 채팅 앱 만들기" 튜토리얼을 작성해보겠습니다.

  • Screenpipe 백엔드 통합
  • Next.js 채팅 UI
  • Rust로 AI API 호출
  • 단일 .exe 파일로 배포

Stay tuned! 👋

728x90