0Pricing
Linux Command Line & Bash Scripting Mastery · 강의

jq로 JSON 객체 변환 및 생성

map, to_entries 및 객체 생성을 사용하여 데이터를 재구성하고 새로운 JSON 페이로드를 만듭니다.

jq로 JSON 객체 변환 및 생성은(는) CoddyKit의 무료 Linux Command Line & Bash Scripting Mastery 강의입니다. 이것은 4개 중 2번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Linux Command Line & Bash Scripting Mastery 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Linux Command Line & Bash Scripting Mastery 강의에는 총 4개의 강의가 포함되어 있습니다.

JSON을 변환하는 이유

API나 로그 파일에서 받은 원시 JSON은 필요한 형태와 정확히 일치하는 경우가 드뭅니다. 큰 객체를 받았지만 특정 필드만 필요할 수도 있고, 키 이름을 바꾸거나 중첩된 구조를 평탄화하거나 다른 서비스로 보낼 완전히 새로운 페이로드를 만들어야 할 수도 있습니다.

jq는 이러한 변환을 하나의 파이프라인에서 수행할 수 있게 해 주는 가볍고 강력한 명령줄 JSON 처리 도구입니다. 이 강의에서는 데이터를 재구성하는 세 가지 핵심 기법을 배웁니다.

  • 객체 구성 — 처음부터 새로운 JSON 객체 만들기
  • map — 배열의 모든 요소에 변환 적용하기
  • to_entries / from_entries — 객체의 키-값 쌍을 배열처럼 다루어 필터링하고 다시 구성하기

모든 예제에서는 jq가 설치되어 있다고 가정합니다(apt install jq / brew install jq).

객체 구성 기초

jq의 가장 기본적인 기능은 객체 구성입니다. 표현식을 {}로 감싸 새로운 JSON 객체를 만듭니다. 어떤 필드를 포함할지와 필드 이름을 어떻게 지정할지를 직접 선택할 수 있습니다.

구문:

  • { newKey: .existingField } — 필드 이름 바꾸기
  • { name, age } — 새 키가 필드 이름과 같을 때 사용하는 축약형
  • { total: (.price * .qty) } — 인라인으로 값 계산하기

아래 코드는 상품 JSON을 읽고 계산된 subtotal 필드를 포함한 더 간결한 형태를 만듭니다.

#!/usr/bin/env bash
# Object construction: pick and rename fields
product='{
  "id": 42,
  "name": "Widget Pro",
  "price": 9.99,
  "qty": 3,
  "warehouse": "EU-West"
}'

echo "$product" | jq '{
  productId: .id,
  name,
  subtotal: (.price * .qty)
}'

중첩된 데이터에서 객체 구성하기

실제 JSON은 중첩되어 있는 경우가 많습니다. jq를 사용하면 객체 생성자 안에서 중첩된 경로에 접근하면서 동시에 구조를 평탄화할 수 있습니다.

생성자 값 표현식 안에서 점으로 구분된 경로 표기법을 사용하세요.

  • { city: .address.city }
  • { lat: .location.coords.lat }

아래 예제는 깊게 중첩된 사용자 레코드를 가져와 CSV 헤더 행이나 API 요청 본문에 적합한 평탄한 요약으로 만듭니다.

#!/usr/bin/env bash
user='{
  "id": "u-001",
  "profile": {
    "displayName": "Ada Lovelace",
    "contact": { "email": "ada@example.com", "phone": "+44-700" }
  },
  "plan": "pro"
}'

echo "$user" | jq '{
  id,
  name: .profile.displayName,
  email: .profile.contact.email,
  plan
}'

map으로 배열 변환하기

map(expr)는 jq에서 각 요소에 적용하는 반복에 해당합니다. 입력 배열의 모든 요소에 expr을 적용하고, 같은 길이의 새로운 배열을 반환합니다.

