Flux Engine 설계 노트: 모든 제품을 위한 하나의 런타임
우리의 온디바이스 추론 런타임 뒤에 있는 아키텍처 선택과, 그것을 만든 엔지니어링 제약을 들여다본다.
래퍼가 아니라 런타임
온디바이스 앱 하나를 만드는 건 어렵다. 다섯 개를 만드는 건 더 어렵다. 다섯 개가 일관된 기술 기반을 공유하고, 같은 호흡으로 업데이트되고, 배터리 성능이 후퇴하지 않게 하는 것 — 그건 런타임 문제다.
Flux Engine이 그 답이다. 각 레인에서 최고의 오픈소스 런타임 위에 얹은 얇고 의견 있는 한 겹 — 음성(whisper.cpp / faster-whisper), 비전(llama.cpp / mlx-vlm), 언어(llama.cpp / MLC-LLM, 안드로이드에선 executorch) — 을 지금 메모리에 무엇이 있는지, 사용자가 무엇을 하고 있는지, 디바이스가 얼마나 버틸 수 있는지를 아는 단일 스케줄러가 묶고 있다.
세 가지 제약
1. 콜드 스타트 지연
모델은 대부분 디스크에서 자고, 사용자는 그렇지 않다. Flux Engine은 앱 사용 패턴과 작은 온디바이스 분류기에 기반해 다음에 불릴 가능성이 가장 높은 모델을 미리 데운다. 분류기 자체는 50KB짜리 MLP라서, 깨어날 때마다 돌려도 부담이 없다.
2. 작은 NPU에서의 지속 처리량
같은 가속기를 두고 다투는 병렬 워크로드를 만들지 않는다. 스케줄러는 큐 기반이고 우선순위를 알며, 포그라운드 앱에는 강제로 양보한다. ASR 스트림은 백그라운드 요약보다 우선이고, 탭 번역은 백그라운드 인덱싱보다 우선한다.
3. 메모리 부족 시 우아한 강등
사용자가 4K 비디오를 편집 중일 때 요약을 돌리려고 폰을 OOM 시키지 않는다. 엔진은 "남은 여유" 소프트 신호를 내보내고, 제품은 그걸 존중한다 — 더 작은 모델로 내려가거나, 백그라운드로 미루거나, "기기가 식으면 계속" 안내를 띄운다.
Flux Engine이 실제로 노출하는 것
소수의 C++ 추상과 얇은 Swift / Kotlin / Rust 바인딩:
FluxSession— 모델+디바이스에 묶인 장수 추론 세션.FluxStream— 토큰 중간에 취소 가능한 점진적 출력.FluxBudget— 디바이스 상태를 반영한 용량 보고서.FluxRouter— 디바이스 티어, 배터리, 발열 상태, 제품 선호를 보고 요청에 맞는 모델을 고른다.
여기까지다. 다섯 개의 프리미티브. 모든 Flux* 제품이 이 위에 선다.
이게 우리에게 주는 것
버그 픽스 한 건, 성능 개선 한 건, 양자화 개선 한 건 — 다섯 제품이 동시에 좋아진다. 스케줄러 회귀 픽스 한 건 — 다섯 제품의 배터리 스파이크가 동시에 멈춘다. 우리 정도 크기의 팀에서, 공유 런타임의 경제성은 압도적이다.
우리가 틀렸던 것
- 처음 6개월간 그래프 컴파일러에 과투자했다. 결국 손으로 다듬은 모델 로더가 이겼다.
- 프로파일링에 충분히 투자하지 않았다. 9개월차에 다시 짰다.
- 전 제품 공통 양자화 체계를 가정했다. 지금은 제품별 혼합을 출시한다.