Skip to content

성능 평가 — MCU 타겟 및 서버 동시성

Xylolabs API — 종합 성능 평가 개정: 2026-03-23


1. XAP 코덱 벤치마크 결과

모든 측정은 Apple M 시리즈 호스트에서 --release 모드로 수행되었다. XAP 인코더는 crates/xylolabs-sdk/src/codec/xap.rs에 구현되어 있다. ADPCM 인코더는 crates/xylolabs-sdk/src/codec/adpcm.rs의 IMA-ADPCM 구현이다.

1.1 프레임당 인코딩 시간 — 모노, 10ms

샘플레이트 채널 샘플 수 프레임 평균 (us) 최소 (us) 최대 (us) 예산 대비%
8000 1 80 10ms 0.5 0.4 12.7 0.005%
16000 1 160 10ms 1.1 1.0 1.2 0.011%
24000 1 240 10ms 1.9 1.6 6.8 0.019%
32000 1 320 10ms 3.0 2.6 9.0 0.030%
48000 1 480 10ms 512.3 451.1 700.0 5.123%
96000 1 960 10ms 1954.0 1763.8 2207.8 19.540%

핵심 관찰 — 코사인 테이블 임계값: 32kHz (3.0 us)와 48kHz (512.3 us) 사이에 170배의 불연속이 존재한다. 이는 사전 계산된 코사인 테이블의 컷오프가 XAP_PRECOMPUTE_MAX_N = 320 샘플로 설정되어 있기 때문이다. N <= 320인 프레임(10ms에서 최대 32kHz)은 삼각함수 호출 없이 O(N^2) 테이블 검색을 사용한다. N > 320인 프레임(48kHz = 480, 96kHz = 960)은 MDCT 계수마다 런타임 cosf() 호출로 폴백하며, 이로 인해 속도가 대폭 저하된다.

실제 MCU 타겟에서 DSP 확장이 있는 경우, CMSIS-DSP의 arm_rfft_fast_f32가 이 전체 MDCT 경로를 대체하여 불연속이 제거된다. 호스트 벤치마크는 소프트웨어 전용 인코더 동작을 반영한다.

1.2 채널 스케일링 — 16kHz, 10ms

샘플레이트 채널 채널당 샘플 평균 (us) 채널당 (us) 스케일링
16000 1 160 1.0 1.0 1.00x
16000 2 160 1.9 1.0 1.90x
16000 3 160 2.8 0.9 2.80x
16000 4 160 3.7 0.9 3.70x

채널 스케일링은 준선형이다 (4채널에서 4.0배 대신 3.7배). 인코더는 공유 인프라(헤더 쓰기, 디인터리브)와 함께 채널을 독립적으로 처리한다. 채널당 MDCT 비용이 지배적이며, 약간의 준선형성은 헤더/설정 오버헤드의 분산에서 비롯된다.

1.3 4채널 스트레스 — 주요 샘플레이트

샘플레이트 채널 채널당 샘플 평균 (us) 최소 (us) 최대 (us) 예산 대비%
16000 4 160 3.6 3.2 4.6 0.036%
48000 4 480 2004.7 1829.7 2378.2 20.047%
96000 4 960 7930.9 7390.5 10632.4 79.309%

4ch@96kHz 구성은 호스트에서 10ms 프레임 예산의 79.3%를 소비한다. XMBP 인코딩, I/O, 센서, 기타 작업을 위해 2.1ms만 남는다. DSP 가속이 있는 MCU 타겟에서는 MDCT가 하드웨어 가속 FFT 경로로 대체되어 37-56 MIPS로 감소한다(2절 참조).

1.4 프레임 길이 비교 — 48kHz, 2채널

샘플레이트 채널 프레임 길이 채널당 샘플 평균 (us) 예산 대비%
48000 2 7.5ms 360 581.7 7.756%
48000 2 10ms 480 1007.6 10.076%