핵심 사항:

  • map(expr)은 [.[] | expr]의 축약형입니다.
  • 내부의 표현식에는 객체 구성 등 어떤 jq 필터든 사용할 수 있습니다.
  • select()와 연결하면 변환하기 전에 필터링할 수 있습니다.

이 코드는 주문 목록을 처리하여 배송 명세서에 필요한 필드만 남깁니다.

#!/usr/bin/env bash
orders='[
  {"orderId": 1, "customer": "Alice", "total": 42.50, "status": "shipped"},
  {"orderId": 2, "customer": "Bob",   "total": 18.00, "status": "pending"},
  {"orderId": 3, "customer": "Carol", "total": 99.99, "status": "shipped"}
]'

# Produce a shipping manifest: only shipped orders, slim fields
echo "$orders" | jq '[
  .[] | select(.status == "shipped") | {
    id: .orderId,
    recipient: .customer,
    amount: .total
  }
]'

계산된 필드와 함께 사용하는 map

map 안에서는 단순히 값을 복사하는 것뿐 아니라 새로운 값을 계산하고, 형식을 변환하고, 필드를 결합할 수 있습니다. 일반적인 패턴은 다음과 같습니다.

  • 문자열 보간: "\(.first) \(.last)"
  • 산술 연산: 20% 인상을 적용하는 (.price * 1.2 | round)
  • 조건문: if .score >= 90 then "A" else "B" end

아래 예제는 경력 연수에 따라 계산된 fullName과 seniority 레이블을 추가하여 직원 목록을 보강합니다.

#!/usr/bin/env bash
staff='[
  {"first": "Grace", "last": "Hopper",  "years": 15},
  {"first": "Alan",  "last": "Turing",  "years": 4},
  {"first": "Linus", "last": "Torvalds","years": 9}
]'

echo "$staff" | jq 'map({
  fullName: "\(.first) \(.last)",
  years,
  seniority: (if .years >= 10 then "senior" elif .years >= 5 then "mid" else "junior" end)
})'

to_entries 이해하기

to_entries는 JSON 객체를 {key, value} 쌍의 배열로 변환합니다. 이를 통해 객체의 필드에 배열 연산(map, select, sort)을 적용할 수 있습니다. 객체에는 이러한 연산을 직접 적용할 수 없습니다.

변환 예:

  • 입력: {"a": 1, "b": 2}
  • 출력: [{"key": "a", "value": 1}, {"key": "b", "value": 2}]

반대 연산은 from_entries이며, 이 연산은 배열을 다시 객체로 바꿉니다. 두 연산을 함께 사용하면 객체 수준 변환을 위한 to_entries | map(...) | from_entries 관용구를 구성할 수 있습니다.

#!/usr/bin/env bash
# Demonstrate to_entries and from_entries
config='{"host": "db.local", "port": 5432, "ssl": true}'

echo "--- to_entries output ---"
echo "$config" | jq 'to_entries'

echo "--- round-trip back to object ---"
echo "$config" | jq 'to_entries | from_entries'

to_entries로 키 필터링하기

to_entries의 가장 실용적인 용도 중 하나는 키 이름 자체를 기준으로 유지하거나 제외할 키를 동적으로 필터링하는 것입니다. 키 이름을 미리 알 수 없을 때는 객체 구성만으로 이 작업을 수행할 수 없습니다.

패턴:

  • to_entries | map(select(.key | test("regex"))) | from_entries
  • to_entries | map(select(.key != "secret")) | from_entries

아래 코드는 구성 객체를 외부 서비스로 전달하기 전에 밑줄로 시작하는 모든 키(내부/비공개 필드)를 제거합니다.

#!/usr/bin/env bash
raw_config='{
  "endpoint": "https://api.example.com",
  "timeout": 30,
  "_internalToken": "s3cr3t",
  "_debugMode": true,
  "retries": 3
}'

# Remove any key starting with underscore
echo "$raw_config" | jq '
  to_entries
  | map(select(.key | startswith("_") | not))
  | from_entries
'

to_entries로 키 이름을 동적으로 바꾸기

