TrendShift · Electron Desktop App

Streambert — Electron으로
만든 광고 제로 스트리머

IPC 모듈화·세션 분리·m3u8 가로채기·크로스플랫폼 패키징을 한 레포에 다 담은 데스크탑 앱의 안쪽.

truelockmc/streambert · JavaScript · GPL-3.0 · 802★ 2026-05-21
00 — 들어가며Context

먼저, "Electron 데스크탑 앱"이 뭔가?

왜 웹 브라우저가 아니라 데스크탑 앱으로 만드는가.

VS Code, Slack, Discord, Figma 데스크탑 — 우리가 매일 쓰는 데스크탑 앱 상당수가 사실은 Chromium 브라우저 + Node.js로 만들어졌다. 이 조합을 묶어 데스크탑 앱처럼 보이게 해주는 프레임워크가 Electron이다. 웹 기술(HTML/CSS/JS)을 쓰면서도 파일 시스템 접근, OS API, 시스템 트레이, 알림 같은 네이티브 기능을 쓸 수 있다.

Streambert는 영화·드라마·애니메이션을 외부 스트리밍 제공자에서 끌어와 재생하는 데스크탑 앱이다. 핵심은 광고와 추적기를 네트워크 레벨에서 100% 차단하면서 m3u8 스트림만 통과시키는 미들웨어 구조다. 이 한 가지를 위해 Electron의 모든 기능 — Session, webRequest, BrowserWindow, IPC — 을 본격적으로 활용한다.

Term · 용어
IPC (Inter-Process Communication, 프로세스 간 통신)
Electron은 Main 프로세스(Node.js)와 Renderer 프로세스(Chromium)가 메모리를 공유하지 않는다. 두 프로세스가 서로 메시지를 주고받는 통로가 IPC. ipcMain, ipcRenderer 양쪽에서 채널 이름으로 메시지를 송수신한다.
Term · 용어
HLS / m3u8 (HTTP Live Streaming)
Apple이 만든 비디오 스트리밍 프로토콜. 영상을 4초씩 작은 TS 조각으로 쪼개고, .m3u8이라는 텍스트 플레이리스트에 그 조각들의 URL을 나열한다. 네트워크가 느려지면 자동으로 낮은 화질로 전환된다.
Term · 용어
webRequest API (Electron 네트워크 가로채기)
Chromium 확장 프로그램의 핵심 API. Electron에서 그대로 노출돼 있어 session.webRequest.onBeforeRequest앱이 발생시키는 모든 네트워크 요청을 가로채고 취소·수정할 수 있다. 광고 차단기·VPN·프록시의 기반 기술.
01 — 한 줄 요약TL;DR

이 프로젝트의 핵심 메시지

한 문장으로 줄이면.

Core Message

"외부 영상 소스에서 m3u8을 가져와 광고만 골라 차단하고, 사용자에겐 깔끔한 데스크탑 경험을 — Streambert는 그 미들웨어 패턴의 교과서다."

콘텐츠 자체는 외부(VidSrc·videasy·2Embed·AllManga.to)에 있고, Streambert는 운영 레이어다. 핵심 기능은 세 가지 — (1) 메타데이터는 TMDB/AniList에서 가져와 UI 구성, (2) 영상은 외부 임베드를 webview로 띄우되 광고만 네트워크에서 차단, (3) 다섯 가지 OS 패키지로 한 번에 빌드.

"웹사이트의 광고 지옥을 데스크탑 앱이 어떻게 해결하는가"라는 질문에 대한 가장 구체적이고 완성도 높은 답안 중 하나다.

Trap · 학습 관점에서의 주의
이 앱의 콘텐츠 사용은 저작권 회색지대다

README에도 법적 주의문이 있다. 이 문서는 콘텐츠 사용 패턴을 권장하지 않는다 — 순수하게 기술 아키텍처(Electron 보안 모델, IPC 구조, 광고 차단 미들웨어, 메모리 관리, 크로스플랫폼 빌드)를 학습 자료로 다룬다.

02 — 왜 주목받는가Why now

TrendShift 25위 안에 든 이유

차별점 + 경쟁 우위.

차별점 다섯 가지

