JSON null 값 제거, 뭐가 남고 뭐가 지워지나

API 응답이나 설정 파일에 섞여 있는 null, 빈 문자열(""), 빈 배열([]), 빈 객체({})를 한 번에 걸러내려면 결국 하나의 판정 규칙만 알면 됩니다. 어떤 값을 "비어 있다"로 볼지, 그리고 그 판정이 안쪽 값부터 바깥쪽 순서로 적용된다는 점입니다. 이 글은 그 규칙을 코드 기준으로 그대로 설명합니다.

요약 ① 빈 문자열, null, undefined, 빈 배열, 빈 객체만 제거되고 0과 false, 비어 있지 않은 문자열은 그대로 남습니다. ② 자식 값부터 정리한 뒤 부모를 판정하므로, 중첩 객체가 비게 되면 상위 레벨에서도 함께 삭제됩니다. ③ 표준 JSON.parse를 쓰기 때문에 트레일링 콤마·따옴표 없는 키·리터럴 undefined가 있으면 처리 자체가 거부됩니다.

왜 이런 정리가 필요해지나

API 응답 JSON을 파일로 저장해 다음 실행에 재사용하거나, 여러 요청 결과를 모아 로그로 남기는 경우가 있습니다. 이때 선택 필드가 비어 있으면 응답에는 그 자리에 null이나 빈 문자열, 빈 배열이 그대로 채워져 내려옵니다.

파일이 쌓일수록 실제 값이 있는 키보다 비어 있는 키가 더 많아지기도 합니다. 이런 파일을 diff로 비교하거나 눈으로 훑어볼 때, 빈 값이 화면을 채우고 있으면 정작 봐야 할 값을 찾기 어려워집니다.

문제는 빈 값이 최상위에만 있지 않다는 점입니다. 중첩된 객체 안, 배열 안의 객체 안에 또 중첩되어 있는 경우가 흔해서, 한 단계씩 손으로 지우다 보면 빠뜨리는 지점이 생기고 구조가 망가지기 쉽습니다.

도구 없이 직접 정리하는 방법

이 정리 규칙은 특별한 게 아니라 재귀 함수 하나로 표현할 수 있습니다. 브라우저 개발자 도구의 콘솔에 그대로 붙여 넣으면 도구 없이도 같은 결과를 얻을 수 있습니다.

function isEmpty(v) {
  if (v === "" || v === null || v === undefined) return true;
  if (Array.isArray(v) && v.length === 0) return true;
  if (v && typeof v === "object" && Object.keys(v).length === 0) return true;
  return false;
}

function cleanValues(value) {
  if (Array.isArray(value)) {
    return value.map(cleanValues).filter((v) => !isEmpty(v));
  }
  if (value !== null && typeof value === "object") {
    const result = {};
    for (const [key, val] of Object.entries(value)) {
      const cleaned = cleanValues(val);
      if (!isEmpty(cleaned)) result[key] = cleaned;
    }
    return result;
  }
  return value;
}

const data = JSON.parse(원본_JSON_문자열);
console.log(JSON.stringify(cleanValues(data), null, 2));

순서만 정리하면 이렇습니다.

  1. 원본 JSON 문자열을 JSON.parse로 파싱합니다. 문법이 틀리면 이 단계에서 에러가 나므로, 먼저 문법 오류가 없는지부터 확인해야 합니다.
  2. 배열이면 각 항목을 먼저 재귀적으로 정리한 뒤, 정리된 결과가 빈 문자열·null·undefined·빈 배열·빈 객체인 항목만 걸러냅니다.
  3. 객체면 각 속성 값을 먼저 재귀적으로 정리한 뒤, 정리된 값이 같은 기준으로 비어 있으면 그 키 자체를 결과 객체에서 뺍니다.
  4. 배열도 객체도 아닌 값(문자열, 숫자, 불리언)은 그대로 통과시킵니다. 0과 false는 이 판정 기준 어디에도 해당하지 않으므로 그대로 남습니다.

저희 도구로 확인하기.

JSON 내 빈 문자열 및 null 값 필터링 정리

가입이나 설치 없이 JSON을 붙여넣으면 바로 빈 값이 정리됩니다.

흔히 헷갈리는 부분

