FormatArc의 한국어 JSON to CSV 도구. 왼쪽에 중첩된 address를 포함한 JSON 배열, 오른쪽에 address.city 열을 포함한 CSV가 표시된 화면FormatArc의 한국어 JSON to CSV 도구. 왼쪽에 중첩된 address를 포함한 JSON 배열, 오른쪽에 address.city 열을 포함한 CSV가 표시된 화면
저자: FormatArc 편집부게시일: 2026-07-26갱신일: 2026-08-22

JSON CSV 변환 - 중첩 객체·배열·null 처리 차이를 4개 도구로 실측

TL;DR — 용도별 10초 요약표

  • 지금 바로 표로 변환하고 싶을 때: FormatArc JSON to CSV. 브라우저 내에서 완결되며 서버 업로드가 없습니다. 중첩된 객체는 점 표기법(dot notation) 열로 변환됩니다.
  • 1개 레코드 안에 객체 배열이 있을 때 (주문과 주문 항목 등): 먼저 "1개 행 = 1개 주문"으로 둘지 "1개 행 = 1개 항목"으로 둘지 결정합니다. JSON 형태별 대처법을 참고하세요.
  • 배열 요소마다 1개 행을 생성하고 싶을 때: mlr --ijson --ocsv cat (Miller) 또는 pandas.json_normalize(data, record_path=...)를 사용합니다.
  • ID가 16자리 이상일 때: JavaScript 기반 변환기를 사용해서는 안 됩니다. 2^53을 초과하는 정수를 참조하세요.
  • Excel에서 열 계획이 있을 때: 파일을 더블클릭하기 전에 스프레드시트에서 깨지지 않게 열기를 확인하세요.
방법설정중첩된 객체레코드 내 배열브라우저 완결 (업로드 없음)
FormatArc불필요점 표기법 열JSON 문자열로 1개 셀에 유지지원
json-2-csv (npm)npm i json-2-csv점 표기법 열JSON 문자열로 1개 셀에 유지미지원 (Node)
Miller (mlr)brew install miller점 표기법 열items.1.sku, items.2.sku … 형태로 열 확장미지원 (CLI)
pandas json_normalizepip install pandas점 표기법 열Python repr을 1개 셀에 유지, record_path로 행 확장미지원 (Python)
jqbrew install jq매핑을 직접 작성매핑을 직접 작성미지원 (CLI)

위 표의 내용은 모두 실측값입니다. 입력 데이터, 측정 스크립트, 원본 출력은 저장소의 scripts/benchmarks/json-to-csv-guide/에 보관되어 있으며(2026-07-26 측정), 아래에서 인용하는 출력은 모두 해당 실행 결과 그대로입니다.

30초 만에 변환하기

JSON to CSV를 열고, 객체 배열을 붙여넣은 뒤 실행을 누릅니다. 다음 입력:

[
  { "name": "Mika", "email": "mika@example.com", "role": "admin", "address": { "city": "Tokyo" } },
  { "name": "Noah", "email": "noah@example.com", "role": "viewer", "address": { "city": "Osaka" } }
]

에 대해 다음과 같은 CSV가 출력됩니다.

name,email,role,address.city
Mika,mika@example.com,admin,Tokyo
Noah,noah@example.com,viewer,Osaka

FormatArc의 JSON to CSV에서 중첩된 JSON 배열을 address.city 열이 포함된 CSV로 변환한 화면FormatArc의 JSON to CSV에서 중첩된 JSON 배열을 address.city 열이 포함된 CSV로 변환한 화면

변환은 웹 브라우저 안에서 완결됩니다. JSON 데이터가 서버로 전송되는 일은 전혀 없습니다. 고객 정보나 사내 데이터가 포함된 운영 API 응답을 그대로 붙여넣어야 하는 상황에서 이 차이가 중요합니다. 무엇이 보호되고 무엇이 보호되지 않는지는 온라인 변환 사이트 보안 검증에서 정리하고 있습니다.

입력이 올바른 JSON이 아닌 경우에는 JSON 포맷터와 동일한 경로로 줄 번호가 포함된 오류 메시지가 반환됩니다. 원인 파악 및 해결 방법은 JSON 파싱 오류 해결을 참고하세요.

동일한 JSON을 4개 변환기에 전달했을 때 갈라지는 결과

