TrendShift 딥다이브 · 2026-06-29

Sail 딥다이브
— JVM 없는 Rust 분산 컴퓨트, PySpark 코드 그대로 4× 빠르게

SailApache Spark의 드롭인 대체재를 표방하는 Rust 기반 분산 컴퓨트 엔진이다. PySpark 코드 변경 없이 연결만 바꾸면 되고, TPC-H 벤치마크 기준 Spark 대비 약 4× 빠르고 인프라 비용은 94% 절감된다. Spark를 15년간 짓눌러온 JVM 오버헤드를 Rust로 완전히 대체하고, Apache Arrow + Apache DataFusion으로 벡터화 실행을 구현한다. 스트림·배치·AI 워크로드를 하나의 엔진으로 통합하며, 단일 머신부터 Kubernetes 클러스터까지 동일한 API로 확장된다. (저장소: lakehq/sail · Rust + Python · v0.6.4 · Apache-2.0 라이선스)
목차
  1. 프로젝트 한줄 요약
  2. 왜 주목받는가
  3. 기술 스택 전체 지도
  4. 아키텍처 심화 분석
  5. 디렉토리 구조 해부
  6. 학습 포인트 (기술별)
  7. 하드웨어 / 시스템 요구사항
  8. 직접 해볼 수 있는 실습 과제
  9. 관련 기술 심화 학습 로드맵
  10. 핵심 키워드 사전
  11. 참고 링크

1프로젝트 한줄 요약

이 저장소가 대체 무엇인가.

핵심 메시지

"PySpark 코드 그대로, JVM 없이, 4배 빠르게 — Rust로 다시 만든 Spark."

Sail은 Apache Spark의 Spark Connect 프로토콜을 완전 구현하여, 기존 PySpark 코드를 한 줄도 고치지 않고 그대로 연결할 수 있는 분산 컴퓨트 엔진이다. JVM(자바 가상머신) 대신 Rust로 엔진 전체를 재작성했고, 내부적으로 Apache DataFusion과 Arrow를 사용해 컬럼 기반 벡터화 실행을 제공한다.

핵심 가치는 세 가지: 호환성(코드 변경 없음), 성능(4× 빠름, 메모리 60% 절약), 단순함(워커가 수 MB 메모리로 즉시 기동). 배치 ETL뿐 아니라 스트리밍과 AI/ML 워크로드까지 하나의 엔진으로 처리하는 것을 목표로 한다.

용어
드롭인 대체(Drop-in Replacement)
기존 코드·API·설정을 바꾸지 않고 내부 구현체만 교체하는 방식. 플러그를 뽑아 다른 플러그를 꽂는 것처럼, 외부에서는 똑같아 보이지만 안이 다르다. Sail은 Spark Connect 프로토콜 서버 역할을 하므로, PySpark 클라이언트가 "Spark 서버"에 붙는 것처럼 Sail 서버에 붙을 수 있다.

2왜 주목받는가

트렌딩 이유 · 경쟁 대비 장점.

JVM 탈출 + 드롭인 호환 + 압도적 벤치마크 세 조합이 데이터 엔지니어 커뮤니티를 흔들었다. Spark를 대체하고 싶어도 코드 마이그레이션 비용이 무서웠던 팀에게, "코드 건드리지 않아도 된다"는 약속은 큰 유인이다.

벤치마크 수치 (TPC-H SF100, AWS r8g.4xlarge)

지표Apache SparkSail
전체 쿼리 실행 시간387초102초 (3.8×)
쿼리별 속도 향상기준43% ~ 727%
피크 메모리54 GB22 GB (60% 절약)
디스크 셔플 스필110 GB 이상0 GB

경쟁 엔진과의 비교

엔진강점Sail 대비 한계
Apache Spark (JVM)15년 생태계, 광범위한 커넥터JVM GC 일시정지, 높은 메모리 사용, 느린 기동, JVM 튜닝 복잡
Polars단일 노드 Rust DataFrame, 매우 빠름Spark API 없음, 분산 처리 미지원(단일 노드 전용)
DuckDB단일 노드 OLAP, 임베디드 사용 탁월분산 미지원, Spark API 미호환, 대규모 클러스터 부적합
RayPython 네이티브 분산, AI/ML 강점Spark SQL·DataFrame API 없음, SQL 쿼리 최적화 약함
Databricks (Spark 기반)매니지드 Spark + Delta Lake벤더 종속, 높은 비용, 여전히 JVM 기반
Sail의 핵심 차별점
코드 변경 없이 Spark에서 갈아탈 수 있는 유일한 Rust 엔진