판정 기준은 막연히 "비어 보이는 값"이 아니라, 정확히 정해진 목록에 해당하는 값만 제거 대상이 됩니다. 아래 표로 정리했습니다.

처리 결과
"" (빈 문자열)제거
null제거
undefined제거
[] (빈 배열)제거
{} (빈 객체)제거
0유지
false유지
" " (공백 한 칸)유지 (빈 문자열이 아님)
"0" (문자열)유지

0과 false가 남는 이유는 판정 함수가 정확히 "", null, undefined, 빈 배열, 빈 객체 다섯 가지와만 값을 비교하기 때문입니다. 0과 false는 이 다섯 가지 어디에도 속하지 않으므로 판정을 그대로 통과합니다.

공백 한 칸(" ")도 마찬가지입니다. 빈 문자열("")과 문자 하나가 들어 있는 문자열은 다른 값이므로, 공백만 있는 문자열은 제거되지 않고 그대로 남습니다.

출력이 아예 나오지 않고 빨간 에러 메시지만 뜨는 경우는 정리 규칙과는 무관하게, 입력 자체가 유효한 JSON 문법이 아닐 때입니다. 흔한 원인은 다음과 같습니다.

  • 마지막 항목 뒤에 콤마가 남아 있는 경우 (트레일링 콤마): {"a": 1,}
  • 키를 따옴표로 감싸지 않은 경우: {a: 1}
  • 값으로 undefined 리터럴을 직접 쓴 경우: {"a": undefined} — JSON에는 undefined라는 값 자체가 없고 null만 유효합니다
  • 문자열이나 키를 작은따옴표로 감싼 경우: {'a': 'b'}

JSON.parse는 자바스크립트 객체 리터럴보다 엄격한 표준입니다. 이 중 하나라도 섞여 있으면 파싱 단계에서 멈추고 에러가 뜨며, 빈 값을 걸러내는 로직 자체가 실행되지 않습니다.

정리

  • 제거 대상은 정확히 다섯 가지입니다. 빈 문자열, null, undefined, 빈 배열, 빈 객체입니다.
  • 0, false, 공백을 포함한 비어 있지 않은 문자열·배열·객체는 그대로 남습니다.
  • 정리는 자식 값부터 부모 순서로 진행되므로, 자식이 비워져 부모가 빈 객체가 되면 부모도 다음 단계에서 함께 제거됩니다.
  • 입력은 표준 JSON.parse로 검증되므로, 트레일링 콤마·따옴표 없는 키·undefined 리터럴이 있으면 정리에 앞서 에러가 뜹니다.
JSON 내 빈 문자열 및 null 값 필터링 정리

가입이나 설치 없이 JSON을 붙여넣으면 바로 빈 값이 정리됩니다.


📖 실제 사용자들이 겪는 현실적인 사연과 트러블

데이터 파이프라인과 API 연동을 다루는 실무 현장에서는 정리되지 않은 JSON 빈 값들로 인해 치명적인 장애나 성능 저하가 빈번하게 발생합니다. 다음은 개발자들이 현업에서 흔히 마주치는 세 가지 대표적인 실패 및 트러블 슈팅 사례입니다.

사연 1: MongoDB에서 PostgreSQL JSONB로 10만 건 마이그레이션 중 발생한 스토리지 폭발과 제약 조건 위반

백엔드 엔지니어 A씨는 스타트업의 레거시 시스템을 개편하며, MongoDB에 쌓여 있던 10만 건 이상의 고객 레코드를 PostgreSQL의 JSONB 컬럼으로 마이그레이션하는 작업을 맡았습니다. 기존 MongoDB의 유연한 스키마 구조로 인해 대부분의 레코드에는 '{"address": {"street": null, "zip": ""}, "preferences": {}}' 와 같이 아무런 실질적 의미가 없는 빈 객체와 null 필드가 무수히 포함되어 있었습니다. 이 데이터를 아무런 정제 없이 그대로 PostgreSQL에 적재하자, 원래 200MB 남짓일 것으로 예상했던 데이터베이스 테이블 용량이 무려 1.8GB로 폭발적으로 팽창했습니다. 더 큰 문제는 데이터 정합성이었습니다. 'street: null'이라는 값이 명시적으로 들어가 버리면서, PostgreSQL에 설정해둔 서브 필드 대상의 'NOT NULL' 제약 조건이 의도치 않게 작동하거나, 반대로 쿼리 시 'IS NULL' 체크가 아닌 값 자체의 'null' 여부를 검사해야 하는 등 쿼리 복잡도가 급증했습니다. 결국 모든 레코드를 다시 읽어와 재귀적인 빈 값 제거 로직을 적용한 뒤에야 스토리지 사용량을 최적화하고 스키마 무결성을 회복할 수 있었습니다.

