- [Python] JSON 직렬화와 역직렬화(json, ujson, orjson, msgspec)2025년 03월 22일
- 홀쑥
- 작성자
- 2025.03.22.:34
이번 게시글은 Python에서 JSON을 직렬화, 역직렬화 하는 패키지들을 비교해보려고 한다.
TL;DR
일반적인 사용 -> json
속도와 성능 -> orjson
MessagePack을 사용하거나 타입 검증이 필요 -> msgspec
ujson -> 비추천(신규개발 중단)JSON이란?
JSON(JavaScript Object Notation)은 Javascript 객체 문법으로 구조화된 데이터를 표현하기 위한 문자 기반의 표준 포맷이다.
비록 Javascript 객체 문법이지만, 문자 기반이기에 다양한 플랫폼 및 프로그래밍 언어에서 사용할 수 있다.
# JSON 예시 { "key1" : "value1", "key2" : "value2", "key3" : { "child_key_1" : "value3", "child_key_2" : "value4" }, "key4" : [ ... ], }
직렬화와 역직렬화
직렬화
직렬화(Serialization)는 컴퓨터에서 데이터 구조나 객체 상태를 저장하거나 전송할 수 있는 형식으로 변환하고 후에 재구성이 가능하도록 하는 것이다. 보통 사람이 읽을 수 있는 문자를 사용한 텍스트 기반 형식과, 컴퓨터가 쉽게 읽을 수 있게 2진법(binary)으로 저장하는 형식이 있다. Marshalling이라고도 한다.
역직렬화
역직렬화(Deserialization)는 직렬화의 반대작업으로 직렬화된 텍스트 또는 2진법 형식을 데이터구조 또는 객체 상태로 재구성하는 과정이다. Unmarshalling이라고도 한다.
Python에선?
pickle
- Python의 객체를 Byte 단위로 직렬화 하는 내장 모듈로 Python 전용 모듈이기에 다른 언어와 호환되지 않음
json
- Python의 딕셔너리, 리스트, 문자열, 숫자 등 기본 자료형들을 문자열로 직렬화하는 내장 모듈로 다른 언어와 호환됨
Python에서 JSON 직렬화, 역직렬화
- Python에선 JSON을 다루는 라이브러리들이 여러 개 존재한다(json, ujson, orjson, simplejson, rapidjson, ...)
- 그 중 ujson, orjson, msgspec을 비교해보려고 한다.
ujson(UltraJson)
- UltraJSON은 C로 구현되어 빠른 속도를 가진 JSON 라이브러리이다.
- 기본 내장모듈인 json보다 빠르고, json과 유사하게 사용할 수 있는 게 장점이다.
- 하지만 Pypi 저장소에서 공식적으로 구조적으로 보안문제를 고치기 어려워 신규개발은 중단하고, 유지보수만 하겠다고 한다. 따라서 orjson으로 빠른 시일 내에 migrate하라고 한다.
pypi 홈페이지의 내용 일부 orjson(Optimized Rust Json)
- optimized rust json은 Rust로 구현되어 매우 빠른 JSON 라이브러리로 Python 라이브러리 중 가장 빠르다.
- 다른 종속성은 따로 없으며 CPython 3.8부터 지원되지만 PyPy, 모바일용 embedded Python build, PEP554 subinterpreters는 지원하지 않는다고 한다.
- Python 생태계에서 인기를 얻고 있다고 한다.
예제
import orjson import datetime data = {'name': '햄', 'created': datetime.datetime.now()} serialized = orjson.dumps(data) # b'{"name":"thinmug","created":"2025-03-22T00:24:32.677298"}' serialized.decode('utf-8') # '{"name":"thinmug","created":"2025-03-22T00:24:32.677298"}'
특징
성능
- 공식문서에 다른 서드파티 라이브러리보다 더 정확하고 빠르다고 설명하고 있으며 벤치마크 성능도 공개하고 있다.(ijl/orjson: Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy)
- github의 README 서론에서 기존 json보다 직렬화는 약 10배, 역직렬화는 약 2배 빠르다고 한다.
다양한 객체 직렬화 지원
- 기존의 json은 위의 객체들은 직렬화가 안되어 다른과 같은 에러가 발생한다.
# data에 datetime 객체가 들어있는 경우 import datetime import json data = {'name': '햄', 'created': datetime.datetime.now()} serialized = json.dumps(data) """ Traceback (most recent call last): ... TypeError: Object of type datetime is not JSON serializable """
- 이렇게 직렬화가 지원되지 않는 객체에 대해선 JSONEncoder를 만들어 적용하거나 dumps 시엔 default 함수(변환함수)를 통하여 커스터마이징을 했었다.
import json import datetime from dataclasses import dataclass def custom_default(obj): """datetime이나 기타 직렬화 불가능한 객체를 변환""" ... user = dict(name='thinmug', created=datetime.now()) json_str = json.dumps(user, default=custom_default) class CustomEncoder(json.JSONEncoder): def default(self, obj): """default와 같음""" ... json_str = json.dumps(user, cls=CustomEncoder)
- orjson을 사용할 경우 dataclass, datetime, numpy, 그리고 UUID 객체들도 직렬화를 지원한다.
- default 파라미터를 통해 기존 json 라이브러리와 같이 사용할 수 있다.
기본 반환값은 bytes 타입
- 내장 json 라이브러리나 ujson과 달리 문자열이 아닌 utf-8로 인코딩된 bytes로 반환한다.
- 디코딩이 필요할 경우엔 .decode('utf-8')을 통해 문자열로 치환이 필요하다.
- 하지만 공식문서에 따르면 메모리 사용량과 속도를 위해선 디코딩없이 바로 넘기라고 한다.
메모리 효율성
- Rust 기반이기에 메모리관리가 효율적이기에, 대용량 데이터를 다룰 때 효율적이다.
msgspec
- orjson과 비교되는 C로 구현된 직렬화/역직렬화 라이브러리이다.
- JSON뿐 만 아니라 MessagePack, Yaml, Toml 파일들을 지원한다.
- 아직 생태계가 작은 것 같다.
예제
import msgspec import datetime class User(msgspec.Struct): name: str created: datetime.datetime data = User("thinmug", created=datetime.datetime.now()) data # User(name='thinmug', created=datetime.datetime(2025, 3, 22, 1, 0, 35, 690114)) serialized = msgspec.json.encode(data) serialized # b'{"name":"thinmug","created":"2025-03-22T01:00:35.690114"}' decode_user = msgspec.json.decode(serialized, type=User) decode_user # User(name='thinmug', created=datetime.datetime(2025, 3, 22, 1, 0, 35, 690114)) decode_json = msgspec.json.decode(serialized) decode_json # {'name': 'thinmug', 'created': '2025-03-22T01:00:35.690114'}
특징
빠른성능
- orjson과 비슷하거나 Struct 사용 시 더 높은 성능을 제공해준다.
- 가벼운 라이브러리로 orjson과 마찬가지로 다른 종속성은 없다.
- 공식문서에서 MessagePack과 JSON에서 가장 빠르다고 써있고 벤치마크도 공개되어 있는데 msgspec structs로 직렬화시 orjson보다 빠르다고 설명되어 있다.( Benchmarks)
MessagePack 사용
- MessagePack( MessagePack: It's like JSON. but fast and small.)은 바이너리 기반 직렬화로 JSON보다 더 빠르고, 작은 사이즈로 제공할 수 있으며 JSON과 같이 다양한 언어에서 사용할 수 있어 구글의 ProtoBuf와 함께 대중적으로 사용된다.
JSON이 27bytes일 때 18bytes(2/3)만을 사용한다고 한다. 다양한 객체 직렬화 제공
- orjson과 비슷하거나 더 많은 객체 직렬화를 제공한다. (Supported Types)
낮은 메모리 사용량
- Struct가 내부적으로 최소한의 메모리로 압축하여 사용한다.
- 객체 생성 및 처리 시 불필요한 메모리 할당 최소화한다고 한다.
기본 반환값은 bytes 타입
- orjson과 동일하게 직렬화 시 bytes 타입을 반환한다.
Struct 제공
- msgspec은 고성능 데이터를 위해 Struct라는 타입(예제 참고)를 제공하는데, Python의 dataclass나 attrs와 유사하게 제공되어 친숙하게 사용할 수 있다.
- Struct는 데이터의 구조화 및 직렬화, 역직렬화에 특화되어 dataclass 대비 5~60배 빠르다고 하며 Type Annotation을 통한 zero-cost 스키마 검증 기능을 제공한다.
참고문서
- MessagePack: It's like JSON. but fast and small.
- msgspec · PyPI
- https://github.com/ijl/orjson
- JSON이란 무엇인가? | Oracle 대한민국
- ujson · PyPI
- https://en.wikipedia.org/wiki/Serialization
- msgspec
'Language > Python' 카테고리의 다른 글
[Python] Polars의 데이터 타입과 구조 (0) 2025.04.10 [Python] Polars, 빠른 속도와 낮은 메모리의 DataFrame 라이브러리 (1) 2025.04.04 [Python] Python 3.11 cchardet fatal error: longintrepr.h: No such file or directory (0) 2025.03.12 Rocky Linux에 pyenv 설치 (0) 2024.12.02 [Python] Poetry 사용법 (2) 2024.11.10 다음글이전글이전 글이 없습니다.댓글
스킨 업데이트 안내
현재 이용하고 계신 스킨의 버전보다 더 높은 최신 버전이 감지 되었습니다. 최신버전 스킨 파일을 다운로드 받을 수 있는 페이지로 이동하시겠습니까?
("아니오" 를 선택할 시 30일 동안 최신 버전이 감지되어도 모달 창이 표시되지 않습니다.)