Polars·DuckDB가 빠르지만 Spark API를 지원하지 않아 마이그레이션 비용이 크다. Sail은 Spark Connect 프로토콜을 그대로 구현해, 연결 주소만 바꾸면(sc://localhost:50051) 기존 PySpark 코드가 돌아간다.

현실적 주의사항
아직 Beta — Spark 100% 기능 호환은 아님

v0.6.4 기준 "Beta" 단계로, 모든 Spark 함수·기능을 지원하지 않는다. 공식 호환성 체크 스크립트(python -m pysail.examples.spark.compatibility_check)로 기존 코드베이스를 먼저 스캔해 지원 여부를 확인해야 한다. SQL 문자열 내 함수는 스크립트가 감지하지 못하니 실제 테스트도 필수.

3기술 스택 전체 지도

Rust 크레이트 + Python 바인딩 + 인프라 계층 전체.

백엔드 — Rust 크레이트 워크스페이스

크레이트 / 라이브러리역할
sail-spark-connectSpark Connect gRPC 프로토콜 서버 구현. PySpark 클라이언트 요청 수신·세션 관리
sail-sql-parserSpark SQL 방언 전용 파서(chumsky 파서 콤비네이터 사용). Rust 절차형 매크로로 SQL 문법 코드 생성
sail-logical-plan / sail-logical-optimizerSpark 관계(Relation)를 DataFusion 논리 계획으로 변환·최적화
sail-physical-plan / sail-physical-optimizer논리 계획 → 물리 실행 계획 변환. 분산 셔플·병렬 파티션 결정
sail-execution실제 쿼리 실행 엔진 조율. 드라이버-워커 통신, 태스크 분배
sail-python-udfPython/Pandas/Arrow UDF 실행. Arrow 포인터 공유로 직렬화 없음
sail-catalog-* (6개)카탈로그 연동: AWS Glue, Iceberg REST, Unity Catalog, Hive Metastore, OneLake, 인메모리
sail-delta-lake / sail-icebergDelta Lake·Apache Iceberg 테이블 포맷 지원
sail-object-store스토리지 추상화: S3·Azure·GCS·HDFS·HuggingFace·HTTP·인메모리
sail-flightApache Arrow Flight(gRPC 기반) 데이터 전송 서비스
sail-telemetryOpenTelemetry 트레이싱·메트릭 수집
DataFusion 54.0Rust 네이티브 쿼리 실행 엔진. SQL 파싱·벡터화 실행·Parquet I/O 담당
Apache Arrow 58.3컬럼 기반 인메모리 포맷. 모든 데이터가 Arrow 배열로 표현됨
Tokio 1.52Rust 비동기 런타임. 고성능 비동기 I/O와 작업 스케줄링
Tonic 0.14 (gRPC)gRPC 서버/클라이언트. Spark Connect 프로토콜 통신에 사용

Python 계층

구성요소역할
pysail PyPI 패키지pip으로 설치하는 사용자 진입점. Python 3.10~3.14 지원
sail-python 크레이트 (PyO3)Rust-Python 바인딩. Rust 함수를 Python 모듈로 노출
SparkConnectServer Python APIRust 서버를 Python에서 직접 기동하는 클래스
Maturin 빌드 백엔드Rust 코드를 Python 휠(.whl)로 컴파일
pyspark-client 연동기존 PySpark DataFrame/SQL API를 그대로 사용. Spark Connect 프로토콜로 Sail 서버에 연결

인프라 / 배포

도구역할
Docker / devcontainer개발 환경: Python 3.11 + Rust + Zig + Maturin 빌드 환경
Docker Compose로컬 테스트용 MinIO(S3 호환)·Azurite(Azure Blob)·HDFS·OpenTelemetry·Grafana 스택
Kubernetes (sail.yaml)프로덕션 클러스터 배포. 드라이버 Pod가 워커 Pod를 동적 생성(kube API 사용)
kind (로컬 K8s)k8s/kind-config.yaml로 로컬에서 클러스터 테스트
OpenTelemetry + Tempo + Prometheus + Grafana분산 트레이싱·메트릭 수집·대시보드

4아키텍처 심화 분석

Spark Connect 호환부터 DataFusion 실행까지 한 줄기로.

┌────────────────────────────────────────────────────────────────────┐ │ Sail 전체 시스템 구조 │ │ │ │ ┌──────────────────────────────────────────────────────────────┐ │ │ │ 사용자(Python 코드) │ │ │ │ spark = SparkSession.builder.remote("sc://localhost:50051") │ │ │ │ spark.sql("SELECT ...") / df.filter(...).groupBy(...).show()│ │ │ └──────────────────────┬───────────────────────────────────────┘ │ │ │ gRPC (Spark Connect Protocol) │ │ ▼ │ │ ┌─────────────────────────────────────────────────────────────┐ │ │ │ sail-spark-connect (gRPC 서버 · Tonic) │ │ │ │ · Spark Connect 프로토콜 역직렬화 (Protobuf) │ │ │ │ · 세션 관리 (session_manager.rs) │ │ │ │ · Relation/Plan → sail-logical-plan 으로 전달 │ │ │ └──────────────────────────┬──────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────────────────────────────────────────────────────┐ │ │ │ SQL 파싱 / 논리 계획 (sail-sql-parser / sail-logical-plan) │ │ │ │ · chumsky 파서 콤비네이터로 Spark SQL 방언 파싱 │ │ │ │ · Spark Relation → DataFusion LogicalPlan 변환 │ │ │ │ · 논리 최적화 (sail-logical-optimizer): 조건 푸시다운 등 │ │ │ └──────────────────────────┬──────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────────────────────────────────────────────────────┐ │ │ │ 물리 계획 (sail-physical-plan / DataFusion) │ │ │ │ · 파티셔닝·조인 방식·셔플 전략 결정 │ │ │ │ · DataFusion PhysicalPlan 노드 생성 │ │ │ └──────────────────────────┬──────────────────────────────────┘ │ │ 단일 노드 │ 클러스터 모드 │ │ ┌──────┴──────┐ │ ┌──────────┴──────────┐ │ │ │ DataFusion │ │ │ sail-execution │ │ │ │ 로컬 실행 │ │ │ (드라이버 역할) │ │ │ │ (Arrow 벡터) │ │ │ · 태스크 분배 │ │ │ └─────────────┘ │ │ · 워커 Pod 생성(K8s) │ │ │ │ │ · Arrow Flight 셔플 │ │ │ │ └────────┬────────────┘ │ │ │ │ Arrow Flight (gRPC) │ │ │ ┌────────▼────────────┐ │ │ │ │ 워커 Pod × N │ │ │ │ │ · 파티션 단위 실행 │ │ │ │ │ · 결과 → Arrow 배열 │ │ │ │ └─────────────────────┘ │ │ │ │ │ ┌──────────────────────────┴──────────────────────────────────┐ │ │ │ 스토리지 계층 (sail-object-store) │ │ │ │ S3 / Azure / GCS / HDFS / HuggingFace / 로컬 파일시스템 │ │ │ └─────────────────────────────────────────────────────────────┘ │ └────────────────────────────────────────────────────────────────────┘

핵심 설계 패턴 4가지

패턴 1

Spark Connect 프로토콜 호환 — "플러그만 교체"

Spark Connect는 Spark 3.4부터 도입된 클라이언트-서버 분리 아키텍처다. PySpark 클라이언트가 gRPC로 계획(Plan)을 서버에 보내면 서버가 실행한다. Sail은 이 서버 역할을 Rust로 구현했다. PySpark는 자신이 Sail과 대화하는지 모른다 — 프로토콜만 맞으면 된다.

패턴 2

벡터화 실행 (Vectorized Execution) — SIMD로 묶음 처리

전통적인 Spark(JVM)는 행(Row) 단위로 처리하고 Java 객체 오버헤드가 크다. Sail은 Apache Arrow의 컬럼 기반 배열로 데이터를 들고, DataFusion이 SIMD(CPU의 단일 명령 다중 데이터) 명령어로 묶음 연산한다. 예를 들어 100만 행의 `age + 1` 연산을 CPU가 한 번에 32개씩 처리할 수 있다.

패턴 3

제로 복사 Python UDF — Arrow 포인터 공유

Spark에서 Python UDF는 Pickle 직렬화로 JVM ↔ Python 프로세스 간 데이터를 복사했다. Sail은 Arrow 배열 포인터를 Rust와 Python이 직접 공유한다. 데이터를 복사하지 않고 메모리 주소만 전달하므로 Python UDF 오버헤드가 드라마틱하게 낮다.

패턴 4

단일 노드 ↔ 클러스터 투명한 전환

로컬에서 sail spark server를 실행하면 단일 프로세스 모드로 DataFusion이 직접 실행한다. Kubernetes에 배포하면 드라이버 Pod가 동적으로 워커 Pod를 생성하고 Arrow Flight로 데이터를 셔플한다. 코드는 같고 SAIL_MODE=kubernetes-cluster 환경변수 하나로 모드가 바뀐다.

비유 — 주방 비유로 이해하기

JVM Spark는 자바 언어로 된 대형 호텔 주방이다. 주방장(JVM)이 중간에서 모든 걸 조율하는데, 주방장이 가끔 "잠깐만요, 청소 중" (GC)을 외치며 멈춘다. 재료(데이터)를 그릇(Java 객체)에 담아 나르니 그릇도 많이 필요하다.

Sail은 Rust로 지은 주방이다. 주방장 없이 요리사들(워커 스레드)이 직접 효율적으로 움직이고, 멈추는 일(GC)이 없다. 재료를 벨트(Arrow 컬럼 배열)에 줄 세워 한꺼번에(SIMD) 칼질하니 훨씬 빠르다. 손님(PySpark)은 주방이 바뀐 줄 모른다 — 같은 메뉴판(API)으로 주문할 뿐이다.

5디렉토리 구조 해부

37개 Rust 크레이트 + Python 패키지 — 각 폴더의 역할.

sail/ ├── Cargo.toml Rust 워크스페이스 루트. 공통 의존성·lint 규칙 관리 ├── pyproject.toml Python 패키지(pysail) 메타데이터. Maturin 빌드 백엔드 ├── crates/ Rust 크레이트 37개 │ ├── sail-cli/ 사용자 진입점: `sail spark server` CLI 명령 │ ├── sail-python/ PyO3 바인딩: Rust → Python 모듈 노출 │ ├── sail-spark-connect/ Spark Connect gRPC 서버 (핵심!) │ │ ├── proto/ Protobuf 정의 파일 │ │ └── src/ │ │ ├── server.rs gRPC 서버 기동 │ │ ├── session_manager.rs 세션 라이프사이클 │ │ └── proto/ Plan·Expression·DataType 변환 │ ├── sail-sql-parser/ Spark SQL 방언 파서 (chumsky 기반) │ ├── sail-sql-macro/ SQL 관련 Rust 절차형 매크로 │ ├── sail-sql-analyzer/ SQL 의미 분석 (타입 체크 등) │ ├── sail-logical-plan/ Spark Relation → DataFusion LogicalPlan │ ├── sail-logical-optimizer/ 논리 최적화 패스 │ ├── sail-physical-plan/ 물리 실행 계획 생성 │ ├── sail-physical-optimizer/ 물리 최적화 패스 │ ├── sail-execution/ 실행 엔진 조율 (드라이버 역할) │ ├── sail-function/ Spark 내장 함수 구현 │ ├── sail-python-udf/ Python/Pandas/Arrow UDF 실행 │ ├── sail-catalog-*/ 카탈로그 통합 6개 (Glue·Iceberg·HMS·Unity·OneLake·메모리) │ ├── sail-delta-lake/ Delta Lake 포맷 지원 │ ├── sail-iceberg/ Apache Iceberg 포맷 지원 │ ├── sail-object-store/ 스토리지 추상화 레이어 │ ├── sail-flight/ Arrow Flight 데이터 전송 서버 │ ├── sail-server/ gRPC 서버 공통 기반 (Tonic + Axum) │ ├── sail-session/ 세션 상태 관리 │ ├── sail-telemetry/ OpenTelemetry 트레이싱·메트릭 │ ├── sail-cache/ 결과 캐싱 │ ├── sail-common/ 공통 유틸리티 │ └── sail-gold-test/ 골든 테스트 프레임워크 ├── python/ │ └── pysail/ Python 소스 (테스트 유틸·예제·MCP 서버) │ ├── spark/ SparkConnectServer Python API │ ├── testing/ PySpark 호환성 테스트 유틸 │ └── examples/ compatibility_check 스크립트 등 ├── k8s/ Kubernetes 매니페스트 │ ├── sail.yaml 프로덕션 배포 정의 (Namespace·Deployment·Service·RBAC) │ └── kind-config.yaml 로컬 kind 클러스터 설정 ├── compose.yml 로컬 개발용 Docker Compose (MinIO·Azurite·HDFS·Grafana) ├── docs/ 문서 소스 (docs.lakesail.com) └── .devcontainer/ VS Code devcontainer 설정 (Python 3.11 + Rust + Zig)

6학습 포인트 (기술별)

이 레포에서 무엇을 배울 수 있는가.

포인트 1 · Rust 데이터 엔진 설계

37개 크레이트로 이루어진 Rust 워크스페이스 아키텍처

Cargo 워크스페이스의 의존성 설계를 실전에서 배울 수 있다. 공통 의존성 버전을 Cargo.toml 최상단에서 관리하고, 각 크레이트가 { workspace = true }로 참조하는 패턴이다. Clippy 규칙도 워크스페이스 단위로 강제(unwrap_used = "deny", panic = "deny")한다.

볼 파일: 루트 Cargo.toml[workspace.dependencies], [workspace.lints.clippy]

포인트 2 · Apache Arrow & DataFusion

컬럼 기반 데이터 처리의 핵심 두 라이브러리

Apache Arrow는 "메모리 안에서 데이터를 어떻게 표현하는가"의 표준이다. 행 단위 대신 컬럼 단위로 저장해 CPU 캐시 효율을 극적으로 높인다. DataFusion은 Arrow 위에서 SQL 쿼리를 실행하는 Rust 쿼리 엔진이다. Sail은 DataFusion을 실행 계획의 최종 실행자로 사용한다.

볼 파일: crates/sail-common-datafusion/, DataFusion 관련 크레이트 사용 패턴

포인트 3 · gRPC + Protobuf

Spark Connect 프로토콜 구현으로 배우는 gRPC

Spark Connect는 클라이언트-서버가 gRPC(HTTP/2)로 통신하며, 계획(Plan)·표현식(Expression)·데이터 타입 등을 Protobuf로 직렬화한다. sail-spark-connect/proto/에 .proto 파일이 있고, build.rs가 빌드 시 Rust 코드를 생성한다. Tonic으로 gRPC 서버를 구현하는 전체 흐름을 볼 수 있다.

볼 파일: crates/sail-spark-connect/proto/, crates/sail-spark-connect/src/server.rs

포인트 4 · 파서 콤비네이터

chumsky로 SQL 파서 직접 만들기

파서 콤비네이터(parser combinator)는 작은 파서 함수들을 조합해 복잡한 문법을 파싱하는 기법이다. Sail은 chumsky 라이브러리로 Spark SQL 방언(HiveQL·스파크 함수·LATERAL VIEW 등)을 파싱한다. 보통 Yacc/Flex 같은 파서 생성기 대신 Rust 코드로 문법을 표현하는 현대적 접근이다.

볼 파일: crates/sail-sql-parser/src/

포인트 5 · PyO3로 Rust-Python 바인딩

Maturin + PyO3: Rust를 pip 패키지로 배포하기

PyO3는 Rust 코드를 Python 모듈(.pyd/.so)로 컴파일하는 라이브러리다. Maturin은 이 과정을 pip 패키지 빌드·배포까지 자동화해준다. pysailpip install pysail로 설치되는 과정 전체가 이 두 도구의 조합이다. AI/데이터 도구(polars, pydantic 등)의 표준 배포 방식이다.

볼 파일: pyproject.toml의 build-system, crates/sail-python/src/lib.rs

포인트 6 · 쿼리 실행 계획 (Query Planning)

SQL이 실행되기까지: 파싱 → 논리 계획 → 물리 계획 → 실행

SQL 엔진 내부의 4단계를 Sail 크레이트 구조와 대응하며 배울 수 있다. ① SQL 문자열 → AST (sail-sql-parser), ② AST → 논리 계획 (sail-logical-plan), ③ 논리 최적화 (sail-logical-optimizer: 조건 푸시다운·컬럼 가지치기), ④ 물리 계획 (sail-physical-plan: 셔플 방식·조인 알고리즘 결정) → DataFusion 실행. 데이터베이스 내부 원리를 실제 코드로 볼 수 있는 드문 기회.

7하드웨어 / 시스템 요구사항

단일 노드 개발부터 프로덕션 클러스터까지.

목적최소 사양 / 방법
빠른 시작 (pip 설치)Python 3.10+ · pip install pysail pyspark-client · 수 초 내 서버 기동 가능
소스 빌드Rust 1.95+, Python 3.10+, protobuf-compiler, Maturin. devcontainer 사용 시 자동 설정
단일 노드 개발/테스트일반 개발 노트북으로 충분. 벤치마크 기준 Spark 대비 22GB vs 54GB 피크 메모리 (60% 절약)
프로덕션 클러스터Kubernetes 환경 필수. 워커 Pod는 기동 시 수 MB만 사용, 태스크 수신 시 확장. 공식 벤치마크는 AWS r8g.4xlarge (32 vCPU, 128GB RAM)
스토리지S3·GCS·Azure Blob·HDFS·로컬 파일시스템 지원. 로컬 개발 시 Docker Compose로 MinIO(S3 호환) 제공
OS / 아키텍처Linux/macOS/Windows. Apple Silicon(M1/M2/M3) 네이티브 빌드 지원
포트기본 50051 (Spark Connect gRPC). 설정으로 변경 가능
Sail의 인프라 이점
워커가 "가볍고 빠르다"는 의미

Spark 워커는 JVM 기동에 수 초 ~ 수십 초가 걸리고, 메모리도 수백 MB를 기본으로 잡아먹는다. Sail 워커는 Kubernetes Pod로 배포되며 수 MB 메모리에 수십 밀리초 안에 뜬다. 수요에 따라 워커를 빠르게 추가/제거할 수 있어 클라우드 비용을 극적으로 줄인다.

8직접 해볼 수 있는 실습 과제

난이도별로 손에 익히는 단계.

실습 1

Sail 서버 띄우고 PySpark로 쿼리 실행 난이도 ★☆☆ 입문

pip으로 설치하고 Sail 서버를 기동한 뒤, 기존 PySpark 코드로 연결한다. SELECT 1 + 1부터 spark.range(1000000).filter(...).groupBy(...).count()까지 실행해보며 응답 속도를 체감한다.

# 설치
pip install pysail "pyspark-client"

# 서버 기동
sail spark server --port 50051

# 다른 터미널에서 PySpark로 연결
from pyspark.sql import SparkSession
spark = SparkSession.builder.remote("sc://localhost:50051").getOrCreate()
spark.sql("SELECT 1 + 1").show()
df = spark.range(1_000_000)
df.filter("id % 2 == 0").groupBy().count().show()
실습 2

Python API로 Sail 서버 내장 기동 난이도 ★★☆ 중급

CLI 대신 Python 코드 안에서 Sail 서버를 기동하고 종료하는 패턴을 익힌다. 테스트 코드나 Jupyter Notebook에서 Sail을 프로그래밍적으로 제어하는 방식이다.

from pysail.spark import SparkConnectServer
from pyspark.sql import SparkSession

# 서버를 백그라운드로 기동
server = SparkConnectServer(port=50051)
server.start(background=True)

spark = SparkSession.builder.remote("sc://localhost:50051").getOrCreate()

# Parquet 파일 읽고 SQL 쿼리
df = spark.read.parquet("/path/to/data.parquet")
df.createOrReplaceTempView("my_table")
spark.sql("SELECT COUNT(*), AVG(value) FROM my_table GROUP BY category").show()

server.stop()
실습 3

기존 PySpark 코드 호환성 체크 실행 난이도 ★★☆ 중급

이미 PySpark 코드베이스가 있다면 호환성 체크 스크립트로 어떤 함수가 지원되는지 스캔한다. 지원 안 되는 함수를 파악하고 대안을 찾거나, Sail 이슈 트래커에 기여 가능성을 검토한다.

# 기존 PySpark 코드 디렉토리를 스캔
python -m pysail.examples.spark.compatibility_check ./my_spark_project

# 결과 예시:
# [OK]     pyspark.sql.functions.col
# [OK]     pyspark.sql.functions.sum
# [WARN]   pyspark.sql.functions.some_experimental_func → 미구현
# 주의: SQL 문자열 내 함수는 감지 안 됨 → 실제 실행 테스트 필수
실습 4

Docker Compose로 로컬 MinIO 연동 난이도 ★★★ 고급

Docker Compose의 storage 프로파일로 MinIO(로컬 S3 호환 스토리지)를 기동하고, Sail에서 S3 프로토콜로 Parquet 파일을 읽고 쓰는 실습이다. 로컬에서 클라우드 스토리지 연동을 시뮬레이션하는 방법을 익힌다.

# MinIO 기동
docker compose --profile storage up minio -d

# MinIO 콘솔: http://localhost:19001 (sail/password)
# Python에서 S3 스타일로 Parquet 읽기
spark = SparkSession.builder.remote("sc://localhost:50051") \
    .config("spark.hadoop.fs.s3a.endpoint", "http://localhost:19000") \
    .config("spark.hadoop.fs.s3a.access.key", "sail") \
    .config("spark.hadoop.fs.s3a.secret.key", "password") \
    .getOrCreate()
df = spark.read.parquet("s3a://my-bucket/data/")
df.show()
실습 5

kind로 로컬 Kubernetes 클러스터 배포 난이도 ★★★★ 도전

kind(로컬 K8s)로 Sail을 클러스터 모드로 배포하고, 워커 Pod가 동적으로 생성되는 과정을 kubectl로 관찰한다. 단일 노드와 클러스터 모드의 실행 방식 차이를 직접 확인한다.

# kind 클러스터 생성
kind create cluster --config k8s/kind-config.yaml

# Sail 이미지 빌드 후 배포
docker build -t sail:latest .
kind load docker-image sail:latest
kubectl apply -f k8s/sail.yaml
kubectl -n sail port-forward service/sail-spark-server 50051:50051

# 쿼리 실행 중 워커 Pod 확인
kubectl -n sail get pods -w

9관련 기술 심화 학습 로드맵

한 주씩 따라가는 "Rust 데이터 엔지니어" 코스.

주차주제학습 자료 / 할 일
1주차Apache Spark 기초PySpark DataFrame API, SQL, RDD 개념. pyspark 튜토리얼 공식 문서. Sail 실습 1 완료
2주차Spark Connect 프로토콜Spark Connect 아키텍처 문서. gRPC·Protobuf 기본 개념. Sail의 sail-spark-connect/proto/ 파일 읽기
3주차Apache Arrow 이해Arrow 컬럼 포맷 공식 문서. pyarrow로 배열 생성·변환 실습. "왜 행보다 열이 빠른가" 개념 정리
4주차Apache DataFusion 탐구DataFusion 깃허브 예제. 커스텀 UDF 등록, LogicalPlan 직접 조작 실습. Sail과의 관계 이해
5주차Rust 기초 + 비동기The Rust Book. Tokio 비동기 런타임 기초. async/await, Future 개념
6주차PyO3 + MaturinPyO3 가이드북. Maturin 튜토리얼. 간단한 Rust 함수를 Python 모듈로 배포 실습
7주차쿼리 최적화 이론카네기 멜런 15-445 DB 강의(무료). 조건 푸시다운·컬럼 가지치기·조인 순서 최적화 개념
8주차분산 컴퓨트 + KubernetesKubernetes 공식 튜토리얼. Sail 클러스터 모드(실습 5). Arrow Flight 셔플 동작 원리 분석

10핵심 키워드 사전

본문에 나온 용어 빠른 참조.

용어의미
Apache Spark2014년 출시된 JVM 기반 분산 컴퓨트 엔진. Hadoop MapReduce를 대체. SQL·DataFrame·스트리밍·ML 통합 API 제공. 업계 표준이지만 JVM 오버헤드가 약점.
Spark ConnectSpark 3.4부터 도입된 클라이언트-서버 분리 아키텍처. 클라이언트(PySpark)와 서버(실행 엔진)가 gRPC로 통신. Sail이 이 서버 역할을 대체한다.
Apache Arrow컬럼 기반 인메모리 데이터 포맷 표준. 행 대신 열로 데이터를 저장해 CPU 캐시 효율을 높이고, 언어 간 제로 복사 공유를 가능하게 한다.
Apache DataFusionRust로 만든 쿼리 실행 엔진 라이브러리. Arrow 위에서 SQL 파싱·최적화·실행을 담당. 벡터화 실행과 SIMD를 활용해 빠르다. Sail의 핵심 실행 계층.
벡터화 실행데이터를 한 행씩이 아니라 컬럼 배열 단위(벡터)로 한꺼번에 처리하는 방식. SIMD CPU 명령어를 활용해 처리량을 수십 배 높인다.
SIMDSingle Instruction Multiple Data. CPU 하나의 명령으로 여러 데이터를 동시 처리. 예: 32비트 정수 8개를 한 번에 더하기. 벡터화 실행의 하드웨어 기반.
JVM (Java Virtual Machine)Java·Scala·Kotlin 코드가 돌아가는 런타임. GC(가비지 컬렉션) 일시정지, 높은 메모리 사용, 느린 기동이 Spark 성능의 병목이었다.
가비지 컬렉션 (GC)JVM이 사용 안 하는 메모리를 자동으로 회수하는 과정. 이 동안 프로그램 실행이 잠깐 멈추는 "GC 일시정지(Stop-the-World)"가 지연을 유발한다.
gRPCHTTP/2 기반의 고성능 원격 프로시저 호출(RPC) 프레임워크. Spark Connect가 클라이언트-서버 통신에 사용. Protobuf로 데이터를 직렬화해 효율적이다.
ProtobufProtocol Buffers. 구글이 만든 이진 직렬화 포맷. JSON보다 작고 빠르며, .proto 파일에서 타입을 정의하면 여러 언어용 코드를 자동 생성한다.
논리 계획 (Logical Plan)쿼리의 "무엇을 할 것인가"를 추상적으로 표현한 트리. "테이블 A에서 조건 B로 필터하고 C 컬럼으로 집계" 같은 수준. 어떻게 실행할지는 결정 안 된 상태.
물리 계획 (Physical Plan)논리 계획을 "어떻게 실행할 것인가"로 구체화한 것. 어떤 조인 알고리즘(해시 조인 vs 정렬 병합 조인)을 쓸지, 파티션을 어떻게 나눌지 결정된 상태.
셔플 (Shuffle)분산 처리에서 데이터를 재분배하는 과정. 예: GROUP BY 시 같은 키를 가진 행들을 같은 워커로 모아야 한다. 네트워크 I/O가 많아 대용량 처리의 병목이 된다.
Arrow FlightArrow 데이터를 gRPC로 고속 전송하는 프로토콜. Sail 클러스터 모드에서 워커 간 Arrow 배열 셔플에 사용된다.
PyO3Rust 코드를 Python 확장 모듈(.pyd/.so)로 컴파일해주는 라이브러리. Rust의 성능을 Python에서 쓸 수 있게 해준다. Polars·pydantic 등도 같은 방식.
MaturinPyO3 기반 Rust 프로젝트를 pip 패키지(휠)로 빌드·배포하는 도구. pyproject.toml의 빌드 백엔드로 설정하면 pip install이 자동으로 Rust를 컴파일한다.
Delta Lake / Iceberg오픈 테이블 포맷. Parquet 파일 위에 트랜잭션·스키마 진화·타임 트래블 등을 추가한다. Sail이 두 포맷 모두 네이티브 지원한다.
파서 콤비네이터작은 파서를 조합해 복잡한 문법을 처리하는 함수형 파싱 기법. Sail의 SQL 파서(chumsky)가 이 방식을 사용한다. Yacc/Flex 대신 Rust 타입 시스템으로 문법을 표현한다.

11참고 링크