콘텐츠로 이동
Tauri

아이솔레이션 패턴(Isolation Pattern)

아이솔레이션(분리, 격리) 패턴은 프론트엔드에서 전송된 Tauri API 메시지가 Tauri 코어부에 도달하기 전에 JavaScript를 사용하여 가로채고 변경하는 방법입니다. 아이솔레이션 패턴으로 삽입되는 안전한 JavaScript 코드는 아이솔레이션 애플리케이션이라고 합니다.

아이솔레이션 패턴의 목적은 Tauri 코어부에 대한 원치 않거나 악의적인 프론트엔드 호출로부터 애플리케이션을 보호하기 위한 메커니즘을 개발자에게 제공하는 것입니다. 아이솔레이션 패턴이 필요하게 된 것은 프론트엔드에서 실행되는 신뢰할 수 없는 콘텐츠로 인해 발생하는 위협에 대응하기 위해 만들어졌습니다. 이러한 위협은 많은 종속성을 가진 애플리케이션에서 흔히 볼 수 있는 사례입니다. 애플리케이션이 마주칠 수 있는 많은 위협 원인의 목록은 보안: 위협 모델을 참조하십시오.

위의 가장 큰 위협 모델은 “개발 시 위협”이었지만, 이러한 위협은 아이솔레이션 패턴을 설계할 때 염두에 두었던 것입니다. 많은 프론트엔드 빌드 도구가 종종 깊이 중첩된 수십(또는 수백) 개의 종속성으로 이루어져 있을 뿐만 아니라, 복잡한 애플리케이션 측에도 수많은 (이 또한 종종 깊이 중첩된) 종속성이 있을 수 있으므로 최종 출력 버전에 번들로 제공됩니다.

Tauri는 아이솔레이션 패턴을 사용할 수 있는 경우 항상 사용하는 것을 강력히 권장합니다. 아이솔레이션 애플리케이션에서는 프론트엔드의 모든 메시지를 “캡처”(인터셉트)하므로 아이솔레이션 패턴이 항상 사용됩니다.

또한 Tauri는 외부 Tauri API를 사용할 때 항상 애플리케이션을 “잠금”(록다운)할 것을 강력히 권장합니다. 앱 개발자는 안전한 아이솔레이션 애플리케이션을 이용하여 IPC 입력을 검증하고, 그 입력 내용이 확실히 예상되는 매개변수 범위 내에 있는지 확인합니다. 사례로는 파일 읽기 또는 쓰기 호출이 해당 애플리케이션의 예상치 못한 위치의 경로에 액세스하려고 하지 않는지 확인하거나, Tauri API의 “HTTP 페치 콜”이 “Origin 헤더”에 해당 애플리케이션이 예상하는 것만 설정하고 있는지 확인하는 것입니다.

하지만 프론트엔드의 모든 메시지를 캡처하기 때문에, 상시 동작 API, 예를 들어 Events 등에서도 작동합니다. 일부 이벤트에서는 앱 고유의 Rust 코드로 작업을 실행시킬 가능성이 있으므로, 그에도 유사한 검증 방법으로 대응할 수 있습니다.

아이솔레이션 패턴에서 중요한 것은 프론트엔드와 Tauri Core(타우리 코어부) 사이에 안전한 애플리케이션을 삽입하여 IPC 수신 메시지를 캡처하고 수정하는 것입니다. 이는 <iframe>의 샌드박스 기능(격리 기능)을 사용하여 메인 프론트엔드 애플리케이션과 병행하여 JavaScript를 안전하게 실행함으로써 실현됩니다. Tauri는 페이지 로드 중에 아이솔레이션 패턴을 발동하여 Tauri Core에 대한 모든 IPC 호출을 직접이 아닌 샌드박스화(격리화)된 아이솔레이션 애플리케이션을 통해 강제로 라우팅을 전환합니다. Tauri Core에 전달될 메시지가 준비되면, 메시지는 브라우저 구현의 SubtleCrypto를 사용하여 암호화되어 메인 프론트엔드 애플리케이션으로 반환됩니다. 프론트엔드로 돌아오자마자 메시지는 직접 Tauri Core로 전달되어 거기서 평소와 같이 복호화되어 읽힙니다.

누군가가 애플리케이션의 특정 버전의 키를 수동으로 읽고 암호화 후 해당 키를 사용하여 메시지를 변경할 수 없도록 하기 위해, 애플리케이션이 실행될 때마다 새로운 키가 생성됩니다.

동작 흐름을 알기 쉽게 하기 위해, 아이솔레이션 패턴의 IPC 메시지가 Tauri Core로 전송될 때 실행되는 대략적인 절차를 순서 있는 목록으로 아래에 나타냅니다:

  1. Tauri의 IPC 핸들러가 메시지를 받습니다
  2. IPC 핸들러 → 아이솔레이션 애플리케이션
  3. [sandbox] 아이솔레이션 애플리케이션의 후크가 실행되어 메시지를 변경할 수 있습니다.
  4. [sandbox] 메시지는 “실행 시 생성되는 키”를 사용하여 AES-GCM으로 암호화됩니다
  5. [encrypted] 아이솔레이션 애플리케이션 → IPC 핸들러
  6. [encrypted] IPC 핸들러 → Tauri Core