사연 2: 외부 결제 게이트웨이 웹훅 연동 중 발생한 치명적인 회계 원장 누락 장애

프론트엔드와 백엔드를 오가며 개발하던 풀스택 개발자 B씨는 서드파티 결제 게이트웨이(Payment Gateway)로부터 전송되는 웹훅(Webhook) 페이로드를 처리하는 로직을 작성했습니다. 결제 서버가 보내오는 JSON 페이로드에는 '{"discount_amount": 0, "is_refunded": false, "notes": ""}' 와 같은 데이터가 포함되어 있었습니다. B씨는 불필요한 'notes' 필드의 빈 문자열을 걸러내어 데이터베이스 저장을 간소화하겠다는 목적으로, 자바스크립트의 단순한 Truthy/Falsy 검증인 'if (val)' 조건문으로 객체의 키를 필터링하는 실수를 저질렀습니다. 결과는 참혹했습니다. 자바스크립트에서 '0'과 'false'는 Falsy 값으로 평가되기 때문에, 'if (val)' 조건문을 통과하지 못해 할인 금액('discount_amount: 0')과 환불 여부('is_refunded: false') 데이터가 모두 통째로 삭제된 채 회계 원장 데이터베이스에 기록된 것입니다. 할인이 없는 정상 결제 건이 할인 데이터 누락으로 오작동을 일으켰고, 결국 전체 결제 기록을 수동으로 대조하며 복구해야만 했습니다. 0과 false를 명시적으로 보존하는 정확한 JSON 클리닝의 중요성을 뼈저리게 깨달은 순간이었습니다.

사연 3: 셀룰러 네트워크에서 3MB에 달하는 모바일 앱 분석 데이터 전송 지연 문제

모바일 앱 개발자 C씨는 사용자의 행동 로그와 디바이스 상태를 서버로 전송하는 애널리틱스 모듈을 개발했습니다. 초기 구현에서는 화면 이동, 터치 이벤트, 디바이스 센서 데이터를 수집하는 과정에서 모든 선택적 필드가 포함된 거대한 JSON 객체를 생성했습니다. 사용하지 않는 설정값이나 비활성화된 센서 데이터에는 모두 'null' 또는 빈 객체 '{}'가 할당되었고, 그 결과 한 번의 세션 전송마다 페이로드 크기가 무려 3MB에 달했습니다. LTE나 5G 네트워크 환경이 불안정한 지하철이나 이동 중인 상황에서 이 3MB짜리 압축되지 않은 JSON을 전송하다 보니, API 응답 지연(Latency)이 극심해지고 사용자의 4G 데이터 소모량도 비정상적으로 치솟았습니다. 이를 해결하기 위해 C씨는 모바일 클라이언트 측에서 네트워크 요청을 보내기 직전, 재귀적인 빈 값 제거기(Recursive Empty Value Stripper)를 실행하도록 파이프라인을 수정했습니다. 그 결과 무의미한 껍데기 필드들이 전부 가지치기(Pruning)되면서 페이로드 크기가 65%나 감소한 1.05MB로 줄어들었고, 네트워크 병목 현상을 완벽히 해소할 수 있었습니다.


🔬 핵심 기술 메커니즘 — 재귀적 트리 순회와 값 판정의 원리

단순히 문자열 치환(Replace)이나 정규식(Regex)만으로는 깊이가 예측 불가능한 중첩 JSON의 빈 값을 완벽하게 제거할 수 없습니다. 이는 JSON 데이터가 본질적으로 트리(Tree) 자료구조를 띠고 있기 때문입니다. JSON 빈 값 제거기가 작동하는 내부 알고리즘과 수학적 복잡도, 그리고 표준 규격의 제약을 심층적으로 살펴보겠습니다.

