Bluetooth Low Energy (BLE)는 최소 전력 소비로 소량의 데이터를 전송하도록 최적화된 무선 통신 표준입니다. Bluetooth SIG, 2025에 따르면, 이 기술은 전 세계적으로 50억 개 이상의 기기에서 사용됩니다. GATT(Generic Attribute Profile)는 데이터를 Service → Characteristic → Descriptor 계층 구조로 구성하며, 이는 iOS 및 Android용 모든 BLE 애플리케이션의 기반을 형성합니다.
핵심 요점
Bluetooth Low Energy (BLE)는 두 가지 역할(Central(모바일 기기) 및 Peripheral(기기))로 클라이언트-서버 모델에서 작동합니다. Central은 전파를 스캔하고 연결을 시작하며, Peripheral은 데이터를 전송합니다. 클래식 Bluetooth와 달리 BLE는 오디오 스트림용이 아니며 최소 전력 소비로 작은 패킷을 전송하는 것이 목적입니다. Bluetooth SIG Core Specification 5.4(2025)에 따르면 BLE는 활성 모드에서 15mA 미만의 전류로 최대 2Mbps의 속도를 지원합니다.
GATT(Generic Attribute Profile)는 Bluetooth Low Energy의 데이터 구조를 정의합니다. Service는 특성의 논리적 그룹입니다(예: Heart Rate Service 0x180D). Characteristic은 특정 값을 가진 데이터 포인트입니다. Descriptor는 알림 관리를 위한 CCCD를 포함한 특성 메타데이터입니다. 각 요소에는 UUID가 있으며 표준 Bluetooth SIG 프로필의 경우 16비트, 사용자 정의의 경우 128비트입니다.
모바일 애플리케이션의 Bluetooth Low Energy는 이 계층 구조를 사용하여 스마트폰과 주변 기기 간의 데이터 교환을 구성합니다. GATT의 올바른 이해는 두 플랫폼에서 BLE 애플리케이션을 개발하는 기초입니다. 개발자는 기기의 서비스 및 특성 UUID와 각 특성의 속성(read, write, notify, indicate)을 알고 있어야 합니다.
BLE 기기는 검색을 위해 광고 패킷(advertising packets)을 전송합니다. Advertising Data에는 기기 이름, 서비스 UUID, RSSI 및 Manufacturer Specific Data가 포함됩니다. 광고 패킷 크기는 31바이트로 제한됩니다. 추가 데이터를 전송하기 위해 Scan Response가 사용됩니다. 이는 중앙 기기가 검색 후 요청하는 두 번째 패킷입니다.
iOS에서 Core Bluetooth 프레임워크가 Bluetooth Low Energy를 담당합니다. CBCentralManager는 스캔 및 연결을 관리하고, CBPeripheral은 원격 BLE 기기를 나타냅니다. 프로세스는 표준적입니다: CBCentralManager 초기화, poweredOn 상태 확인, scanForPeripherals 시작, 연결 및 서비스 검색. Core Bluetooth는 무선 모듈의 전원을 자동으로 관리하며 BLE를 사용하지 않으면 꺼집니다.
iOS의 모바일 개발에서 BLE는 백그라운드 모드를 고려해야 합니다. Core Bluetooth 백그라운드 모드는 프로젝트 Capabilities(Uses Bluetooth LE accessories)를 통해 활성화됩니다. 백그라운드에서 앱은 특성의 알림을 받을 수 있지만 스캔은 제한되며 시스템은 기기가 이동할 때만 스캔을 다시 시작합니다. iBeacon의 경우 CLLocationManager를 통해 백그라운드 스캔이 더 활발히 작동합니다.
import CoreBluetooth
class DeviceScanner: NSObject, CBCentralManagerDelegate {
var centralManager: CBCentralManager!
func start() {
centralManager = CBCentralManager(delegate: self, queue: nil)
}
func centralManagerDidUpdateState(_ central: CBCentralManager) {
guard central.state == .poweredOn else { return }
central.scanForPeripherals(withServices: nil, options: nil)
}
func centralManager(_ central: CBCentralManager,
didDiscover peripheral: CBPeripheral,
advertisementData: [String: Any],
rssi RSSI: NSNumber) {
print("발견: \(peripheral.name ?? "unknown")")
}
}
이 예시에서 CBCentralManagerDelegate는 모든 BLE 연결 이벤트를 처리합니다. centralManagerDidUpdateState 메서드는 모바일 기기에서 Bluetooth가 켜져 있는지 확인합니다. 초기화 성공 후 스캔이 시작됩니다. 발견된 각 기기에 대해 didDiscover 콜백이 호출됩니다.
기기를 검색한 후 connect 및 discoverServices를 호출해야 합니다. CBPeripheralDelegate는 각 단계를 처리하는 메서드를 제공합니다: didDiscoverServices, didDiscoverCharacteristics, didUpdateValueFor. 각 메서드는 비동기식이며 데이터는 델리게이트 콜백을 통해 도착합니다. RSSI(Received Signal Strength Indicator)는 신호 레벨을 나타내며 0에 가까울수록 신호가 강합니다.
Android에서 Bluetooth Low Energy는 android.bluetooth 패키지를 통해 구현됩니다. BluetoothAdapter는 모든 BLE 작업의 진입점입니다. BluetoothLeScanner는 ScanCallback 콜백으로 스캔을 시작합니다. 기기를 검색한 후 BluetoothGatt가 생성되어 주변 기기에 연결됩니다. BluetoothGattCallback은 연결, 서비스 검색, 특성 읽기, RSSI 변경 등의 이벤트를 처리합니다.
Android의 모바일 애플리케이션에서 Bluetooth Low Energy에는 명시적인 BLUETOOTH_SCAN, BLUETOOTH_CONNECT 및 ACCESS_FINE_LOCATION 권한이 필요합니다. Android 12부터 권한이 분리되었습니다: 스캔용 BLUETOOTH_SCAN, 연결용 BLUETOOTH_CONNECT. ACCESS_FINE_LOCATION은 특정 유형의 기기를 스캔하는 경우에만 필요합니다. 이러한 권한 없이 앱은 BLE를 사용할 수 없습니다.
class BLEScanner(private val bluetoothAdapter: BluetoothAdapter) {
fun startScan() {
val scanner = bluetoothAdapter.bluetoothLeScanner
val settings = ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
.build()
scanner.startScan(null, settings, scanCallback)
}
private val scanCallback = object : ScanCallback() {
override fun onScanResult(callbackType: Int, result: ScanResult) {
val device = result.device
val rssi = result.rssi
Log.d("BLE", "기기: ${device.name}, RSSI: $rssi")
}
}
}
ScanSettings를 사용하여 스캔 모드를 구성할 수 있습니다: 배터리 절약용 LOW_POWER, 표준 작업용 BALANCED, 최대 검색 속도용 LOW_LATENCY. ScanFilter는 서비스 UUID, 기기 이름 또는 MAC 주소로 검색을 좁힙니다. 필터링은 전력 소비를 줄이고 원하는 기기의 검색을 가속화합니다.
connectGatt를 통해 BluetoothGatt를 생성한 후 앱은 discoverServices를 호출합니다. BluetoothGattCallback에는 onServicesDiscovered, onCharacteristicRead, onCharacteristicChanged가 포함됩니다. 특성 변경에 대한 알림을 받으려면 setCharacteristicNotification을 호출해야 합니다. 이 프로세스는 주의가 필요합니다: 각 GATT 작업은 비동기식이며 결과는 별도의 콜백으로 도착합니다.
iBeacon은 UUID, Major 및 Minor를 전송하는 BLE 비콘을 위한 Apple의 기술입니다. 비콘 기기는 광고 패킷을 브로드캐스트하고 모바일 애플리케이션은 이 데이터를 기반으로 위치와 거리를 결정합니다. iOS에서 iBeacon은 CLLocationManager를 통해 기본적으로 지원됩니다. Android에서는 타사 라이브러리(예: AltBeacon 또는 Android iBeacon Library)가 필요합니다.
Bonding은 BLE 기기 간에 영구적인 안전한 연결을 생성하는 절차입니다. Bonding 후 암호화 키가 저장되며 기기가 다시 가까워지면 자동으로 연결됩니다. iOS에서 본딩은 시스템에 의해 자동으로 관리됩니다. Android에서는 BluetoothDevice.createBond()를 통해 수행됩니다. Bonding은 빠른 재연결이 필요한 웨어러블 기기 및 피트니스 트래커에 중요합니다.
Advertising Data는 Bluetooth Low Energy의 핵심 검색 메커니즘입니다. 기기 제조업체는 사용자 정의 데이터를 전송하기 위해 광고 패킷에 Manufacturer Specific Data를 추가할 수 있습니다. 패킷 형식에는 Company Identifier(2바이트)와 임의 데이터가 포함됩니다. iOS에서 CBCentralManager는 필터링을 위해 서비스 UUID 배열을 허용하여 배터리를 절약합니다. Android에서 ScanFilter도 동일한 원리로 작동합니다.
| 매개변수 | iOS (Core Bluetooth) | Android (BluetoothGatt) |
|---|---|---|
| 관리자 | CBCentralManager | BluetoothLeScanner |
| 연결 | connect(to:) | connectGatt() |
| 서비스 | discoverServices() | discoverServices() |
| 읽기 | readValue(for:) | readCharacteristic() |
| 알림 | setNotifyValue(_:for:) | setCharacteristicNotification() |
| 권한 | 자동 | BLUETOOTH_SCAN, BLUETOOTH_CONNECT |
| iBeacon | CLLocationManager (기본) | AltBeacon / 라이브러리 |
MTU(Maximum Transmission Unit)는 단일 Bluetooth Low Energy 데이터 패킷의 최대 크기입니다. 기본적으로 MTU는 23바이트(3바이트 헤더 + 20바이트 데이터)입니다. MTU를 512바이트로 늘리면 구성 또는 로그 교환 시 전송 속도가 크게 향상됩니다. iOS에서 maximumWriteValueLength는 사용 가능한 MTU를 표시합니다. Android에서는 MTU를 늘리기 위해 requestMtu()가 사용됩니다.
Connection Interval은 중앙 기기가 주변 기기를 폴링하는 빈도입니다. 간격이 짧을수록 전송 속도는 빨라지지만 전력 소비도 증가합니다. 일반적인 값은 7.5ms에서 4초까지입니다. 피트니스 트래커의 경우 100ms면 충분하며 오디오의 경우 7.5ms가 필요합니다. 모바일 개발의 BLE는 전송 속도와 기기 배터리 수명 간의 균형이 필요합니다.
iOS는 Background Modes를 통해 백그라운드에서 BLE를 지원하지만 제한이 있습니다. 백그라운드의 앱은 특성의 알림을 받지만 활성 스캔은 불가능합니다. 시스템은 기기 위치가 변경될 때 스캔을 다시 시작합니다. Android에서 백그라운드 스캔에는 지속적인 알림이 있는 Foreground Service가 필요합니다. 그렇지 않으면 모바일 시스템이 앱 최소화 시 프로세스를 종료합니다.
모바일 애플리케이션에서 안정적인 BLE 작동을 위해 다음 규칙을 따르십시오. 폴링 대신 notify 사용 — 알림이 있는 특성은 변경 시 데이터를 전송하여 배터리를 절약합니다. 연결 시작 시 최적의 MTU를 설정합니다. 스캔 시 서비스 UUID로 기기를 필터링합니다. 다른 모델에서 BLE 스택 호환성을 확인합니다. 제조업체(Xiaomi, Huawei, Samsung)는 Bluetooth 동작에 영향을 미치는 변경을 수행합니다.
자주 묻는 질문
Bluetooth Low Energy (BLE)는 낮은 전력 소비로 작은 패킷을 주기적으로 전송하도록 최적화되었습니다. 클래식 Bluetooth는 오디오 스트림과 대용량 데이터의 지속적인 전송을 위해 설계되었습니다.
GATT(Generic Attribute Profile)는 Service → Characteristic → Descriptor 계층 구조를 정의하는 BLE 데이터 교환 프로토콜입니다. GATT는 BLE 기기에서 데이터 읽기, 쓰기 및 알림 수신에 사용됩니다.
Android 12 이전에는 BLE 스캔이 위치 확인에 사용될 수 있었기 때문에 Google이 이러한 권한을 통합했습니다. Android 12부터 위치와 별개인 BLUETOOTH_SCAN 권한이 도입되었습니다.
Android에서는 requestMtu(), iOS에서는 maximumWriteValueLength를 사용하여 MTU를 늘리십시오. Connection Interval도 속도에 영향을 미치며 짧을수록 전송이 빠릅니다. 최적의 조합은 최대 10배까지 향상됩니다.
Bonding은 BLE 기기 간에 영구적인 안전한 연결을 생성하는 절차입니다. Bonding 후 암호화 키가 저장되며 기기가 반복 검색 없이 자동으로 연결됩니다.
요약
턴키 방식의 모바일 애플리케이션을 개발해 드립니다
IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.