JSON은 계층 구조(트리)이고, CSV는 2차원 직사각형 표입니다. 모든 변환기는 트리를 직사각형으로 압축하기 위해 고유한 규칙을 적용하며, 그 규칙은 도구마다 다릅니다. 15개의 입력을 4개의 변환기에 통과시키고 각각의 출력을 기록했습니다.

실행 환경(results.json 기준): macOS arm64 환경의 Node v26.3.1, FormatArc는 lib/tooling.ts (PapaParse 5.5.2), json-2-csv 5.5.11, Miller 6.19.0, pandas 3.0.5입니다. 4개 도구 모두 옵션을 지정하지 않은 기본(default) 설정입니다. 아무런 설정을 하지 않았을 때 무엇이 나오는지 확인하는 것이 목적이기 때문입니다.

4개 도구가 일치한 부분

중첩된 객체는 점 표기법(dot notation)으로 평탄화(flatten)됩니다. {"name":"Mika","address":{"city":"Tokyo","zip":"150-0001"}}에 대해 4개 도구 모두 다음과 같이 출력합니다.

name,address.city,address.zip
Mika,Tokyo,150-0001

3단계 중첩(meta.created.by.name)도 동일합니다. 배열로 감싸이지 않은 단일 객체는 4개 도구 모두 1개 행의 CSV로 변환합니다. 쉼표, 큰따옴표, 줄바꿈을 포함한 값의 인용 부호(quoting) 처리도 일치했습니다.

who,quote,note
"Smith, John","She said ""hi""","line1
line2"

이는 RFC 4180새 탭에서 열립니다 2절의 인용 규칙과 정확히 일치합니다. 줄바꿈, 큰따옴표, 쉼표를 포함하는 필드는 큰따옴표로 감싸고, 내부의 큰따옴표는 2개를 겹쳐서 이스케이프한다는 규칙입니다. 파일 차이(diff)를 확인하는 분들을 위해 한 가지 덧붙이자면, 행 구분자(줄바꿈)는 FormatArc가 CRLF(PapaParse의 기본값이자 RFC 4180 규정)를 사용하고, json-2-csv, Miller, pandas는 LF를 사용했습니다.

배열은 3가지 방식으로 나뉜다

입력:

[{"name":"Mika","tags":["admin","billing"]},{"name":"Noah","tags":["viewer"]}]
변환기출력
FormatArcname,tags / Mika,"[""admin"",""billing""]" / Noah,"[""viewer""]"
json-2-csvFormatArc와 동일
Millername,tags.1,tags.2 / Mika,admin,billing / Noah,viewer,
pandasname,tags / Mika,"['admin', 'billing']" / Noah,['viewer']

완전히 서로 다른 3가지 결과물이 나옵니다. FormatArc와 json-2-csv는 배열을 "유효한 JSON 텍스트"로 1개 셀 안에 유지하므로, 나중에 셀 단위로 다시 파싱할 수 있습니다. Miller는 표를 가로로 넓힙니다. 편리하지만 특정 레코드의 태그가 40개라면 열 수가 40개로 늘어납니다. pandas는 작은따옴표가 포함된 Python의 repr 문자열을 출력하므로, 이는 올바른 JSON 형식이 아니며 이후 단계에서 JSON.parse를 실행하면 실패합니다.

객체 배열도 마찬가지입니다. {"order":"A-1","items":[{"sku":"X1","qty":2},{"sku":"X2","qty":1}]}는 FormatArc와 json-2-csv에서 1개 셀의 JSON 텍스트가 되고, Miller에서는 items.1.sku, items.1.qty, items.2.sku, items.2.qty 열로 확장됩니다.

키 누락: 빈 셀인가, "undefined" 문자열인가, 오류인가

실제 API 응답에는 선택적(optional) 필드가 자주 포함됩니다. 입력:

[{"id":1,"name":"Mika"},{"id":2,"name":"Noah","nickname":"No"},{"id":3,"phone":"03-0000-0000"}]

FormatArc와 pandas는 빈 셀로 처리합니다.

id,name,nickname,phone
1,Mika,,
2,Noah,No,
3,,,03-0000-0000

json-2-csv는 누락된 부분에 undefined라는 문자열을 작성합니다.

id,name,nickname,phone
1,Mika,undefined,undefined
2,Noah,No,undefined
3,undefined,undefined,03-0000-0000

Miller는 파일 자체를 거부합니다: mlr: CSV schema change: first keys "id,name"; current keys "id,phone". 스트리밍 처리 도구로서는 타당한 설계이지만, 선택적 필드가 하나 추가되었다는 이유로 어제까지 잘 동작하던 파이프라인이 멈출 수 있습니다.