7.5ms 프레임은 더 적은 샘플(360 vs 480)을 처리하여 절대 시간이 42% 빠르지만, 짧은 예산에서 더 높은 비율을 차지한다 (7.8% vs 10.1%). MCU 타겟에서는 10ms 프레임이 선호되는데, 더 긴 예산 창이 스케줄링 지터와 인터럽트 지연에 더 많은 여유를 제공하기 때문이다.

1.5 ADPCM 인코딩 시간 — 10ms

샘플레이트 채널 샘플 수 평균 (us) 최소 (us) 최대 (us) 예산 대비%
16000 1 160 0.93 0.83 7.21 0.009%
16000 2 320 1.83 1.71 2.58 0.018%
16000 4 640 3.70 3.50 10.21 0.037%
48000 1 480 2.87 2.62 9.58 0.029%
48000 2 960 5.68 5.38 12.33 0.057%
48000 4 1920 11.56 10.79 19.67 0.116%
96000 1 960 5.79 5.38 13.50 0.058%
96000 2 1920 11.51 10.83 20.42 0.115%
96000 4 3840 23.00 21.75 48.79 0.230%

ADPCM은 모든 구성에서 비용이 매우 낮다. 4ch@96kHz에서도 23 us (예산의 0.23%)만 소비한다. 이는 ADPCM이 스펙트럼 변환 없이 순수 정수 산술을 사용하여 룩업 테이블로 샘플별 델타를 인코딩하기 때문이다.

1.6 XAP 대 ADPCM 비용 비율

구성 XAP (us) ADPCM (us) 비율
1ch@16kHz 1.0 0.93 1x
4ch@16kHz 3.6 3.66 1x
4ch@48kHz 2054.1 11.72 175x
4ch@96kHz 7973.9 22.91 348x

저 샘플레이트(<=32kHz)에서 XAP과 ADPCM은 사전 계산된 코사인 테이블이 런타임 삼각함수를 제거하므로 비슷한 비용이다. 48kHz 이상에서 XAP은 런타임 cosf()를 사용하는 O(N^2) MDCT로 인해 175-348배 더 비싸다. MCU 타겟에서 DSP 가속 FFT 경로는 이 격차를 크게 좁히지만(약 20-40배), ADPCM은 CPU 제약 타겟에서 여전히 가장 가벼운 옵션이다.


2. MCU 실현 가능성 매트릭스

2.1 타겟별 최대 지속 가능 구성

PERFORMANCE-PROFILE.mdCODEC-ANALYSIS.md의 문서화된 MIPS 프로파일을 기반으로 평가하고, 벤치마크 측정값과 교차 검증했다. CPU%에는 코덱 인코딩, I/O 스택(I2S DMA, 전송 프로토콜, 센서 샘플링) 및 시스템 오버헤드가 포함된다. RAM%에는 SDK 클라이언트 상태, 코덱 버퍼, 링 버퍼, XMBP 프레이밍, 전송 스택 및 태스크 스택이 포함된다.

타겟 클럭 SRAM DSP/FPU 최대 오디오 구성 CPU% RAM% 판정
RP2350 (Pico 2) 150 MHz 520 KB M33 DSP+FPU 4ch @96kHz XAP 46.0% 16.9% 여유
ESP32-S3 240 MHz 512 KB + 8MB PSRAM PIE SIMD+FPU 4ch @96kHz XAP 17.7% 24.2% 여유
STM32F411 100 MHz 128 KB M4F DSP+FPU 4ch @48kHz XAP 40.0% 34.4% 적합
nRF52840 64 MHz 256 KB M4F DSP+FPU 2ch @48kHz XAP 42.2% 21.9% 적합
nRF9160 64 MHz 256 KB M33 DSP+FPU 2ch @48kHz XAP 44.5% 21.9% 적합
STM32WB55 64 MHz 256 KB M4F DSP+FPU 2ch @48kHz XAP 42.2% 17.2% 적합
RP2040 (Pico) 133 MHz 264 KB 없음 ADPCM 4ch @96kHz 3.0% 12.1% ADPCM 전용
ESP32-C3 160 MHz 400 KB M ext만 ADPCM 4ch @96kHz 2.5% 8.0% ADPCM 전용
STM32F103 72 MHz 20 KB 없음 ADPCM 2ch @24kHz 1.4% 80.0% 센서 전용

