재재의 개발블로그

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).

주요 옵션

이외에도 JSON 스펙 상 허용되지 않는 NaN, Infinity 같은 값 처리도 옵션으로 가능하다.

orjson 대신 c바인딩인 ujson 이라는것도있는데 이미 orjson 이 훨씬 압도적인 퍼포먼스라 굳이 쓸 이유가 없어보인다

Polars

polars는 예전부터 알고있었는데 딱히 dataframe 상으로 많이 조작하는게 없었다가 최근에 리서치팀분에게 이런패키지가 있다고 알려드렸더니 너무좋아하시면서 당장도입해야겠다고 하셨었다.

왜 polars인가?

기본예제

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와 비교했을 때 장단점

장점

단점

이 두 라이브러리 외에도 Robyn 같이 Rust 기반 비동기 서버 프레임워크같은 많은 라이브러리들이 있다. https://github.com/PyO3/pyo3#tools-and-libraries 이 링크에서 보듯 PyO3 라는 것을 이용해서 Rust 와 Python 을 결합시키는 것 같다.

이러한 것들을 봤을 때 Python 자체도 속도가 올라오고있지만 나중에는 glue 코드로서의 Python 만 남아있을 수도 있다는 생각을 한다.

#orjson #polars #python #rust