FormatArc는 전체 레코드에 등장하는 모든 키의 합집합을 처음 나타난 순서대로 수집하여, 1번째 행을 작성하기 전에 전체 열 수를 확정합니다. 행 위치가 어긋나는 일은 발생하지 않습니다.

null은 빈 셀인가, n-u-l-l 4글자 문자열인가

[{"id":1,"deleted_at":null},{"id":2,"deleted_at":"2026-07-01"}]

FormatArc와 pandas는 빈 셀로 출력하고, json-2-csv와 Miller는 null이라는 4글자 문자열을 작성합니다. 이 CSV를 그대로 데이터베이스에 가져오면 전자는 진짜 NULL이 되고, 후자는 NULL처럼 보이는 문자열이 됩니다. JSON에서 CSV로 변환한 뒤 "WHERE 절 조건이 일치하지 않는다"며 겪는 문제의 대부분이 여기서 비롯됩니다.

빈 객체에서는 4가지 형태의 표가 생성된다

[{"id":1,"meta":{}},{"id":2,"meta":{"source":"api"}}]의 경우:

변환기출력
FormatArcid,meta,meta.source — 빈 {} 때문에 모든 행이 빈 meta 열이 남음
json-2-csv헤더는 같지만 {}{"source":"api"}를 셀에 그대로 작성하여 값이 중복됨
Miller오류 발생: CSV schema change: first keys "id,meta"; current keys "id,meta.source"
pandasmeta 열 자체가 사라짐: id,meta.source

FormatArc의 동작은 정직하지만 외관상 깔끔하지는 않습니다. 사용되지 않는 빈 열이 하나 생겼다면 페이로드 어딘가에 빈 객체 {}가 포함되어 있다는 뜻입니다.

키 이름에 점이 포함되면 3개 도구가 열을 덮어쓴다

데이터가 손실되는 케이스이며, 4개 도구 중 3개가 데이터를 유실합니다. 입력:

[{"a.b":1,"a":{"b":2}}]

이 레코드에는 서로 다른 값이 2개 있습니다. 문자 그대로 a.b라는 이름을 가진 키의 값 1과, 중첩된 ab 경로가 가진 값 2입니다. FormatArc, Miller, pandas는 모두 다음을 출력합니다.

a.b
2

1이 사라졌습니다. 이를 구분해 낸 것은 json-2-csv뿐으로, 리터럴 키 쪽에 이스케이프를 적용합니다.

a\.b,a.b
1,2

page.view.count 같은 분석 이벤트 이름, MongoDB 문서, Prometheus 라벨 등 점(.)을 포함하는 키 이름을 사용하는 JSON에서는 변환 전에 충돌 여부를 확인하거나 json-2-csv를 사용해야 합니다.

2^53을 초과하는 정수는 JavaScript 계열에서 반올림된다

[{"id":9007199254740993,"order_no":12345678901234567890}]
변환기출력
FormatArc9007199254740992,12345678901234567000
json-2-csv9007199254740992,12345678901234567000
Miller9007199254740993,12345678901234567890
pandas9007199254740993,12345678901234567890

이것은 CSV의 문제가 아니며 JavaScript 기반 도구의 버그도 아닙니다. JavaScript의 JSON.parse는 모든 숫자를 배정밀도 부동소수점(double)으로 변환하므로 2^53보다 큰 정수를 정확하게 표현할 수 없습니다. 값은 CSV 변환기에 전달되기 전 단계에서 이미 왜곡됩니다. Snowflake ID, X(Twitter) ID, 결제 고유 번호, 64비트 데이터베이스 정수 키 등이 이 범위에 해당합니다. 자릿수가 긴 ID를 다룬다면 JSON 단계에서 문자열로 감싸 두거나, 정수 자릿수를 그대로 유지하는 Miller, pandas, jq를 사용하세요.

잘못된 입력: 명시적 오류인가, 무언의 빈 파일인가

입력FormatArcjson-2-csvMillerpandas
["a","b","c"]오류: "배열의 각 요소는 객체여야 합니다"빈 줄 3개, 오류 없음예외 발생예외 발생
[]오류: "JSON 배열이 비어 있습니다"빈 줄 1개, 오류 없음빈 출력, 오류 없음빈 출력, 오류 없음

