본문 바로가기
Frontend2026년 3월 30일9분 읽기

Electron 대안 Tauri 심화 — Rust 플러그인과 시스템 API

YS
김영삼
조회 381

Tauri 심화 개발

Tauri는 Rust 기반 데스크톱 앱 프레임워크로, Electron 대비 10배 작은 번들 크기와 낮은 메모리 사용량이 특징입니다. Rust의 강력한 시스템 접근 능력을 활용한 플러그인 개발을 살펴봅니다.

Tauri 커맨드 (Rust → JS 브릿지)

use tauri::command;
use std::fs;
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
struct FileInfo {
    name: String,
    size: u64,
    is_dir: bool,
    modified: String,
}

#[command]
fn list_directory(path: String) -> Result<Vec<FileInfo>, String> {
    let entries = fs::read_dir(&path)
        .map_err(|e| format!("디렉토리 읽기 실패: {}", e))?;

    let mut files = Vec::new();
    for entry in entries {
        let entry = entry.map_err(|e| e.to_string())?;
        let metadata = entry.metadata().map_err(|e| e.to_string())?;

        files.push(FileInfo {
            name: entry.file_name().to_string_lossy().to_string(),
            size: metadata.len(),
            is_dir: metadata.is_dir(),
            modified: format!("{:?}", metadata.modified().unwrap_or(
                std::time::SystemTime::UNIX_EPOCH
            )),
        });
    }

    files.sort_by(|a, b| a.name.cmp(&b.name));
    Ok(files)
}

#[command]
async fn read_file_content(path: String) -> Result<String, String> {
    tokio::fs::read_to_string(&path)
        .await
        .map_err(|e| format!("파일 읽기 실패: {}", e))
}

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

프론트엔드에서 호출

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

interface FileInfo {
  name: string;
  size: number;
  is_dir: boolean;
  modified: string;
}

async function loadDirectory(path: string) {
  try {
    const files = await invoke<FileInfo[]>('list_directory', { path });
    return files;
  } catch (error) {
    console.error('Error:', error);
    return [];
  }
}

Tauri 플러그인 작성

use tauri::{
    plugin::{Builder, TauriPlugin},
    Manager, Runtime,
};

#[tauri::command]
fn copy_to_clipboard(text: String) -> Result<(), String> {
    use clipboard::{ClipboardContext, ClipboardProvider};
    let mut ctx: ClipboardContext = ClipboardProvider::new()
        .map_err(|e| e.to_string())?;
    ctx.set_contents(text)
        .map_err(|e| e.to_string())
}

#[tauri::command]
fn read_clipboard() -> Result<String, String> {
    use clipboard::{ClipboardContext, ClipboardProvider};
    let mut ctx: ClipboardContext = ClipboardProvider::new()
        .map_err(|e| e.to_string())?;
    ctx.get_contents()
        .map_err(|e| e.to_string())
}

pub fn init<R: Runtime>() -> TauriPlugin<R> {
    Builder::new("clipboard")
        .invoke_handler(tauri::generate_handler![
            copy_to_clipboard,
            read_clipboard,
        ])
        .build()
}

시스템 트레이와 글로벌 단축키

use tauri::{
    menu::{Menu, MenuItem},
    tray::{TrayIconBuilder, TrayIconEvent},
    Manager,
};

fn main() {
    tauri::Builder::default()
        .setup(|app| {
            let quit = MenuItem::with_id(app, "quit", "종료", true, None::<&str>)?;
            let show = MenuItem::with_id(app, "show", "보이기", true, None::<&str>)?;
            let menu = Menu::with_items(app, &[&show, &quit])?;

            TrayIconBuilder::new()
                .icon(app.default_window_icon().unwrap().clone())
                .menu(&menu)
                .on_menu_event(|app, event| match event.id.as_ref() {
                    "quit" => app.exit(0),
                    "show" => {
                        if let Some(window) = app.get_webview_window("main") {
                            window.show().unwrap();
                            window.set_focus().unwrap();
                        }
                    }
                    _ => {}
                })
                .build(app)?;

            Ok(())
        })
        .run(tauri::generate_context!())
        .expect("error while running application");
}

Electron vs Tauri 비교

항목ElectronTauri
번들 크기~150MB+~3-10MB
메모리 사용~150MB+~30-50MB
백엔드 언어Node.jsRust
렌더링 엔진Chromium시스템 WebView
보안 모델느슨함권한 기반 (엄격)
성숙도높음성장 중
  • Tauri v2부터 iOS/Android 모바일 앱도 지원
  • Rust의 메모리 안전성으로 보안 취약점 대폭 감소
  • 권한 시스템(tauri.conf.json)으로 API 접근을 세밀하게 제어
  • 시스템 WebView 사용으로 번들 크기와 메모리 사용량 대폭 절감
  • Rust 학습 곡선이 있지만, JS/TS 프론트엔드는 그대로 사용 가능

댓글 0

아직 댓글이 없습니다.
Ctrl+Enter로 등록