2.2 판정 기준

판정 CPU 사용률 의미
여유 (COMFORTABLE) < 50% 추가 처리, OTA 업데이트 또는 향후 기능을 위한 충분한 여유.
적합 (FEASIBLE) 50-70% 신중한 스케줄링으로 안정적인 운영을 위한 충분한 여유.
빡빡함 (TIGHT) 70-85% 운영 가능하나 최악의 인터럽트 지연에서 지터 발생 가능.
한계 (MARGINAL) 85-100% 부하 시 프레임 드롭 위험. 프로덕션에 권장하지 않음.
ADPCM 전용 해당 없음 (XAP 불가) DSP/FPU 없음; XAP 인코더 실행 불가. 4:1 압축 ADPCM만 가능.
센서 전용 해당 없음 (오디오 제한) 극심한 SRAM 제약. ADPCM 1-2ch + 센서 텔레메트리만 가능.

2.3 타겟별 상세 CPU 예산

RP2350 (Pico 2) — 4ch XAP @96kHz

150 MHz 듀얼코어 Cortex-M33. Core 0은 I2S DMA + XAP 인코딩, Core 1은 XMBP + HTTP + 센서를 처리한다.

구성 요소 기준 MIPS DSP MIPS 150 MHz 대비%
I2S DMA 처리 2 2 1.3%
XAP MDCT 순방향 50 35 23.3%
XAP 양자화+패킹 15 10 6.7%
XMBP 배치 인코딩 5 5 3.3%
HTTP 전송 10 10 6.7%
센서 샘플링 (26ch) 5 5 3.3%
워치독 + 기타 2 2 1.3%
합계 89 69 46.0%
여유 61 81 54.0%

듀얼코어 분할 시: 시스템 사용률이 ~39.3%로 감소한다.

ESP32-S3 — 4ch XAP @96kHz

240 MHz 듀얼코어 Xtensa LX7 (총 480 MIPS).

구성 요소 기준 MIPS PIE MIPS 480 MHz 대비%
I2S DMA 처리 2 2 0.4%
XAP MDCT 순방향 50 20 4.2%
XAP 양자화+패킹 15 6 1.3%
WiFi 스택 (FreeRTOS) 30 30 6.3%
XMBP 배치 인코딩 5 5 1.0%
HTTP/TLS 전송 20 12 2.5%
센서 샘플링 (26ch) 5 5 1.0%
PSRAM DMA 관리 3 3 0.6%
워치독 + 기타 2 2 0.4%
합계 132 85 17.7%
여유 348 395 82.3%

ESP32-S3는 MDCT 내부 루프의 128비트 PIE SIMD와 TLS를 위한 하드웨어 AES/SHA 오프로드 덕분에 가장 넉넉한 마진을 제공한다.

STM32F411 — 4ch XAP @48kHz

100 MHz 싱글코어 Cortex-M4F.

구성 요소 기준 MIPS DSP MIPS 100 MHz 대비%
I2S DMA 처리 2 2 2.0%
XAP MDCT 순방향 25 15 15.0%
XAP 양자화+패킹 8 5 5.0%
XMBP 배치 인코딩 3 3 3.0%
UART LTE-M1 전송 8 8 8.0%
센서 샘플링 (26ch) 5 5 5.0%
워치독 + 기타 2 2 2.0%
합계 53 40 40.0%
여유 47 60 60.0%

M4F FPU는 XAP 부동소수점 인코더 경로를 가능하게 하며, 이 코어에서는 고정소수점보다 빠르다. 4ch@96kHz는 권장하지 않는다(80% 사용률 초과).