객체 구성은 작성 시점에 이름을 알고 있는 키의 이름을 바꿉니다. to_entries를 사용하면 키 이름을 프로그래밍 방식으로 바꿀 수 있습니다. 예를 들어 camelCase를 snake_case로 변환하거나 접두사를 추가할 수 있습니다.

map 안에서 각 항목의 .key 필드를 업데이트한 다음 from_entries로 전달합니다.

  • map(.key |= gsub("(?<=[a-z])(?=[A-Z])"; "_") | .key |= ascii_downcase) — camelCase를 snake_case로 변환
  • map(.key |= "app_" + .) — 모든 키에 접두사 추가

이 예제는 컨테이너에 주입하기 전에 모든 환경 변수 이름에 APP_ 접두사를 붙여 이름 공간을 만듭니다.

#!/usr/bin/env bash
env_vars='{"host": "localhost", "port": "8080", "debug": "false"}'

# Add APP_ prefix and uppercase all keys
echo "$env_vars" | jq '
  to_entries
  | map({ key: ("APP_" + (.key | ascii_upcase)), value })
  | from_entries
'

with_entries: 편리한 축약형

to_entries | map(...) | from_entries 패턴은 매우 자주 사용되므로 jq는 with_entries(expr)라는 축약형을 제공합니다.

동일한 기능을 더 간결하게 표현한 것입니다.

  • with_entries(.value |= . * 2) — 모든 숫자 값을 두 배로 만들기
  • with_entries(select(.value != null)) — 값이 null인 키 제거하기
  • with_entries(.key |= ascii_upcase) — 모든 키를 대문자로 바꾸기

아래 코드는 REST API에 PATCH 요청을 보내기 전에 값이 null이거나 빈 문자열인 모든 키를 제거합니다. 이는 흔히 수행하는 정리 단계입니다.

#!/usr/bin/env bash
patch_body='{
  "name": "Mehmet",
  "email": "",
  "phone": null,
  "city": "Istanbul"
}'

# Drop empty/null fields before PATCH
cleaned=$(echo "$patch_body" | jq '
  with_entries(select(.value != null and .value != ""))
')

echo "Cleaned payload:"
echo "$cleaned"

# In practice you would pipe to curl:
# curl -s -X PATCH https://api.example.com/users/1 \
#   -H "Content-Type: application/json" \
#   -d "$cleaned"

파이프라인에서 map과 객체 구성 결합하기

실제 변환에서는 여러 jq 연산을 함께 연결합니다. API 페이로드를 준비하는 일반적인 파이프라인은 다음 작업을 수행할 수 있습니다.

  1. map(select(...))로 입력 배열 필터링하기
  2. 객체 구성으로 각 요소의 형태 재구성하기
  3. 계산된 필드 추가하기
  4. 결과 정렬하기

아래 예제는 서버 지표 목록을 읽고 CPU 사용량이 높은 서버만 남긴 다음, 웹훅에 POST할 수 있는 간결한 경고 페이로드를 만듭니다.

#!/usr/bin/env bash
metrics='[
  {"host": "web-01", "cpu": 23, "mem": 60, "region": "eu"},
  {"host": "web-02", "cpu": 91, "mem": 88, "region": "eu"},
  {"host": "db-01",  "cpu": 78, "mem": 95, "region": "us"},
  {"host": "db-02",  "cpu": 12, "mem": 40, "region": "us"}
]'

alerts=$(echo "$metrics" | jq '[
  .[] | select(.cpu > 75 or .mem > 85) | {
    server: .host,
    region,
    severity: (if .cpu > 90 or .mem > 90 then "critical" else "warning" end),
    metrics: { cpu: .cpu, mem: .mem }
  }
] | sort_by(.severity)')

echo "$alerts"

여러 소스에서 새로운 JSON 객체 만들기

jq에서는 덧셈 연산자 +와 as $var를 사용한 변수 바인딩으로 입력을 병합하고 여러 JSON 소스에서 값을 가져오는 객체를 구성할 수 있습니다.

