BLE 멀티 클라이언트 대응

BLEIoTEmbedded

BLE 4.1부터 peripheral이 여러 central(client)과 동시에 연결할 수 있다. 단일 라디오를 시분할로 공유하므로, 연결 수가 늘면 throughput, 전력, 메모리 모두 영향을 받는다.

플랫폼별 최대 연결 수

플랫폼스택최대 연결peripheral 역할 제한
nRF52840SoftDevice S14020제한 없음 (역할 자유 배분)
STM32WB55ST BLE Stack8central로부터 최대 2개
ESP32NimBLE9기본값 3, 설정으로 변경
EFR32Gecko SDK32기본값 4

STM32WB55는 총 8개 링크를 지원하지만, peripheral(slave) 역할은 2개로 제한된다.

구현 패턴

연결 테이블

고정 크기 배열로 연결 상태를 관리한다.

#define MAX_CONNECTIONS 8

typedef struct {
    uint16_t conn_handle;    // BLE_CONN_HANDLE_INVALID if unused
    uint8_t  peer_addr[6];
    uint16_t mtu;            // 연결별 개별 협상
    uint16_t conn_interval;
    bool     is_encrypted;
    app_state_t app_state;   // 애플리케이션 프로토콜 상태
} conn_entry_t;

static conn_entry_t conn_table[MAX_CONNECTIONS];

BLE_GAP_EVT_CONNECTED에서 슬롯 할당, BLE_GAP_EVT_DISCONNECTED에서 해제. 모든 GATT 연산은 conn_handle로 라우팅한다.

CCCD는 연결별 독립

CCCD(Client Characteristic Configuration Descriptor)는 스펙상 연결별 상태다. 클라이언트 A가 notification을 켜도 클라이언트 B에는 영향이 없다.

typedef struct {
    uint16_t conn_handle;
    bool     notifications_enabled;
} cccd_state_t;

cccd_state_t sensor_cccd[MAX_CONNECTIONS];
  • bonded 디바이스는 CCCD를 flash에 영속 저장 (Nordic Peer Manager 등)
  • 비bonded 디바이스는 연결 해제 시 CCCD 초기화

연결 중 advertising 재개

추가 central을 받으려면 연결 후 advertising을 다시 시작해야 한다.

void on_connected(uint16_t conn_handle) {
    conn_table_add(conn_handle);
    if (conn_table_count() < MAX_CONNECTIONS) {
        ble_advertising_start(BLE_ADV_MODE_CONNECTABLE);
    }
}

advertising과 기존 연결 이벤트가 같은 라디오를 공유하므로, 스케줄러가 자동으로 시분할 배치한다.

단일 연결 대비 시스템 단점

1. 스케줄링 충돌

각 central이 독립적으로 connection interval과 anchor point를 설정한다. peripheral은 Connection Parameter Update Request를 보낼 수 있지만, central이 거부할 수 있다.

  • 연결 이벤트 하나를 처리하는 데 최소 2.5 ms 필요
  • N개 연결, connection interval CI일 때 연결당 가용 시간: CI / N - guard_band
  • 각 central의 클럭이 독립적으로 drift하므로, 충돌이 간헐적으로 발생하고 예측 불가
  • iOS는 최소 CI 15 ms, Android는 다를 수 있어 서로 다른 OS가 연결되면 파라미터 불일치 발생

2. throughput 저하

단일 라디오를 시분할로 공유하므로, 연결 수에 비례해 throughput이 떨어진다.

연결 수연결당 throughput비고
1 (BLE 5.0, 2M PHY, DLE)~140 kB/s최적 단일 링크
3 (동일 CI)~10 kB/s약 14배 감소

연결당 throughput 공식:

throughput ≈ (packets_per_event × payload_size) / CI
packets_per_event ∝ event_length = CI / N - guard_band

3. 메모리 오버헤드

연결마다 별도의 컨텍스트를 유지해야 한다.

리소스설명연결당 크기
Link Layer 컨텍스트타이밍, 채널맵, 암호화 상태1~2 KB
ATT/GATT 버퍼TX/RX 큐, MTU 크기 버퍼MTU에 비례
CCCD 상태characteristic별 구독 상태2 bytes × characteristic 수
보안 컨텍스트암호화 키, 본딩 정보80~100 bytes

nRF52 기준 연결당 1.4~3.8 KB (MTU, 큐 설정에 따라 변동). 256 KB RAM에서 8개 연결 + DLE(251 bytes) 설정 시 BLE 스택만 35~40 KB를 차지한다.

4. 전력 소비 증가

연결 수에 비례해 라디오 wake-up 횟수가 늘어난다.

  • 단일 연결 CI=100 ms: 초당 10회 wake-up
  • N개 연결 CI=100 ms: 초당 10×N회 wake-up
  • 단일 연결 CI=75 ms 기준 평균 전류: ~230 μA (Silicon Labs EFR32 측정값)
  • peripheral latency로 이벤트를 건너뛸 수 있지만, 각 central이 독립 제어하므로 멀티 연결 시 효과 제한

5. notification fanout

연결 모드에서 BLE는 multicast를 지원하지 않는다. 같은 데이터를 N개 클라이언트에 보내려면 N번 개별 전송해야 한다.

  • 연결 테이블 순회 → CCCD 확인 → notify() 호출을 연결 수만큼 반복 (O(N))
  • HVN 큐 깊이가 제한적 (보통 1~4/연결). 큐 풀이면 HVN_TX_COMPLETE 이벤트를 기다려야 한다
  • 5개 클라이언트, CI=100 ms일 때 첫 번째와 마지막 클라이언트 사이 최대 500 ms 지연
  • RF 상태가 나쁜 클라이언트는 재전송으로 큐를 점유해 다른 클라이언트의 notification도 지연

6. WiFi 공존 악화 (단일 라디오 칩)

ESP32처럼 BLE와 WiFi가 하나의 2.4 GHz 라디오를 공유하는 경우:

  • WiFi+BLE 시 라디오 시간을 50:50으로 분할 (TDM)
  • 단일 BLE 연결이면 BLE 50%를 독점하지만, N개 연결이면 50% / N으로 분산
  • WiFi 고부하 시 BLE 연결 이벤트가 누락되어 supervision timeout 발생 가능
  • WiFi throughput: BLE 없이 ~20 Mbps → BLE 공존 시 ~8 Mbps (TCP RX)

메모

  • STM32WB55에서 멀티 클라이언트 peripheral을 구현할 경우, slave 역할 2개 제한을 반드시 확인해야 한다
  • throughput이 중요한 서비스(OTA 등)는 해당 연결 진행 중 다른 연결의 CI를 늘리거나, 연결 수를 제한하는 설계가 필요하다
  • notification fanout 지연이 문제되면 BLE 5.0 extended advertising의 periodic advertising (connectionless broadcast)을 대안으로 검토할 수 있다