# jq보다 빠른 jsongrep

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

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=27940](https://news.hada.io/topic?id=27940)
- GeekNews Markdown: [https://news.hada.io/topic/27940.md](https://news.hada.io/topic/27940.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2026-03-28T09:50:17+09:00
- Updated: 2026-03-28T09:50:17+09:00
- Original source: [micahkepe.com](https://micahkepe.com/blog/jsongrep/)
- Points: 17
- Comments: 3

## Summary

JSON 탐색을 **DFA 기반 정규 언어 쿼리**로 처리해 `jq`보다 훨씬 빠른 Rust CLI 도구 **jsongrep**이 공개되었습니다. 쿼리를 미리 DFA로 컴파일해 JSON 트리를 단 한 번만 순회하므로, 대용량 데이터에서도 **O(n)** 시간에 검색을 끝냅니다. `serde_json_borrow`를 이용한 **zero-copy 파싱**으로 메모리 사용을 최소화하며, `ripgrep`처럼 속도 중심의 설계를 따릅니다.

## Topic Body

- JSON 문서를 **경로 기반으로 탐색**하는 Rust CLI 도구로, 기존 `jq`, `jmespath`, `jsonpath-rust`, `jql`보다 **검색 속도**가 빠름
- 쿼리를 **정규 언어로 표현해 DFA로 컴파일**하고, JSON 트리를 단일 패스로 탐색하는 구조로 **O(n)** 시간에 처리
- **zero-copy 파싱**을 지원하는 `serde_json_borrow`를 사용해 메모리 할당을 최소화하고, **ripgrep**의 성능 철학을 참고해 설계됨
- 벤치마크 결과, 대용량 JSON에서도 **엔드투엔드 성능이 가장 우수**하며, 검색 중심의 단순 쿼리 언어를 제공
- **MIT 라이선스**로 공개되어 있으며, DFA 기반 쿼리 엔진을 **Rust 라이브러리로 재사용 가능**함

---

### jsongrep 개요
- **jsongrep**은 JSON 문서에서 경로 기반으로 값을 검색하는 **Rust 기반 CLI 도구**로, `jq`, `jmespath`, `jsonpath-rust`, `jql`보다 빠른 성능을 목표로 함
- JSON 문서를 트리로 보고, **경로(path)** 를 **정규 언어(regular language)** 로 표현해 **DFA(Deterministic Finite Automaton)** 로 컴파일 후 단일 패스로 탐색 수행
- 쿼리 언어는 단순하며, **검색 중심**으로 설계되어 변환이나 계산 기능은 없음
- `serde_json_borrow`를 이용한 **zero-copy 파싱**으로 메모리 할당을 최소화
- `ripgrep`의 설계 철학과 성능 접근 방식을 참고해 개발됨

### jsongrep 사용 예시
- 명령어 `jg`는 **쿼리**와 **JSON 입력**을 받아, 경로가 쿼리와 일치하는 모든 값을 출력
- **점 표기(dot path)** 로 중첩 필드 접근
  - `jg 'roommates[0].name'` → `"Alice"`
- **와일드카드**(`*`, `[*]`)로 모든 키나 인덱스 매칭
- **Alternation**(`|`)으로 여러 경로 중 하나 선택
- **재귀 탐색**(`(* | [*])*`)으로 임의 깊이의 필드 검색
- **Optional**(`?`)로 0회 또는 1회 매칭 지원
- `-F` 옵션으로 특정 필드명을 빠르게 검색 가능
- 파이프(`| less`, `| sort`) 사용 시 자동으로 경로 출력 생략, `--with-path`로 강제 표시 가능

### jsongrep의 핵심 개념
- JSON은 **트리 구조**이며, 객체 키와 배열 인덱스가 **엣지(edge)** 역할을 함
- 쿼리는 루트에서 특정 노드까지의 **경로 집합**을 정의
- 쿼리 언어는 **정규 언어**로 설계되어 DFA로 변환 가능
- DFA는 입력을 한 번만 읽으며, **백트래킹 없이 O(n)** 시간에 탐색 수행
- 기존 도구(`jq`, `jmespath` 등)는 쿼리를 **인터프리트**하며 재귀적으로 탐색하지만, jsongrep은 **사전 컴파일된 DFA**로 단일 패스 탐색 수행

### DFA 기반 쿼리 엔진 구조
- 파이프라인은 5단계로 구성
  1. `serde_json_borrow`로 JSON을 트리로 파싱
  2. 쿼리를 AST로 파싱
  3. Glushkov 알고리듬으로 NFA 생성
  4. Subset Construction으로 DFA로 변환
  5. DFA 전이를 따라 JSON 트리를 단일 DFS로 탐색
- ## 쿼리 파싱
  - PEG 문법(`pest` 라이브러리 사용)으로 쿼리를 `Query` AST로 변환
  - 주요 구문 요소: `Field`, `Index`, `Range`, `FieldWildcard`, `ArrayWildcard`, `Optional`, `KleeneStar`, `Disjunction`, `Sequence`
  - 예: `roommates[*].name` → `Sequence(Field("roommates"), ArrayWildcard, Field("name"))`
- ## JSON 트리 모델
  - 객체 키와 배열 인덱스는 **엣지**, 값은 **노드**
  - 예: `roommates[*].name`은 `roommates` → `[0]` → `name` 경로를 탐색
- ## NFA 구성 (Glushkov 알고리듬)
  - **ε-전이 없는 NFA** 생성
  - 단계
    1. 쿼리 심볼에 위치 번호 부여
    2. First/Last/Follows 집합 계산
    3. 각 위치 간 전이 구성
  - 예시 쿼리 `roommates[*].name`의 NFA는 4개 상태로 구성된 단순 선형 구조
- ## DFA 변환 (Subset Construction)
  - NFA의 상태 집합을 기반으로 **결정적 DFA** 생성
  - 각 상태는 하나의 NFA 상태 집합에 대응
  - `Other` 심볼을 추가해 불필요한 키를 효율적으로 건너뜀
  - 단순 쿼리는 NFA와 동일한 구조의 DFA로 변환됨
- ## DFS 기반 탐색
  - 루트에서 시작해 각 엣지를 따라 DFA 전이 수행
  - 전이가 없으면 해당 서브트리 **가지치기(prune)**
  - DFA 상태가 **accepting**이면 경로와 값을 기록
  - 각 노드는 최대 한 번 방문하며, 전체 탐색은 **O(n)**
  - `serde_json_borrow`로 문자열 복사 없이 원본 버퍼 참조

### 벤치마크 방법론
- **Criterion.rs**로 통계 기반 벤치마크 수행
- ## 데이터셋
  - `simple.json` (106B), `kubernetes-definitions.json` (~992KB), `kestra-0.19.0.json` (~7.6MB), `citylots.json` (~190MB)
- ## 비교 도구
  - `jsongrep`, `jsonpath-rust`, `jmespath`, `jaq`, `jql`
- ## 벤치마크 그룹
  1. `document_parse`: JSON 파싱 속도
  2. `query_compile`: 쿼리 컴파일 시간
  3. `query_search`: 탐색만 수행
  4. `end_to_end`: 전체 파이프라인
- ## 공정성 고려
  - zero-copy 파싱 이점은 별도 측정
  - DFA 컴파일 비용은 분리 측정
  - 기능이 없는 도구는 해당 테스트 제외
  - 데이터 복제 비용은 분리 처리

### 벤치마크 결과
- **문서 파싱 시간**: `serde_json_borrow`가 가장 빠름
- **쿼리 컴파일 시간**: `jsongrep`은 DFA 생성으로 가장 큰 비용 발생, `jmespath`는 훨씬 빠름
- **검색 시간**: `jsongrep`이 모든 도구 중 가장 빠름
- **엔드투엔드 성능**: 190MB 데이터셋 기준으로도 `jq`, `jmespath`, `jsonpath-rust`, `jql`보다 **압도적으로 빠름**
- 전체 결과는 [라이브 벤치마크 사이트](https://micahkepe.com/jsongrep/report/index.html)에서 확인 가능

### 라이선스 및 활용
- **MIT 라이선스**의 오픈소스 소프트웨어
- GitHub, Crates.io, Docs.rs에서 이용 가능
- DFA 기반 쿼리 엔진을 **라이브러리 형태로 재사용 가능**, Rust 프로젝트에 직접 통합 가능

### 참고 문헌
- Glushkov, V. M. (1961), *The Abstract Theory of Automata*
- Rabin, M. O., & Scott, D. (1959), *Finite Automata and Their Decision Problems*

## Comments



### Comment 54571

- Author: roxie
- Created: 2026-04-03T15:10:15+09:00
- Points: 1

멋있네요

### Comment 54029

- Author: lamanus
- Created: 2026-03-28T12:20:26+09:00
- Points: 1

| 파이프 표시가 왜 본문에서는 다르게 보일까요? 신기하네요..

### Comment 54023

- Author: neo
- Created: 2026-03-28T09:50:17+09:00
- Points: 1

###### [Hacker News 의견들](https://news.ycombinator.com/item?id=47539825) 
- jq의 **문법이 너무 난해**해서 매번 단순한 JSON 값 하나를 가져오려 해도 검색해봐야 함
  - 흥미로움. 나는 jq의 문법이 직관적이라 느끼며, **쉘 파이프라인**처럼 점, 파이프, 대괄호만 쓰는 게 익숙함  
    주로 일회성 필터를 작성하기 때문에 읽는 시간보다 쓰는 시간이 많음  
    아마 내 사용 사례가 단순하거나 jq가 내 사고방식에 잘 맞는 듯함  
    모든 CLI 도구가 JSON을 입출력하고 jq로 연결되는 세상을 꿈꾸지만, 그건 당신에게는 악몽일 듯함
  - jq는 자주 쓰지 않아서 **‘배움의 골짜기’** 에 머무는 도구임  
    쓸 때마다 새로 배워야 해서 직관적이지 않음  
    sed도 [Turing 완전함](https://catonmat.net/proof-that-sed-is-turing-complete)에도 불구하고 대부분은 정규식 치환 정도만 씀
  - 내가 만든 [celq](https://github.com/IvanIsCoding/celq)를 추천함  
    jq를 좋아하지만, 예전에 내가 쓴 쿼리를 이해 못할 때가 있었음  
    celq는 더 익숙한 **CEL 언어**를 사용함
  - 나도 비슷한 이유로 [dq](https://crespo.business/posts/dq-its-just-js/)라는 도구를 직접 만듦  
    단순히 **JavaScript로 JSON을 다루는** 방식인데, 놀랍게도 jq보다 빠름  
    `$ cat package.json | dq 'Object.keys(data).slice(0, 5)'` 같은 식으로 사용함
  - JSON 자체가 **불필요한 구문적 잡음**이 많아서 귀찮음  
    나는 Clojure를 배운 덕분에 이제는 JSON 대신 **EDN**을 씀  
    더 간결하고 읽기 쉬우며 구조적으로 다루기 쉬움  
    요즘은 borkdude/jet이나 babashka로 데이터를 다루고, djblue/portal로 시각화함  
    jq의 복잡한 연산자를 고집하는 이유를 이해 못하겠음  

- 성능을 중요하게 생각하지만, 나노초 단위의 비교는 **과시적 퍼포먼스**처럼 느껴짐  
  대부분의 경우 지금 쓰는 도구로 충분함  
  예를 들어, 나는 큰 파일에서만 grep 대신 rg를 씀
  - 이런 생각이 들면 “나는 **타깃 사용자가 아니다**”라고 생각하면 됨  
    2ms와 0.2ms의 차이는 사소해 보여도, TB 단위의 스트림을 처리하는 사람에게는 중요함
  - 하지만 모두가 그렇게 생각하면 결국 **작은 비효율이 누적**되어 전체가 느려짐  
    하드웨어는 빨라졌는데 소프트웨어는 오히려 느려지는 현실임
  - jq가 차별화되려면 **직관적인 문법과 실전 예시**가 더 많아야 함
  - “충분히 빠르다”는 말이 늘 마음에 걸림  
    최적화를 거부하는 건 **게으름과 상상력 부족**처럼 느껴짐  
    네트워크 지연보다 빠르다는 이유로 안심하는 건 변명처럼 들림
  - 나도 속도보다 **사용성**과 기능을 더 중요하게 생각함  
    만약 JSON이 너무 크다면, JSON 대신 **이진 포맷**을 써야 함  
    CLI에서 복잡한 파이프라인을 짜야 한다면, 차라리 프로그램을 작성하는 게 낫다고 봄  

- 많은 새로운 CLI 도구들이 “더 빠르다”를 내세우지만, 실제로 jq가 느리다고 느낀 적은 거의 없음  
  - 나는 TB 단위의 ndjson 파일을 다룸  
    jq로 필드 이름만 바꾸는 단순 작업도 너무 느려서 **Node나 Rust 스크립트**로 직접 처리함
  - **초대형 로그 파일**을 다루는 경우 jq가 느리게 느껴질 수 있음  
    하이퍼스케일러 환경에서는 수 TB의 로그를 직접 내려받아 분석함
  - 우리는 수천 개의 노드에서 JSON 응답을 파싱함  
    모니터링 해상도에 따라 성능 차이가 체감될 수 있음
  - 새로운 도구가 나올 때마다 “Rust로 다시 만든 더 빠른 버전” 패턴이 반복됨  
    기능 일부만 구현하고 벤치마크로 승리를 주장하는 식임  
    이번 프로젝트도 그런 **‘부분집합이 더 빠르다’** 트렌드의 일환으로 보임
  - 어떤 도구가 느리다는 건 실제로 **느려지는 순간**에만 깨닫게 됨  
    그때부터는 모든 게 느리게 느껴짐  
    ripgrep처럼 한 번 빠른 도구를 쓰면 다시 돌아가기 어려움  

- jq와 yq를 모두 써봤지만, yq는 훨씬 느림에도 불만이 없었음  
  jq보다 빠른 도구가 있다면 멋지지만, 그건 **특정 사용자층**에게만 필요함  
  그래도 최적화를 사랑하는 사람으로서 존경을 표함
  - 어떤 yq를 말하는지 궁금함 — Go 버전인지 Python 버전인지?
  - 서버 통합 환경에서는 성능이 중요하지만, CLI에서는 대부분 충분히 빠름
  - 나는 ArcGIS에서 내보낸 **GeoJSON 수 GB**를 jq로 처리함  
    ETL 단계에서 시간이 꽤 걸림
  - 모든 사람이 같은 방식으로 도구를 쓰는 건 아님  

- 페이지를 처음 열었을 때 **라이트 모드 색상 깨짐**이 있었음  
  다크 모드로 전환했다가 돌아오면 해결됨
  - 사이트도 도구처럼 **‘vibe-coded’** 된 느낌임
  - 작성자인 내가 라이트 모드를 안 써서 테스트를 깜빡했음, 바로 수정 예정임
  - CSS에서 다크 모드 스타일이 일부 새어 나왔던 문제였음
  - Android Firefox에서는 괜찮았지만, **차트 스케일이 제각각**이라 비교가 어려움
  - 이제 수정 완료됨  

- 나는 **정확성** 때문에 [Jaq](https://github.com/01mf02/jaq)으로 갈아탐  
  성능도 jq보다 낫다고 함
  - 추천 고마움. jaq는 jsongrep보다 **올바른 방향으로 더 발전**한 듯함
  - 다만 jaq 3.0이 배포판 jq보다 빠르지만, **직접 빌드한 jq**가 더 빠름  
    jq의 느리다는 평판은 배포 패키징 문제 때문으로 보임  

- 나는 업무상 **newline-delimited JSON(jsonl)** 을 자주 다룸  
  각 줄이 완전한 JSON 객체인데, 주요 CLI 도구들이 이 포맷을 지원하는지 궁금함  

- jq, mlr, htmlq, xsv, yq 등 여러 **데이터 처리 CLI 도구**를 써봤지만,  
  [Nushell](https://www.nushell.sh/)을 발견한 뒤로는 전부 대체됨  
  하나의 문법으로 모든 포맷을 다룰 수 있어 신선한 경험이었음
  - 나도 2023년 중반부터 Nushell을 **주력 쉘**로 사용 중임  
    동료들과 협업할 때만 jq, yq, mlr을 병행함
  - 나도 Nushell로 대부분 대체함  
    자동완성 설정과 명령어 검색성에 약간의 불편이 있지만, **oh-my-zsh보다 훨씬 낫음**  
    타입 주석 강제, 정적 바이너리 컴파일, TUI 라이브러리까지 생기면 소규모 앱 작성에도 쓸 듯함
  - 나도 동의함. Nushell은 **직관적이고 일관된 문법** 덕분에 자동화가 훨씬 쉬워짐  

- 멋진 도구임! 다만 **벤치마크 시각화**가 조금 아쉬움  
  모든 도구가 같은 색이라 jsongrep이 어디 있는지 찾기 어려움  
  jq 자체도 그래프에 없어서 혼란스러웠음  
  xLarge 파일이 190MiB라 작은 편인데, 나는 400MiB~1GiB JSON을 자주 다룸
  - 작성자인 내가 답변함. 현재 벤치마크 범위는 106B~190MB 정도임  
    더 큰 공개 JSON 문서가 있다면 알려주면 좋겠음  

- **벤치마크 시각화**가 거칠게 느껴짐  
  색상이나 형태를 활용해 더 많은 차원을 표현하면 좋겠음  
  파일 경로를 직접 읽어야 결과를 이해할 수 있는 건 불편함
