jq 파이프라인으로 JSON 필터링 및 선택
jq 선택자, 파이프 및 select 필터를 사용하여 중첩된 객체와 배열을 탐색합니다.
jq 파이프라인으로 JSON 필터링 및 선택은(는) CoddyKit의 무료 DevOps Bootcamp 강의입니다. 이것은 4개 중 1번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 DevOps Bootcamp 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. DevOps Bootcamp 강의에는 총 4개의 강의가 포함되어 있습니다.
jq란 무엇이며 왜 사용합니까?
jq는 JSON 데이터를 구문 분석하고, 필터링하고, 변환하는 가볍고 강력한 명령줄 도구입니다. jq는 JSON의 sed와 같은 도구입니다. JSON을 jq에 파이프로 전달하면 구조화된 출력을 돌려받습니다.
- 대부분의 Linux 배포판에 사전 설치되어 있거나
apt install jq/brew install jq로 설치할 수 있습니다. curl,cat및 기타 도구와 함께 셸 파이프라인에서 자연스럽게 작동합니다.- 필터링, 매핑, 축약 및 형식 변환을 지원합니다.
기본 호출 방식은 jq '<filter>' file.json이며, cat file.json | jq '<filter>'처럼 파이프로 연결할 수도 있습니다. 필터 .(점)는 항등 필터로, 문서 전체를 보기 좋게 출력합니다.
# Pretty-print a JSON file
jq '.' data.json
# Or pipe from curl
curl -s https://api.github.com/users/torvalds | jq '.'점 표기법으로 객체 필드 선택하기
JSON 객체의 필드에 접근하려면 점 표기법을 사용합니다: .fieldName. 선택자를 연결하여 중첩된 객체를 탐색할 수 있습니다.
.name— 최상위 필드.address.city— 중첩된 필드."field-with-dash"— 특수 문자가 있는 필드에는 따옴표가 필요합니다.
필드가 존재하지 않으면 jq는 오류를 발생시키는 대신 null을 반환합니다. 따라서 선택적 필드마다 별도의 null 확인을 하지 않고도 스크립트에서 안전하게 사용할 수 있습니다.
# Given: {"name":"Alice","address":{"city":"Berlin","zip":"10115"}}
echo '{"name":"Alice","address":{"city":"Berlin","zip":"10115"}}' | jq '.name'
# Output: "Alice"
echo '{"name":"Alice","address":{"city":"Berlin","zip":"10115"}}' | jq '.address.city'
# Output: "Berlin"배열 요소에 접근하고 순회하기
JSON 배열에는 대괄호 표기법으로 접근합니다. jq는 0부터 시작하는 인덱스를 사용합니다.
.items[0]— 첫 번째 요소.items[-1]— 마지막 요소.items[1:3]— 조각(인덱스 1부터 3 직전까지).items[]— 배열을 분해합니다. 각 요소를 별도의 값으로 출력하며, 이것이 반복자입니다.
반복자 []는 jq 파이프라인의 기본 요소입니다. 이를 사용하면 뒤따르는 필터를 각 요소에 독립적으로 적용할 수 있습니다.
# Given an array of users
echo '[{"name":"Alice"},{"name":"Bob"},{"name":"Carol"}]' | jq '.[0]'
# Output: {"name":"Alice"}
# Iterate all elements and extract .name from each
echo '[{"name":"Alice"},{"name":"Bob"},{"name":"Carol"}]' | jq '.[].name'
# Output:
# "Alice"
# "Bob"
# "Carol"파이프 연산자로 jq 파이프라인 구성하기
셸 파이프 |와 마찬가지로 jq에도 자체적인 내부 파이프 연산자가 있습니다. 이 연산자는 한 필터의 출력을 다음 필터의 입력으로 전달합니다.
jq '.users[] | .name'— 사용자를 순회한 다음 각 사용자의 이름을 추출합니다.jq '.data | .items[] | .id'— 데이터로 이동하고, 항목을 분해한 다음, ID를 추출합니다.
jq 표현식 안의 파이프를 사용하면 복잡한 변환을 단계별로 구성할 수 있습니다. 각 단계는 이전 단계가 생성한 값을 받으며, 여기에는 반복자가 생성한 여러 값도 포함됩니다.
핵심 통찰: 반복자가 N개의 값을 생성하면 이후의 각 필터는 값마다 한 번씩, 총 N번 실행됩니다.
# Nested pipeline: navigate -> iterate -> extract
echo '{"users":[{"name":"Alice","age":30},{"name":"Bob","age":25}]}' \
| jq '.users[] | .name'
# Output:
# "Alice"
# "Bob"
# Chain more stages
echo '{"users":[{"name":"Alice","age":30},{"name":"Bob","age":25}]}' \
| jq '.users[] | .age'
# Output:
# 30
# 25select()로 필터링하기
select(condition) 필터는 조건이 참일 때만 값을 통과시키고, 그렇지 않으면 출력을 생성하지 않습니다. 이는 SQL의 grep 또는 WHERE에 해당하는 jq 기능입니다.
select(.age > 18)— 나이가 18보다 큰 객체만 남깁니다.select(.status == "active")— 같은지 확인합니다.select(.name | startswith("A"))— 중첩된 문자열 테스트입니다.
반복자와 select를 함께 사용하여 배열을 필터링할 수 있습니다: .items[] | select(.active)는 .active가 참으로 처리되는 요소만 출력합니다.
# Filter array elements by a condition
echo '[{"name":"Alice","age":30},{"name":"Bob","age":17},{"name":"Carol","age":25}]' \
| jq '.[] | select(.age >= 18) | .name'
# Output:
# "Alice"
# "Carol"
# Filter by string equality
echo '[{"name":"Alice","role":"admin"},{"name":"Bob","role":"user"}]' \
| jq '.[] | select(.role == "admin") | .name'
# Output: "Alice"{}와 []로 객체와 배열 재구성하기
jq에서는 {}로 새 객체를 만들고 []로 새 배열을 만들어 데이터를 재구성할 수 있습니다.
{name: .name, city: .address.city}— 필드를 선택하고 이름을 바꾸어 새 객체에 넣습니다.[.items[] | .id]— 순회하면서 얻은 값들을 다시 배열로 모읍니다.- 축약형인
{name, age}는{name: .name, age: .age}와 같습니다.
파이프라인을 [...]으로 감싸는 것을 배열 생성이라고 합니다. 값의 스트림이 아니라 JSON 배열을 출력하려 할 때 반드시 필요합니다.
# Reshape: keep only selected fields
echo '[{"id":1,"name":"Alice","password":"secret"},{"id":2,"name":"Bob","password":"secret"}]' \
| jq '[.[] | {id, name}]'
# Output:
# [
# {"id": 1, "name": "Alice"},
# {"id": 2, "name": "Bob"}
# ]
# Collect filtered names into an array
echo '[{"name":"Alice","active":true},{"name":"Bob","active":false}]' \
| jq '[.[] | select(.active) | .name]'
# Output: ["Alice"]중첩 배열과 재귀적 탐색 다루기
실제 JSON은 깊게 중첩된 경우가 많습니다. jq는 깊이 탐색을 위해 다음 두 가지 도구를 제공합니다.
.a.b.c— 구조를 알고 있을 때 사용하는 명시적 경로.. | .fieldName?— 재귀적 탐색: 트리의 모든 노드를 순회하며 키가 존재하는 노드의 값을 출력합니다.
?(시도) 연산자는 특정 노드에 필드가 없을 때 오류를 억제합니다. 이는 서로 다른 구조가 섞인 트리에서 재귀적 탐색을 사용할 때 매우 중요합니다.
큰 문서에서는 재귀적 탐색을 신중하게 사용하십시오. 모든 노드를 방문하므로 느려질 수 있습니다. 구조가 예측 가능하다면 명시적 경로를 사용하는 편이 좋습니다.
# Explicit deep path
echo '{"a":{"b":{"c":42}}}' | jq '.a.b.c'
# Output: 42
# Recursive descent: find all "id" values anywhere in the tree
echo '{"users":[{"id":1,"profile":{"id":99}},{"id":2}]}' \
| jq '.. | .id?'
# Output:
# 1
# 99
# 2실전 예제: curl API 응답 구문 분석하기
가장 일반적인 jq 사용 사례 중 하나는 curl로 가져온 REST API 응답을 구문 분석하는 것입니다. curl -s(자동 출력 억제)와 jq 파이프라인을 함께 사용하면 깔끔하고 스크립트에서 활용하기 쉬운 데이터 추출이 가능합니다.
- 단일 값 추출:
curl -s URL | jq '.field' - 요약 표 작성: 배열을 순회하고 필요한 필드만 포함하도록 객체를 재구성합니다.
-r(원시 출력)을 사용하여 문자열 값을 둘러싼 따옴표를 제거합니다. 셸 변수에 할당할 때 필수적입니다.
팁: jq 출력이 셸 변수로 사용되거나 다른 명령으로 파이프될 때는 항상 -r을 추가하십시오.
#!/usr/bin/env bash
# Fetch GitHub repo info and extract specific fields
REPO="torvalds/linux"
RESPONSE=$(curl -s "https://api.github.com/repos/${REPO}")
# Extract fields
STARS=$(echo "$RESPONSE" | jq -r '.stargazers_count')
LANG=$(echo "$RESPONSE" | jq -r '.language')
DESC=$(echo "$RESPONSE" | jq -r '.description')
echo "Stars : $STARS"
echo "Lang : $LANG"
echo "Desc : $DESC"map()과 map_values() 사용하기
jq는 컬렉션을 변환할 수 있는 다음 두 가지 편리한 고차 함수를 제공합니다.
map(f)— 배열의 모든 요소에 필터f를 적용하여 새 배열을 반환합니다.[.[] | f]와 같습니다.map_values(f)— 객체 또는 배열의 모든 값에f를 적용하면서 키와 인덱스는 유지합니다.
이 함수들은 파이프라인을 수동으로 []으로 감싸는 방식보다 읽기 쉽고, 배열 형태를 유지해야 하는 변환에 사용하는 관용적인 jq 스타일입니다.
# map: extract a field from each element
echo '[{"name":"Alice","score":95},{"name":"Bob","score":80}]' \
| jq 'map(.name)'
# Output: ["Alice", "Bob"]
# map with select: filter + transform in one step
echo '[{"name":"Alice","score":95},{"name":"Bob","score":60}]' \
| jq 'map(select(.score >= 70) | .name)'
# Output: ["Alice"]
# map_values: multiply every value in an object by 2
echo '{"a":1,"b":2,"c":3}' | jq 'map_values(. * 2)'
# Output: {"a":2,"b":4,"c":6}//로 선택적 필드와 기본값 처리하기
외부 소스의 JSON 데이터는 일관되지 않은 경우가 많습니다. 필드가 누락되거나 null일 수 있습니다. jq는 대체 연산자 //(이중 슬래시)를 제공하여 기본값을 지정할 수 있게 합니다.
.nickname // "anonymous"—.nickname이 null이나 false가 아니면 사용하고, 그렇지 않으면"anonymous"를 사용합니다..count // 0— 숫자 기본값입니다.select와 함께 사용:select((.status // "inactive") == "active")
이는 셸에서 이에 해당하는 ${VAR:-default}보다 훨씬 간결하며, 더 긴 파이프라인 안에서도 깔끔하게 조합할 수 있습니다.
# Provide defaults for missing/null fields
echo '[{"name":"Alice","role":"admin"},{"name":"Bob"}]' \
| jq '[.[] | {name, role: (.role // "user")}]'
# Output:
# [
# {"name": "Alice", "role": "admin"},
# {"name": "Bob", "role": "user"}
# ]
# Numeric default
echo '{"items":[1,2,3]}' | jq '.total // 0'
# Output: 0실전 스크립트: JSON 로그 구문 분석기
구조화된 JSON 로깅은 현대 시스템의 표준입니다. 다음은 줄로 구분된 JSON 로그 파일을 읽고, 오류 항목만 필터링한 뒤, 사람이 읽기 쉬운 요약으로 서식을 지정하는 실제적인 스크립트입니다.
사용된 핵심 패턴은 다음과 같습니다.
-c(간결한 출력) — 한 줄에 JSON 객체 하나를 출력하며, 셸 반복문으로 파이프할 때 유용합니다.--arg name value— 셸 변수를 jq 문자열 인수로 주입합니다.- 로그 수준 필터링에
select를 사용합니다. echo에 적합한 원시 문자열 출력에-r을 사용합니다.
#!/usr/bin/env bash
# Parse newline-delimited JSON logs and report ERRORs
# Each log line: {"level":"ERROR","msg":"...","ts":"2024-01-15T10:23:00Z","svc":"auth"}
LOG_FILE="/var/log/app/app.log"
LEVEL="ERROR"
echo "=== $LEVEL entries in $LOG_FILE ==="
jq -r --arg lvl "$LEVEL" \
'select(.level == $lvl) | "[\(.ts)] [\(.svc)] \(.msg)"' \
"$LOG_FILE"
# Count errors per service
echo ""
echo "=== Error count by service ==="
jq -r --arg lvl "$LEVEL" \
'select(.level == $lvl) | .svc' "$LOG_FILE" \
| sort | uniq -c | sort -rn지식 확인: jq select() 동작
jq 파이프라인 안에서 select()가 어떻게 작동하는지 이해했는지 확인해 보세요.
다음 명령이 주어졌습니다.
echo '[{"name":"Alice","age":30},{"name":"Bob","age":17},{"name":"Carol","age":22}]' | jq '[.[] | select(.age >= 18) | .name]'출력 결과는 무엇일까요?
강의 요약: JSON 필터링을 위한 jq 파이프라인
명령줄에서 JSON을 탐색하고 필터링하는 데 필요한 jq 핵심 도구를 살펴보았습니다.
- 점 표기법(
.field,.a.b.c)을 사용하면 객체에서 필드를 선택할 수 있습니다. - 배열 접근(
.[0],.[])을 사용하면 배열의 인덱스에 접근하고 배열을 순회할 수 있습니다. - 파이프 연산자(
|)는 필터를 연결하며, 각 단계는 이전 단계의 모든 값을 처리합니다. - select(cond)는 값을 필터링하여 조건이 참인 값만 전달합니다.
- 객체/배열 구성(
{},[],map())을 사용하면 데이터를 새로운 구조로 재구성할 수 있습니다. - 대체 연산자(
//)는 null이거나 누락된 필드에 기본값을 제공합니다. - -r 플래그는 셸 변수에 할당할 때 따옴표를 제거하며, --arg는 셸 변수를 안전하게 주입합니다.
- 재귀 하강(
.. | .field?)은 경로를 모를 때 깊게 중첩된 트리를 검색합니다.
이러한 구성 요소를 사용하면 터미널을 벗어나지 않고도 어떤 JSON API 응답, 로그 파일 또는 구성도 스크립트에 필요한 정확한 데이터로 변환할 수 있습니다.
자주 묻는 질문
“jq 파이프라인으로 JSON 필터링 및 선택” 강의는 무료인가요?
네 — “jq 파이프라인으로 JSON 필터링 및 선택” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 DevOps Bootcamp 강의 전체를 잠금 해제할 수 있습니다. DevOps Bootcamp 강의에는 총 4개의 강의가 포함되어 있습니다.
“jq 파이프라인으로 JSON 필터링 및 선택”에서 뭘 배우나요?
jq 선택자, 파이프 및 select 필터를 사용하여 중첩된 객체와 배열을 탐색합니다. 브라우저에서 직접 실행하는 실습 코드로 DevOps Bootcamp을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
DevOps Bootcamp을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 DevOps Bootcamp은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 1번째 강의입니다.
“jq 파이프라인으로 JSON 필터링 및 선택” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 DevOps Bootcamp 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 DevOps Bootcamp 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- jq 파이프라인으로 JSON 필터링 및 선택
- jq로 JSON 객체 변환 및 생성
- curl과 jq를 함께 사용한 REST API 활용
- yq로 YAML 구성 파일 편집