1. 트리 순회 알고리즘 (Tree Traversal Algorithms)

JSON 데이터를 정제할 때 가장 중요한 개념은 **재귀적 후위 순회(Bottom-up Post-order Traversal)**입니다.

  • 상향식 후위 순회 (Bottom-Up)의 필수성: 자식 노드를 먼저 평가하고 처리한 뒤, 그 결과를 바탕으로 부모 노드를 평가하는 방식입니다. 'cleanValues(child) -> isEmpty(cleanedChild)'의 순서로 실행됩니다. 만약 '{"parent": {"child": {"grandchild": ""}}}' 라는 데이터가 있을 때, 가장 안쪽의 'grandchild'가 빈 문자열이므로 제거됩니다. 그러면 'child' 객체는 빈 객체 '{}'가 됩니다. 이제 'child'를 평가하면 빈 객체이므로 다시 제거됩니다. 결국 'parent' 역시 빈 객체가 되어 최종적으로 모든 껍데기가 완벽하게 지워집니다.
  • 하향식 전위 순회 (Pre-order Traversal)의 한계: 부모를 먼저 평가하는 방식입니다. 위 예시에서 처음에 'parent'나 'child'를 검사할 때는 내부에 키가 존재하므로 "비어 있지 않다"고 오판하게 됩니다. 나중에 자식의 값을 지우고 나면 부모가 빈 객체로 남게 되지만, 이미 부모에 대한 평가는 끝난 상태이므로 의미 없는 빈 껍데기 객체들이 그대로 남는 치명적인 결함이 발생합니다.

2. 정밀한 값 식별 논리 (Value Discrimination Logic)

Falsy 값이라고 해서 무조건 지워서는 안 되며, 애플리케이션의 비즈니스 로직에 영향을 주지 않는 '진짜 의미 없는 빈 값'만을 골라내야 합니다.

  • 가지치기 대상 (Pruned values):
    • '""' (빈 문자열)
    • 'null'
    • 'undefined' (JSON 파싱 후 내부 객체 조작 시 발생 가능)
    • '[]' (요소가 하나도 없는 빈 배열)
    • '{}' (키가 하나도 없는 빈 객체)
  • 반드시 보존해야 하는 값 (Preserved falsy primitives):
    • '0' (숫자 0은 은행 잔고, 수량, 인덱스 등 매우 중요한 데이터입니다)
    • 'false' (불리언 false는 권한 없음, 비활성화, 미결제 등의 명확한 상태를 나타냅니다)
    • '" "' (공백 문자열은 의도된 띄어쓰기 입력일 수 있습니다)

3. 시간 및 공간 복잡도 (Time & Space Complexity)

  • 시간 복잡도: $O(N)$ — 여기서 $N$은 JSON 트리 내의 전체 노드(키와 값의 쌍) 개수입니다. 모든 노드를 정확히 한 번씩만 순회하며 검사하기 때문에 데이터 크기에 비례하여 선형적으로 증가합니다.
  • 공간 복잡도: $O(D)$ — 여기서 $D$는 트리의 최대 중첩 깊이(Maximum Nesting Depth)입니다. 재귀 함수가 호출될 때마다 콜 스택이 쌓이므로, 깊이가 매우 깊은 JSON의 경우 콜 스택 오버플로우가 발생할 수 있습니다. 하지만 일반적인 API 응답의 깊이는 10단계를 넘지 않으므로 실무에서는 매우 안전하고 빠릅니다.

4. RFC 8259 JSON 표준 규약의 제약