Analogy · 한식당 vs 카페테리아

일반 스트리밍 사이트(웹브라우저로 접속)는 여러 광고 손님과 같은 테이블에 앉는 카페테리아다. Streambert는 같은 음식(영상)을 가져오긴 하지만, 광고 손님을 입구에서 막고 사용자를 독립된 룸(BrowserWindow + persist:player 세션)에 안내한다. 음식의 출처는 같지만, 식사 경험은 다르다.

경쟁 비교 — 웹브라우저 vs Streambert

비교 항목브라우저로 직접 시청Streambert
광고 차단uBlock 등 확장에 의존네트워크 레벨 강제 차단
추적기잔존 가능50+ 도메인 사전 차단
UI 일관성사이트마다 다름통일된 React UI
메타데이터사이트 의존TMDB/AniList 통합
다운로드대부분 차단외부 CLI로 위임
PiP브라우저 PiP API네이티브 alwaysOnTop 창
03 — 기술 스택Stack

전체 기술 지도

메인 · 렌더러 · 외부 API · 패키징.

메인 프로세스 (Electron / Node.js)

런타임 · 패키징

  • Electron 40.4 — Chromium + Node.js 데스크탑 런타임
  • electron-builder 26.7 — 크로스플랫폼 패키징/설치파일 생성
  • cross-env 7.0 — OS 무관 환경변수 (ELECTRON_DIST=1)
  • terser 5.46 — JS 최소화

렌더러 (Frontend)

UI 프레임워크

  • React 18.2 — UI 컴포넌트 (페이지 + 모달 + Sidebar)
  • Vite 7.3 — 번들러, 렌더러 코드를 dist/로 빌드
  • @vitejs/plugin-react 4.7 — JSX/HMR 지원
  • global.css — 다크 테마, woff2 폰트 로컬 호스팅

외부 API · 데이터 소스

메타데이터

  • TMDB — 영화/TV 메타데이터 (포스터, 줄거리, 평점) — 사용자가 API 토큰 직접 입력
  • AniList — 애니메이션 메타데이터 (TMDB와 별도 파이프라인)

스트림 / 자막

  • VidSrc · videasy.net · 2Embed — 영상 스트림 임베드 제공자
  • AllManga.to — 애니 미디어 파일 스크레이핑 (ani-cli 패턴 차용)
  • Wyzie — 자막 다운로드 API (앱 안에 BrowserWindow로 토큰 발급 페이지를 띄움)

인프라 · 패키징 형식

  • NSIS — Windows 설치파일 빌더 (커스텀 사이드바, 설치 디렉토리 선택)
  • AppImage / .deb / .rpm / .pacman — Linux 배포 형식 4종
  • asar — Electron 앱 코드를 단일 아카이브로 패키징 (asarUnpack으로 폰트만 예외)
  • ffmpeg — 외부 의존성 (다운로드 시 영상 합치기)
  • vid-dl-cli-only — m3u8 다운로드 외부 CLI
04 — 아키텍처Design

시스템 구조와 6가지 설계 패턴

전체 구조도 → 핵심 패턴 하나하나.

시스템 구조도

