본문으로 건너뛰기
피드

jsongrep: DFA 기반으로 jq보다 훨씬 빠른 JSON 검색 도구 (Rust)

backend 약 5분
vote
0
댓글
북마크

JSON 쿼리를 정규 언어로 취급하고 DFA로 컴파일해서 트리를 한 번만 순회하는 검색 도구. 190MB JSON 기준 엔드투엔드 성능에서 jq, jmespath 등을 압도하며, 제로카피 파싱과 서브트리 가지치기가 속도의 핵심.

  • 1

    쿼리를 DFA로 컴파일하여 노드당 O(1) 전이, 백트래킹 없음

  • 2

    serde_json_borrow로 제로카피 파싱, 메모리 오버헤드 최소화

  • 3

    190MB JSON에서 엔드투엔드 벤치마크 압도적 우위

  • 4

    jq 대체가 아닌 검색 특화 도구 — 변환/필터 기능 없음

  • 5

    MIT 라이선스, cargo/brew 설치 가능, 라이브러리 크레이트로도 제공

jsongrep: jq보다 빠른 JSON 검색 도구가 나옴

  • Rust로 작성된 jsongrep이라는 JSON 쿼리 도구가 나왔는데, ripgrep에서 영감을 받은 프로젝트임. jq처럼 JSON을 변환하는 게 아니라 JSON 트리에서 값을 검색하는 것에 특화된 도구
  • 핵심 아이디어: JSON 쿼리를 정규 언어(regular language)로 취급하고, 이를 DFA(결정적 유한 오토마타)로 컴파일해서 JSON 트리를 딱 한 번만 순회하면서 매칭함. 노드당 O(1) 전이, 백트래킹 없음, 재귀 스택 없음
  • jq, jmespath, jsonpath-rust 같은 기존 도구들은 경로 표현식을 해석(interpret)하는 방식이라 각 노드에서 쿼리를 평가하고 재귀적으로 내려가야 함. jsongrep은 검색 전에 쿼리를 DFA로 컴파일해놓으니 검색 자체는 거의 공짜

쿼리 언어: 정규표현식인데 문자 대신 JSON 경로를 매칭

  • roommates[0].name — 점(.)으로 중첩 필드 접근
  • favorite_drinks[*] — 와일드카드로 모든 배열 인덱스 매칭
  • name | roommates — 파이프로 OR 매칭 (정규표현식의 alternation)
  • (* | [*])*.name — 클레이니 스타로 재귀 하강. 아무 키/인덱스를 0번 이상 따라간 뒤 name 필드를 찾음
  • -F name 플래그로 재귀 하강 단축 가능 — 모든 깊이에서 name 필드를 찾아줌

내부 구조: 5단계 파이프라인

  • 1단계: serde_json_borrow로 JSON을 제로카피(zero-copy) 파싱. 원본 버퍼의 &str을 빌려 쓰므로 문자열 할당이 없음
  • 2단계: 쿼리 문자열을 PEG 문법(pest 라이브러리)으로 AST로 파싱
  • 3단계: Glushkov 알고리즘으로 NFA 구성. Thompson 방식과 달리 ε-전이가 없는 NFA를 만들어서 후속 처리가 깔끔함
  • 4단계: 부분집합 구성(subset construction)으로 NFA → DFA 변환. 각 DFA 상태는 NFA 상태들의 집합에 대응
  • 5단계: JSON 트리를 DFS로 순회하면서 DFA 상태 전이. 전이가 없는 엣지를 만나면 해당 서브트리 전체를 O(1)에 가지치기 — 대형 문서에서 이게 속도의 핵심