참고: 화살표(→)는 메시지 전달(패싱)을 나타냅니다.

안전한 아이솔레이션 애플리케이션은 메시지 암호화가 이루어지기 때문에, 아무것도 하지 않는 경우에도 브라운필드 패턴과 비교하여 추가적인 오버헤드 비용이 발생합니다. (적절한 성능을 유지하기 위해 신중하게 유지 관리되고 종속성도 적을) 성능 중심의 애플리케이션을 제외하면, 대부분의 애플리케이션은 비교적 작고 AES-GCM 암호화 방식도 비교적 빠르기 때문에 IPC 메시지의 암호화/복호화 실행 시 비용을 의식할 필요는 없습니다. 만약 AES-GCM에 익숙하지 않더라도, 여기서 관련된 것은 그것이 SubtleCrypto에 포함된 유일한 인증 모드 알고리즘이며, 아마도 “TLS 암호화 프로토콜” 내부에서 이미 매일 사용하고 있다는 것뿐입니다.

Tauri 애플리케이션이 시작될 때마다 한 번, 암호화된 안전한 키도 생성되지만, 시스템이 이미 충분한 엔트로피(랜덤성)를 갖추고 있어 즉시 충분한 난수를 반환한다면 이 처리에는 보통 눈치채지 못합니다. 이는 “데스크톱 환경”에서는 매우 일반적입니다. “헤드리스 환경”에서 WebDriver와의 통합 테스트 등을 실행하는 경우, 운영 체제에 엔트로피 생성 서비스<번역 주: “난수 생성” 기능>가 포함되어 있지 않은 경우에는 haveged와 같은 어떤 엔트로피 생성 서비스를 설치하는 것을 권장합니다. Linux 5.6 (2020년 3월) 버전부터 추측 실행에 의한 엔트로피 생성이 포함되었습니다.

아이솔레이션 패턴에는 플랫폼과의 불일치로 인해 발생하는 몇 가지 제한 사항이 있습니다. 가장 중대한 제한은 Windows의 샌드박스화된 <iframes> 내에 외부 파일이 올바르게 로드되지 않는 것입니다. 이 때문에 아이솔레이션 애플리케이션과 관련된 스크립트의 내용을 가져와 인라인으로 삽입하는, 빌드 시 간단한 스크립트 인라인화 절차를 구현했습니다. 즉, 이는 <script src="index.js"></script>와 같은 파일의 일반적인 번들, 또는 단순한 삽입은 여전히 정상적으로 작동하지만, ES Modules(ECMAScript Modules)와 같은 새로운 메커니즘은 잘 로드되지 않는다는 것을 의미합니다.

아이솔레이션 애플리케이션의 목적은 개발 시 위협으로부터 보호하는 것이므로, 아이솔레이션 애플리케이션은 가능한 한 단순하게 유지하는 것을 강력히 권장합니다. 종속성을 최소한으로 유지하도록 노력할 뿐만 아니라, 필요한 빌드 절차를 최소한으로 줄이는 것을 검토해야 합니다. 이를 통해 프론트엔드 애플리케이션을 덮고 있는 아이솔레이션 애플리케이션에 대한 공급망 공격에 대해 걱정할 필요가 없어집니다.

다음 예에서는 작은 “hello-world”와 같은 아이솔레이션 애플리케이션을 만들고, 그것을 가상으로 기존 Tauri 애플리케이션에 연결하는 것을 가정합니다. 이 앱에서는 통과하는 메시지의 검증은 수행되지 않고, WebView 콘솔에 내용이 출력될 뿐입니다.

이 사례의 목적을 위해, tauri.conf.json과 같은 디렉토리에 있다고 가정합니다. 기존 Tauri 애플리케이션의 distDir../dist로 설정되어 있습니다.

../dist-isolation/index.html:

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Isolation Secure Script</title>
</head>
<body>
<script src="index.js"></script>
</body>
</html>

../dist-isolation/index.js:

window.__TAURI_ISOLATION_HOOK__ = (payload) => {
// 아무것도 검증하거나 수정하지 않고, 그냥 hook에서 내용을 인쇄하기만 합니다.
console.log('hook', payload);
return payload;
};

이제 아이솔레이션 패턴을 사용하도록 tauri.conf.json설정을 변경하고, 부트 처리 경로를 브라운필드 패턴에서 아이솔레이션 패턴으로 전환하기만 하면 됩니다.

메인 프론트엔드 distDir../dist로 설정되어 있다고 가정합니다. 또한, 아이솔레이션 애플리케이션을 ../dist-isolation에 출력합니다.

{
"build": {
"distDir": "../dist"
},
"app": {
"security": {
"pattern": {
"use": "isolation",
"options": {
"dir": "../dist-isolation"
}
}
}
}
}

© 2025 Tauri Contributors. CC-BY / MIT