이 정제 알고리즘의 최전선에는 반드시 'JSON.parse()'가 위치해야 합니다. RFC 8259 표준은 데이터 교환의 무결성을 위해 매우 엄격한 문법을 요구합니다. 자바스크립트에서는 허용되지만 표준 JSON에서는 절대 허용되지 않는 (SyntaxError 유발) 요소들은 다음과 같습니다:

  • 배열이나 객체의 마지막 속성 뒤에 붙는 쉼표 (Trailing commas)
  • 문자열이나 객체 키를 감싸는 작은따옴표 (''')
  • 따옴표 없이 작성된 객체의 키
  • 'NaN', 'Infinity', '-Infinity' 같은 특수 숫자 리터럴
  • 'undefined' 키워드의 직접 사용

따라서 완벽한 클리닝을 위해서는 항상 규격에 맞는 직렬화된 문자열을 입력받아 파싱하는 단계가 선행되어야 합니다.


📊 상황별 JSON 클리닝 방식 비교 분석 매트릭스 (Comparison Table)

다양한 환경과 라이브러리에서 JSON 빈 값을 제거하는 방식들의 장단점과 지원 범위를 한눈에 비교해 드립니다.

비교 항목Pure Recursive JS (추천)JSON.stringify(obj, replacer)Lodash (_.omitBy / _.pickBy)jq 쉘 필터 (CLI 환경)
작동 원리완벽한 후위 순회 재귀 알고리즘직렬화 과정 중 필터링얕은 수준의 객체 속성 필터링'walk' 함수를 이용한 트리 순회
중첩 빈 부모 제거✅ 완벽 지원 (Bottom-Up)❌ 불가능 (Top-Down 방식의 한계)❌ 불가능 (1 depth만 적용됨)✅ 완벽 지원 (walk 함수 재귀)
0과 false 보존✅ 완벽 지원 (명시적 타입 체크)✅ 지원 (조건부 처리 가능)⚠️ 주의 필요 (_.identity 사용 시 유실)✅ 완벽 지원 ('!= null')
배열 내 빈 요소 처리✅ 완벽하게 필터링하여 압축⚠️ 'null'로 치환됨 (배열 길이 유지)❌ 배열 요소에는 적용 불가✅ 'map'과 'select'로 가능
처리 속도 및 성능매우 빠름 ($O(N)$ 선형 탐색)빠름 (네이티브 C++ 엔진 최적화)다소 느림 (라이브러리 오버헤드)빠름 (C 기반 컴파일 바이너리)
적합한 사용 환경브라우저 프론트엔드, Node.js 백엔드로그 포맷팅, 단순 1차원 데이터이미 Lodash를 의존성으로 쓰는 프로젝트서버 SSH 접속, Bash 쉘 스크립팅 자동화

위 표에서 보듯, 'JSON.stringify'의 두 번째 인자인 'replacer' 함수는 하향식으로 작동하기 때문에 자식이 지워져서 텅 빈 부모 객체를 감지하고 지울 수 없으며, 배열의 요소를 지우면 완전히 사라지는 대신 'null'로 자리가 채워지는 한계가 있습니다. 따라서 재귀적 커스텀 함수(Pure Recursive JS) 방식이 데이터 무결성 측면에서 압도적으로 우수합니다.


⚠️ 흔히 저지르는 치명적인 실수 5가지

경험이 풍부한 시니어 개발자조차도 엣지 케이스를 간과하여 서비스에 큰 타격을 입히는 실수를 범하곤 합니다.

  1. 단순 Truthy/Falsy 검증 ('if (!value)')의 남용 앞선 사연 2에서 보았듯이, 자바스크립트의 유연한 타입 캐스팅을 믿고 'if (!value)'로 검증하면 데이터베이스의 숫자 '0'(예: 잔액 0원)과 'false'(예: 마케팅 수신 동의 거부)가 통째로 증발하여 비즈니스 로직이 붕괴됩니다.
  2. 하향식(Top-Down) 필터링으로 인한 빈 껍데기 객체 잔류 부모 객체를 먼저 검사하는 로직을 짜면, 자식 노드의 빈 값이 지워지면서 생성된 새로운 빈 부모 객체('{ "user": {} }')를 처리하지 못해 페이로드 용량 최적화에 실패합니다.
  3. 원본 객체를 직접 수정(In-place Mutation)하여 부작용(Side Effect) 유발 재귀 함수 내에서 'delete obj[key]'를 사용해 원본 객체를 직접 뜯어고치면, 애플리케이션의 다른 모듈에서 해당 객체를 참조하고 있을 때 예기치 못한 메모리 참조 오류와 상태 불일치 버그가 발생합니다. 항상 새로운 객체를 반환하는 불변성(Immutability)을 유지해야 합니다.
  4. 순환 참조(Circular Reference)에 대한 방어 로직 부재 객체 A가 객체 B를 참조하고, 다시 B가 A를 참조하는 구조(예: 양방향 ORM 모델)를 클리닝 함수에 넣으면, 함수가 영원히 멈추지 않고 재귀를 반복하다가 'Maximum call stack size exceeded' 에러를 뿜으며 Node.js 서버 전체를 다운시킵니다.
  5. 예외 처리가 없는 무방비한 JSON.parse() 실행 외부에서 인입되는 텍스트를 검증 없이 'JSON.parse()'에 집어넣었다가 문법 오류(Syntax Error)가 발생하면 애플리케이션 크래시가 발생합니다. 반드시 'try-catch' 블록으로 감싸거나 안전한 래퍼 함수를 사용해야 합니다.

💡 실무 생산성을 높이는 5단계 프로덕션 레벨 워크플로우

단순한 클리닝을 넘어 엔터프라이즈 환경에서 안전하게 JSON을 가공하고 저장하기 위한 체계적인 5단계 파이프라인입니다.

  • 1단계: 스키마 및 문법 사전 검증 (Syntax Validation) 먼저 들어온 문자열 데이터가 RFC 8259 규격을 준수하는지 'try-catch'로 파싱을 시도하고, 필요하다면 Ajv나 Zod 같은 스키마 밸리데이터를 통해 데이터의 기본 뼈대가 예상과 일치하는지 1차 방어선을 구축합니다.
  • 2단계: 상향식 재귀 정제(Bottom-Up Pruning) 실행 본문의 'cleanValues'와 같은 재귀 함수를 호출하여 의미 없는 'null', '""', '[]', '{}' 노드를 깊은 레벨부터 완벽하게 걷어냅니다.
  • 3단계: 핵심 Falsy 데이터('0', 'false') 보존 무결성 교차 검증 정제된 객체에 비즈니스 크리티컬한 0이나 false 값이 유실되지 않았는지 단위 테스트(Unit Test)를 통해 검증합니다. 특히 금융이나 인증 관련 페이로드에서는 이 단계가 생략되어서는 안 됩니다.
  • 4단계: 환경에 맞춘 최적화 직렬화 (Serialization) 클리닝된 순수 자바스크립트 객체를 전송이나 저장 목적에 맞게 문자열로 변환합니다. 운영 환경의 네트워크 전송용이라면 공백 없는 'JSON.stringify(cleaned, null, 0)'을 적용하고, 사람의 눈으로 로그를 읽어야 한다면 'JSON.stringify(cleaned, null, 2)'로 가독성을 높입니다.
  • 5단계: 영구 저장 및 다운스트림 API로의 안전한 배포 군더더기가 완벽히 제거되어 가벼워진 JSON 페이로드를 PostgreSQL, MongoDB에 적재하거나 클라이언트/서버 API 응답으로 안전하게 전송합니다.

🔍 전문가가 공개하는 JSON 페이로드 최적화 팁 7선

대규모 트래픽을 감당하는 시스템에서 밀리초(ms) 단위의 성능을 끌어올리기 위한 시니어 개발자들의 고급 테크닉입니다.

  1. 운영(Production) API 전송 시에는 인덴트(들여쓰기) 완전 제거: 디버깅 목적이 아니라면 API 응답을 생성할 때 불필요한 줄바꿈(' ')과 스페이스바 공간을 모두 날려버리는 콤팩트(Compact) 직렬화를 적용하세요. 대규모 JSON에서는 여백 문자가 차지하는 용량이 전체의 20%를 넘기도 합니다.
  2. GraphQL 및 REST 응답 전송 직전 null 스트립(Strip) 처리: 스키마에 의해 억지로 채워진 껍데기 'null' 필드들은 네트워크 대역폭만 갉아먹습니다. 프레임워크의 미들웨어나 인터셉터(Interceptor) 레벨에서 클리닝 함수를 공통 적용하여 응답 크기를 최소화하세요.
  3. 마이크로서비스 간 통신에는 스키마 기반 직렬화 도구 도입: Node.js 환경이라면 내부 서비스 간 통신 시 네이티브 'JSON.stringify' 대신 'fast-json-stringify' 같은 스키마 사전 컴파일 기반 라이브러리를 도입하면 CPU 연산 오버헤드를 비약적으로 줄일 수 있습니다.
  4. 웹훅(Webhook) 페이로드는 DB 영구 저장 전에 반드시 살균(Sanitize): 외부 결제사나 파트너 API가 보내오는 거대한 웹훅 덩어리를 원본 그대로 RDBMS의 JSON 컬럼에 박아넣으면 스토리지 비용이 급증합니다. 반드시 클리닝을 거친 엑기스 데이터만 적재하세요.
  5. WeakSet을 이용한 순환 참조(Circular Reference) 회피 및 탐지: 복잡한 메모리 객체를 JSON으로 변환하거나 클리닝할 때 콜 스택 폭발을 막기 위해, 재귀 함수 진입 시 'WeakSet'에 현재 객체를 저장해 두고 이미 방문한 객체인지 검사하는 방어 코드를 심어야 합니다.
  6. ISO 8601 Date 객체의 직렬화 타이밍 제어: 빈 값 클리닝 함수가 자바스크립트의 'Date' 객체를 빈 객체 '{}'로 오인하여 삭제하지 않도록, 'typeof value === "object"' 분기 안에 'value instanceof Date' 예외 처리를 추가하거나 클리닝 전에 문자열로 직렬화해 두어야 합니다.
  7. 본 웹 도구를 활용한 엣지 케이스 및 복잡계 데이터 테스트: 복잡하게 얽힌 수천 줄의 JSON 데이터를 코드에 바로 적용하기 전, 본 페이지의 클리닝 툴에 붙여넣어 '0'이나 'false', 배열 내 객체들이 의도대로 유지되는지 눈으로 먼저 확인하는 습관을 들이세요.

🎯 최종 결정 트리: 어떤 전략과 도구를 선택해야 할까?

현재 처한 개발 환경과 요구사항에 맞춰 최적의 빈 값 제거 방식을 1초 만에 결정해 드립니다.

  • 상황 A (쉘 환경, CI/CD 파이프라인, DevOps 로그 분석)'jq' 명령어의 'walk' 필터 사용: CLI 환경에서는 브라우저를 열지 않고 파이프('|')로 데이터를 넘겨 'walk(if type == "object" then ...)' 정제 스크립트를 즉시 실행하는 것이 최고 효율을 냅니다.
  • 상황 B (단순 1차원 설정 파일, 깊이 중첩되지 않은 데이터)'lodash'의 '_.omitBy' 또는 'JSON.stringify' 리플레이서 함수 활용: 깊은 재귀가 필요 없는 평면적인 객체라면 기존에 프로젝트에 세팅된 유틸리티 라이브러리나 네이티브 기능을 활용해 보일러플레이트 코드를 줄이는 것이 현명합니다.
  • 상황 C (깊은 중첩 구조, API 응답 압축, 무결성이 생명인 금융 데이터)본문에 제시된 'cleanValues' 하위-상위 재귀(Bottom-Up Recursive) 함수 구현: 객체 속 빈 객체까지 완벽하게 도려내야 하며 '0'과 'false'의 보존이 절대적인 최우선 과제일 경우 커스텀 재귀 로직만이 유일한 정답입니다.
  • 상황 D (코딩 없이 즉각적인 1회성 데이터 정제 및 눈부신 시각화)본 웹사이트의 JSON 빈 값 정리기(Web Tool) 사용: 어떤 라이브러리를 설치할 시간조차 아깝고 당장 엑셀이나 보고서에 넣을 깔끔한 JSON 데이터가 필요할 때 가장 완벽한 선택입니다.

📑 핵심 용어 사전 (Terminology Cheatsheet)

복잡한 데이터 엔지니어링 생태계에서 길을 잃지 않기 위한 6가지 핵심 키워드 정리입니다.

  • 재귀적 후위 순회 (Bottom-up Post-order Traversal): 가장 깊은 곳에 있는 자식 노드부터 먼저 처리하고 점진적으로 부모 노드를 평가하는 트리 탐색 알고리즘. 중첩된 빈 객체를 지우는 핵심 원리입니다.
  • 펄시 값 (Falsy Value): 자바스크립트에서 불리언 문맥을 만났을 때 'false'로 평가되는 값. ('false', '0', '-0', '0n', '""', 'null', 'undefined', 'NaN')
  • RFC 8259: 전 세계 인터넷 데이터 교환의 근간이 되는 JavaScript Object Notation (JSON) 포맷의 최신 IETF 공식 표준 규격 명세서.
  • JSON.stringify 리플레이서 (Replacer): 자바스크립트 객체를 JSON 문자열로 변환할 때, 특정 속성을 걸러내거나 변환하기 위해 두 번째 인자로 전달하는 콜백 함수 또는 배열.
  • 순환 참조 (Circular Reference): 객체가 자기 자신을 직간접적으로 다시 가리키는 상태. 이 상태로 JSON 직렬화나 재귀 함수를 돌리면 무한 루프에 빠져 치명적 에러가 발생합니다.
  • 페이로드 최적화 (Payload Optimization): 네트워크를 통해 클라이언트와 서버가 주고받는 데이터 덩어리(Payload)에서 불필요한 공백과 의미 없는 껍데기 키를 제거하여 전송 속도와 비용을 획기적으로 개선하는 작업.

자주 묻는 질문

단순한 궁금증을 넘어 원리를 꿰뚫는 3가지 심층 질문과 답변입니다.

Q1. "0"과 "false"는 왜 지우면 안 되며, 어떻게 예외 처리를 하나요?

A1. API 통신에서 '0'은 할인율 0%, 잔액 0원, 배열의 0번째 인덱스 등 비즈니스 로직에 핵심적인 의미를 갖는 데이터입니다. 'false' 역시 인증 실패나 기능 비활성화를 뜻합니다. 만약 이를 지워버리면 시스템은 "데이터가 아직 수집되지 않았다"는 뜻인 'null'이나 'undefined'로 잘못 인식하여 결제 누락이나 권한 우회 버그를 일으킬 수 있습니다. 이를 막기 위해 판정 함수(isEmpty)에서는 'if (!value)' 같은 광범위한 부정 연산자 대신, 'v === "" || v === null || v === undefined' 와 같이 제거 대상을 명시적(Strict Equality)으로 콕 집어내어 타입 강제를 회피해야 합니다.

Q2. 5단계 깊이로 중첩된 부모 객체가 있는데, 맨 끝 자식의 빈 값을 지웠더니 부모들도 다 비어버렸습니다. 이것들을 한 번에 다 지우려면 어떻게 해야 하죠?

A2. "하향식(Top-Down)"이 아닌 "상향식(Bottom-Up)"으로 순회해야 합니다. 자바스크립트의 네이티브 리플레이서(Replacer)는 위에서 아래로 내려가므로 이미 훑고 지나간 부모 객체가 뒤늦게 텅 비어버리는 현상을 감지하지 못합니다. 반면, 본문의 'cleanValues' 함수는 재귀 호출의 반환값을 받아온 뒤에야 부모 키에 할당할지 말지를 결정('if (!isEmpty(cleaned)) result[key] = cleaned;')합니다. 즉, 끝단 자식이 사라져서 부모가 '{}'가 되면, 그 부모를 감싸는 조부모 단계의 'isEmpty'가 이를 귀신같이 캐치하여 삭제합니다.

Q3. Bash 쉘 환경에서 'jq' 명령어로도 똑같이 완벽한 재귀적 정제가 가능한가요?

A3. 네, 완벽히 가능합니다! 'jq' 1.5 버전 이상부터 지원되는 내장 함수인 'walk'를 활용하면 됩니다. 'walk'는 내부적으로 완벽한 후위 순회(Post-order Traversal)를 수행합니다. 쉘에 다음과 같이 입력하세요: 'jq 'walk(if type == "object" then with_entries(select(.value != null and .value != "" and .value != [] and .value != {})) else . end)' input.json' 이 강력한 한 줄의 명령어로 리눅스 서버 모니터링 로그나 크론(Cron) 작업에서 생성된 수기가바이트짜리 덤프 파일도 찰나의 순간에 완벽하게 압축해 낼 수 있습니다.

가격 보기카톡 무료 상담