nRF52840 — 2ch XAP @48kHz

64 MHz 싱글코어 Cortex-M4F.

구성 요소 기준 MIPS DSP MIPS 64 MHz 대비%
I2S DMA 처리 1 1 1.6%
XAP MDCT 순방향 12 7 10.9%
XAP 양자화+패킹 4 3 4.7%
BLE GATT 스택 10 10 15.6%
XMBP 배치 인코딩 2 2 3.1%
센서 샘플링 (4ch) 2 2 3.1%
워치독 + 기타 2 2 3.1%
합계 33 27 42.2%
여유 31 37 57.8%

BLE 스택 오버헤드가 코덱 외 가장 큰 소비자(15.6%)이다. 4ch@48kHz도 가능(~28 MIPS with DSP, 44% 사용률)하지만 여유가 최소화된다.

STM32F103 — 센서 전용 + ADPCM 폴백

72 MHz 싱글코어 Cortex-M3, 20 KB SRAM.

구성 요소 MIPS 72 MHz 대비%
ADPCM 인코딩 2ch @24kHz 1 1.4%
XMBP 배치 인코딩 2 2.8%
UART LTE-M1 전송 8 11.1%
센서 샘플링 (4ch) 3 4.2%
워치독 + 기타 2 2.8%
합계 16 22.2%
여유 56 77.8%

XAP은 불가능하다: 4채널 인코더 상태 32 KB가 전체 SRAM 20 KB를 초과한다. 모노 XAP(인코더 상태 8 KB)조차 나머지 모든 것에 12 KB만 남긴다. ADPCM 2ch @24kHz가 실용적 최대 오디오 구성이다.


3. DSP/FPU 영향 분석

3.1 DSP 아키텍처별 속도 향상

DSP 아키텍처 플랫폼 핵심 명령어 XAP 속도 향상 메커니즘
ARMv8-M DSP (Cortex-M33) RP2350, nRF9160 SMLAD 듀얼 MAC, QADD, SSAT ~30% 듀얼 16x16 MAC이 16비트 오디오에서 처리량을 2배로 증가. 포화 산술이 분기 기반 클리핑을 제거. 고정소수점 (Q15) 경로 선호.
Cortex-M4F FPU+DSP STM32F411, STM32WB55, nRF52840 FPU + SMLAD + SDIV ~35-40% 하드웨어 부동소수점 곱셈-누산이 1-3 사이클. 부동소수점 인코더 경로가 고정소수점보다 빠름. CMSIS-DSP arm_rfft_fast_f32로 MDCT를 3-5배 가속.
Xtensa PIE SIMD (ESP32-S3) ESP32-S3 128비트 4x f32, 8x i16 ~60% 전용 128비트 레지스터에서 4-wide 벡터 연산. 하드웨어 AES/SHA가 TLS를 CPU에서 오프로드. 대형 버퍼 전송을 위한 PSRAM DMA.
DSP 없음 RP2040, ESP32-C3, STM32F103 소프트웨어 곱셈만 0% (기준) 모든 연산이 소프트웨어. SIMD 없음, 하드웨어 부동소수점 없음. XAP MDCT에 소프트웨어 cosf()가 필요하며 DSP 가속 FFT보다 10-50배 느림.

3.2 MDCT 경로 선택

MDCT 순방향 변환은 인코더 핫 패스로, 총 XAP 인코딩 시간의 60-70%를 소비한다. SDK는 컴파일 시점에 최적 경로를 선택한다:

코어 FPU 컴파일 경로 MDCT 전략
Cortex-M33 (RP2350, nRF9160) 단정밀도 cmsis-dsp 피처 SMLAD 듀얼 MAC으로 고정소수점 Q15. Q15 형식의 사전 계산 코사인 테이블.
Cortex-M4F (F411, WB55, nRF52840) 단정밀도 cmsis-dsp 피처 arm_rfft_fast_f32로 부동소수점. 하드웨어 FPU가 부동소수점 경로를 고정소수점보다 빠르게 만듦.
Xtensa LX7 (ESP32-S3) 단정밀도 esp32-simd 피처 PIE 128비트 SIMD로 부동소수점. 벡터 명령어당 4개의 f32 값 처리.
Cortex-M0+ (RP2040) 없음 기본 (DSP 없음) 불가능. 소프트웨어 부동소수점 MDCT가 CPU 예산 초과. ADPCM만 가능.
Cortex-M3 (STM32F103) 없음 기본 (DSP 없음) 불가능. M0+과 동일. ADPCM만 가능.
RISC-V (ESP32-C3) 없음 기본 (DSP 없음) 불가능. M 확장이 정수 곱셈을 제공하지만 SIMD 없음. ADPCM만 가능.

3.3 벤치마크 측정 코사인 테이블 영향

호스트 벤치마크에서 사전 계산된 코사인 테이블의 영향이 명확히 드러난다:

샘플레이트 프레임 샘플 테이블 사용 인코딩 시간 (1ch) 비고
8 kHz 80 0.5 us O(N^2) 테이블 검색, 삼각함수 호출 없음
16 kHz 160 1.1 us O(N^2) 테이블 검색
24 kHz 240 1.9 us O(N^2) 테이블 검색
32 kHz 320 예 (한계) 3.0 us 사전 계산 테이블의 최대 N
48 kHz 480 아니오 512.3 us 계수당 런타임 cosf() -- 170배 느림
96 kHz 960 아니오 1954.0 us 런타임 cosf() -- 32kHz 대비 651배 느림

테이블 한계(XAP_PRECOMPUTE_MAX_N = 320)는 메모리 사용량을 200 KB 미만으로 유지한다 (51,200개 i32 항목 = 200 KB). 480으로 확장하면 (480/2)*480 = 115,200개 항목 = 450 KB가 필요하며, 이는 대부분의 MCU 타겟의 SRAM을 초과한다. MCU 타겟에서 CMSIS-DSP는 전체 MDCT를 하드웨어 가속 FFT로 대체하므로 이 테이블은 무관하다.


4. 메모리 예산 분석

4.1 타겟별 메모리 분석

모든 값은 KB 단위. 표시된 구성은 2절의 최대 권장 구성이다.

타겟 SRAM SDK+코덱 링 버퍼 XMBP HTTP 스택 사용 여유 RAM%
RP2350 (Pico 2) 520 20 32 16 4 16 88 432 16.9%
ESP32-S3 512+8M 20 64* 16 8 16 124 388+ 24.2%
STM32F411 128 20 8 4 4 8 44 84 34.4%
nRF52840 256 20 16 8 4 8 56 200 21.9%
nRF9160 256 20 16 8 4 8 56 200 21.9%
STM32WB55 256 20 8 4 4 8 44 212 17.2%
RP2040 (Pico) 264 8 8 4 4 8 32 232 12.1%
ESP32-C3 400 8 8 4 4 8 32 368 8.0%
STM32F103 20 4 4 2 2 4 16 4 80.0%

*ESP32-S3 링 버퍼는 DMA를 통해 PSRAM에 배치된다.

4.2 메모리 제한 시나리오

RP2350 (520 KB SRAM): 4ch @96kHz + 26개 센서 + HTTP = 88 KB (16.9%). 애플리케이션 로직, OTA 스테이징 버퍼 및 파일시스템을 위해 432 KB가 남는다. 넉넉한 SRAM 여유는 RP2350을 기능이 풍부한 배포에 가장 균형 잡힌 타겟으로 만든다.

STM32F411 (128 KB SRAM): 4ch @48kHz XAP = 44 KB (34.4%). 남은 84 KB는 애플리케이션에 적합하지만 OTA 스테이징 공간은 없다. 펌웨어 업데이트는 외부 플래시 또는 스왑 기반 부트로더를 사용해야 한다. 2ch@48kHz로 줄이면 사용량이 36 KB로 감소하여 8 KB가 확보된다.

