# Apache Fory Rust – JSON/Protobuf보다 10~20배 빠른 직렬화 프레임워크

> Clean Markdown view of GeekNews topic #24063. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=24063](https://news.hada.io/topic?id=24063)
- GeekNews Markdown: [https://news.hada.io/topic/24063.md](https://news.hada.io/topic/24063.md)
- Type: GN+
- Author: [xguru](https://news.hada.io/@xguru)
- Published: 2025-11-01T07:23:15+09:00
- Updated: 2025-11-01T07:23:15+09:00
- Original source: [fory.apache.org](https://fory.apache.org/blog/2025/10/29/fory_rust_versatile_serialization_framework/)
- Points: 9
- Comments: 2

## Summary

Rust 생태계에 새로 합류한 **Apache Fory**는 직렬화의 고질적 딜레마—**성능, 유연성, 언어 호환성** 중 하나를 포기해야 했던 문제—를 정면 돌파합니다. **제로카피 기반의 타입 안전한 Rust 구현** 위에서 **IDL 없이 다언어 간 데이터 교환**을 지원하며, JSON이나 Protobuf보다 **10~20배 빠른 처리 속도**를 기록했습니다. 특히 **순환 참조·트레이트 객체·스키마 진화**를 자동 처리해 복잡한 도메인 모델이나 마이크로서비스 환경에서도 안정적으로 동작합니다. “직렬화는 느리다”는 전제를 뒤집는 이 프로젝트는, 고성능 데이터 파이프라인이나 실시간 시스템을 다루는 개발자라면 꼭 눈여겨볼 만합니다.

## Topic Body

- **Apache Fory Rust**는 **초고속 직렬화 성능**과 **자동 참조 관리**를 제공하는 **크로스랭귀지 직렬화 프레임워크**  
- Rust의 **제로카피 기술**과 **타입 안전성**을 기반으로, **순환 참조·트레이트 객체·스키마 진화**를 자동 처리  
- **IDL 파일이나 코드 생성 없이** Rust, Python, Java, Go 등 다양한 언어 간 데이터 교환 지원  
- 벤치마크 결과, JSON·Protobuf 대비 **10~20배 이상 빠른 처리 속도**를 기록  
- **마이크로서비스·데이터 파이프라인·실시간 시스템** 등 고성능 환경에서 활용 가치 높음  
  
---  
  
### 직렬화의 딜레마와 Apache Fory Rust의 등장  
- 기존 직렬화 방식은 **속도·유연성·언어 호환성** 중 하나를 포기해야 하는 한계 존재  
  - 수작업 바이너리 포맷은 빠르지만 스키마 변경에 취약  
  - JSON/Protobuf는 유연하지만 10배 이상의 성능 오버헤드  
  - 기존 솔루션은 언어 고유 기능 지원 부족  
- Apache Fory Rust는 **성능과 유연성을 동시에 확보**, **IDL·수동 스키마 관리 불필요**  
  
### 주요 특징  
- ## 1\. 진정한 크로스랭귀지 지원  
  - 동일한 **바이너리 프로토콜**을 Java, Python, C++, Go 등에서 공유  
  - Rust에서 직렬화한 데이터를 Python에서 그대로 역직렬화 가능  
  - **스키마 파일·코드 생성·버전 불일치 문제 없음**, 다언어 마이크로서비스 간 데이터 교환 단순화  
- ## 2\. 자동 순환·공유 참조 처리  
  - 대부분의 프레임워크가 실패하는 **순환 참조 구조**를 자동 추적 및 보존  
  - 동일 객체를 여러 번 참조해도 **한 번만 직렬화**, 참조 동일성 유지  
  - **그래프 데이터베이스·ORM·복잡한 도메인 모델**에 적합  
- ## 3\. 트레이트 객체 직렬화  
  - Rust의 `Box` 등 **트레이트 객체 직렬화**를 지원  
  - `register_trait_type!` 매크로로 다형적 타입 등록 가능  
  - `Box`, `Rc`, `Arc`, `dyn Any` 등 다양한 형태 지원  
  - **플러그인 시스템·이질적 컬렉션·확장 가능한 아키텍처** 구현 가능  
- ## 4\. 스키마 진화(호환 모드)  
  - **Compatible 모드**로 서비스 버전 간 스키마 변경 허용  
    - 필드 추가·삭제·순서 변경·옵션 타입 변환 가능  
    - 타입 변경은 불가  
  - **무중단 배포**와 **독립적 마이크로서비스 진화**에 유용  
  
### 기술적 기반  
- ## 프로토콜 설계  
  - 구조: `| fory header | reference meta | type meta | value data |`  
  - **가변 길이 정수·압축 메타데이터·참조 추적·리틀엔디언 레이아웃** 적용  
  - **공유 객체 중복 제거** 및 **타입 메타데이터 압축**으로 성능 향상  
- ## 컴파일 타임 코드 생성  
  - **리플렉션 대신 매크로 기반 코드 생성**으로 런타임 오버헤드 제거  
  - `#[derive(ForyObject)]` 매크로가 직렬화·역직렬화 함수 자동 생성  
  - **타입 안전성 확보**, **바이너리 크기 최소화**, **IDE 자동완성 지원**  
- ## 아키텍처 구성  
  - `fory/`: 고수준 API  
  - `fory-core/`: 직렬화 엔진 (버퍼 I/O, 타입 등록, 메타 압축 등)  
  - `fory-derive/`: 프로시저 매크로 정의  
  - **모듈화된 구조**로 유지보수성과 확장성 확보  
  
### 벤치마크 결과  
- JSON 및 Protobuf 대비 **10~20배 이상 빠른 처리 속도**  
- 예시:  
  - `simple_struct`(small) → Fory 35,729,598 TPS / JSON 10,167,045 / Protobuf 8,633,342  
  - `person`(medium) → Fory 3,839,656 TPS / JSON 337,610 / Protobuf 369,031  
- 모든 테스트 케이스에서 **Fory가 최고 성능 기록**  
  
### 활용 시나리오  
- ## 적합한 사용 사례  
  - **다언어 마이크로서비스**: 스키마 파일 없이 데이터 교환  
  - **고성능 데이터 파이프라인**: 초당 수백만 레코드 처리  
  - **복잡한 도메인 모델**: 순환 참조·다형성 구조 지원  
  - **실시간 시스템**: 1ms 이하 지연, 제로카피 역직렬화  
- ## 대안 고려  
  - 사람이 읽기 쉬운 포맷 필요 시 → JSON/YAML  
  - 장기 저장 포맷 필요 시 → Parquet  
  - 단순 데이터 구조 → serde + bincode  
  
### 시작하기  
- ## 설치  
  - `Cargo.toml`에 추가:  
    ```  
    [dependencies]  
    fory = "0.13"  
    ```  
- ## 기본 직렬화 예시  
  - `#[derive(ForyObject)]`로 구조체 등록 후 `serialize()` / `deserialize()` 사용  
  - 타입 ID 등록으로 데이터 일관성 유지  
- ## 크로스랭귀지 직렬화  
  - `compatible(true).xlang(true)` 설정으로 다언어 호환 모드 활성화  
  - ID 또는 이름 기반 등록(`register_by_namespace`, `register_by_name`) 지원  
  
### 지원 타입  
- **기본형**: bool, 정수, 부동소수, String  
- **컬렉션**: Vec, HashMap, BTreeMap, HashSet, Option  
- **스마트 포인터**: Box, Rc, Arc, RcWeak, ArcWeak, RefCell, Mutex  
- **날짜/시간**: chrono 타입  
- **사용자 정의 객체**: ForyObject, ForyRow  
- **트레이트 객체**: Box/Rc/Arc, Rc/Arc  
  
### 로드맵  
- ## v0.13에서 제공  
  - 정적 코드 생성, 제로카피 Row 포맷, 순환 참조 추적, 트레이트 객체 직렬화, 스키마 호환 모드  
- ## 예정 기능  
  - **크로스랭귀지 참조 직렬화**, **부분 Row 업데이트**  
  
### 프로덕션 고려사항  
- **스레드 안전성**: 등록 완료 후 `Arc`로 공유 가능 (`Send + Sync`)  
- **에러 처리**: `Result` 기반, 타입 불일치·버퍼 부족 등 명시적 오류 구분  
  
### 문서 및 커뮤니티  
- 공식 문서: [fory.apache.org/docs](https://fory.apache.org/docs)  
- API 문서: [docs.rs/fory](https://docs.rs/fory/latest/fory/)  
- 커뮤니티: GitHub, Slack, Issue Tracker 운영  
- **Apache License 2.0** 기반 오픈소스  
  
### 결론  
- Apache Fory Rust는 **성능·유연성·언어 호환성의 절충을 제거한 차세대 직렬화 프레임워크**  
- **매크로 기반 자동화**, **트레이트 객체 지원**, **순환 참조 처리**로 개발 효율 극대화  
- **마이크로서비스·데이터 파이프라인·실시간 시스템** 등에서 즉시 활용 가능

## Comments



### Comment 45736

- Author: qlghwp123
- Created: 2025-11-01T11:29:32+09:00
- Points: 1

이 성능이 말이 되나 ?

### Comment 45727

- Author: neo
- Created: 2025-11-01T07:23:16+09:00
- Points: 1

###### [Hacker News 의견](https://news.ycombinator.com/item?id=45736400) 
- 새로운 포맷을 만들기보다 **W3C EXI(Binary XML)** 같은 기존 기술의 툴링을 개선하는 데 집중했으면 좋겠음  
  단순히 빠르기만 해서는 부족하고, Aeron/SBT처럼 생태계가 없는 포맷은 확산이 어려움. XML은 이미 그 생태계를 갖추고 있음
  - Binary XML 인코딩은 특정 상황에서는 유용하지만, 최신 **바이너리 직렬화 포맷**들보다 효율적이지 않음  
    또한 **공유 참조나 순환 참조** 같은 복잡한 객체 그래프를 자연스럽게 표현하지 못함  
    Fory 포맷은 이런 문제를 해결하면서도 언어 간 호환성과 스키마 진화를 지원하도록 처음부터 설계되었음
  - W3C EXI나 ASN.1 BER 중 어느 것이 더 나은지는 모르겠지만, **DOP(데이터 중심 설계)** 접근이 맞다고 생각함  
    즉, 인코딩을 먼저 설계하고 언어나 클라이언트로 거꾸로 확장하는 방식이 바람직함

- 벤치마크가 공정한지 의문이 듦  
  [코드 링크](https://github.com/apache/fory/blob/fd1d53bd0fbbc5e0ce6d53ef7a2ca06935539abf/rust/benches/src/lib.rs#L205-L213)를 보면, Fory 구조체가 아닌 경우 직렬화 과정에서 **to/from 변환**이 포함되어 있음  
  이 변환 과정에서 문자열 복제나 배열 재할당이 발생함  
  실제 시스템에서는 [tonic](https://github.com/hyperium/tonic/blob/147c94cd661c0015af2e54e44fc750c9f5572e21/tonic/src/codec/mod.rs#L26)이 8KB 버퍼를 제공하므로, 단순 Vec::default()보다 효율적일 것임  
  - 이 벤치마크는 **공정하지 않음**  
    Xeon Gold 6136 CPU 기준으로 10배 향상처럼 보이지만, to/from 변환과 Vec 복제를 제거하고 8KB 버퍼를 미리 할당하면 실제로는 3배 수준임  
    벤치마크는 Fory 관련 코드가 전혀 없는 **tower service/codec 스타일**로 다시 작성되어야 함  
    Fory는 테스트 중 **writer pool**을 사용하고 있음  
    [관련 코드](https://github.com/apache/fory/blob/fd1d53bd0fbbc5e0ce6d53ef7a2ca06935539abf/rust/fory-core/src/fory.rs#L366) 참고

- 장기적으로 언어 간 호환성을 유지하려면 **IDL 기반의 명세화된 계약**이 필요하다고 생각함  
  언어에서 직렬화로 출발하는 접근은 초기엔 편하지만, 시간이 지나면 언어 런타임 변화에 취약해짐
  - 언어가 많아질수록 **공식 스키마**가 중요해짐  
    단일 언어 프로젝트는 IDL 없이도 단순하게 유지 가능하지만, 세 언어 이상부터는 IDL이 **단일 진실의 원천** 역할을 함  
    Apache Fory는 선택적으로 IDL 지원을 추가할 예정이며, 팀 상황에 맞게 언어 우선 혹은 스키마 우선 방식을 선택할 수 있게 할 계획임

- 스키마 없이 언어 간 **공유 타입**을 어떻게 유지하는지 궁금함  
  - [타입 매핑 표](https://fory.apache.org/docs/docs/guide/xlang_type_mapping)가 존재함  
    타입 언어에서는 클래스 정의에서 스키마를 유추하고, 비타입 언어에서는 코드에 직접 주석을 다는 방식임  
    Python 예시는 [여기](https://fory.apache.org/docs/docs/guide/python_serialization#cross-language-sserialization)에서 확인 가능함  
  - 다국어(polyglot) 팀을 주요 사용 사례로 내세우면서도 스키마 파일이 필요 없다고 하는 점이 혼란스러움  
    [관련 블로그 글](https://fory.apache.org/blog/2025/10/29/fory_rust_versatile_serialization_framework/#-ideal-use-cases) 참고  
  - 이런 접근이 장기적으로 잘 작동할지 **회의적임**  
  - 실제 프로덕션에서 얼마나 쓰이는지 설명이 부족해 신뢰가 가지 않음

- CapnProto나 Flatbuffers 같은 **직렬화 없는 포맷** 대신 Fory를 써야 하는 이유가 궁금함  
  압축이 필요하면 zstd를 쓰면 됨  
  그래도 Fory의 **광범위한 언어 지원**과 사용 편의성은 인상적임  
  Python에서는 여전히 dill을 선호함 — 코드 객체까지 직렬화 가능하기 때문임  
  [dill 링크](https://github.com/uqfoundation/dill)
  - dill과 비교한 벤치마크 결과, Fory가 **20~40배 빠르고 최대 7배 높은 압축률**을 보였음  
    [벤치마크 코드](https://github.com/chaokunyang/python_benchmarks) 참고  
  - Apache Fory는 **pickle/cloudpickle 대체재**로도 사용 가능하며, 로컬 함수나 클래스 같은 **코드 객체 직렬화**도 지원함  
    [예시 링크](https://github.com/apache/fory/tree/main/python#serialize-local-functionslambdas)  
    pyfory는 cloudpickle 대비 3배 높은 압축률을 보이고, **보안 감사 기능**으로 악성 역직렬화 공격을 방지함

- 벤치마크 링크가 404였지만, [정상 링크](https://fory.apache.org/docs/docs/introduction/benchmark)를 찾았음

- 이름을 “Fury”에서 “Fory”로 바꾼 게 아쉬움  
  Fury는 빠른 직렬화 프레임워크에 딱 맞는 이름이었음  
  - “Fury”는 원래 내가 지은 이름이라 애착이 있었지만, 어쩔 수 없이 변경해야 했음

- 대부분의 **바이너리 프로토콜**은 데이터 크기를 줄이려 함  
  Protobuf는 정수 압축(varint, zigzag)을 사용함  
  단순 TPS만 비교하면 C 구조체를 그대로 전송하는 “do nothing” 방식이 항상 이길 수밖에 없음  
  - Fory도 정수 압축을 지원하며, Protobuf와 **데이터 크기가 거의 동일함**  
    다양한 데이터셋에서의 비교표를 제시함
  - 두 가지 **스키마 호환 모드**가 존재하지만, 마이너 버전 간 **바이너리 호환성 보장**은 없음

- Fory의 **4096 타입 제한**이 충분한지 궁금함  
  [관련 코드](https://github.com/apache/fory/blob/fd1d53bd0fbbc5e0ce6d53ef7a2ca06935539abf/java/fory-core/src/main/java/org/apache/fory/resolver/XtypeResolver.java#L108-L109) 참고  
  - 모든 경우에 충분하지는 않겠지만, 필요하다면 확장 가능함  
    실제로 4096개 이상의 프로토콜 메시지를 정의한 사례는 거의 보지 못했음

- [Rust 벤치마크 링크](https://fory.apache.org/docs/benchmarks/rust)가 404 오류를 냄  
  [문서 루트](https://fory.apache.org/docs/)에서는 벤치마크 디렉터리를 찾을 수 없었음  
  - 아마 [이 링크들](https://fory.apache.org/docs/docs/introduction/benchmark), [Rust 직렬화 가이드](https://fory.apache.org/docs/docs/guide/rust_serialization)가 해당 내용일 것으로 추정함
