핵심 요약
- Flask 창시자이자 센트리 출신 아민 로나허가 러스트 표준 직렬화 라이브러리 Serde의 구조적 결함과 대안 라이브러리 'Deser'를 정리해 발표했습니다.
- Serde는 하위 호환성 제약과 스택 재귀 기반 설계 때문에 태그 enum 파싱 오류, flatten 시 정수 키 유실 등 고질적 문제를 해결하기 어렵습니다.
- Deser는 힙/아레나 기반 이벤트 푸시 구조로 스택 재귀를 없애고 설계를 단순화하여 대규모 JSON 처리 등에서의 한계를 극복하고자 했습니다.
요약 파이썬 Flask의 창시자이자 센트리(Sentry) 출신 유명 개발자 아민 로나허(Armin Ronacher)가 Rust 진영의 사실상 표준 직렬화 라이브러리인 'Serde'의 고질적 한계와 이를 해결하기 위해 개발 중인 대체 라이브러리 'Deser'를 공개했습니다.
Serde는 러스트 생태계의 생산성을 크게 끌어올린 핵심 라이브러리지만, 오랜 세월 강력한 하위 호환성 보장 정책에 묶여 근본적인 설계 결함을 고치지 못하고 있습니다. 필자가 제시한 대표적인 문제점은 세 가지입니다. 첫째, 임의 정밀도 숫자(arbitrary precision) 옵션을 켤 경우 내부 태그 enum 파싱 시 버퍼가 매직 키를 인식하지 못해 숫자가 map으로 잘못 인식되는 현상입니다. Cargo 특성상 의존성 트리의 어떤 크레이트 하나만 이 옵션을 켜도 프로젝트 전체에 영향을 미칩니다. 둘째, `#[serde(flatten)]`을 사용할 때 정수형 키를 가진 맵을 파싱하면 버퍼링 과정에서 타입 정보를 잃고 단순 문자열로 처리되어 에러가 발생하며, 에러 위치도 엉뚱하게 문서 끝을 가리키는 문제입니다. 셋째, 커스텀 역직렬화 함수 어댑터(`deserialize_with`)가 합성되지 않아 Option이나 Vec 내부 요소에 재사용할 수 없고 래퍼 함수를 매번 따로 만들어야 하는 번거로움입니다.
이러한 문제들은 버그라기보다는 Serde의 근본적 설계 선택에서 비롯됩니다. 모든 포맷(자기 기술 포맷과 비자기 기술 포맷)을 하나의 트레이트로 처리하려다 보니 런타임에만 문제가 드러나고, 버퍼링 시 정보가 유실되며, 중첩 구조 처리 시 콜 스택 재귀 호출을 사용하여 스택 오버플로 위험이 존재합니다.
이를 해결하기 위해 개발된 'Deser'는 Serde의 구조를 완전히 뒤집었습니다. 타입이 역직렬화를 주도하고 재귀를 타는 Serde와 달리, Deser는 포맷이 다음 값 이벤트를 sink에 밀어넣는 푸시 방식을 사용합니다. 중첩 값이 시작되면 드라이버에 새 sink를 넘겨 모든 상태를 힙(아레나 메모리)에서 관리하므로 스택 재귀 폭주 문제를 원천 차단합니다. 대신 Protobuf처럼 스키마가 미리 필요한 비자기 기술 포맷 지원을 과감히 포기함으로써 설계의 명확성을 확보했습니다. 센트리 릴레이(Sentry Relay)에서 대규모 비신뢰 JSON 데이터를 처리하며 겪은 한계에서 출발한 이 실험적 프로젝트가 러스트 직렬화 생태계에 새로운 대안을 제시할 수 있을지 기대를 모으고 있습니다.
Sponsored · 광고