가장 위험한 결과는 "종료 코드 0으로 빈 파일을 출력하는 것"입니다. cron 배치 작업이 정상적인 이전 파일을 아무런 경고 없이 빈 파일로 덮어쓸 수 있기 때문입니다.

FormatArc의 변환 규칙 (구현 그대로)

다음은 요약이 아니라 실제 구현된 규칙입니다. lib/tooling.tsconvertJsonToCsv 함수에 해당하며, 위 실측 결과와 정확히 일치합니다.

  1. 최상위는 객체 배열 또는 단일 객체여야 합니다. 단일 객체는 1개 행의 CSV가 됩니다. 원시 값(primitive) 배열, 빈 배열, 단독 문자열이나 숫자는 안내 메시지와 함께 거부됩니다.
  2. 중첩된 객체는 재귀적으로 점 표기법 열로 평탄화됩니다 (address.city, meta.created.by.name). 중첩 깊이 제한은 없습니다.
  3. 배열은 행으로 전개하지 않습니다. JSON.stringify로 직렬화하여 1개 셀 안에 유지하므로 ["admin","billing"]은 파싱 가능한 상태로 남습니다.
  4. 열은 전체 레코드 키의 합집합을 처음 나타난 순서대로 나열합니다. 마지막 레코드에만 나타나는 키에도 열이 할당되며, 이전 행에는 빈 셀이 들어갑니다. 행 위치가 밀리는 일은 없습니다.
  5. nullundefined는 빈 셀이 됩니다. 빈 객체 {}도 빈 셀이 되며 고유한 열을 유지합니다.
  6. 인용 부호 처리는 PapaParse의 unparse 규칙을 따릅니다. 쉼표, 큰따옴표, 줄바꿈을 포함하는 필드는 큰따옴표로 감싸고 내부 따옴표는 2중화하며, 행 구분자는 CRLF입니다.
  7. 올바르지 않은 JSON은 줄 번호와 함께 오류로 보고됩니다 (JSON 포맷터와 동일한 파싱 오류 처리 경로).

데이터는 브라우저 탭 바깥으로 나가지 않습니다. 업로드 과정이나 서버 상의 임시 파일이 없으며, 이미 로드된 페이지 안에서 함수가 한 번 실행될 뿐입니다.

JSON 형태별: 무엇을 어떻게 변환할까

평탄한(Flat) 객체 배열

판단할 내용이 없습니다. 붙여넣고 실행하면 바로 변환됩니다.

중첩된 객체를 포함하는 레코드

점 표기법은 대부분의 도구에서 표준적으로 사용하는 방식이며, 사람이 눈으로 봐도 원래 위치를 쉽게 파악할 수 있습니다 (address.city의 출처는 명확합니다). 사전에 확인할 점은 두 가지뿐입니다. 기존 키 이름에 이미 점(.)이 포함되어 있는지 여부(앞서 언급한 충돌), 그리고 CSV를 읽는 프로그램이 헤더의 점을 정상적으로 처리할 수 있는지 여부입니다. 일부 SQL 로더는 헤더 인용 부호가 필요하지만, Google 스프레드시트나 Excel은 문제없이 읽습니다.

스칼라 배열을 포함하는 레코드

3가지 선택지가 있습니다.

  • JSON 텍스트 그대로 1개 셀에 유지하기 (FormatArc의 기본 동작). CSV가 중간 파일이고 이후 스크립트가 다시 읽는 경우에 적합합니다.
  • Miller를 사용해 tags.1, tags.2 열로 전개하기. 요소 수가 적고 고정된 경우(좌표 쌍, RGB 3개 값 등)에 적합합니다.
  • 사람이 직접 읽는 표라면 변환 전에 구분자로 합치기: jq '.[] |= (.tags |= join(";"))' data.json을 거친 뒤 변환합니다. 셀이 불필요하게 인용 부호로 감싸이지 않도록 쉼표 대신 세미콜론(;)을 구분자로 사용하는 편이 좋습니다.

객체 배열을 포함하는 레코드 (가장 까다로운 형태)

