Rust binding 패키지들(orjson, polars...)
요즘 회사에서 아예 데이터분석 및 AI 관련 python 엔진쪽에만 개발을 맡아서 하고있어서 중간중간 심심할 때 뭐 괜찮은 패키지가 python 관련팁이 있나 기웃거리고있다. 그러던 와중 Rust 를 활용해서 순수 python은 물론이고 c 바인딩 패키지들을 웃도는 퍼포먼스를 내는 Rust 바인딩 패키지들을 발견하고 사용하게 되어서 소개해보려한다.
orjson
orjson 같은경우는 현재 우리팀에서 데이터분석 시각화관련 데이터를 json 파일로 저장한뒤 그거를 그대로 서버에서 전송하는경우가 있어서 json serialize 를 좀 더 빠르게 해주고 파서 찾아보았다. 이뿐만아니라 NaN이나 numpy(←이게 미쳤음) 같은 json 에서 지원하지않는 데이터타입도 serialize 잘해줘서 더더욱 기존 코드를 많이 대체할 수 있었다.
기본 예제
import orjson
# Python 객체 → JSON 직렬화
data = {"id": 1, "name": "Heejae", "active": True}
json_bytes = orjson.dumps(data)
print(json_bytes)
# b'{"id":1,"name":"Heejae","active":true}'
# JSON 문자열 → Python 객체
obj = orjson.loads(json_bytes)
print(obj)
# {'id': 1, 'name': 'Heejae', 'active': True}
orjson.dumps()의 반환값은 bytes라는 점이 특징이다. 만약 문자열이 필요하다면 .decode()를 붙여주면 된다. Pydantic 모델/Dataclass 도 비슷하게 직렬화가 가능하고. 덕분에 FastAPI 같은 프레임워크에서 orjson을 기본 Response Serializer로 설정해 쓰는 경우가 많다(ORJSONRespone).
주요 옵션
OPT_INDENT_2
: 사람이 읽기 좋은 포맷(들여쓰기)OPT_SORT_KEYS
: 키 정렬OPT_NAIVE_UTC
: naive datetime을 UTC로 처리OPT_SERIALIZE_NUMPY
: numpy 배열 직렬화 지원
이외에도 JSON 스펙 상 허용되지 않는 NaN, Infinity 같은 값 처리도 옵션으로 가능하다.
orjson 대신 c바인딩인 ujson 이라는것도있는데 이미 orjson 이 훨씬 압도적인 퍼포먼스라 굳이 쓸 이유가 없어보인다
Polars
polars는 예전부터 알고있었는데 딱히 dataframe 상으로 많이 조작하는게 없었다가 최근에 리서치팀분에게 이런패키지가 있다고 알려드렸더니 너무좋아하시면서 당장도입해야겠다고 하셨었다.
왜 polars인가?
빠른 성능
Rust + 멀티스레드 최적화 덕분에 수천만 ~ 수억 행도 무리 없이 처리 가능.
Lazy Evaluation 지원
쿼리를 최적화해서 실행하므로, 불필요한 연산을 줄이고 속도를 크게 향상시킴.
메모리 효율성
Apache Arrow 포맷 기반으로, pandas보다 훨씬 적은 메모리로 대규모 데이터 처리 가능.
직관적인 API
pandas 유저가 쉽게 적응할 수 있는 직관적인 문법 제공.
기본예제
import polars as pl
# CSV 로드
df = pl.read_csv("data.csv")
# 기본 조회
print(df.head())
# 필터링 & 선택
filtered = df.filter(pl.col("age") > 30).select(["name", "age"])
print(filtered)
# 그룹바이 & 집계
agg = df.groupby("city").agg([
pl.col("salary").mean().alias("avg_salary"),
pl.count().alias("count")
])
print(agg)
pandas와 문법이 꽤 유사하면서도, 체이닝 방식이 훨씬 깔끔하다.
pandas와 비교했을 때 장단점
장점
- 대규모 데이터 처리 속도가 압도적(멀티스레드 활용)
- SQL-like 쿼리 최적화 지원 (LazyFrame)
- Arrow 포맷 기반으로 다양한 언어와 호환성 우수
단점
- pandas 생태계에 비해 아직 라이브러리 호환성이 적음
- 머신러닝 라이브러리(예: scikit-learn, XGBoost)와의 직접 연동은 제한적 → 중간에
to_pandas()
변환 필요 - 학습 곡선이 약간 있음
이 두 라이브러리 외에도 Robyn 같이 Rust 기반 비동기 서버 프레임워크같은 많은 라이브러리들이 있다. https://github.com/PyO3/pyo3#tools-and-libraries 이 링크에서 보듯 PyO3 라는 것을 이용해서 Rust 와 Python 을 결합시키는 것 같다.
이러한 것들을 봤을 때 Python 자체도 속도가 올라오고있지만 나중에는 glue 코드로서의 Python 만 남아있을 수도 있다는 생각을 한다.