Service UUID는 Bluetooth Low Energy(BLE)의 고유한 16비트 또는 128비트 식별자로, 장치의 기능적 서비스를 명확하게 정의합니다. Bluetooth SIG는 Battery Service(0x180F), Device Information(0x180A), Heart Rate(0x180D)와 같은 일반적인 서비스에 표준 16비트 UUID를 할당하여 크로스 플랫폼 호환성을 단순화했습니다. Bluetooth Core Specification 5.4(2023)에 따르면 타사 개발자의 사용자 정의 서비스는 128비트 UUID를 사용해야 하며, 그 형식은 중앙 레지스트리 없이 전역 고유성을 보장합니다. Service UUID의 올바른 선언은 주변 장치의 GATT 서버가 올바르게 작동하기 위한 첫 번째 단계입니다.
핵심 요점
Service UUID는 Bluetooth Low Energy GATT 서비스에 할당되어 다른 장치가 명확하게 인식할 수 있도록 하는 식별자입니다. BLE 아키텍처에서 각 서비스는 공통 기능으로 연결된 특성의 논리적 그룹을 나타냅니다. 예를 들어 Battery Service에는 현재 배터리 충전량을 전송하는 Battery Level 특성이 포함되어 있습니다.
Bluetooth SIG(Special Interest Group)는 가장 일반적인 서비스에 할당된 표준 16비트 UUID의 레지스트리를 관리합니다. 이를 통해 다른 제조업체의 장치가 사전 구성 없이 서로의 서비스를 인식할 수 있습니다. 모든 브랜드의 피트니스 트래커는 UUID 0x180D로 Heart Rate Service를 선언할 수 있으며, 모든 스마트폰은 이것이 심박수 서비스임을 이해합니다.
Bluetooth Core Specification 5.4(2023)에 따르면 16비트 UUID 범위(0x0000–0xFFFF)는 두 부분으로 나뉩니다: 0x0001~0xFFFE는 Bluetooth SIG 표준 서비스이고 0xFFFF는 예약되어 있습니다. 개발자가 SIG 레지스트리에 없는 고유한 서비스를 필요로 하는 경우 128비트 UUID를 사용합니다.
표준 UUID와 사용자 정의 UUID의 차이는 길이뿐만이 아닙니다. 16비트 UUID는 16바이트 대신 2바이트로 전송되어 광고 패킷의 에어 타임을 절약합니다. 광고 패킷 크기에 제한이 있는 장치(최대 31바이트)의 경우 이는 매우 중요합니다.
표준 16비트 UUID는 BLE 장치의 주요 범주(의료용 센서, 피트니스 트래커, 웨어러블 전자 기기 및 액세서리)를 다룹니다. 장치가 표준 기능을 구현하는 경우 개발자는 최대 호환성을 위해 Bluetooth SIG 레지스트리에서 해당 UUID를 사용하는 것이 좋습니다.
다음은 표준 서비스 UUID의 몇 가지 예입니다:
| UUID (hex) | 서비스 이름 | 목적 |
|---|---|---|
| 0x1800 | Generic Access | 액세스 제어, 장치 이름, 외형 |
| 0x180A | Device Information | 제조업체, 모델, 일련번호, 펌웨어 버전 |
| 0x180D | Heart Rate | 맥박 측정, 센서 위치, 배터리 전원 |
| 0x180F | Battery Service | 배터리 충전 수준(백분율) |
| 0x181A | Environmental Sensing | 온도, 습도, 압력, 조도 |
| 0x181C | User Data | 나이, 체중, 키, 성별, 안정 시 맥박 |
사용자 정의 128비트 UUID는 장치가 고유한 기능을 제공할 때 필요합니다. 예를 들어 스마트 잠금 제조업체는 XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX 형식의 UUID로 자체 Lock Control 서비스를 만듭니다. 이러한 UUID는 128비트 값 공간이 실질적으로 무한하기 때문에 다른 서비스와 충돌하지 않음이 보장됩니다.
128비트 UUID는 표준 UUID RFC 4122 형식으로 작성됩니다: 8개의 16진수 문자, 하이픈, 4개, 하이픈, 4개, 하이픈, 4개, 하이픈, 12개 문자. BLE의 경우 Bluetooth SIG UUID의 기본 부분에 고정 비트가 있는 버전이 사용됩니다.
Bluetooth SIG는 기본 UUID를 정의합니다: 0000XXXX-0000-1000-8000-00805F9B34FB. 표준 16비트 서비스의 경우 UUID 값이 이 마스크에 대체됩니다. 예를 들어 0x180F는 0000180F-0000-1000-8000-00805F9B34FB가 됩니다. 사용자 정의 서비스는 개발자가 생성한 완전히 독립적인 UUID를 사용합니다.
사용자 정의 UUID를 만들 때는 UUID 생성기(UUID v4)를 사용할 수 있습니다. 무작위 UUID v4는 122비트의 엔트로피를 제공하여 충돌을 사실상 불가능하게 만듭니다. 사용자 정의 서비스에 기본 Bluetooth SIG UUID의 수정 버전을 사용하지 마십시오. 이는 사양을 위반합니다.
UUID로 서비스 선언은 GATT 서버를 만들 때 Peripheral 쪽에서 수행됩니다. iOS에서는 Core Bluetooth가, Android에서는 android.bluetooth.le가 사용됩니다. 두 접근 방식을 살펴보겠습니다.
Swift에서는 UUID를 지정하여 CBMutableService를 통해 서비스를 생성한 후 CBMutableCharacteristic을 통해 특성을 추가합니다.
import CoreBluetooth
// Standard 16-bit UUID
let batteryServiceUUID = CBUUID("180F")
// Custom 128-bit UUID
let customServiceUUID = CBUUID("E20A39F4-73F5-4BC4-A12F-17D1AD07A961")
let service = CBMutableService(
type: customServiceUUID,
primary: true
)
// Add characteristics
service.characteristics = [characteristic]
// Publish service via peripheralManager
peripheralManager.add(service)
Android에서는 BluetoothGattServer와 BluetoothGattService를 통해 서비스가 등록됩니다. UUID는 java.util.UUID.fromString을 통해 문자열로 전달됩니다.
import android.bluetooth.*;
// Custom service UUID
private static final UUID CUSTOM_SERVICE_UUID =
UUID.fromString("E20A39F4-73F5-4BC4-A12F-17D1AD07A961");
BluetoothGattService service = new BluetoothGattService(
CUSTOM_SERVICE_UUID,
BluetoothGattService.SERVICE_TYPE_PRIMARY
);
// Add characteristics
service.addCharacteristic(characteristic);
// Register on GATT server
gattServer.addService(service);
Service UUID로 스캔하면 Central이 발견된 모든 Peripheral에 연결하지 않고도 필요한 서비스를 제공하는 장치를 찾을 수 있습니다. BLE 광고 패킷에는 서비스 UUID 목록이 포함될 수 있어 Central이 스캔 단계에서 장치를 필터링할 수 있습니다.
iOS에서 CBCentralManager는 서비스 UUID로 필터링하여 장치를 스캔합니다. 이는 전력 소비를 줄이고 필요한 장치 발견을 가속화합니다.
import CoreBluetooth
let centralManager = CBCentralManager()
func scanForHeartRateMonitor() {
let services: [CBUUID] = [
CBUUID("180D") // Heart Rate Service
]
centralManager.scanForPeripherals(
withServices: services,
options: nil
)
}
// Delegate receives only Heart Rate Service devices
func centralManager(
_ central: CBCentralManager,
didDiscover peripheral: CBPeripheral,
advertisementData: [String: Any],
rssi RSSI: NSNumber
) {
// peripheral has only devices with UUID 0x180D
}
Android에서도 ScanFilter.Builder를 통해 UUID로 필터링이 지원됩니다. 이는 각 장치에 연결하지 않고 검색 범위를 좁히는 효율적인 방법입니다.
import android.bluetooth.le.*;
ScanFilter filter = new ScanFilter.Builder()
.setServiceUuid(
new ParcelUuid(
UUID.fromString("0000180D-0000-1000-8000-00805F9B34FB")
)
)
.build();
BluetoothLeScanner scanner = bluetoothAdapter.getBluetoothLeScanner();
scanner.startScan(
Collections.singletonList(filter),
scanSettings,
scanCallback
);
하나의 BLE 장치는 여러 서비스를 동시에 선언할 수 있습니다. 예를 들어 피트니스 밴드에는 Battery Service(0x180F), Heart Rate Service(0x180D) 및 클라우드와 데이터 동기화를 위한 사용자 정의 서비스가 포함될 수 있습니다. 각 서비스에는 고유한 UUID와 고유한 특성 집합이 있습니다.
여러 서비스가 있는 경우 광고 패킷 제한을 고려하는 것이 중요합니다. BLE 광고 패킷에는 최대 31바이트의 데이터가 포함될 수 있습니다. 서비스 UUID가 너무 많은 공간을 차지하면 일부가 광고 패킷에 맞지 않을 수 있습니다. 이 경우 스캔 응답이 사용됩니다 — Central의 요청에 따라 전송되는 두 번째 패킷입니다.
Bluetooth Core Specification 5.4(2023)에 따르면 단일 GATT 서버의 기본 서비스 최대 수는 사양에 의해 제한되지 않지만 실제로는 장치 메모리 및 성능 요구 사항에 의해 제한됩니다. 256KB 플래시 메모리가 있는 임베디드 장치의 경우 5~10개 이하의 서비스를 권장합니다.
자주 묻는 질문
16비트 UUID는 Bluetooth SIG가 표준 서비스를 위해 예약했으며 광고 패킷에서 2바이트를 차지합니다. 128비트 UUID는 사용자 정의 서비스에 사용되며 16바이트를 차지합니다. 선택은 서비스 유형에 따라 다릅니다: 표준 기능은 16비트 UUID를 사용하고 고유 기능은 128비트 UUID를 사용합니다.
UUID v4를 사용하세요 — 온라인 도구, 터미널 명령 uuidgen 또는 프로그래밍 언어 API로 생성되는 무작위 UUID입니다. 예: Java의 UUID.fromString(UUID.randomUUID().toString()) 또는 Swift의 UUID().
아니요, 등록이 필요하지 않습니다. Bluetooth SIG는 16비트 UUID만 등록합니다. 사용자 정의 128비트 UUID는 개발자가 독립적으로 생성하며 방대한 주소 공간(2^128 조합) 덕분에 고유성을 보장합니다.
네, 표준 GATT 서비스에는 무제한의 특성이 포함될 수 있습니다. 예를 들어 Battery Service에는 Battery Level(0x2A19)과 Battery Power State(0x2A1A)가 포함될 수 있습니다. 각 특성에는 고유한 UUID와 속성 집합이 있습니다.
UUID가 일치하면 Central은 추가 정보 없이 서비스를 구분할 수 없습니다. 무작위 UUID v4의 충돌 확률은 무시할 수 있을 정도로 낮습니다 — 약 5.3 × 10^−37. 무작위 UUID 생성기를 사용하고 예제에서 UUID를 복사하지 마세요.
요약
턴키 방식의 모바일 애플리케이션을 개발해 드립니다
IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.