파이썬 cbor2로 CBOR 직렬화하기, IoT와 임베디드에서 쓰는 바이너리 데이터 포맷 완전 정리
📌 파이썬 cbor2와 CBOR로 더 작고 빠르게 데이터를 보내는 방법
센서 데이터를 주고받는 작은 보드나 배터리로만 동작하는 IoT 기기한테 JSON 문자열은 조금 버겁다는 얘기, 한 번쯤 들어본 적 있을 겁니다.
문자열 키가 길고, 숫자도 전부 텍스트라서 전송 크기가 커지죠.
이럴 때 훨씬 가볍고 이식성 좋은 포맷으로 많이 언급되는 게 CBOR이라는 바이너리 직렬화 포맷입니다.
CBOR은 IETF에서 표준화된 포맷이고, 아주 작은 코드로도 구현 가능하고, 메시지도 짧게 만들 수 있게 설계되어 있어서 임베디드나 IoT 통신 프로토콜에서 즐겨 쓰입니다.
실제로 CBOR은 CoAP 계열 등 IoT 환경에서 권장되는 데이터 표현 방식이고, FIDO2 인증 장치 같은 보안 장비에서도 사용될 만큼 신뢰성이 높은 편으로 알려져 있습니다.
이 글에서는 파이썬에서 CBOR을 쉽게 다룰 수 있게 해주는 라이브러리인 cbor2를 기준으로, 왜 CBOR이 IoT·임베디드 친화적인지, 정수나 날짜, 바이너리 같은 값이 어떻게 태그 형태로 표현되는지, 그리고 deterministic 인코딩이라는 중요한 키워드가 왜 요즘 더 주목받는지까지 한 번에 정리해보려고 합니다.
파이썬 측면에서 보면 cbor2는 표준 라이브러리의 json 모듈처럼 dumps, loads 식으로 직렬화/역직렬화를 바로 쓸 수 있고, 큰 정수(bignum)나 반정밀 부동소수(float16) 같은 것도 처리할 수 있게 설계된 점이 매력 포인트입니다.
CBOR은 “Concise Binary Object Representation”의 약자로, 사람이 읽기 편한 대신 덩치가 커지기 쉬운 JSON과 달리 바이너리 구조로 데이터를 담아서 더 짧고 전송 비용이 적습니다.
게다가 CBOR은 단순히 JSON을 이진화한 수준이 아니라, JSON에 없는 타입들도 기본으로 지원합니다.
예를 들어 64비트 범위를 넘어가는 아주 큰 정수(빅인트), 원시 바이트 시퀀스(바이너리), 날짜/시간 정보, 심지어 반정밀도(float16) 부동소수까지 직접 담을 수 있습니다.
cbor2 같은 파이썬 구현은 이런 값을 태그(tag)라는 메커니즘으로 표현하고 다시 복원해주는데, 이 덕분에 파이썬 객체(예: datetime.date 등)를 안전하게 주고받을 수 있는 구조를 제공합니다.
또 하나 중요한 특징이 deterministic 인코딩이라는 개념입니다.
같은 데이터라면 인코딩 결과 바이트 스트림도 항상 같아야 한다는 요구사항인데, 보안 토큰 서명, 캐시 키, 무결성 검증 같은 영역에서는 이게 사실상 필수 규칙처럼 다뤄지고 있습니다.
RFC 8949 이후에는 “Common Deterministic Encoding”이라는 베스트 프랙티스까지 정리되고 있을 정도로, CBOR 진영에서 계속 발전 중입니다.
쉽게 말하면 CBOR은 작고 빠르고, 형식이 안정적이고, 기계가 다루기 편하며, 검증도 쉬운 포맷이라서 임베디드·IoT 장비와 서버 사이의 데이터 교환에 굉장히 잘 맞습니다.
📋 목차
📡 CBOR과 파이썬 cbor2의 기본 원리
CBOR은 Concise Binary Object Representation의 약자로, 이름 그대로 데이터를 아주 간결한 바이너리 형태로 직렬화하는 포맷입니다.
IETF 인터넷 표준(RFC 8949)으로 관리되고 있고, 목표 자체가 명확합니다.
코드 크기는 아주 작게, 메시지 크기도 짧게, 그리고 다양한 타입을 확장 가능하게.
즉 리소스가 부족한 환경에서도 안정적으로 돌 수 있게 설계된 포맷이라는 거죠.
JSON과 비교해보면 감이 더 쉽게 옵니다.
JSON은 사람이 읽기 편한 문자열 중심 구조라서, 숫자든 바이너리든 결국 문자 형태의 텍스트로 감싸서 보내게 됩니다.
반면 CBOR은 처음부터 “기계 친화적”을 전제로 해서, 숫자면 숫자 그대로, 바이트면 바이트 그대로 패킹합니다.
덕분에 전송 데이터가 훨씬 짧아지고 파싱도 빠릅니다.
이 특징은 특히 IoT(배터리로만 동작, 네트워크가 불안정, 패킷 크기가 제한된 경우 많음)나 임베디드 시스템(메모리 수십 KB~수백 KB 단위로 아끼는 환경) 쪽에서 굉장히 중요합니다.
실제로 CBOR은 CoAP 같은 IoT용 경량 프로토콜 계열에서 권장되는 표현 방식이며, FIDO2의 인증 장치 등에서도 안전하게 구조화된 데이터를 교환할 때 쓰이고 있습니다.
파이썬에서는 cbor2 라이브러리를 사용하면 CBOR 인코딩/디코딩을 바로 쓸 수 있습니다.
cbor2는 파이썬 객체를 CBOR 바이트로 변환(dumps / dump)하고, 그 반대로 바이트를 다시 파이썬 객체로 복구(loads / load)하는 식으로 작동합니다.
느낌상 json 모듈이랑 거의 동일한 인터페이스라서, 기존 JSON 직렬화 코드를 CBOR 기반으로 바꾸는 진입 장벽이 낮습니다.
흥미로운 건 cbor2가 단순히 dict, list, str, int 같은 기본 타입만 지원하는 게 아니라는 점입니다.
CBOR 자체가 이미 다양한 타입을 기본 스펙으로 갖고 있고(예: 정수, 부동소수, 바이너리 시퀀스, 텍스트 문자열, 배열, 맵 등), 여기에 더해 “태그(tag)”라는 기능으로 날짜/시간 같은 의미까지 넣을 수 있게 해줍니다.
cbor2는 이런 태그 기반 의미 정보를 파이썬 쪽에서 datetime 같은 실제 객체로 되살릴 수 있도록 디코딩 훅을 지원합니다.
즉 단순히 직렬화 포맷이 아니라, 타입 정보와 의미(semantic type)까지 같이 주고받는 구조라고 보면 됩니다.
CBOR의 인코딩 방식 자체도 꽤 치밀합니다.
각 데이터 아이템은 “헤더 한 바이트 + 필요 시 추가 길이 정보 + 실제 페이로드” 순서로 이루어진 바이트 스트림으로 표현됩니다.
헤더에는 어떤 종류(type)의 값인지, 그리고 그 값의 길이나 크기가 어느 정도인지가 함께 담깁니다.
그래서 수십 바이트짜리 미세한 센서 데이터라도 매우 촘촘하게 모아 보낼 수 있고, 반대로 디코더 입장에서는 헤더를 읽는 것만으로 다음에 어떤 바이트를 얼마나 읽을지 바로 알 수 있습니다.
이 구조 덕분에 CBOR은 메시지 길이가 짧고, 파싱도 빠르고, 구현 코드까지 작게 만들 수 있게 되어 있습니다.
또 한 가지 실무에서 체감되는 장점은 “확장 가능성”입니다.
CBOR은 표준 타입 외에도 새로운 태그 번호를 정의해서 새로운 의미 체계를 안전하게 붙일 수 있도록 설계돼 있습니다.
이건 버전 협상 없이도 점진적으로 기능을 확장할 수 있다는 뜻이라, 하드웨어 펌웨어나 장치 프로토콜을 자주 못 바꾸는 환경에서 특히 유용합니다.
💡 TIP: 파이썬 cbor2는 순수 파이썬 구현이면서도 선택적으로 C 백엔드를 사용해 성능을 끌어올릴 수 있게 되어 있습니다.
즉 라즈베리파이 계열이나 PyPy 환경 같은 데서도 비교적 빠르게 동작하도록 설계되어 있다는 점이 현업에서 꽤 사랑받는 이유입니다.
🔐 태그로 표현되는 정수, 날짜, 바이너리 데이터
CBOR의 진짜 매력은 ‘태그(tag)’ 시스템에 있습니다.
태그는 단순한 데이터 값에 ‘이게 어떤 의미를 갖는지’를 추가로 명시할 수 있게 해주는 확장 메커니즘이에요.
예를 들어 단순히 숫자 1700000000000000000000000을 보낸다고 해도, CBOR은 그걸 “아주 큰 정수(bignum)”로 지정해서 정확하게 표현할 수 있습니다.
JSON에서는 이 정도 크기의 수가 정밀도 손실 없이 표현되지 않기 때문에, CBOR이 훨씬 안정적이죠.
태그는 RFC 8949에서 명시된 기본 규칙에 따라 동작합니다.
각 데이터 항목 앞에 ‘태그 번호’를 붙이면, 수신 측에서 해당 번호에 맞는 의미를 해석할 수 있습니다.
예를 들어 태그 0은 날짜/시간을 나타내고, 태그 2는 양의 큰 정수(bignum), 3은 음의 큰 정수, 21은 정규표현식, 22는 MIME 타입을 의미합니다.
이런 태그 덕분에 단순한 이진 포맷임에도 데이터의 맥락을 잃지 않고 유지할 수 있죠.
import cbor2
from datetime import datetime
data = {
"id": 123,
"timestamp": datetime.utcnow(),
"payload": b"\xde\xad\xbe\xef"
}
encoded = cbor2.dumps(data)
decoded = cbor2.loads(encoded)
print(decoded)
위 예시에서 datetime 객체는 CBOR 내부적으로 태그 0을 통해 ISO 8601 형식의 시간 문자열로 인코딩됩니다.
바이너리 데이터(payload)는 별도의 타입으로 저장되며, 텍스트 문자열과 구분되어 네트워크 전송 중에도 손상되지 않습니다.
이런 특성이 있기 때문에 CBOR은 IoT 환경에서 펌웨어나 센서 데이터 전송에 최적화되어 있는 겁니다.
흥미로운 점은 태그 시스템이 단지 “표준 태그 번호”로만 제한되지 않는다는 것입니다.
직접 정의한 사용자 태그를 통해, 특정 도메인에서만 의미 있는 데이터 구조를 표현할 수도 있습니다.
예를 들어 태그 1000번대를 자사 프로토콜 전용 포맷으로 예약해서, 센서 데이터 패킷이나 암호화된 페이로드를 자체 규칙으로 정의할 수 있습니다.
수신 측에서도 같은 태그 해석기를 두면, 손쉽게 확장 가능한 데이터 전송 체계를 구축할 수 있죠.
💎 핵심 포인트:
CBOR은 단순히 데이터를 “작게” 만드는 것에 그치지 않습니다.
그 안에 “의미(semantic)”까지 담을 수 있는 구조이기 때문에, IoT 장치처럼 스키마가 자주 바뀌지 않는 환경에서 장기적인 호환성과 안정성을 제공합니다.
⚙️ IoT·임베디드 친화적인 이유
CBOR이 IoT와 임베디드 환경에서 인기가 높은 이유는 단순히 “용량이 작아서”가 아닙니다.
진짜 핵심은 구조적 효율성, 확장성, 그리고 계산 리소스를 거의 쓰지 않는 설계 방식에 있습니다.
CBOR은 데이터를 인코딩할 때 메타데이터(길이, 타입 등)를 최소화하고, 해석할 때도 정해진 규칙에 따라 빠르게 파싱할 수 있습니다.
이 말은 곧 CPU 부하와 메모리 사용량이 줄어든다는 뜻이에요.
IoT 기기나 마이크로컨트롤러(MCU) 기반 보드는 대체로 연산 속도와 메모리가 제한되어 있습니다.
예를 들어 ESP32나 STM32 계열 칩은 수십 MHz~수백 MHz CPU에 RAM도 수백 KB 단위밖에 되지 않습니다.
이런 장치에서 JSON을 문자열 기반으로 처리하면 파싱 과정에서 문자열 버퍼를 계속 할당해야 하고, float 변환도 반복적으로 일어나기 때문에 전력 소모가 커집니다.
CBOR은 이런 불필요한 문자열 처리 과정이 거의 없어서 훨씬 효율적이에요.
게다가 바이너리 기반이라 UTF-8 인코딩 문제나 따옴표 이스케이프 같은 불편함도 사라집니다.
또 다른 장점은 네트워크 전송 효율입니다.
MQTT나 CoAP 같은 IoT용 경량 메시징 프로토콜에서 CBOR을 페이로드로 사용하면, 같은 구조의 데이터를 JSON보다 30~60% 정도 더 작게 보낼 수 있습니다.
이 차이는 Wi-Fi가 아닌 LoRa나 BLE 같은 저대역폭 환경에서는 훨씬 크게 체감됩니다.
전송 크기가 줄면 배터리 수명도 길어지고, 전송 지연도 줄어들죠.
즉, CBOR은 IoT 네트워크에서 ‘데이터 포맷의 최적화’ 그 자체라고 할 수 있습니다.
파이썬 cbor2는 이런 구조 덕분에 임베디드 디바이스와 서버 간 통신에서도 자주 사용됩니다.
특히 서버는 cbor2를 이용해 CBOR로 인코딩된 데이터를 빠르게 파싱하고, 반대로 장치는 마이크로파이썬(micropython-cbor) 같은 경량 구현으로 동일한 데이터를 생성할 수 있습니다.
서로 다른 플랫폼이지만, 동일한 CBOR 구조를 기반으로 완벽하게 호환되는 것이죠.
이건 IoT 생태계에서 큰 장점으로 작용합니다.
또 하나 주목할 부분은 CBOR의 안정적인 디코딩 구조입니다.
CBOR은 각 타입의 길이를 명시적으로 포함하기 때문에, 스트림을 읽다가 중간에 끊기거나 손상되어도 비교적 쉽게 오류를 감지할 수 있습니다.
이건 네트워크 품질이 불안정한 IoT 환경에서 굉장히 중요한 특징이에요.
즉, 데이터 손실 감지 및 복구가 쉬운 구조라 실제 산업용 IoT 현장에서도 채택률이 점점 늘어나고 있습니다.
⚠️ 주의: CBOR은 효율적이지만, 디버깅 과정에서는 사람이 읽기 어려운 바이너리 형태라는 점을 고려해야 합니다.
테스트 중에는 cbor2.tool 또는 cbor-diag 같은 도구로 구조를 시각적으로 확인하는 것이 좋습니다.
🧮 deterministic 인코딩과 신뢰성
CBOR의 또 다른 강력한 특징 중 하나는 바로 deterministic 인코딩입니다.
이 개념은 같은 데이터가 주어졌을 때, 인코딩된 바이트 스트림이 항상 동일해야 한다는 원칙을 말합니다.
일반적인 직렬화 포맷에서는 딕셔너리 순서가 바뀌거나 부동소수점 표현 방식이 달라지면 결과가 달라질 수 있지만, deterministic 모드는 이런 변동을 완전히 없애버립니다.
이게 왜 중요할까요?
예를 들어, CBOR 데이터를 전자 서명하거나 해시 검증을 해야 하는 경우를 생각해보면 금세 이해됩니다.
만약 같은 내용인데 인코딩할 때마다 결과가 다르면 서명 검증이 불가능하겠죠.
그래서 CBOR은 RFC 8949 이후부터 ‘Common Deterministic Encoding’이라는 표준 규칙을 정의했습니다.
이 규칙에 따라 모든 키는 정렬된 순서로 배치되고, 수와 문자열 표현은 가장 짧고 명확한 형태로 인코딩되며, 불필요한 가변 표현을 허용하지 않습니다.
파이썬 cbor2 라이브러리에서도 canonical=True 옵션을 주면 deterministic 모드로 데이터를 인코딩할 수 있습니다.
이 모드를 사용하면, 동일한 데이터 구조를 여러 번 직렬화하더라도 매번 같은 바이트 결과를 얻게 됩니다.
이건 블록체인, 보안 토큰, 인증서 서명, 혹은 캐시 시스템 같은 곳에서 매우 중요한 보장입니다.
import cbor2
data = {"b": 1, "a": 2}
encoded = cbor2.dumps(data, canonical=True)
print(encoded.hex())
위 코드에서 canonical=True를 지정하면, CBOR은 내부적으로 키를 정렬해 ‘a’ → ‘b’ 순서로 인코딩합니다.
이렇게 하면 어떤 환경에서 실행하든 동일한 바이트 결과를 얻을 수 있고, 나중에 SHA-256 같은 해시 알고리즘으로 검증할 때도 결과가 일관되게 나옵니다.
결국 deterministic 인코딩은 “데이터 무결성과 재현성”을 확보하기 위한 필수 옵션이라 할 수 있습니다.
CBOR은 이 deterministic 인코딩 덕분에 IoT뿐 아니라 보안 기술 영역에서도 점점 더 많이 활용되고 있습니다.
FIDO2 프로토콜, WebAuthn 인증 토큰, COSE 서명 메시지 같은 곳에서도 CBOR이 표준 직렬화 포맷으로 자리 잡은 이유가 바로 여기에 있습니다.
데이터를 작게 만들면서도, 재현성과 무결성을 보장할 수 있는 포맷이기 때문이죠.
💎 핵심 포인트:
CBOR의 deterministic 인코딩은 단순한 옵션이 아니라, 보안·신뢰성을 위해 반드시 지켜야 하는 규칙입니다.
이 덕분에 CBOR은 암호화 인증, 서명 검증, 캐시 무결성 보장 같은 민감한 시스템에서도 널리 채택되고 있습니다.
📏 큰 정수와 반정밀 float 처리
CBOR은 기본적으로 JSON보다 훨씬 폭넓은 수치 타입을 지원합니다.
특히 큰 정수(bignum)와 반정밀도(float16) 부동소수점 타입은 CBOR을 고성능 IoT 포맷으로 만들어주는 핵심 요소입니다.
일반적인 JSON은 자바스크립트의 number 한계(53비트 정밀도) 때문에 매우 큰 정수나 특수한 실수를 정확히 표현하지 못하지만, CBOR은 그런 제약이 없습니다.
큰 정수는 태그 2(양수)와 태그 3(음수)을 사용해 표현되며, 임의 길이의 바이트 배열로 저장됩니다.
즉, 128비트, 256비트 같은 초대형 정수도 손실 없이 직렬화할 수 있습니다.
이건 블록체인, 암호화 키, 고정밀 계산 같은 분야에서 특히 중요합니다.
예를 들어 CBOR 기반의 COSE(CBOR Object Signing and Encryption)는 공개키를 bignum 형식으로 안전하게 직렬화합니다.
파이썬 cbor2는 이런 bignum을 자동으로 int 타입으로 복원해주기 때문에 별도 변환이 필요 없습니다.
반정밀도 부동소수(float16) 역시 CBOR에서 기본적으로 지원됩니다.
float16은 16비트로 구성된 부동소수점 형식으로, 32비트 float보다 표현 범위는 좁지만 데이터 크기가 절반이라 IoT나 센서 환경에서 매우 유용합니다.
예를 들어 온도, 압력, 전류 등 소수점 두세 자리 정밀도만 필요한 데이터라면 float16으로 충분하죠.
덕분에 전송 크기를 줄이면서도 필요한 수준의 정확도는 유지할 수 있습니다.
import cbor2
import numpy as np
data = {
"big": 2**200,
"sensor": np.float16(24.375)
}
encoded = cbor2.dumps(data)
decoded = cbor2.loads(encoded)
print(decoded)
이 코드에서는 2200이라는 초대형 정수와 16비트 부동소수(float16)가 모두 CBOR로 손실 없이 직렬화됩니다.
JSON으로는 표현이 불가능하거나 부정확해질 수 있는 데이터들이 CBOR에서는 안정적으로 전송되고 복원되는 거죠.
즉, CBOR은 단순한 포맷이 아니라 ‘숫자 표현의 정확성’을 보장하는 구조라고 할 수 있습니다.
💡 TIP: 파이썬에서 float16을 다루려면 numpy.float16 타입을 사용하는 것이 좋습니다.
cbor2는 numpy 객체도 자동 직렬화 대상이므로, 센서 데이터 처리 파이프라인에서 바로 CBOR 변환을 적용할 수 있습니다.
이처럼 CBOR은 단순히 데이터를 압축적으로 표현하는 포맷이 아니라, 수치 데이터의 정밀도까지 제어할 수 있는 구조를 갖추고 있습니다.
이건 IoT, 암호화, 보안, 그리고 고정밀 연산을 다루는 현대 파이썬 개발 환경에서 큰 경쟁력이 되는 요소입니다.
❓ 자주 묻는 질문 (FAQ)
CBOR과 JSON의 가장 큰 차이는 무엇인가요?
또한 JSON이 문자열 중심인 반면, CBOR은 숫자·바이너리·날짜 등 다양한 데이터 타입을 직접 표현할 수 있습니다.
cbor2 라이브러리는 파이썬 표준 라이브러리인가요?
PyPI에서 pip install cbor2로 손쉽게 설치할 수 있습니다.
표준 라이브러리는 아니지만, RFC 8949 스펙을 충실히 따르는 안정적인 구현체입니다.
CBOR의 deterministic 인코딩은 언제 필요한가요?
CBOR의 canonical 인코딩 옵션이 바로 이런 상황에 맞춰 설계되었습니다.
CBOR은 IoT 외에도 어디에 사용되나요?
또한 블록체인, 인증 토큰, 금융 데이터 전송 등에서도 빠르고 안정적인 직렬화 포맷으로 채택되고 있습니다.
CBOR에서 태그(tag)는 꼭 써야 하나요?
하지만 날짜나 큰 정수, 바이너리 데이터처럼 JSON으로는 구분이 어려운 타입을 표현할 때 매우 유용합니다.
태그를 사용하면 의미(semantic)를 함께 전달할 수 있어 데이터 호환성이 좋아집니다.
CBOR이 BSON이나 MessagePack보다 좋은 점이 있나요?
특히 태그 시스템과 deterministic 인코딩을 지원하기 때문에, 신뢰성과 재현성이 필요한 환경에서는 CBOR이 더 적합합니다.
CBOR로 직렬화한 데이터를 사람이 읽을 수 있나요?
대신 cbor2.tool이나 cbor-diag 도구를 사용하면 사람이 읽을 수 있는 형태로 구조를 출력할 수 있습니다.
CBOR은 향후 JSON을 완전히 대체할까요?
즉, CBOR은 ‘대체’보다는 ‘보완’의 개념으로 자리잡고 있습니다.
📘 파이썬 cbor2로 여는 차세대 데이터 직렬화의 핵심
CBOR은 단순히 “이진화된 JSON”이 아닙니다.
정확히는, IoT와 임베디드 시대에 맞게 진화한 차세대 데이터 직렬화 포맷이라 할 수 있습니다.
파이썬의 cbor2 라이브러리를 통해 우리는 더 작고, 더 빠르고, 더 정확한 데이터 교환을 손쉽게 구현할 수 있습니다.
특히 태그를 활용한 의미 정보 표현, deterministic 인코딩을 통한 무결성 확보, 큰 정수 및 반정밀 float 지원 등은 단순한 효율성을 넘어 시스템 신뢰성까지 끌어올려 줍니다.
이제 CBOR은 CoAP, FIDO2, WebAuthn 등 다양한 표준에서 사실상 필수 포맷으로 자리잡았고, JSON의 한계를 보완하는 역할을 하고 있습니다.
데이터가 기기 간, 네트워크 간, 그리고 언어 간을 오가는 시대에 CBOR은 그 중심에서 안정적이고 효율적인 다리 역할을 해주고 있습니다.
cbor2를 활용하면 파이썬 개발자도 이 표준의 이점을 손쉽게 누릴 수 있죠.
IoT 프로젝트, 보안 토큰, 인증 시스템, 혹은 단순히 더 빠른 직렬화가 필요한 곳이라면 CBOR은 분명 값진 대안이 될 겁니다.
파이썬의 강력한 생태계와 결합된 cbor2는 바로 그 실용적인 시작점입니다.
🏷️ 관련 태그 : CBOR, cbor2, 파이썬직렬화, IoT데이터, 임베디드시스템, deterministic인코딩, 반정밀float, 빅인트처리, 데이터포맷, CoAP프로토콜