nRF52840 (256 KB SRAM): 2ch @48kHz + BLE GATT 스택 = 56 KB (21.9%). SoftDevice BLE 스택 자체가 추가로 ~30 KB를 소비한다. SoftDevice 포함 시: 총 ~86 KB 사용, 170 KB 여유. BLE 기반 배포에 적합하다.

STM32F103 (20 KB SRAM): 센서 전용 ADPCM = 16 KB (80.0%). 애플리케이션 로직에 4 KB만 남는다. 이는 절대 최소 실행 가능 구성이다. 추가 센서 스트림 하나만 추가해도 신중한 스택 최적화가 필요하다. XAP은 완전히 불가능하다: 인코더 상태만으로 (채널당 8 KB, 4ch에 32 KB) 전체 SRAM을 초과한다.

ESP32-S3 (512 KB + 8 MB PSRAM): PSRAM이 가용 메모리를 대폭 확장한다. 오디오 링 버퍼(64 KB+)와 XMBP 배치 버퍼가 DMA 접근 가능한 PSRAM에 상주할 수 있어, 빠른 SRAM은 코덱 상태와 스택에 자유롭게 유지된다. 이로 인해 ESP32-S3는 메모리 압박 없이 4ch@96kHz를 초과하는 구성(예: 서라운드 모니터링을 위한 8ch@48kHz)을 실행할 수 있는 유일한 타겟이다.


5. 서버 동시성 평가

5.1 아키텍처 개요

Xylolabs API 서버는 Axum을 사용한 Tokio 비동기 런타임으로 구축되었다. 수집 파이프라인(crates/xylolabs-server/src/ingest/manager.rs)은 MCU 디바이스로부터 XMBP 배치를 처리하고, 메모리에 샘플을 버퍼링하고, spawn_blocking에서 zstd로 압축한 후, S3와 PostgreSQL로 플러시한다.

5.2 연결 매개변수

매개변수 비고
런타임 Tokio 멀티스레드 워커 스레드 = CPU 코어 수
DB 커넥션 풀 20 (기본, 설정 가능) DATABASE_MAX_CONNECTIONS 환경 변수
세션당 메모리 스트림 버퍼당 ~1-4 KB 누적 샘플 제외
업로드 본문 제한 최대 2 GB 현재 전체 버퍼링 (스트리밍 아님)
SSE 라이브 연결 무제한 세션별 브로드캐스트 채널
HTTP keep-alive 75초 Axum 기본값
인증 요청 제한 IP당 분당 10회 인메모리 캐시, 60초 TTL, 10K IP 용량
수집 플러시 창 10초 (설정 가능) S3 쓰기 전 샘플 누적
세션 타임아웃 300초 (설정 가능) 비활성 세션 자동 종료

5.3 수집 파이프라인 처리량

단계 지연 시간 동시성 모델 비고
XMBP 배치 디코딩 배치당 < 100 us 인라인 비동기 순수 CPU, I/O 없음
샘플 버퍼링 샘플당 < 1 us Mutex 보호 HashMap 스트림별 Vec
라이브 이벤트 브로드캐스트 이벤트당 < 10 us broadcast::channel 구독자가 있을 때만
zstd 압축 청크당 ~200 us spawn_blocking 비동기 런타임에서 오프로드
S3 업로드 청크당 ~5-20 ms 비동기 I/O 네트워크 바운드; MinIO 로컬 ~2 ms
DB 삽입 (청크 레코드) 레코드당 ~1-2 ms 비동기 sqlx 플러시 창 내 배치 처리
DB 통계 업데이트 배치당 ~1 ms 인라인 비동기 배치당 단일 UPDATE

코어당 추정 처리량: ~500 XMBP 배치/초 (CPU 바운드 단계는 ~200 us/청크의 압축이지만, 블로킹 풀로 오프로드됨).