변환 도구를 사용하기 전에 "CSV의 1개 행이 무엇을 나타내는지"를 먼저 정의해야 합니다.

  • 1개 행 = 부모 (주문 1건): 배열을 JSON 텍스트 그대로 1개 셀에 둡니다. FormatArc의 기본 동작입니다. 상세 항목이 훼손되지 않고 보존되어 추후 스크립트로 셀을 파싱할 수 있습니다.
  • 1개 행 = 자식 (주문 항목 1건): 이것은 단순한 형식 변환이 아니라 완전히 다른 테이블입니다. pandas.json_normalize(data, record_path="items", meta=["order"])를 사용하면 부모 필드를 자식의 각 행에 반복하여 확장할 수 있습니다.
  • 2개 파일로 분리하기: 부모 필드를 orders.csv로 변환하고, 자식 항목은 jq '[.[] | .order as $o | .items[] | {order:$o} + .]' data.json으로 추출하여 items.csv로 만듭니다. 정규화된 형태이며 CSV를 데이터베이스에 적재할 때 권장되는 방식입니다.

피해야 할 방법은 가변 길이 배열을 Miller의 기본 동작처럼 items.1.sku, items.1.qty, items.2.sku, items.2.qty … 형태로 가로로 늘리는 것입니다. 열 수가 "가장 많은 자식 요소를 가진 레코드"에 의해 결정되므로, 데이터가 바뀔 때마다 스키마가 달라집니다.

키가 일치하지 않는 레코드

FormatArc와 pandas는 별도 설정 없이 처리합니다. Miller의 경우 unsparsify 옵션을 추가하면 중단되지 않고 누락된 값을 채워 줍니다.

mlr --ijson --ocsv unsparsify data.json

또는 jq '[.[] | {id, name, nickname, phone}]'을 실행해 미리 모든 레코드가 전체 키를 갖도록 정규화해도 됩니다.

Excel과 Google 스프레드시트에서 깨지지 않게 열기

