외부 바이너리 포함
애플리케이션에 기능을 추가하거나 사용자가 추가 종속성(Node.js나 Python 등)을 설치하지 못하게 하려면 외부 바이너리를 포함해야 할 수 있습니다. 이러한 바이너리를 “사이드카 sidecar
”라고 합니다.
바이너리는 모든 프로그래밍 언어로 작성된 실행 파일입니다. 일반적인 사용 예로는 pyinstaller
를 사용하여 번들된 Python CLI 애플리케이션이나 API 서버 등이 있습니다.
원하는 바이너리를 번들링하려면 tauri.conf.json
의 tauri > bundle
객체에 externalBin
속성을 추가합니다.
externalBin
설정에는 절대 경로 또는 상대 경로를 사용하여 대상 바이너리를 지정하는 “문자열 목록”이 필요합니다.
다음은 “사이드카” 설정을 설명하기 위한 “Tauri 설정”의 발췌(스니펫)입니다:
{ "bundle": { "externalBin": [ "/absolute/path/to/sidecar", "../relative/path/to/binary", "binaries/my-sidecar" ] }}
지원되는 모든 아키텍처에서 외부 바이너리가 작동하도록 하려면 지정된 경로에 “동일한 이름”과 “접미사 -$TARGET_TRIPLE
”(대상 트리플)을 가진 바이너리가 있어야 합니다.
예를 들어, "externalBin": ["binaries/my-sidecar"]
의 경우, Linux에서는 실행 파일 “src-tauri/binaries/my-sidecar-x86_64-unknown-linux-gnu
”가, Apple Silicon을 탑재한 Mac OS에서는 실행 파일 “src-tauri/binaries/my-sidecar-aarch64-apple-darwin
”이 필요합니다.
《번역 주》 대상 트리플 원문은 target triple. Rust에서 크로스 컴파일을 수행할 때 아키텍처를 지정하는 방식으로, 컴파일 대상(target)을 세 가지(triple) 항목 “CPU 제품군 이름”, “제조사 이름”, “OS 이름”으로 지정합니다. 위의 설명 예에서는
aarch64-apple-darwin
과 같이 하이픈으로 연결된 표기법이 사용됩니다.
다음 명령으로 표시되는 “host:
” 속성을 보면 현재 플랫폼의 “접미사 -$TARGET_TRIPLE
”을 알 수 있습니다:
rustc -Vv
대부분의 Unix 시스템에 탑재된 grep
명령과 cut
명령을 사용할 수 있는 경우, 다음 명령으로 대상 트리플을 직접 추출할 수 있습니다:
rustc -Vv | grep host | cut -f2 -d' '
Windows에서는 shell 대신 PowerShell을 사용합니다:
rustc -Vv | Select-String "host:" | ForEach-Object {$_.Line.split(" ")[1]}
다음 예는 대상 트리플을 바이너리에 추가하는 Node.js 스크립트입니다.
import { execSync } from 'child_process';import fs from 'fs';
const extension = process.platform === 'win32' ? '.exe' : '';
const rustInfo = execSync('rustc -vV');const targetTriple = /host: (\S+)/g.exec(rustInfo)[1];if (!targetTriple) { console.error('Failed to determine platform target triple');}fs.renameSync( `src-tauri/binaries/sidecar${extension}`, `src-tauri/binaries/sidecar-${targetTriple}${extension}`);
이 스크립트는 실행되는 아키텍처와 다른 아키텍처용으로 컴파일한 경우 작동하지 않으므로, 자신만의 빌드 스크립트를 만들기 위한 출발점으로 사용하십시오.
Rust 측에서는 tauri_plugin_shell::ShellExt
트레이트를 가져오고 AppHandle에서 shell().sidecar()
함수를 호출합니다:
《번역 주》 트레이트 원문은 trait(성격의 “특징”, “특성”, 유전적인 “형질”을 나타내는 단어). 『Rust 한국어판』에서는 다른 유형에 대해 공통된 동작을 정의하는 것과 같은 설명이 있습니다. “유형의 형질” = “유형질?”
use tauri_plugin_shell::ShellExt;use tauri_plugin_shell::process::CommandEvent;
let sidecar_command = app.shell().sidecar("my-sidecar").unwrap();let (mut rx, mut _child) = sidecar_command .spawn() .expect("Failed to spawn sidecar");
tauri::async_runtime::spawn(async move { // stdout(표준 출력) 등의 이벤트를 읽습니다 while let Some(event) = rx.recv().await { if let CommandEvent::Stdout(line_bytes) = event { let line = String::from_utf8_lossy(&line_bytes); window .emit("message", Some(format!("'{}'", line))) .expect("failed to emit event"); // stdin(표준 입력)에 씁니다 child.write("message from Rust\n".as_bytes()).unwrap(); } }});
이 코드를 Tauri 명령 내에 배치하면 AppHandle을 쉽게 전달할 수 있으며, 빌더 스크립트 내에 AppHandle에 대한 참조를 저장하면 애플리케이션 내 어디에서나 AppHandle에 액세스할 수 있습니다.
“사이드카”를 실행하는 경우, Tauri에서는 자식 프로세스에서 execute
또는 spawn
메서드를 실행할 권한을 “사이드카”에 부여해야 합니다. 이 권한을 부여하려면 파일 <PROJECT ROOT>/src-tauri/capabilities/default.json
으로 이동하여 다음 섹션을 권한 배열에 추가합니다. 앞서 “참고”란에서 설명한 “상대 경로 기술 방법”에 따라 “사이드카”를 기술하는 것을 잊지 마십시오.
{ "permissions": [ "core:default", { "identifier": "shell:allow-execute", "allow": [ { "name": "binaries/app", "sidecar": true } ] } ]}
JavaScript 코드 내에서는 @tauri-apps/plugin-shell
모듈에서 Command
클래스를 가져오고 sidecar
정적 메서드를 사용합니다.
import { Command } from '@tauri-apps/plugin-shell';const command = Command.sidecar('binaries/my-sidecar');const output = await command.execute();
일반적인 명령을 실행하는 경우와 마찬가지로 Sidecar의 명령에 인수를 전달할 수 있습니다.
인수는 정적 static(예: -o
또는 serve
) 또는 동적 dynamic(예: <file_path>
또는 localhost:<PORT>
) 중 하나가 될 수 있습니다. 인수는 호출하는 순서대로 정의합니다. “정적 인수”는 그대로 정의되지만, “동적 인수”는 정규식을 사용하여 정의합니다.
먼저, src-tauri/capabilities/default.json
에 사이드카 명령에 전달해야 하는 인수를 정의합니다:
{ "$schema": "../gen/schemas/desktop-schema.json", "identifier": "default", "description": "Capability for the main window", "windows": ["main"], "permissions": [ "core:default", { "identifier": "shell:allow-execute", "allow": [ { "args": [ "arg1", "-a", "--arg2", { "validator": "\\S+" } ], "name": "binaries/my-sidecar", "sidecar": true } ] } ]}
이제 사이드카 명령을 호출하려면 모든 인수를 배열로 전달하기만 하면 됩니다.
Rust에서는:
use tauri_plugin_shell::ShellExt;#[tauri::command]async fn call_my_sidecar(app: tauri::AppHandle) { let sidecar_command = app .shell() .sidecar("my-sidecar") .unwrap() .args(["arg1", "-a", "--arg2", "any-string-that-matches-the-validator"]); let (mut _rx, mut _child) = sidecar_command.spawn().unwrap();}
JavaScript에서는:
import { Command } from '@tauri-apps/plugin-shell';// 인수 배열은 `capabilities/default.json`에 지정된 것과 완전히 일치해야 합니다.const command = Command.sidecar('binaries/my-sidecar', [ 'arg1', '-a', '--arg2', 'any-string-that-matches-the-validator',]);const output = await command.execute();
【※ 이 한국어판은, 「Jan 06, 2025 영문판」에 근거하고 있습니다】
© 2025 Tauri Contributors. CC-BY / MIT