유용한 패턴:

  • obj1 + obj2 — 두 객체 병합하기(키가 충돌하면 오른쪽 값이 우선합니다)
  • --argjson — 두 번째 JSON 문서를 변수로 전달하기
  • $ENV — jq 내부에서 환경 변수를 직접 읽기

이 코드는 기본 구성과 환경별 재정의를 병합합니다. 셸 스크립트에서 12요소 애플리케이션 구성 관리를 할 때 흔히 사용하는 패턴입니다.

#!/usr/bin/env bash
base_config='{
  "logLevel": "info",
  "timeout": 30,
  "retries": 3,
  "database": "postgres://db.local/app"
}'

env_overrides='{
  "logLevel": "debug",
  "database": "postgres://db.staging/app_staging"
}'

# Merge: overrides win on conflicts
merged=$(echo "$base_config" | jq --argjson overrides "$env_overrides" '. + $overrides')

echo "Merged config:"
echo "$merged"

지식 확인: to_entries와 map 비교

다음 JSON 객체에서 값이 0보다 작은 모든 키를 제거하여 음이 아닌 값만 포함하는 새 객체를 만들어야 합니다. 이를 올바르게 수행하는 jq 표현식은 무엇일까요?

입력: {"a": 10, "b": -3, "c": 0, "d": 5}

강의 요약: jq로 JSON 변환하기

jq로 JSON을 재구성하는 데 필요한 핵심 기법을 살펴보았습니다.

  • 객체 구성 {} — 입력에서 필드를 선택하고, 이름을 바꾸고, 값을 계산하여 새 객체 만들기
  • map(expr) — 중첩된 객체 구성과 필터링을 위한 select()를 포함해 배열의 모든 요소에 변환 적용하기
  • to_entries / from_entries — 객체를 {key, value} 쌍의 배열로 변환하여 키와 값에 배열 연산을 적용한 다음 다시 객체로 변환하기
  • with_entries(expr) — 전체 to_entries → map → from_entries 파이프라인을 간결하게 표현하는 축약형
  • +와 --argjson를 사용하여 여러 소스의 페이로드를 위해 객체 병합하기

이러한 구성 요소는 서로 결합할 수 있습니다. select로 필터링하고, 객체 구성으로 형태를 재구성하고, 계산된 필드로 보강한 다음, 읽기 쉬운 하나의 jq 표현식으로 모두 연결할 수 있습니다. 이러한 패턴을 익히면 Python이나 Node로 전용 스크립트를 작성하지 않고도 셸에서 거의 모든 JSON 페이로드를 직접 다룰 수 있습니다.

자주 묻는 질문

“jq로 JSON 객체 변환 및 생성” 강의는 무료인가요?

네 — “jq로 JSON 객체 변환 및 생성” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Linux Command Line & Bash Scripting Mastery 강의 전체를 잠금 해제할 수 있습니다. Linux Command Line & Bash Scripting Mastery 강의에는 총 4개의 강의가 포함되어 있습니다.

“jq로 JSON 객체 변환 및 생성”에서 뭘 배우나요?

map, to_entries 및 객체 생성을 사용하여 데이터를 재구성하고 새로운 JSON 페이로드를 만듭니다. 브라우저에서 직접 실행하는 실습 코드로 Linux Command Line & Bash Scripting Mastery을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

Linux Command Line & Bash Scripting Mastery을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 Linux Command Line & Bash Scripting Mastery은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 2번째 강의입니다.

“jq로 JSON 객체 변환 및 생성” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 Linux Command Line & Bash Scripting Mastery 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 Linux Command Line & Bash Scripting Mastery 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. jq 파이프라인으로 JSON 필터링 및 선택
  2. jq로 JSON 객체 변환 및 생성
  3. curl과 jq를 함께 사용한 REST API 활용
  4. yq로 YAML 구성 파일 편집
← Linux Command Line & Bash Scripting Mastery(으)로 돌아가기