5.4 동시 세션 용량

시나리오 세션 수 오디오 구성 센서 스트림 서버 CPU DB 부하 RAM
경량 10 10 x 2ch @16kHz 40 @100Hz < 5% 낮음 ~40 KB
표준 50 50 x 4ch @48kHz 200 @100Hz ~20% 보통 ~200 KB
고부하 100 100 x 4ch @96kHz 2600 @100Hz ~60% 높음 ~400 KB
한계 ~200 DB 풀 제한 DB 풀 제한 ~90% 포화 ~800 KB

제한 요소는 PostgreSQL 커넥션 풀(기본 20)이다. 각 플러시 작업에 청크 INSERT를 위한 DB 연결이 필요하다. 100개 세션이 10초마다 플러시하면, DB 풀은 연결당 ~10 플러시 작업/초를 처리하며 이는 용량 내이다. 200개 이상의 세션에서 공격적인 플러시 간격 시, 풀 고갈이 병목이 된다.

5.5 동시성 위험 요소 — 식별 및 해결

문제 심각도 상태 해결
ConfigManager 비동기 컨텍스트에서 블로킹 RwLock P2 수정됨 std::sync::RwLock에서 tokio::sync::RwLock으로 마이그레이션. 비동기 런타임에서 블로킹 락이 경합 시 스레드 기아 발생.
S3 실패 시 수집 플러시 데이터 손실 P0 수정됨 이전에는 S3 쓰기 확인 전에 샘플을 드레인. 현재는 플러시 전 샘플을 복제; 실패 시 원본 유지하여 재시도. flushing 플래그가 동일 버퍼의 동시 플러시를 방지.
list_uploads의 N+1 태그 쿼리 P1 수정됨 업로드당 태그 가져오기(1+N 쿼리)를 단일 JOIN 배치 쿼리로 교체.
stats_overview 순차 쿼리 P2 수정됨 6개의 독립 COUNT 쿼리가 tokio::try_join!을 통해 동시 실행.
S3 전체 파일 버퍼링 업로드 P1 미해결 2 GB 업로드 = 2 GB RAM. 백프레셔가 있는 스트리밍 멀티파트 업로드 필요.
업로드 본문 메모리 버퍼링 P1 미해결 큰 업로드 본문이 S3 쓰기 전 전체 메모리에 유지. 스트리밍 본문 처리 필요.
연결 요청 제한 없음 (일반) P3 미해결 인증 엔드포인트에 IP 기반 요청 제한(분당 10회) 있음. 일반 API 엔드포인트는 요청 제한 없음.
mem::forget을 통한 파일 디스크립터 누수 P0 수정됨 임시 파일이 mem::forget으로 누수. 결정적 정리를 위해 into_temp_path로 수정.
세션 락 경합 P2 완화됨 IngestManager.sessionstokio::sync::RwLock 사용. 개별 세션은 tokio::sync::Mutex 사용. 플러시 작업이 I/O 수행 전 세션 락 해제. 비활성 세션 확인은 세션 Mutex 잠금 없이 원자적 last_activity_ms 사용.

5.6 남은 성능 위험

S3 전체 파일 버퍼링: 가장 중요한 미해결 문제. 단일 2 GB 업로드가 2 GB 서버 RAM을 소비한다. 10개의 대용량 동시 업로드 시 서버에 업로드 버퍼링만으로 20 GB RAM이 필요하다. 수정을 위해 경계된 메모리 버퍼와 클라이언트에 대한 백프레셔 신호를 사용한 스트리밍 멀티파트 업로드가 필요하다.

DB 풀 고갈: 기본 20개 연결 풀은 현재 플러시 간격에서 약 200개의 동시 세션을 지원한다. 이를 초과하면 플러시 작업이 풀 뒤에 대기하여 지연 시간과 샘플 버퍼 메모리가 증가한다. 풀 크기 증가는 해당하는 PostgreSQL max_connections 튜닝이 필요하다.