┌────────────────────────────────────────────────────────────────────┐
│                       사용자 데스크탑                                │
│                                                                    │
│  ┌──────────────────────────────────────────────────────────────┐  │
│  │                    Electron 앱 (Streambert)                    │  │
│  │                                                              │  │
│  │  ┌─────────────────────┐      ┌──────────────────────────┐  │  │
│  │  │  MAIN PROCESS       │ IPC  │  RENDERER (React)        │  │  │
│  │  │  index.js           │◄────►│  src/App.jsx             │  │  │
│  │  │                     │      │  + pages, components     │  │  │
│  │  │  - BrowserWindow    │      │  - HomePage              │  │  │
│  │  │  - Session 제어      │      │  - MoviePage / TVPage    │  │  │
│  │  │  - IPC 핸들러:        │      │  - LibraryPage           │  │  │
│  │  │    · storage         │      │  - SettingsPage          │  │  │
│  │  │    · downloads       │      │  - DownloadsPage         │  │  │
│  │  │    · subtitles       │      │                          │  │  │
│  │  │    · allmanga        │      │  ┌────────────────────┐ │  │  │
│  │  │    · player          │      │  │ <webview>          │ │  │  │
│  │  │    · blockStats      │      │  │ persist:player     │ │  │  │
│  │  │  - 광고 차단 미들웨어  │      │  │ (VidSrc 임베드)     │ │  │  │
│  │  └─────────┬───────────┘      │  └────────────────────┘ │  │  │
│  │            │                  └──────────────────────────┘  │  │
│  │            ▼                                                │  │
│  │      preload.js (contextBridge)                              │  │
│  └──────────────────────────────────────────────────────────────┘  │
│              ▲                            ▲                        │
│              │ HTTPS/메타데이터              │ HTTPS/m3u8 스트림      │
│              ▼                            ▼                        │
│  ┌─────────────────────┐         ┌──────────────────────────────┐  │
│  │  TMDB / AniList     │         │  VidSrc / AllManga.to /      │  │
│  │  (메타데이터)         │         │  videasy.net / 2Embed         │  │
│  └─────────────────────┘         └──────────────────────────────┘  │
│                                                                    │
│  ┌─────────────────────────────────────────────────────────────┐   │
│  │  외부 CLI 의존성: vid-dl-cli-only + ffmpeg (다운로드 시)        │   │
│  └─────────────────────────────────────────────────────────────┘   │
└────────────────────────────────────────────────────────────────────┘

패턴 1 — 3-Process Electron 모델

Electron은 한 앱 안에 세 가지 종류의 프로세스가 동시에 돈다. 각자 역할이 다르고, 메모리도 공유하지 않는다.

Term · Electron 3프로세스
Main / Renderer / Preload
Main은 Node.js 환경, 한 앱에 하나만 존재(index.js). Renderer는 Chromium 환경, 창마다 하나씩(src/App.jsx 트리). Preload는 둘 사이의 안전한 다리, contextBridge.exposeInMainWorld로 화이트리스트한 API만 노출(preload.js).
Analogy · 회사 조직도

Main = 총무팀(예산 집행, 출입증 발급, 사무용품 구매). Renderer = 현장 직원(고객 응대 = UI 표시). Preload = 총무팀이 미리 정해둔 신청 양식. 현장 직원은 양식에 적힌 항목만 신청할 수 있고, 신청서를 받은 총무팀이 검토 후 실행한다. 직원이 직접 금고를 열 수는 없다.

패턴 2 — Session Partitioning (세션 분리)

Streambert는 한 앱 안에서 3개의 분리된 Electron 세션을 운영한다. 각 세션은 독립된 쿠키 저장소·캐시·권한을 가진다.

// index.js 발췌
const playerSession  = session.fromPartition("persist:player");   // 영화/시리즈 재생용
const trailerSession = session.fromPartition("persist:trailer");  // 예고편 재생용
const redeemSession  = session.fromPartition("partition:wyzie-redeem"); // 자막 키 (비영구)

왜 분리하나? 플레이어 세션엔 광고 차단 + m3u8 가로채기를 강하게 걸고, 트레일러 세션엔 가벼운 차단만 건다. 자막 발급 세션은 partition: 접두사(persist: 없음)로 영구 저장하지 않아 보안에 유리하다.

패턴 3 — webRequest 미들웨어 (광고 차단)

const BLOCKED_HOSTS = [
  "*://www.google-analytics.com/*",
  "*://googletagmanager.com/*",
  "*://doubleclick.net/*",
  // ... 50여 개의 광고/추적기 도메인
];

playerSession.webRequest.onBeforeRequest(
  { urls: [...BLOCKED_HOSTS, ...MEDIA_URLS] },
  (details, callback) => {
    const { url } = details;
    const isMedia = url.includes(".m3u8") || url.includes(".vtt");
    if (!isMedia) {
      blockStats.recordBlockedRequest(url);  // 통계 기록
      callback({ cancel: true });              // 요청 취소!
      return;
    }
    // 미디어 URL은 통과 + 렌더러에 알림
    mainWindow.webContents.send("m3u8-found", url);
    callback({});  // 요청 허용
  }
);
Fix · 좋은 패턴
한 함수가 세 가지 일을 동시에