벤치마크: 190MB JSON에서 압도적

  • Criterion.rs로 벤치마킹. 4개 데이터셋(106B, 992KB, 7.6MB, 190MB)에서 테스트
  • 비교 대상: jsonpath-rust, jmespath, jaq (jq 호환), jql
  • 파싱: serde_json_borrow(제로카피)가 serde_json::Value(할당형)보다 빠름 — 예상대로
  • 컴파일: jsongrep의 가장 큰 비용이 여기 있음. DFA 구성에 시간이 걸림. jmespath보다 한 자릿수 느림
  • 검색만 따로 측정: DFA 기반이라 검색 자체는 다른 도구들을 압도
  • 엔드투엔드(파싱+컴파일+검색): xlarge(190MB) 데이터셋에서 "비교가 안 됨(it's not even close)"이라고 본인이 직접 표현할 정도로 차이가 큼

💡

> cargo install jsongrep 또는 brew install jsongrep으로 설치 가능. MIT 라이선스이고, DFA 기반 쿼리 엔진을 라이브러리 크레이트로도 제공하니 Rust 프로젝트에 임베딩할 수도 있음

솔직한 안티피치

  • jq만큼 범용적이지 않음 — jsongrep은 검색 도구이지 변환 도구가 아님. 필터, 산술 연산, 문자열 보간 없음
  • 아직 신생 프로젝트라 실전에서 검증되지 않았음
  • jq를 대체하는 게 아니라 "JSON에서 특정 값을 빠르게 찾고 싶다"는 유스케이스에 특화된 도구로 보면 됨

ripgrep이 grep에 한 것을 JSON 세계에서 하려는 시도. DFA 컴파일 비용을 감수하고도 대형 파일에서 압도적 성능을 보여주는 게 인상적.

댓글

댓글

댓글을 불러오는 중...

backend

잘못된 추상화보다 중복이 낫다는 샌디 메츠의 고전 조언

샌디 메츠는 중복을 없애려다 잘못된 추상화를 만들면 코드가 조건문과 파라미터로 부풀어 더 위험해진다고 말한다. 이미 틀어진 추상화는 억지로 보존하지 말고, 다시 호출부에 인라인해서 중복을 되살린 뒤 현재 요구사항에 맞는 새 구조를 찾는 편이 빠르다는 주장이다.

backend

리눅스 커널, 6년·360개 넘는 패치 끝에 strncpy 제거

리눅스 커널이 오랫동안 버그의 원인이던 strncpy API 사용을 Linux 7.2에서 제거했어. NUL 종료 동작이 직관적이지 않고 불필요한 zero-fill로 성능 문제도 있던 API를 6년 동안 약 362개 커밋으로 걷어낸 작업임.

backend

덕디비는 왜 빠를까: 서버 없는 분석 엔진의 내부 구조 뜯어보기

DuckDB가 단일 바이너리, 인프로세스 실행, 컬럼형 저장, 최적화 패스, Parquet 푸시다운으로 빠른 분석 쿼리를 처리하는 방식을 깊게 설명한 글이다. 6GB Parquet 파일을 노트북에서 바로 SQL로 읽는 경험 뒤에 어떤 설계가 깔려 있는지 따라간다.

backend

피지독, 포스트그레스를 수평 확장시키겠다고 550만 달러 투자 유치

피지독은 포스트그레스 앞단에 프록시를 두고 샤딩과 라우팅을 처리해 수평 확장을 가능하게 하겠다는 오픈소스 프로젝트다. 이미 프로덕션에서 초당 200만 건이 넘는 쿼리를 처리하고, 확인된 규모만 20테라바이트 이상을 샤딩했다고 밝히며 550만 달러 투자를 공개했다.

backend

펜타시스템, EDB 포스트그레SQL로 국내 엔터프라이즈 DB 전환 시장 공략

펜타시스템테크놀러지가 EDB와 파트너 계약을 맺고 국내에 EDB 포스트그레SQL 기반 데이터 플랫폼을 공급한다. 기존 상용 DBMS 정책 변화로 비용 부담이 커진 기업들을 겨냥해, 오픈소스 기반 엔터프라이즈 데이터 플랫폼 전환 수요를 잡겠다는 전략이다. 금융, 공공, 제조, 유통, 클라우드, AI 데이터 분석 환경까지 적용 범위를 넓히려는 움직임이다.