Electron 애플리케이션 연동 가이드¶
Windows SDK 통합 시에는 네이티브 Bridge 모드를 사용하세요
이 페이지는 Browser RUM이 Session을 독립적으로 관리하고 직접 업로드하는 Web 연동 방식을 설명합니다. Electron 애플리케이션이 Windows RUM SDK를 통합하는 경우 Windows SDK Electron 네이티브 Bridge 연동을 사용하세요. Browser RUM은 Renderer에서 수집 및 직렬화만 담당하며, 실제 애플리케이션 ID, Session, 샘플링, Context, 지속성 및 업로드는 모두 Windows Native Core가 담당합니다. 이 모드에서는 이 페이지의 applicationId, clientToken, site 또는 sessionPersistence 설정을 그대로 사용하지 마세요.
Electron 애플리케이션은 main process와 renderer process로 구성됩니다. RUM SDK는 브라우저 환경에서 실행되므로 renderer process에서만 초기화해야 하며, 창 내 페이지의 방문, 리소스, 요청, 오류 및 사용자 행동 데이터를 수집하는 데 사용됩니다.
이 문서는 현재 SDK의 초기화 파라미터를 기준으로 Electron 애플리케이션의 연동 방식을 설명합니다.
연동 원칙¶
- renderer process에서만 RUM SDK를 초기화하고, main process에서는 초기화하지 마세요.
- 모니터링이 필요한 각
BrowserWindow,BrowserView또는webview에 해당하는 renderer 페이지마다 한 번씩 연동해야 합니다. - 페이지가
file://로 로드되는 경우, 사용 불가능하거나 불안정한 쿠키에 의존하지 않도록sessionPersistence: 'local-storage'를 반드시 사용하세요. - 페이지가
https://로 로드되는 경우 기본 쿠키 세션 전략을 계속 사용할 수 있습니다. 또는local-storage를 통일하여 사용할 수 있지만, RUM과 Logs SDK의 세션 전략이 일치하는지 확인해야 합니다. - 동일한 Electron 애플리케이션이 로컬
file://페이지와 원격http(s)://페이지를 동시에 사용하는 경우, 브라우저 동일 출처 정책에 의해 격리되어 일반적으로 서로 다른 session이 생성됩니다.
권장 연동 방식¶
NPM 연동¶
Webpack, Vite, Rollup 등을 사용하여 renderer 코드를 빌드하는 Electron 애플리케이션에 적합합니다.
renderer 진입 파일에서 초기화합니다:
import { datafluxRum } from '@cloudcare/browser-rum'
datafluxRum.init({
applicationId: '<애플리케이션 ID>',
// Public DataWay 연동
clientToken: '<clientToken>',
site: '<Public DataWay 주소>',
// DataKit을 사용하는 경우 datakitOrigin으로 변경
// datakitOrigin: '<DataKit 도메인 또는 IP>',
service: 'electron-renderer',
env: 'production',
version: '<애플리케이션 버전>',
sessionSampleRate: 100,
trackUserInteractions: true,
// file:// 페이지는 반드시 설정
sessionPersistence: 'local-storage'
})
Session Replay가 필요한 경우:
CDN 연동¶
renderer HTML을 직접 유지 관리하는 애플리케이션에 적합합니다. SDK 파일을 애플리케이션 정적 리소스와 함께 번들로 묶어, 데스크톱 애플리케이션이 오프라인 또는 약한 네트워크 환경에서 원격 CDN에 의존하지 않도록 하는 것을 권장합니다.
<script src="./vendor/dataflux-rum.js" type="text/javascript"></script>
<script>
window.DATAFLUX_RUM &&
window.DATAFLUX_RUM.init({
applicationId: '<애플리케이션 ID>',
clientToken: '<clientToken>',
site: '<Public DataWay 주소>',
service: 'electron-renderer',
env: 'production',
version: window.__APP_VERSION__,
sessionSampleRate: 100,
trackUserInteractions: true,
sessionPersistence: 'local-storage'
})
</script>
renderer 페이지가 항상 https://로 로드되고 쿠키를 사용할 수 있는 경우, sessionPersistence를 설정하지 않아도 됩니다.
main process 예시¶
main process는 창 생성만 담당하며, RUM SDK를 가져오거나 초기화할 필요가 없습니다. 필요한 버전, 채널 등의 정보만 renderer에 전달하는 것을 권장합니다.
const { app, BrowserWindow } = require('electron')
const path = require('path')
function createWindow() {
const win = new BrowserWindow({
width: 1200,
height: 800,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
contextIsolation: true,
nodeIntegration: false
}
})
win.loadFile('index.html')
}
app.whenReady().then(createWindow)
preload.js에서는 안전하고 읽기 전용인 애플리케이션 정보만 노출할 수 있습니다:
const { contextBridge } = require('electron')
const { version } = require('./package.json')
contextBridge.exposeInMainWorld('electronAppInfo', {
version
})
renderer에서 읽어와 RUM 설정에写入합니다:
datafluxRum.init({
applicationId: '<애플리케이션 ID>',
clientToken: '<clientToken>',
site: '<Public DataWay 주소>',
service: 'desktop-app',
env: 'production',
version: window.electronAppInfo.version,
sessionSampleRate: 100,
trackUserInteractions: true,
sessionPersistence: 'local-storage'
})
다중 창 연동¶
애플리케이션이 동시에 여러 창을 여는 경우:
- 각 창의 renderer 페이지에서 RUM SDK를 초기화해야 합니다.
sessionPersistence: 'local-storage'를 사용하는 경우, 여러 창 간의 localStorage 동기화에 극히 짧은 지연이 발생할 수 있습니다.- 초기화 직후 동시에 많은 창을 생성하면 매우 짧은 임시 session이 생성될 수 있습니다. 창 생성과 초기화 사이에 최소 수십 밀리초의 간격을 두거나, 비즈니스 순서에 따라 창을 하나씩 생성하는 것을 권장합니다.
로컬 페이지와 원격 페이지¶
Electron 애플리케이션에서 흔히 볼 수 있는 두 가지 페이지 소스:
| 페이지 소스 | 권장 설정 | 설명 |
|---|---|---|
file:// 로컬 페이지 |
sessionPersistence: 'local-storage' |
쿠키가 신뢰할 수 없으므로 localStorage를 사용하여 session을 저장해야 합니다. |
https:// 원격 페이지 |
기본 쿠키 또는 local-storage |
기본 쿠키를 사용하는 경우, 페이지 도메인과 보안 정책에서 쿠키 쓰기를 허용하는지 확인해야 합니다. |
file://와 https:// 혼합 |
각각 연동하고 각각 분석 | 동일 출처 정책의 영향으로 로컬 페이지와 원격 페이지는 일반적으로 동일한 session을 공유하지 않습니다. |
애플리케이션이 로컬 랜딩 페이지에서 원격 사이트로 이동하는 경우, RUM에서는 두 개의 다른 세션으로 표시됩니다. user.id, service, env, version 필드를 통일하여 연관 분석하는 것을 권장합니다.
API 요청과 분산 추적¶
renderer의 fetch 및 XMLHttpRequest는 브라우저 SDK 로직에 따라 자동으로 수집됩니다. 백엔드 API에 Trace Header를 주입해야 하는 경우, allowedTracingUrls를 설정해야 합니다:
NPM + TypeScript 연동 시, traceType은 browser-core 패키지에서 가져온 TraceType 열거형을 사용합니다:
import { TraceType } from '@cloudcare/browser-core'
import { datafluxRum } from '@cloudcare/browser-rum'
datafluxRum.init({
applicationId: '<애플리케이션 ID>',
clientToken: '<clientToken>',
site: '<Public DataWay 주소>',
service: 'desktop-app',
env: 'production',
version: window.electronAppInfo.version,
sessionPersistence: 'local-storage',
allowedTracingUrls: [
'https://api.example.com',
/https:\/\/.*\.internal-api\.example\.com/
],
traceType: TraceType.DDTRACE
})
CDN 연동은 모듈 가져오기가 없으므로, 해당 유형을 명시적으로 지정할 때는 런타임 값 'ddtrace'를 사용합니다. 설정하지 않으면 기본값으로도 이 값이 사용됩니다.
file:// 페이지 주소는 allowedTracingUrls에 넣지 마세요. 이 설정은 백엔드 API 요청을 매칭하기 위한 것이며, renderer 페이지 자체가 아닙니다.
오류와 SourceMap¶
Electron 로컬 페이지의 오류 스택은 종종 file://로 시작하며, 서버는 공개 URL처럼 SourceMap을 직접 매칭하지 못할 수 있습니다. 다음과 같이 하는 것을 권장합니다:
service,env,version과 빌드 산출물 버전을 일치시키세요.- renderer 산출물에 대한 SourceMap을 생성하고, 릴리스 버전별로 저장하세요.
- 로컬 파일 경로를 수정해야 하는 경우,
beforeSend에서 비즈니스 컨텍스트를 추가하여 추후 검색에 용이하게 할 수 있습니다.
datafluxRum.init({
// ...
beforeSend: (event) => {
if (event.type === 'error') {
event.context = {
...event.context,
electron: true,
rendererUrl: window.location.href
}
}
return true
}
})
CSP와 Worker¶
Session Replay, compressIntakeRequests 또는 캔버스 녹화를 활성화한 경우, SDK에서 Worker를 사용할 수 있습니다. Electron 애플리케이션에서 엄격한 CSP를 설정한 경우, 해당 Worker 출처를 허용해야 합니다.
기본 인라인 Worker는 일반적으로 다음이 필요합니다:
blob:를 허용하지 않는 경우, worker 파일을 애플리케이션 정적 리소스로 번들링하고 동일 출처 주소를 설정하세요:
@cloudcare/browser-rum-slim을 사용하는 경우, 이 패키지에는 Session Replay 및 compressIntakeRequests 압축 기능이 포함되어 있지 않으므로 일반적으로 이 두 기능을 위해 worker를 설정할 필요가 없습니다.
보안 권장사항¶
- main process에서 RUM token이나 기타 민감한 설정을 쓰기 위한 인터페이스를 노출하지 마세요.
preload에서는 애플리케이션 버전, 채널, 빌드 번호 등 필요한 읽기 전용 정보만 노출하세요.contextIsolation: true와nodeIntegration: false를 유지하세요.beforeSend에서 로컬 파일 절대 경로, 사용자 이름 디렉터리 또는 기타 민감한 정보를 보고하지 마세요.- 사용자 입력, 파일 이름, 경로 등의 필드는 사용자 정의 컨텍스트에写入하기 전에 마스킹 처리하세요.
검증 방법¶
연동 후 다음 순서로 검증할 수 있습니다:
- Electron 애플리케이션의 대상 창을 엽니다.
- DevTools Network에서 RUM 업로드 요청이 있는지 확인합니다.
- 페이지 방문, 버튼 클릭, API 요청 및 프론트엔드 오류를 한 번씩 트리거합니다.
view,action,resource,error데이터가 Guance에 전송되는지 확인합니다.- 동일 사용자가 여러 창 또는 로컬/원격 페이지 전환 시 session이 예상대로 동작하는지 확인합니다.
로컬 디버깅 시 임시로 beforeSend에서 이벤트 유형을 출력할 수도 있습니다:
datafluxRum.init({
// ...
beforeSend: (event) => {
console.log('[RUM]', event.type, event)
return true
}
})
자주 묻는 질문¶
main process에 데이터가 없는 이유는 무엇인가요?¶
RUM SDK는 브라우저 측 SDK로, renderer process의 페이지 동작만 수집합니다. main process의 크래시, IPC, 파일 시스템 또는 네이티브 모듈 오류는 애플리케이션 자체의 로그 또는 크래시 수집 방식을 통해 처리해야 합니다.
file:// 페이지에 session이 없는 이유는 무엇인가요?¶
일반적으로 sessionPersistence: 'local-storage'가 설정되지 않았거나, renderer 페이지가 실행되는 환경에서 localStorage가 비활성화되었기 때문입니다. 먼저 해당 설정과 localStorage의 사용 가능 여부를 확인하세요.
로컬 페이지에서 원격 페이지로 이동한 후 session이 변경된 이유는 무엇인가요?¶
file://와 https://는 서로 다른 origin에 속하므로, 브라우저는 동일한 쿠키나 localStorage를 공유하지 않습니다. setUser()를 사용하여 안정적인 사용자 ID를 설정하고, 분석 시 사용자별로 연관시키는 것을 권장합니다.
여러 창에서 매우 짧은 session이 나타나는 이유는 무엇인가요?¶
여러 창을 동시에 초기화할 때, localStorage가 창 간에 동기화되는 데 극히 짧은 지연이 발생할 수 있습니다. 동시에 많은 창을 생성하고 초기화하지 말고, 창 생성 사이에 짧은 간격을 두는 것을 권장합니다.