① 광고 도메인 차단, ② 차단 통계 기록, ③ m3u8 URL을 가로채서 렌더러에 알림. 미들웨어 패턴(요청 가로채기)의 좋은 예다. Express.js의 app.use((req, res, next) => {...})와 거의 같은 개념을 데스크탑 앱 네트워크 레이어에 적용한 것.

패턴 4 — IPC 모듈 분리

index.js가 통째로 길어지지 않도록, IPC 핸들러를 도메인별 모듈로 쪼갰다. 각 모듈은 register() 함수를 export하고, index.js는 그냥 호출만 한다.

src/ipc/
├── allmanga.js     ← 애니 스크레이퍼 (AllManga.to)
├── blockStats.js   ← 광고 차단 통계 저장/조회
├── downloads.js    ← 다운로드 큐, 외부 CLI 호출
├── player.js       ← 플레이어 제어 (mute, fullscreen)
├── storage.js      ← TMDB 키, 설정, 시크릿 마이그레이션
└── subtitles.js    ← 자막 다운로드 (Wyzie)
storageIpc.register();
downloadsIpc.register(getMainWindow);
subtitlesIpc.register({ getDownloads, saveDownloads });
allmangaIpc.register();
playerIpc.register(getMainWindow, { writeSecretMigration });
blockStats.init(getMainWindow);

패턴 5 — Picture-in-Picture (Pop-Out 창)

영상을 작은 별도 창으로 띄우는 PiP 기능. 새 BrowserWindow를 만들고 alwaysOnTop: true로 설정하되, 같은 세션 파티션을 공유해 광고 차단 규칙이 자동 적용된다.

pipWindow = new BrowserWindow({
  width: 640, height: 360,
  minWidth: 320, minHeight: 180,
  alwaysOnTop: true,           // 다른 창 위에 항상 표시
  webPreferences: {
    partition: "persist:player",  // 같은 세션 공유 → 광고 차단 그대로
    contextIsolation: true,
    nodeIntegration: false,
    preload: "popout-preload.js"
  }
});

패턴 6 — 메모리 관리 (V8 캡 + 명시적 정리)

장시간 재생 시 메모리가 쌓이지 않게 적극적으로 관리한다. Electron 앱이 부풀어 오르는 흔한 문제를 정면 대응.

  1. V8 힙 캡--max-old-space-size=256으로 OldGen 힙을 256MB로 제한
  2. 렌더러 수 제한--renderer-process-limit=3으로 동시에 3개까지만
  3. 디스크 캐시 캡--disk-cache-size=80MB
  4. player-stopped 시 정리 — 추적 중인 webContents.destroy() → 캐시 플러시 → 수동 GC 호출
// player-stopped 이벤트 처리 (영상 페이지 unmount 시 발생)
ipcMain.on("player-stopped", () => {
  // 1) 추적 중인 player webContents 모두 destroy
  for (const id of playerWcIds) {
    const wc = webContents.fromId(id);
    if (wc && !wc.isDestroyed()) {
      wc.setAudioMuted(true);
      wc.destroy();
    }
  }
  // 2) 플레이어 세션 캐시 플러시
  const ps = session.fromPartition("persist:player");
  ps.clearCache();
  ps.clearStorageData({ storages: ["shadercache", "cachestorage"] });
  // 3) GC 힌트 (메인 + 렌더러)
  if (typeof global.gc === "function") global.gc();
});
Trap · 함정
CSP / X-Frame-Options 제거

Streambert는 임베드 사이트의 CSP와 X-Frame-Options 헤더를 제거해서 동작시킨다 (보안 트레이드오프). 본인이 만드는 앱에서 이 패턴을 그대로 따라하면 보안 위협이 될 수 있다 — 악성 스크립트가 들어올 통로가 생긴다. 학습 차원에서는 "왜 보통은 이걸 안 건드리는가"를 이해하는 게 더 중요하다.

05 — 디렉토리Repo map

레포 구조 해부

어디에 뭐가 있는지.

