TrendShift 딥다이브 · 2026-07-11 · Daily #3

pgrust 딥다이브
— PostgreSQL 전체를 Rust로 다시 쓴다: 진짜 Postgres 테스트를 "정답지"로 삼은 77만 줄의 재작성

pgrustPostgreSQL 18.3 서버를 밑바닥부터 Rust로 새로 구현한 프로젝트다. 단순한 "장난감 SQL 엔진"이 아니라, 파서·플래너·실행기·인덱스(B-tree/GIN/GiST…)·MVCC·WAL·복제·PL/pgSQL까지 실제 Postgres 백엔드 전부를 옮겼고, 진짜 Postgres 회귀 테스트 46,000개 이상을 통과하며 기존 Postgres 18.3 데이터 디렉토리로 그대로 부팅된다(디스크 호환). 핵심 전략은 "동작은 Postgres 그대로 유지, Postgres의 진짜 테스트를 정답지로 고정, Rust + AI 보조 프로그래밍으로 더 깊은 서버 개조를 탐험한다"는 것. (저장소: malisper/pgrust · 제작자 Michael Malis / Jason Seibel · Rust 77만 줄·크레이트 1,464개 · AGPL-3.0 · Postgres 18.3 대상 · New 2026 · TrendShift 오늘 Daily #3)
목차
  1. 프로젝트 한줄 요약
  2. 왜 주목받는가
  3. 기술 스택 전체 지도
  4. 아키텍처 심화 분석
  5. 디렉토리 구조 해부
  6. 학습 포인트 (기술별)
  7. 빌드/시스템 요구사항
  8. 직접 해볼 수 있는 실습 과제
  9. 관련 기술 심화 학습 로드맵
  10. 핵심 키워드 사전
  11. 참고 링크

1프로젝트 한줄 요약

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

pgrust세계에서 가장 널리 쓰이는 오픈소스 데이터베이스인 PostgreSQL의 서버 부분(백엔드)을 통째로 Rust로 다시 작성한 프로젝트다. "SQL을 흉내 내는 미니 DB"가 아니라, 실제 Postgres 18.3과 바이트 단위로 똑같이 동작하는 것을 목표로 한다. 얼마나 똑같은가? Postgres가 자기 자신을 검증할 때 쓰는 공식 회귀 테스트(46,000+ 쿼리)의 출력이 한 글자도 안 틀리게 일치하고, 기존 Postgres로 만들어 둔 데이터 폴더를 그대로 열어 부팅한다.

한 줄 개념
Rust rewrite (러스트 재작성) + 테스트 오라클
거대한 C 프로그램을 안전한 Rust로 "한 줄 한 줄 옮기되", 옮긴 게 맞는지는 원본 프로그램의 진짜 테스트로 판정한다. 사람의 눈이 아니라 46,000개 자동 테스트가 "정답지(oracle)" 역할을 한다. 그래서 대규모 AI 보조 이식을 하면서도 "동작이 원본과 같은가"를 기계적으로 보장할 수 있다.
비유로 이해하기

"고성능 자동차 엔진을, 시동 상태로 부품을 하나씩 갈아 끼우기"

PostgreSQL은 30년 묵은 거대한 C 엔진이다 — 잘 돌지만, 내부를 뜯어고치기가 무섭다(수동 메모리 관리, 다중 프로세스). pgrust는 이 엔진을 부품 하나(C 소스 파일 하나)를 Rust 부품으로 교체할 때마다, 원래 자동차의 정비 매뉴얼(회귀 테스트)로 "여전히 똑같이 달리는가"를 즉시 확인하는 방식으로 옮긴다.

그래서 pgrust의 파일 구조는 Postgres의 C 소스 트리와 거의 1:1로 대응한다. src/backend/parser/analyze.ccrates/backend/parser/.../parser_analyze 크레이트가 되는 식이다. "새 DB를 발명"한 게 아니라 "같은 DB를 다른 언어로 옮긴" 것이다.

라이선스는 AGPL-3.0(카피레프트·네트워크 사용 조항 포함)로, Postgres 자체의 관대한 라이선스보다 훨씬 엄격하다는 점은 짚고 가야 한다. 코드 규모는 순수 Rust 약 77만 줄, 파일 3,525개, 크레이트(작은 패키지) 1,464개에 달한다. 최신 커밋은 2026-07-10, 웹에서 바로 써 보는 WASM 데모(pgrust.com)와 Discord도 있다.

먼저 짚고 갈 것 — 이 문서의 초점
"또 하나의 DB"가 아니라 "데이터베이스 내부 구조 + 대규모 언어 이식 방법론 교재"

"Postgres를 Rust로 다시 썼다"는 건 겉모습이다. 이 레포의 진짜 가치는 진짜 프로덕션 DB의 파서→플래너→실행기→저장소→WAL→MVCC 전체 파이프라인을 읽을 수 있는 Rust로 볼 수 있다는 점, 그리고 "1,464개 크레이트 사이의 순환 의존을 끊는 seam 패턴", "C 메모리 컨텍스트를 Rust 수명(lifetime)으로 바꾸기", "bison 문법을 c2rust로 자동 변환", "진짜 회귀 테스트를 정답지로 쓰는 이식 규율" 같은 대규모 코드 이식의 실전 방법론을 통째로 담고 있다는 점이다.

주의 — 현실 감각과 사실 확인
"호환된다"와 "빠르다·프로덕션이다"는 다르다 — 성능 수치는 미공개 WIP 버전 주장

이 공개 저장소는 호환성 중심이며, README도 "아직 성능 최적화 안 됨"이라고 명시한다. 화제가 된 "트랜잭션 50% 빠름·분석 쿼리 300배·스레드당 커넥션" 같은 수치는 이 코드에 들어있지 않은 미공개 WIP 버전에 대한 주장이며, "회귀 스위트 100% 통과"라는 헤드라인도 그 WIP 버전 이야기다(이 트리에서 검증되는 수치는 "46,000+ 쿼리 일치"). 또 PL/Python·Perl·Tcl 미이식, 일부 contrib만 이식됨, 확장(extension) 일반 호환 안 됨. "진지한 연구 프로젝트"이지 "지금 프로덕션에 올릴 DB"는 아니다.

2왜 주목받는가

트렌딩 이유와, 여느 "Rust로 만든 DB"들과의 결정적 차이.

① "테스트를 정답지로 삼는" 이식 규율 — 그래서 진짜로 호환된다

Rust로 DB를 만든 프로젝트는 많지만 대개 "SQL 일부를 새로 설계한 장난감"이다. pgrust는 정반대다. Postgres 자신의 회귀 테스트를 그대로 정답지로 고정하고, 옮긴 코드가 그 46,000개 쿼리의 출력을 한 글자도 안 틀리게 재현할 때만 통과로 친다. 덕분에 대규모 AI 보조 이식이라는 위험한 작업을 하면서도 "동작이 원본과 같은가"를 사람 눈이 아니라 기계가 보증한다. 이게 이 프로젝트를 여느 "Rust DB"와 구분 짓는 핵심이다.

② 디스크·와이어 프로토콜 완전 호환 — 기존 psql이 그대로 붙는다

pgrust는 실제 postgres.bki와 시스템 SQL을 읽어 기존 Postgres 18.3 데이터 디렉토리로 부팅하고, v3 와이어 프로토콜(SCRAM·MD5·LDAP·PAM·TLS 인증 포함)을 말한다. 즉 평범한 psql·libpq 클라이언트가 코드 수정 없이 접속된다. 심지어 공식 postgres 도커 이미지의 드롭인 대체재로 설계되어(같은 환경변수·/docker-entrypoint-initdb.d·uid 999·5432 포트), docker run malisper/pgrust로 바로 띄울 수 있다.

③ 안전한 언어로 DB 내부를 "고칠 수 있게" 만든다

Postgres의 C 코드는 잘 돌지만 30년치 복잡성이 쌓여 안전하게 바꾸기 어렵다. pgrust의 진짜 목적은 "Postgres를 안쪽에서 바꾸기 쉽게 만드는 것"이다 — 멀티스레드 내부, no-vacuum 저장소, AI가 만든 나쁜 SQL에 대한 가드레일 같은 더 깊은 서버 개조를 실험하는 발판으로. Rust의 borrow checker가 "이 메모리는 이 시점 뒤엔 못 쓴다"를 컴파일 타임에 강제하니, C에서는 무서웠던 개조를 시도해 볼 수 있다.

④ 규모 자체가 사건 — 77만 줄, 크레이트 1,464개의 완결성

파서·플래너(1.2만 줄짜리 planner)·실행기(모든 nodeXxx + 병렬 쿼리)·인덱스 AM 전종(nbtree/hash/gin/gist/spgist/brin)·MVCC·WAL·복제·PL/pgSQL·13개 contrib 모듈까지 옮겨져 있다. "일부만 흉내"가 아니라 뜨거운 경로(hot path)의 대부분이 진짜로 구현되어 있고, 미구현은 조용히 넘어가지 않고 seam이 전체 경로를 찍으며 요란하게 panic한다. 그 완결성이 46,000+ 테스트 통과로 증명된다.

3기술 스택 전체 지도

무엇으로 만들어졌나 — 언어·크레이트·의존성·빌드.

언어와 규모

항목내용
주 언어Rust (edition 2021, resolver v2) — 약 77만 줄, .rs 파일 3,525개
워크스페이스Cargo 워크스페이스, 멤버 크레이트 1,464개 (대략 C 소스 파일 1개 ≈ 크레이트 1개)
SQL / C 헤더SQL 34개(시스템/테스트), 벤더 C 헤더 4개(nodetags.h 등)
라이선스AGPL-3.0 (Postgres 자체보다 엄격)
최신 커밋2026-07-10 (c9aecbd0) — WIP 신버전·성능 관련
데모pgrust.com (WASM 브라우저 빌드), Discord 운영

외부 의존성은 놀랄 만큼 적다 (crates.io ~54개)

거의 전부 암호/인증 지원용이다: aes 0.8.4·blowfish·des·cast5(pgcrypto), md-5 0.9.1·sha-1/sha2 0.9.9·hmac 0.10.1·pwhash(SCRAM/MD5 인증), num-bigint·rand 0.8.6·getrandom, 그리고 hashbrown·ahash·libc 0.2.186·libm·zerocopy 0.8.52. tokio도, async 런타임도, rayon도 없다 — 진짜 Postgres처럼 커넥션당 프로세스 모델을 따른다(스레드당 커넥션은 미공개 WIP 이야기).

용어
FFI (Foreign Function Interface, 외부 함수 인터페이스)
Rust 코드에서 C로 짜인 라이브러리를 직접 호출하는 다리. pgrust는 순수 Rust로 대체 불가능한 6곳에서만 FFI를 쓴다: ICU(유니코드/로케일), libxml2(XML), OpenSSL(TLS), OpenLDAP, PAM, libm(수학). 그 외는 전부 Rust로 다시 썼다.

빌드 시스템의 특이점 — 크레이트를 잘게 쪼갠 이유

Cargo 커스텀 프로파일이 여럿 있다: dev(빠른 링크), fast-check, release(codegen-units=1, 심볼 스트립), profiling, 그리고 브라우저 데모용 wasm64 크기 최적화 프로파일(opt-level="z"). C 파일 하나를 크레이트 하나로 쪼갠 덕에 바뀐 파일만 다시 컴파일되어 거대 코드베이스에서도 증분 빌드가 견딜 만해진다.

# 워크스페이스 구성 (상위 디렉토리별 크레이트 수) crates/backend/ 1,248개 ← 서버 코어 (src/backend/* 를 그대로 반영) crates/_support/ 125개 ← pgrust 고유 런타임 발판 (seam·mcx·c2rust 문법 등) crates/common/ 44개 ← libpgcommon (md5·sha2·scram·pglz·jsonapi…) crates/port/ 18개 ← OS 이식성 shim (src/port) crates/contrib/ 17개 ← 이식된 확장 (hstore·pg_trgm·pgcrypto…) crates/interfaces/ 3개 ← libpq 클라이언트측 등 crates/pl/ 8개 ← PL/pgSQL

4아키텍처 심화 분석

쿼리 하나가 어떻게 흐르고, 어떤 설계가 이 거대한 이식을 지탱하는가.

쿼리 실행 흐름 — Postgres와 똑같다

트래픽 코프(traffic cop) 루프는 crates/backend/tcop/postgres/src/lib.rsPostgresMain에 있고, 흐름은 원본 Postgres와 동일하다:

psql 클라이언트가 SQL 문자열을 보냄 (v3 와이어 프로토콜) │ ▼ [1] pg_parse_query ← 원시 파싱 (c2rust 변환한 bison 문법) │ raw parse tree ▼ [2] pg_analyze_and_rewrite ← 파스 분석 + 규칙 재작성 (parser_analyze) │ Query 노드 ▼ [3] pg_rewrite_query ← 뷰/규칙 전개 │ ▼ [4] pg_plan_query ← 플래너/옵티마이저 (planner 1.2만 줄, createplan 8.7천 줄, GEQO) │ PlannedStmt ▼ [5] PortalRun → 실행기 ← nodeSeqScan / nodeHashJoin / nodeAgg / Gather(병렬) … │ ▼ 결과 튜플을 와이어로 반환 (전체가 start_xact_command / finish_xact_command 트랜잭션으로 감싸짐)

핵심 설계 패턴 ① — seam(솔기): 크레이트 순환 의존을 끊는 함수 슬롯

여기가 pgrust 전체를 지탱하는 가장 영리한 장치다. C는 하나의 링크 단위라 어떤 함수든 서로 자유롭게 호출한다. 그런데 Rust 크레이트는 의존 그래프에 순환(cycle)이 있으면 안 된다. 서로 호출하는 두 C 파일을 각각 크레이트로 쪼개면 곧바로 순환이 생긴다.

pgrust는 이걸 603개의 *_seams 크레이트seam! 매크로로 푼다. 함수의 "선언(빈 슬롯)"은 X_seams 크레이트에 두고, "진짜 구현"은 소유 크레이트가 프로세스 시작 시 init::init_all()로 슬롯에 꽂아 넣는다. 호출하는 쪽은 슬롯만 알면 되므로 순환이 사라진다.

용어
순환 의존 (dependency cycle)
크레이트 A가 B를 쓰고, B가 다시 A를 쓰는 상태. Cargo는 이를 금지한다. seam은 "A와 B가 공통으로 아는 빈 함수 슬롯 크레이트 S"를 하나 두고, A·B가 S만 의존하게 만들어 순환을 없앤다(간접 참조).
이 설계가 주는 공짜 이득
seam이 곧 "미구현 추적기"

아직 안 옮긴 함수의 seam을 호출하면 전체 경로를 찍으며 요란하게 panic한다(조용한 폴백 없음). 게다가 CI 게이트(crates/_support/todo_guard)가 모든 소스를 훑어 todo!()·unimplemented!()가 다시 들어오면 빌드를 깨뜨린다. "어디가 아직 빈칸인가"가 코드 구조 자체로 드러난다.

핵심 설계 패턴 ② — c2rust로 문법 자동 변환

bison이 생성한 gram.c와 flex 스캐너는 사람이 손으로 옮기기엔 너무 기계적이다. 그래서 c2rust로 자동 변환crates/_support/pgrust/gram_c2rust_fgram/src/gram.rs에 넣었다 — 무려 31만 줄(LR 파싱 테이블 + 약 4,800개 액션 블록). 손으로 쓴 support 모듈이 palloc·리스트 생성자·ereport와, 테스트된 Rust 스캐너로 잇는 base_yylex 다리를 제공한다.

핵심 설계 패턴 ③ — C 메모리 컨텍스트를 Rust 수명으로

Postgres는 전역 CurrentMemoryContext + MemoryContextSwitchTo로 메모리를 관리한다(실수하기 쉽다). pgrust의 crates/_support/mcx전역 컨텍스트를 아예 없앴다. MemoryContext는 이름 붙은 할당 도메인이고, 컬렉션은 Mcx<'mcx> 핸들을 통해 할당한다. 그 결과 할당된 메모리는 자기 컨텍스트보다 오래 살 수 없다 — borrow checker가 컴파일 타임에 강제한다. C의 컨텍스트 트리 계단식 삭제가 Rust 소유권(ownership)으로 바뀐 것.

어디까지 진짜인가 — 구현 vs 스텁

서브시스템상태
파서/분석완전 — 스캐너 + c2rust 문법 + 모든 분석 패스(CTE·집계·타입 강제)
플래너/옵티마이저완전 — planner 1.2만 줄, createplan 8.7천 줄, GEQO 포함
실행기사실상 완전 — 모든 nodeXxx, 병렬 쿼리(Gather), Memoize, SPI
인덱스 AMheap + nbtree·hash·gin·gist·spgist·brin
트랜잭션/MVCC스냅샷·리소스 오너·교착 감지
WAL·복제xlog·rmgr, 논리 복제 워커 타입
PLPL/pgSQL만 (Python·Perl·Tcl 미이식)
미구현seam이 panic + todo_guard가 빌드 차단 (조용한 스텁 없음)

5디렉토리 구조 해부

어디에 무엇이 있나 — Postgres C 트리를 그대로 반영한 지도.

pgrust/ ├─ Cargo.toml # 워크스페이스: 멤버 1,464개, 프로파일, edition 2021 ├─ Cargo.lock # 413KB인데 crates.io 의존은 ~54개뿐 ├─ Dockerfile # 공식 postgres 이미지의 3단계 드롭인 대체 ├─ README.md ├─ crates/ │ ├─ backend/ # 1,248 크레이트 — 서버 (src/backend/* 반영) │ │ ├─ tcop/postgres/ # PostgresMain 쿼리 루프 (파싱→계획→실행) │ │ ├─ parser/ # 분석 패스 + 스캐너 │ │ ├─ optimizer/ # planner, createplan, GEQO │ │ ├─ executor/ # 모든 nodeXxx + 병렬 실행 + SPI │ │ ├─ access/ storage/ catalog/ commands/ replication/ … │ │ ├─ main/ # main.c 이식 + pgrust 고유 initdb │ │ ├─ libpq/ # 와이어 프로토콜 + 인증(SCRAM/LDAP/PAM/TLS) │ │ └─ postmaster/ # 서버 감독자 │ ├─ common/ # 44 크레이트 (md5·sha2·scram·pglz·jsonapi…) │ ├─ port/ # 18 크레이트 (OS 이식성 shim) │ ├─ contrib/ # 17 이식 확장 │ ├─ pl/plpgsql/ # PL/pgSQL │ ├─ _support/ # 125 크레이트: pgrust 런타임 발판 │ │ ├─ mcx/ # 메모리 컨텍스트 할당기 (수명에 묶임) │ │ ├─ seam/ # seam! 매크로 + init 레지스트리 + postgres 바이너리 껍데기 │ │ ├─ pgrust/gram_c2rust_fgram/ # c2rust bison 문법 (31만 줄) │ │ ├─ todo_guard/ # todo!/unimplemented! 금지 CI 게이트 │ │ └─ types/ # ~130 공유 노드구조/카탈로그 타입 크레이트 │ └─ wasm-libc-shim/ # 서버를 브라우저에서 돌리는 libc shim (WASM) ├─ scripts/ # 회귀 + TAP 테스트 러너 ├─ docker/entrypoint.sh # 공식 이미지 호환 진입점 └─ vendor/postgres-18.3/ # share/(postgres.bki, 시스템 SQL, tz), regress/, isolation/

핵심은 디렉토리 이름만 봐도 원본 Postgres의 어느 부분인지 안다는 것. 각 크레이트의 문서 주석은 원본 파일 경로를 인용한다(예: main_main → "Port of PostgreSQL's main.c").

6학습 포인트 (기술별)

이 레포에서 실제로 배울 수 있는 것.

① 데이터베이스 내부 구조 (DBMS internals)

교과서로만 배우던 쿼리 파이프라인(파싱→분석→재작성→계획→실행)을 읽을 수 있는 코드로 본다. 특히 옵티마이저(planner/createplan), 실행기의 다양한 조인 노드(NestLoop·HashJoin·MergeJoin), 인덱스 접근법(B-tree·GIN·GiST), MVCC 스냅샷, WAL이 한 코드베이스에 모여 있다. "진짜 프로덕션 DB가 이렇게 생겼구나"를 배우는 최고의 표본.

② 대규모 C → Rust 이식 방법론

seam 패턴(순환 의존 끊기), c2rust 자동 변환, 메모리 컨텍스트→수명 매핑은 어떤 대형 레거시 코드든 안전한 언어로 옮길 때 재사용 가능한 전략이다. "테스트를 정답지로 고정하고 파일 단위로 옮긴다"는 규율 자체가 소프트웨어 마이그레이션의 정석.

③ Rust 고급 기법

#![no_std] + alloc만으로 도는 할당기, 수명 매개변수로 안전성을 강제하는 API 설계, 1,464개 크레이트 워크스페이스의 빌드 구성, WASM 타깃 크로스 컴파일 등 대규모 Rust 프로젝트 운영의 실물 사례.

④ 테스트 오라클 · CI 규율

회귀 테스트를 정답지로 쓰는 하네스(scripts/run-regression), 미구현을 빌드 실패로 만드는 todo_guard 게이트는 "AI가 대량으로 코드를 짜도 품질을 무너뜨리지 않게 하는" 실전 가드레일의 좋은 예다.

실습 아이디어

한 쿼리를 따라가 보기: SELECT 1+1;PostgresMain에서 파서→플래너→실행기로 흐르는 경로를 crates/backend/tcop/postgres/src/lib.rs부터 grep으로 추적. ② seam 하나 열어보기: 아무 *_seams 크레이트를 열어 "빈 슬롯 선언 + init에서 채우기" 구조를 확인. ③ 내가 좋아하는 C 파일의 Rust 짝 찾기: Postgres의 nodeHashjoin.c가 pgrust에서 어떻게 생겼는지 대조.

7빌드/시스템 요구사항

무엇이 있어야 돌아가나.

항목요구
툴체인Rust + Cargo만 (Postgres C 소스 불필요 — nodetags.h 등은 벤더됨)
시스템 라이브러리ICU, OpenSSL 3, LDAP, PAM (Debian: libicu-dev libssl-dev libldap2-dev libpam0g-dev + postgresql-client-18)
스택 크기깊은 재귀 플래너/파서 때문에 큰 스택 필요 — ulimit -s 65520, RUST_MIN_STACK=33554432, -c max_stack_depth=60000
유일한 C 도구클라이언트 psql(Postgres 18) — 테스트·접속용

빌드 · 실행 (요약)

# 1) 빌드 (벤더 share 디렉토리를 가리킨 채)
PGRUST_PGSHAREDIR="$PWD/vendor/postgres-18.3/share" \
  cargo build --release --locked --bin postgres

# 2) pgrust 자체 initdb 로 데이터 폴더 생성
target/release/postgres --initdb -D /tmp/pgrust-data \
  -L vendor/postgres-18.3/share --no-locale --encoding UTF8 -U postgres

# 3) 큰 스택으로 서버 실행 → 평범한 psql 로 접속
ulimit -s 65520
RUST_MIN_STACK=33554432 target/release/postgres -D /tmp/pgrust-data \
  -c max_stack_depth=60000

가장 쉬운 길은 도커다: docker run malisper/pgrust:v0.1 — 공식 postgres 이미지의 드롭인 대체(같은 환경변수·/docker-entrypoint-initdb.d·uid 999·5432 포트). 또는 설치 없이 pgrust.com WASM 데모.

회귀 테스트는 어떻게 "통과"를 판정하나

scripts/run-regression이 (1) pgrust 릴리스 바이너리 + 벤더된 PG 18.3 테스트 파일(sql 232개, expected/*.out 265개)만으로, (2) pgrust 고유 --initdb로 부팅해 regression DB를 만들고, (3) 공식 parallel_schedule 순서대로 각 *.sqlpsql로 흘려 (4) 출력을 기대 파일과 diff — 0줄 차이일 때만 PASS. 하나라도 PASS가 아니면 스크립트가 non-zero로 종료. regress.c의 C 테스트 헬퍼 ~60개도 test_regress 크레이트로 인프로세스 재구현되어 .so 없이 로드된다.

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

코드를 안 짜도 되는 것부터, 실제로 빌드·개조까지.

난이도 ★☆☆ — 클론만

1. 워크스페이스 지도 그리기

git clone --depth 1 https://github.com/malisper/pgrustcrates/backend/ 아래를 ls로 훑어 Postgres C 트리와의 1:1 대응을 눈으로 확인한다. 좋아하는 서브시스템(예: executor) 하나를 골라 크레이트 목록을 적어 본다. 빌드 불필요.

난이도 ★☆☆

2. seam 한 개 해부

아무 *_seams 크레이트와 crates/_support/seam/seam_core를 열어 seam! 매크로, "빈 슬롯 선언 → init_seams()에서 채움 → 미설치 호출 시 panic" 구조를 읽는다. 순환 의존이 왜 문제이고 어떻게 풀렸는지 한 단락으로 정리.

난이도 ★★☆ — 빌드

3. 빌드해서 psql로 접속

§7대로 빌드·initdb·실행 후 평범한 psql로 접속SELECT version();, 테이블 생성·인덱스·조인 쿼리를 날려 본다. "이게 진짜 Rust로 짜인 Postgres구나"를 체감. 도커 경로가 가장 빠르다.

난이도 ★★☆

4. 회귀 테스트 돌려 보기

scripts/run-regression을 실행해 46,000+ 쿼리가 어떻게 expected/*.out과 diff 판정되는지 관찰한다. 일부러 소스 한 줄을 바꿔 테스트가 어떻게 FAIL로 잡아내는지 확인 — "테스트 오라클"의 위력을 직접 본다.

난이도 ★★★ — 개조

5. 한 쿼리 경로 추적 + 작은 개조

EXPLAIN 한 줄이 파서→플래너→실행기로 흐르는 경로를 추적한 뒤, 실행기 노드 하나(예: nodeSeqScan)에 로그를 심어 스캔이 몇 번 호출되는지 관찰한다. Rust이므로 borrow checker가 실수를 잡아 준다 — C 원본에선 겁났을 개조를 안전하게 시도.

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

이 레포를 제대로 씹으려면 무엇을 곁들여 공부할까 (주차별).

주차주제무엇을
1주차DBMS 기초쿼리 처리 단계(파서→플래너→실행기), 관계 대수, 실행 계획 읽는 법. CMU 15-445 강의가 정석.
2주차Postgres 내부"The Internals of PostgreSQL" 무료 책 — MVCC, 버퍼 관리, WAL, 인덱스 AM. pgrust의 크레이트 이름과 대조.
3주차Rust 소유권·수명The Rust Book 4·10장, no_std+alloc. mcx가 왜 수명으로 안전을 강제하는지 이해할 밑바탕.
4주차Cargo 워크스페이스다중 크레이트 구조, 프로파일, 피처 플래그. 크레이트 순환이 왜 금지인지 실습으로 재현.
5주차파서/컴파일러bison/flex, LR 파싱, c2rust. 왜 문법만 자동 변환하고 스캐너는 손으로 옮겼는지.
6주차쿼리 최적화비용 기반 옵티마이저, 조인 순서, GEQO(유전 알고리즘). planner 크레이트를 읽으며.
7주차와이어 프로토콜·인증Postgres v3 프로토콜, SCRAM-SHA-256. libpq 크레이트로 "psql이 어떻게 붙나".

10핵심 키워드 사전

이 문서에 나온 용어 빠른 정리.

seam (솔기)
크레이트 순환 의존을 끊기 위한 "빈 함수 슬롯". 선언은 *_seams 크레이트에, 구현은 소유 크레이트가 시작 시 꽂아 넣는다. 미설치 호출 = panic → 미구현 추적기 역할도 겸함.
회귀 테스트 오라클 (regression test oracle)
"정답지". 옮긴 코드가 맞는지를 사람이 아니라 Postgres 공식 회귀 테스트 46,000+ 쿼리의 출력 일치로 판정한다.
c2rust
C 코드를 (동작 보존) Rust로 자동 변환하는 도구. pgrust는 기계적인 bison 문법(gram.c)에만 적용해 31만 줄 Rust로 만들었다.
메모리 컨텍스트 (memory context)
Postgres의 할당 도메인. 컨텍스트를 지우면 그 안 할당이 한꺼번에 해제된다. pgrust는 이를 Rust 수명(lifetime)으로 바꿔 "메모리가 컨텍스트보다 오래 못 살게" 컴파일 타임에 강제.
MVCC (다중 버전 동시성 제어)
여러 트랜잭션이 서로를 막지 않고 각자의 "스냅샷"을 보게 하는 기법. Postgres 동시성의 핵심.
WAL (Write-Ahead Log, 선행 기록 로그)
데이터 파일을 고치기 전에 "무엇을 바꿀지"를 먼저 로그에 적는 것. 크래시 복구·복제의 기반.
와이어 프로토콜 (wire protocol)
클라이언트(psql)와 서버가 주고받는 바이트 규약. pgrust가 v3를 그대로 말하기에 기존 클라이언트가 수정 없이 붙는다.
접근 방법 (Access Method, AM)
테이블/인덱스를 실제로 읽고 쓰는 방식. heap(테이블), nbtree·hash·gin·gist·spgist·brin(인덱스)이 각각 하나의 AM.
AGPL-3.0
네트워크로 서비스만 해도 소스 공개를 요구하는 강한 카피레프트 라이선스. Postgres 본체(관대한 라이선스)보다 훨씬 엄격 — 재사용 시 반드시 확인.

11참고 링크

더 파고들 곳.