브로드캐스트 채널 무제한 구독자: SSE 라이브 이벤트 엔드포인트가 구독자 수 제한 없이 브로드캐스트 수신자를 생성한다. 악의적인 클라이언트가 수천 개의 SSE 연결을 열면 브로드캐스트 채널 버퍼로 메모리가 고갈될 수 있다.


6. 권장 사항

6.1 용도별 플랫폼 선택

용도 권장 플랫폼 코덱 최대 구성 근거
풀 스펙트럼 산업 모니터링 ESP32-S3 XAP 4ch @96kHz 82% 여유, 내장 WiFi, 대형 버퍼를 위한 PSRAM
배터리 구동 현장 센서 RP2350 (Pico 2) XAP 4ch @96kHz 54% 여유, 최저 활성 전력 (25 mA), 듀얼코어
컴팩트 산업 노드 STM32F411 XAP 4ch @48kHz 60% 여유, 검증된 M4F 생태계, UART LTE-M
BLE 웨어러블 / 비콘 nRF52840 XAP 2ch @48kHz 58% 여유, BLE 전송, 초저전력 슬립 (1.5 uA)
셀룰러 IoT (LTE-M) nRF9160 XAP 2ch @48kHz 55% 여유, 통합 LTE-M 모뎀
BLE + Thread 메시 STM32WB55 XAP 2ch @48kHz 58% 여유, 듀얼 프로토콜 BLE + 802.15.4
음성 전용 / 레거시 센서 STM32F103 IMA-ADPCM 2ch @24kHz 78% 여유, ADPCM만, 20 KB SRAM 제한
저가 WiFi 센서 ESP32-C3 IMA-ADPCM 4ch @96kHz 98% 여유, ADPCM만, RISC-V, 내장 WiFi
교육 / 프로토타이핑 RP2040 (Pico) IMA-ADPCM 4ch @96kHz 97% 여유, ADPCM만, 최저 비용 ($1)

6.2 서버 스케일링 권장사항

부하 단계 세션 수 서버 구성 DB 풀 비고
개발 1-10 단일 인스턴스, 2 CPU 10 기본 구성으로 충분
소규모 배포 10-50 단일 인스턴스, 4 CPU 20 기본 풀 적합
중규모 배포 50-200 단일 인스턴스, 8 CPU 40 풀 증가, 플러시 지연 모니터링
대규모 배포 200-1000 다중 인스턴스 + LB 60/인스턴스 스트리밍 S3 업로드 수정 필요, 수평 확장
엔터프라이즈 1000+ Kubernetes 파드, 자동 확장 커넥션 풀러 (PgBouncer) 모든 P1 문제 해결 필요

6.3 우선 엔지니어링 작업

  1. P1 — 스트리밍 S3 업로드: 전체 파일 버퍼링을 스트리밍 멀티파트 업로드로 교체. O(파일크기) 메모리 소비 제거. 100 MB 이상 파일을 처리하는 모든 배포에 필수.

  2. P1 — 스트리밍 업로드 본문: HTTP 본문에서 S3로의 백프레셔 인식 스트리밍 구현, 경계된 버퍼(예: 4 MB) 이상을 메모리에 유지하지 않음.

  3. P2 — SSE 구독자 제한: 세션당 브로드캐스트 채널 수신자 제한(예: 100). 초과 시 429 반환.

  4. P3 — 일반 API 요청 제한: 인증뿐만 아니라 모든 API 엔드포인트에 Tower 요청 제한 미들웨어 추가.

  5. 최적화 — 코사인 테이블 확장: 충분한 SRAM을 가진 타겟(PSRAM이 있는 ESP32-S3)에서 XAP_PRECOMPUTE_MAX_N을 480으로 확장하여 DSP 의존성 없이 48kHz 테이블 기반 인코딩 고려. 이는 48kHz 사용 사례의 170배 불연속을 제거한다.


7. 관련 문서