streambert/
├── index.js                  # 핵심 Main process 엔트리 (창 생성, 광고 차단, IPC 등록)
├── preload.js                # 메인 창용 contextBridge (화이트리스트 API)
├── popout-preload.js         # PiP 창용 별도 preload (타이틀바 컨트롤만 노출)
├── index.html                # Vite 빌드 진입 HTML
├── vite.config.js            # Vite 설정 (React 플러그인 등)
├── package.json              # 의존성 + electron-builder 설정
├── tmdb-tutorial.md          # 사용자 가이드: TMDB API 키 발급
│
├── public/                   # 정적 자산 (아이콘, 설치 사이드바)
│   ├── icon.png
│   ├── installer-sidebar.bmp # NSIS 설치 마법사 좌측 이미지
│   ├── logo.svg
│   └── sized/                # Linux용 다해상도 아이콘
│
├── src/                      # 렌더러 소스
│   ├── main.jsx              # React 진입점 (createRoot)
│   ├── App.jsx               # 라우팅 + 전역 상태
│   │
│   ├── components/           # 재사용 컴포넌트
│   │   ├── Sidebar.jsx
│   │   ├── MediaCard.jsx
│   │   ├── SetupScreen.jsx        # 최초 실행 시 TMDB 키 입력
│   │   ├── SearchModal.jsx
│   │   ├── DownloadModal.jsx
│   │   ├── SubtitleDownloaderModal.jsx
│   │   ├── TrailerModal.jsx       # YouTube 트레일러 (별도 세션)
│   │   ├── TrendingCarousel.jsx
│   │   ├── ErrorBoundary.jsx
│   │   ├── KeyboardShortcutsModal.jsx
│   │   ├── BlockedStatsModal.jsx  # 광고 차단 통계 시각화
│   │   ├── UpdateModal.jsx
│   │   ├── CloseConfirmModal.jsx  # 다운로드 중 종료 확인
│   │   ├── WindowTitlebar.jsx     # 커스텀 타이틀바
│   │   └── Icons.jsx
│   │
│   ├── pages/                # 라우트 단위 페이지
│   │   ├── HomePage.jsx
│   │   ├── MoviePage.jsx
│   │   ├── TVPage.jsx
│   │   ├── DownloadsPage.jsx
│   │   ├── LibraryPage.jsx        # 시청 기록, 위시리스트
│   │   └── SettingsPage.jsx
│   │
│   ├── ipc/                  # 메인 프로세스 IPC 모듈
│   │   ├── allmanga.js
│   │   ├── blockStats.js
│   │   ├── downloads.js
│   │   ├── player.js
│   │   ├── storage.js
│   │   └── subtitles.js
│   │
│   ├── styles/
│   │   ├── global.css
│   │   └── fonts/            # Bebas Neue, DM Sans (로컬 호스팅, asarUnpack 예외)
│   │
│   └── utils/                # 렌더러 유틸
│       ├── api.js            # TMDB API 호출 래퍼
│       ├── storage.js        # localStorage 추상화
│       ├── subtitles.js
│       ├── updates.js        # 앱 자동 업데이트 체크
│       ├── backup.js         # 스케줄 백업
│       ├── ageRating.js
│       ├── aniSkip.js        # 애니 오프닝/엔딩 스킵 정보
│       ├── episodeMappings.js
│       ├── homeLayout.js
│       ├── appearance.js     # 테마/UI 설정
│       ├── useBlockedStats.js  # React hook
│       └── useRatings.js       # React hook
│
├── screenshots/              # README 이미지들
├── .github/                  # GitHub Actions, 이슈 템플릿
├── .gitignore
└── LICENSE                   # GPL-3.0
Analogy · 구조의 좋은 점

Main과 Renderer가 물리적으로 분리돼 있다 — Main 코드는 루트의 index.js, Renderer는 src/ 아래. IPC 모듈을 한 폴더(src/ipc/)에 모아 메인 프로세스 코드가 흩어지지 않는다. 재사용 가능한 것은 components/, 라우트 단위는 pages/로 React 표준 컨벤션. React hook은 use 접두사(useBlockedStats.js) 규약을 그대로 지킨다.

06 — 학습 포인트What to learn

분야별 배울 것

기술 영역마다 무엇을 가져갈지.