데이터를 손상시키는 원인은 변환기가 아니라 스프레드시트 프로그램 자체인 경우가 많습니다.

  • 인코딩과 한글 깨짐. CSV 형식 자체에는 인코딩 정보를 저장하는 영역이 없습니다. RFC 4180새 탭에서 열립니다 역시 US-ASCII 이외의 문자 집합은 MIME charset 매개변수와 함께 사용한다고만 명시하고 있으며, 로컬 파일은 해당 매개변수를 갖지 않습니다. FormatArc에서 다운로드한 CSV는 BOM(Byte Order Mark)이 없는 UTF-8 파일입니다. Windows Excel은 BOM이 없으면 한글을 ANSI/CP949 또는 Windows-1252로 잘못 인식하여 글자가 깨질 수 있습니다. 파일을 더블클릭하지 말고 Excel의 "데이터" 탭 > "텍스트/CSV에서" 메뉴를 통해 인코딩을 "65001: 유니코드(UTF-8)"로 지정하여 가져오세요. Google 스프레드시트는 UTF-8을 자동으로 올바르게 판별합니다.
  • 16자리 이상의 숫자. Excel의 공식 사양에는 숫자 정밀도가 15자리새 탭에서 열립니다로 명시되어 있으며, 15자리를 초과하는 자릿수는 0으로 대체됩니다. 앞서 살펴본 2^53 반올림과 겹치면 긴 ID가 이중으로 왜곡될 수 있습니다. 해당 열은 가져오기 단계에서 "텍스트" 형식으로 지정해야 합니다.
  • 0으로 시작하는 숫자(Leading Zero). 007이나 전화번호 010-1234-5678은 열을 텍스트로 가져오지 않으면 숫자 7로 바뀌거나 수식 계산으로 오작동할 수 있습니다.
  • 날짜처럼 보이는 문자열. 2026-07-01은 물론, 1-2 같은 버전 번호도 스프레드시트가 자동으로 날짜형으로 변환합니다. 가져올 때 열 형식을 텍스트로 지정하는 것이 안전합니다.
  • =, +, -, @로 시작하는 셀. 이번에 비교한 4개 도구 모두 이를 이스케이프하지 않았습니다 (=1+1이 그대로 출력됨). 이를 수식으로 평가할지 여부는 스프레드시트가 결정하며, 이것이 CSV Injection(수식 삽입 공격)새 탭에서 열립니다의 기본 형태입니다. 사용자 입력이 포함된 CSV를 다른 사람이 열어보는 환경이라면 해당 셀 앞에 작은따옴표(')를 붙이거나 열을 텍스트로 가져옵니다.

구분 기호는 쉼표인가, 세미콜론인가, 탭인가

FormatArc는 항상 쉼표(,)로 작성합니다. 출력은 PapaParse의 unparse 함수를 기본 설정으로 통과하며(lib/tooling.tsconvertJsonToCsv), 구분 기호 설정 옵션은 없습니다. RFC 4180새 탭에서 열립니다에서도 구분 기호를 쉼표로 정의합니다.

이 기본값으로 문제가 생기는 순간은 누군가 파일을 더블클릭해서 열 때입니다. Microsoft 문서에 따르면 Excel이 통합 문서를 .csv로 저장할 때 "기본 목록 구분 기호는 쉼표입니다. 이는 Windows 국가 및 지역 설정에서 다른 문자로 변경할 수 있습니다"라고 설명합니다 (텍스트 파일 가져오기 또는 내보내기새 탭에서 열립니다). 동일한 문서에는 소수점 기호를 쉼표로 사용하는 지역에서는 "Excel이 목록 구분 기호로 세미콜론을 사용하도록 설정된다"고 명시되어 있습니다. 유럽 대륙과 중남미 대부분이 이 설정입니다. 그러한 환경에서는 쉼표 구분 CSV를 더블클릭으로 열었을 때 열이 나뉘지 않고 A열 한 줄에 모든 내용이 몰려 들어갈 수 있습니다.

올바른 해결책 2가지와 잘못된 방법 1가지가 있습니다.

  • 더블클릭하지 않고 가져오기 기능 사용: Excel의 "데이터" > "텍스트/CSV에서"로 이동하여 구분 기호를 "쉼표", 인코딩을 "UTF-8"로 선택합니다. 앞서 설명한 인코딩 해결 방법과 동일한 경로이므로 추가 단계가 들지 않습니다.
  • 더블클릭할 대상에게 전달해야 한다면 Miller로 세미콜론 구분 파일 생성: 실측에 사용된 Miller 6.19.0에서 mlr --ijson --ocsv --ofs ';' cat data.json을 실행하면 헤더 a,ba;b로 출력됩니다.
  • 쉼표를 세미콜론으로 단순 일괄 치환(Search and Replace)해서는 안 됩니다. 원래 값 안에 쉼표가 들어 있던 필드는 이미 큰따옴표로 감싸여 있는데, 단순 치환을 하면 해당 필드 중간이 쪼개져 데이터가 망가집니다.

브라우저가 적합하지 않은 경우

curl로 가져온 API 응답 결과를 붙여넣고 바로 확인하는 용도라면 브라우저 변환기가 가장 빠르고 안전합니다. 반면 2GB짜리 대용량 덤프 파일이나 야간 자동화 배치의 한 단계로 실행하기에는 적합하지 않습니다.

# Miller: 객체를 평탄화하고 배열은 인덱스 열로 확장, 스트리밍 처리 지원
mlr --ijson --ocsv cat data.json > out.csv

# jq: 매핑을 직접 작성하므로 도구의 임의 추측이 없음
jq -r '(.[0] | keys_unsorted), (.[] | [.[]]) | @csv' data.json > out.csv

# pandas: 점 표기법 평탄화와 더불어 record_path를 통한 배열 요소별 행 전개 가능
python3 -c "import pandas,json; print(pandas.json_normalize(json.load(open('data.json'))).to_csv(index=False))" > out.csv

이 3가지 도구는 완전히 호환되지 않습니다. json_normalize는 딕셔너리를 점 표기법 열로 펼치지만 배열 요소별 행을 만들려면 record_path 지정이 필요합니다. jq@csv는 입력이 미리 스칼라 배열 형태로 정제되어 있어야 하며, 중첩된 객체를 넘기면 평탄화하지 않고 오류를 냅니다. Miller는 객체와 배열을 기본적으로 평탄화하지만(배열 인덱스는 1부터 시작), 레코드 스키마가 일치하지 않으면 앞에서 실측한 대로 실행을 중단합니다. 자세한 내용은 Miller flatten 문서새 탭에서 열립니다, jq 매뉴얼새 탭에서 열립니다, pandas.json_normalize 레퍼런스새 탭에서 열립니다를 참고하세요.

반대 방향 변환(CSV를 JSON으로 변환)과 타입 추론, 인코딩 처리 등의 주의점은 CSV JSON 변환 가이드를 참고하세요.

CSV에서 JSON으로 되돌려도 원래대로 돌아오지 않는다

CSV로 변환한 데이터를 다시 JSON으로 되돌려도(왕복 변환) 원래의 계층 구조를 가진 문서로 온전히 복원되지 않습니다. 첫 번째 예제에서 만든 CSV를 CSV to JSON에 통과시키면 다음과 같은 결과가 됩니다.

[
  {
    "name": "Mika",
    "email": "mika@example.com",
    "role": "admin",
    "address.city": "Tokyo"
  }
]

address.city는 중첩된 address 객체가 아니라 점(.)을 포함하는 이름을 가진 평탄한 키로 돌아옵니다. 점 표기법을 자동으로 다시 중첩 구조로 만들어 주는 범용 도구가 없는 이유는, address.city라는 키 이름 자체도 완전히 적법한 JSON 키 이름이므로 변환기가 사용자의 원래 의도를 구별할 수 없기 때문입니다. 앞서 살펴본 키 충돌 문제와 동일한 이유입니다.

따라서 JSON에서 CSV로의 변환은 "스프레드시트 분석이나 엑셀 보고를 위한 단방향 내보내기"로 간주하고, 데이터의 원본(Source of Truth)은 항상 JSON으로 보관해야 합니다. 중첩 구조로 다시 복원해야 하는 경우에는 jq 'map(reduce (to_entries[]) as {$key,$value} ({}; setpath($key | split("."); $value)))'와 같이 명시적인 경로 재구성 스크립트를 작성하고 결과를 직접 검증해야 합니다.

자주 묻는 질문

CSV가 1개 열밖에 생성되지 않고 그 안에 JSON이 들어 있는 이유는 무엇인가요?

최상위가 {"data":[...]}처럼 "배열을 1개만 갖는 단일 객체" 형태였기 때문입니다. 배열 부분을 먼저 꺼내어 붙여넣거나(data 배열 내용만 복사하거나 jq '.data' response.json 통과), 최상위 구조를 배열로 변경한 뒤 변환하세요. FormatArc는 바깥쪽 객체를 data라는 단일 열로 평탄화할 뿐 내부 배열을 CSV 행으로 자동 전개하지 않습니다.

중첩된 배열의 요소마다 1개 행을 만들 수 있나요?

브라우저 변환기에서는 지원하지 않으며 이는 의도적인 제약입니다. 행 수가 데이터에 따라 가변적으로 변하고 부모 필드가 경고 없이 복제되기 때문입니다. 앞서 설명한 것처럼 pandas.json_normalize(data, record_path="items", meta=[...])를 사용하거나 jq로 먼저 형태를 가공하세요.

열 내용이 [{"sku":"X1"...}] 형태로 나옵니다

객체 배열을 JSON 텍스트 상태 그대로 1개 셀에 유지한 결과입니다. 의도된 동작이며 데이터 손실 없이 안전하게 보존됩니다. 이를 변경하고 싶을 때의 3가지 선택지는 객체 배열을 포함하는 레코드에서 확인할 수 있습니다.

숫자가 변경되는 경우가 있나요?

JavaScript 자체 사양의 범위 내에서만 발생합니다. 2^53을 초과하는 큰 정수는 파싱 과정에서 부동소수점 반올림으로 숫자가 바뀝니다. 문자열 데이터는 전혀 변경되지 않습니다. 16자리 이상의 ID를 다룬다면 JSON 단계에서 문자열로 감싸 두거나 JavaScript 이외의 도구를 사용하세요.

데이터가 어딘가로 업로드되나요?

전송되지 않습니다. 모든 변환은 브라우저 탭 안에서 자바스크립트로 실행되며 네트워크 요청을 발생시키지 않습니다. 개발자 도구의 네트워크 패널에서도 외부 통신이 없음을 직접 확인할 수 있습니다.

JSON 문법이 올바르지 않으면 어떻게 되나요?

깨진 CSV를 출력하는 대신 오류가 발생한 줄 번호와 내용이 포함된 명확한 오류 메시지가 표시됩니다. 데이터를 보기 좋게 정렬하고 유지하는 방법은 JSON 정렬 방법을 참고하세요.

원본 데이터는 어느 형식으로 보관해야 하나요?

계층 구조를 온전히 보존할 수 있는 JSON으로 보관해야 합니다. CSV는 타입이 없는 2차원 표 형식이므로 중첩 구조, 배열, null과 빈 문자열 ""의 구분이 모두 사라집니다. JSON을 원본으로 두고 CSV는 분석용 뷰(view)로 취급하는 것이 안전합니다. CSV 형식 자체의 구조와 제약에 대한 자세한 내용은 CSV 파일이란을 참고하세요.