Electron 기초 + 보안 모델

  • Main vs Renderer vs Preload 3-프로세스 모델
  • contextIsolation: true + nodeIntegration: false = 보안 권장 설정
  • BrowserWindow 옵션 — 프레임 제거, 타이틀바 커스텀
  • Single-instance lock으로 중복 실행 방지

실습: 빈 Electron 앱에 "Hello World" 렌더러 띄우기

IPC (Inter-Process Communication)

  • ipcMain.handle / ipcMain.on 차이 (응답 받을지 여부)
  • contextBridge.exposeInMainWorld로 안전한 API 노출
  • 모듈 단위로 IPC 핸들러를 분리하는 패턴(register())

실습: 카운터 앱 — 버튼 누르면 메인에서 값을 +1 해서 응답

네트워크 가로채기 (webRequest)

  • onBeforeRequest — 요청 전 미들웨어 (취소 가능)
  • onHeadersReceived — 응답 헤더 수정 (CSP/X-Frame-Options 제거)
  • URL glob 패턴으로 차단 도메인 매칭

실습: 특정 도메인의 이미지 요청을 모두 회색 placeholder로 바꾸기

Session Partitioning

  • persist:NAME — 디스크에 저장
  • partition:NAME — 휘발성 (보안용)
  • 세션별 쿠키/캐시/권한 분리

실습: 한 앱에서 두 계정 동시 로그인 (세션 분리)

React + Vite 데스크탑

  • Vite 빌드 결과(dist/)를 loadFile로 로드
  • HMR은 vite build --watch로 구현
  • React hook으로 IPC 상태 관리 (useBlockedStats 패턴)

실습: create-electron-vite 템플릿으로 React + Electron 시작

HLS / m3u8 스트리밍

  • m3u8 = HLS 플레이리스트 (TS 세그먼트 목록)
  • 네트워크에서 m3u8 URL 추출 → 외부 다운로더에 전달
  • ffmpeg로 TS → MP4 합치기

실습: 무료 샘플 m3u8을 ffmpeg로 mp4로 변환

크로스플랫폼 패키징

  • electron-builderbuild 설정 구조
  • 플랫폼별 타깃: nsis, dmg, deb, AppImage, pacman
  • asar로 코드 묶기 + asarUnpack 예외
  • NSIS 옵션 (사이드바, 권한, 시작메뉴)

실습: 본인 앱을 .exe, .deb 두 형식으로 빌드해보기

메모리 / 성능

  • V8 힙 사이즈 캡 (--max-old-space-size)
  • --expose-gc + global.gc() 수동 호출
  • session.clearCache, clearStorageData
  • webContents.destroy()로 명시적 정리

실습: Activity Monitor로 메모리 추적하며 GC 효과 확인

07 — 요구사항Setup

하드웨어·시스템 요구사항

개발용 vs 사용자용.

항목요구사항비고
OSWindows 10/11, macOS 11+, Linux크로스플랫폼
Node.js≥ 22.12.0소스에서 빌드할 때만
RAM최소 2GB, 권장 4GBV8 힙이 256MB로 캡
저장공간500MB+ 앱 + 다운로드용 추가경로는 사용자 지정
외부 도구ffmpeg, vid-dl-cli-only다운로드 시 필요
API 키TMDB Read Access Token (무료)themoviedb.org에서 발급
인터넷스트리밍 가능한 안정적 연결m3u8 = 가변 비트레이트
Trap · Windows 빌드 주의

Windows에서 직접 빌드 시 NSIS와 일부 네이티브 모듈을 위해 Visual C++ Build Tools가 필요할 수 있다. 또 코드사이닝 인증서가 없으면 SmartScreen 경고가 뜬다 — 학습용이면 무시 가능하지만 배포 시엔 인증서 구매 권장.

08 — 실습 과제Hands-on

직접 해볼 수 있는 9단계

난이도별 실습 — Easy → Hard.

실습 1 — Electron 빈 창 띄우기Easy

1) npx create-electron-app my-first-app로 시작 2) BrowserWindow로 "Hello"를 띄워본다 3) app.whenReady(), window-all-closed 이벤트의 의미 확인

배우는 것: Main 프로세스의 라이프사이클

실습 2 — preload로 안전한 API 노출Easy

1) 렌더러에서 window.myAPI.getVersion()을 호출하면 Electron 버전을 돌려주는 다리 만들기 2) contextBridge.exposeInMainWorld 사용 3) nodeIntegration: false인데도 동작하는 이유 확인

배우는 것: contextBridge, 보안 격리 모델

실습 3 — Streambert 클론 후 직접 빌드Easy

1) git clone 2) npm install && npm run start로 dev 모드 실행 3) npm run dist:win으로 설치파일 만들기 4) dist/ 폴더의 결과물 확인

배우는 것: electron-builder 워크플로

실습 4 — 광고 차단 도메인 차단기 만들기Medium

1) Streambert의 BLOCKED_HOSTS 패턴 차용 2) 본인이 자주 보는 사이트의 광고만 차단하는 간단한 Electron 브라우저 작성 3) 차단한 요청 수를 통계 모달로 표시 4) onHeadersReceived로 CSP 헤더 분석

배우는 것: webRequest 미들웨어 패턴, 차단 통계 UX

실습 5 — React + Vite + Electron 보일러플레이트Medium

1) Streambert의 vite.config.js, package.json 스크립트 참고 2) 본인만의 시작 템플릿 만들기 3) Hot reload가 되도록 vite build --watch 활용 4) 메인 프로세스 변경 시 재시작 자동화

배우는 것: Vite + Electron 통합, HMR 우회 패턴

실습 6 — IPC 모듈 패턴 적용Medium

1) 간단한 메모장 앱 만들기 2) src/ipc/notes.js를 분리해 register() 패턴으로 IPC 핸들러 등록 3) 파일 시스템에 JSON으로 저장 4) 렌더러는 window.notesAPI.save(...)만 호출

배우는 것: IPC 모듈화, 책임 분리

실습 7 — 크로스플랫폼 빌드 파이프라인Hard

1) GitHub Actions로 푸시할 때마다 Windows/Linux/macOS 빌드를 자동 생성 2) 릴리스 태그에 첨부 3) Streambert의 .github/를 참고 4) 빌드 매트릭스로 OS별 러너 분리

배우는 것: CI/CD, electron-builder + GitHub Releases

실습 8 — m3u8 다운로더 직접 구현Hard

1) vid-dl-cli-only를 외부에 두지 않고 앱 안에서 직접 구현 2) ffmpeg-staticfluent-ffmpeg로 m3u8 → mp4 변환 3) 진행률 IPC로 렌더러에 스트리밍 4) 일시정지/취소 지원

배우는 것: 외부 프로세스 관리, 스트림 처리

실습 9 — 자동 업데이트 + 코드사이닝Hard

1) electron-updater 통합 2) GitHub Releases를 업데이트 채널로 사용 3) Windows 코드사이닝 인증서 적용 4) SmartScreen 경고 사라지는지 확인 5) macOS notarization 도전

배우는 것: 프로덕션 배포, 코드사이닝 전체 흐름

09 — 학습 로드맵4 weeks

4주 코스 — "Electron 데스크탑 개발자 되기"

주차별로 따라가면 전체 스택 체득.

Week 01
Electron 기초 + 보안 모델

공식 Tutorial 정독 + Security checklist → 실습 1, 2 완수. Main/Renderer/Preload 구조를 손으로 그려 설명할 수 있을 때까지.

Week 02
IPC + 세션 + webRequest

Streambert index.js 정독 → 실습 4, 6 완수. 광고 차단 미들웨어와 세션 분리의 의미를 본인 앱에 적용.

Week 03
React 렌더러 + Vite 빌드 통합

vite-plugin-electron vs electron-vite 비교 → 실습 5 완수. 본인만의 보일러플레이트 완성, HMR 작동 확인.

Week 04
패키징 + 배포 + 자동 업데이트

electron-builder 문서 + GitHub Actions → 실습 7, 9 도전. 5개 OS 패키지 자동 빌드 파이프라인 구축.

주변 기술까지 넓히기

10 — 키워드 사전Glossary

핵심 용어 한눈에

자주 마주칠 단어들.

Electron
Chromium + Node.js를 묶어 데스크탑 앱을 만들 수 있게 해주는 프레임워크. VS Code, Slack, Discord, Figma 데스크탑이 모두 Electron 기반.
IPC
Inter-Process Communication. Main과 Renderer는 메모리를 공유하지 않으므로 메시지 통로(ipcMain, ipcRenderer)가 필요.
contextBridge
Preload에서 메인 월드(렌더러 JS 환경)에 안전하게 API를 노출하는 메커니즘. contextIsolation: true 필수.
contextIsolation
Preload와 렌더러가 같은 window를 공유하지 않게 격리. XSS 공격 면역이 커진다. Electron 12부터 기본값 true.
HLS / m3u8
Apple이 만든 비디오 스트리밍 프로토콜. 영상을 작은 TS 조각으로 쪼개고 m3u8 텍스트 플레이리스트에 나열. 화질 동적 변경.
VTT (WebVTT)
웹 표준 자막 포맷. <video> 태그의 <track>으로 직접 로드 가능. Streambert는 .vtt URL도 가로채서 자막으로 노출.
TMDB
The Movie Database. 오픈 데이터 영화/TV 메타데이터 DB. 무료 API 키 발급. IMDb 대안.
NSIS
Nullsoft Scriptable Install System. Windows용 오픈소스 설치파일 빌더. electron-builder가 내부적으로 사용.
AppImage
Linux 단일 파일 배포 형식. 더블클릭으로 실행, 설치 불필요. 모든 의존성 포함.
.deb / .pacman
Linux 패키지 형식. .deb는 Debian/Ubuntu 계열, .pacman은 Arch Linux 계열.
asar
Electron 앱의 JS/CSS/HTML/리소스를 단일 아카이브로 묶는 포맷. 시작 속도 향상. asarUnpack으로 폰트 등 예외 처리.
webview tag
Electron 특수 태그. 내부에 분리된 Chromium 프로세스로 외부 사이트 임베드. <iframe>보다 더 격리됨.
Single-Instance Lock
같은 앱이 이미 실행 중일 때 새 인스턴스 시작하지 않고 기존 창 포커스. app.requestSingleInstanceLock().
CSP / X-Frame-Options
웹 보안 헤더. CSP는 스크립트 로드 제어, X-Frame-Options는 iframe 임베드 제어. Streambert는 둘 다 제거.
webRequest
Chromium 확장 API. onBeforeRequest, onHeadersReceived로 요청/응답 가로채기 가능. Electron에서 그대로 사용.
V8 Heap
JavaScript 엔진 V8의 메모리 영역. OldGen 힙 크기를 --max-old-space-size로 캡 가능.
11 — 참고 링크Refs

더 깊이 파고들 자료

공식 · Electron 학습 · 관련 라이브러리.

공식 자료

Electron 학습

프론트엔드 · 미디어 라이브러리

Action · 이번 주에 해볼 것

Streambert에서 배운 것을 본인 앱에 적용하는 5단계.

  1. 레포 클론 + dev 실행. npm install && npm run start로 Streambert를 직접 띄워본다. TMDB 키 발급해서 실제로 검색·재생 흐름을 끝까지 경험. 광고 차단 통계 모달도 열어본다.
  2. index.js 정독. Main 프로세스 코드를 처음부터 끝까지 읽으며 — 창 생성, 세션 분리, webRequest 미들웨어, IPC 등록, 메모리 관리 — 각 단계를 손으로 메모.
  3. 실습 4: 광고 차단 브라우저 만들기. Streambert의 BLOCKED_HOSTS를 차용해 본인이 자주 가는 사이트의 광고만 차단하는 미니 Electron 브라우저 작성. 차단 통계 모달까지 구현.
  4. IPC 모듈 패턴으로 메모장 만들기. src/ipc/notes.js를 분리해 register() 패턴으로 IPC 핸들러를 등록. 렌더러는 window.notesAPI.save()만 호출하게.
  5. 크로스플랫폼 빌드 도전. 본인 앱을 .exe + .deb 두 형식으로 빌드. 가능하면 GitHub Actions로 푸시마다 자동 빌드되게 워크플로 작성.
원문 · truelockmc/streambert (GitHub) · 2026-05-21 · TrendShift Featured · 이 문서는 순수하게 기술 아키텍처 학습 자료