JSON 과 JSONL 과 NDJSON 은 같은 파일이 아니다
그 파일이 JSON 이 아니라 JSONL 일 가능성이 높다. .json 파일에는 문서가 정확히 하나 — 객체 하나 또는 배열 하나 — 들어 있고 파서는 그것을 통째로 읽는다. .jsonl 이나 .ndjson 은 한 줄에 완결된 JSON 문서 하나씩을 쉼표도 바깥 괄호도 없이 담는다. 그래서 보통의 파서는 첫 줄을 읽고, 문서가 끝난 뒤에 내용이 더 있는 것을 발견하고, 문법 오류를 낸다. 고칠 것은 파일이 아니라 읽는 방식이다.
각각이 실제로 무엇인가
RFC 8259 가 정의하는 JSON 은 값 하나다. 레코드 만 개짜리 배열을 담은 파일은 배열 하나이고, 파서는 닫는 대괄호를 읽어야만 무언가를 돌려줄 수 있다. 문서 전체가 한 번에 메모리에 올라가야 한다는 뜻이다.
JSON Lines(.jsonl)와 Newline-Delimited JSON(.ndjson)은 같은 발상에 붙은 두 이름이다. 각 줄이 독립된 JSON 문서이고, UTF-8 로 인코딩되며, \n 으로 나뉜다. 최상위 배열도 없고 레코드 사이의 쉼표도 없다. 두 이름이 같은 배치를 가리키고, 도구들은 대개 어느 확장자든 받는다.
스트리밍 형식이 있는 이유
만드는 쪽은 한 줄을 내보내고 넘어가면 되고, 읽는 쪽은 한 줄을 처리하고 버리면 된다. 어느 쪽도 데이터셋 전체를 메모리에 들지 않아도 된다. 로그와 내보내기 파일, 기가바이트 단위의 무언가에서 이 형식이 기본이 된 이유다.
실패하는 모양도 낫다. JSON 배열이 중간에 잘리면 문서 전체가 무효라 아무것도 못 얻는다. JSONL 이 잘리면 잘린 지점 앞의 완결된 줄은 모두 읽힌다 — 파일이 아니라 꼬리를 잃는다.
같은 이유로 덧붙이기가 간단하다. 레코드를 하나 더 쓴다는 것은 줄을 하나 더 쓰는 것이다. JSON 배열에 덧붙이려면 닫는 대괄호를 다시 써야 한다. 로그 파일이 JSON 배열인 경우가 없는 이유다.
가려내는 법, 그리고 변환
첫 글자를 본다. [ 로 시작해서 ] 로 끝나면 JSON 배열 하나다. { 로 시작하는데 뒤쪽 줄의 첫 글자에도 { 가 있으면 JSONL 이다. { 로 시작하고 줄 끝에 쉼표가 있으면 펼쳐 쓴 문서 하나다.
JSONL 을 읽으려면 줄바꿈으로 나눠 줄마다 따로 파싱한다. JSONL 을 JSON 으로 만들려면 파싱한 줄들을 배열로 감싼다. 반대로 가려면 배열의 각 원소를 구분자 없이 한 줄씩 쓴다. 두 변환 모두 몇 줄이면 되고 라이브러리가 필요 없다.
JSONL 로 바꿀 때 한 가지 주의할 것이 있다. 줄바꿈이 들어 있는 레코드는 문자열 안에서 \\n 로 이스케이프되어 있어야 한다. JSONL 에서는 줄바꿈이 레코드 구분자이기 때문이다. 펼쳐 쓴 JSON 객체를 그냥 한 줄로 붙일 수 없다.
관련 도구
이 도구가 따르는 규격
- RFC 8259 — JSON 데이터 교환 형식 — JSON 을 값 하나로 정의한다. 여러 문서가 든 파일이 파싱되지 않는 이유.
- RFC 7464 — JSON 텍스트 시퀀스 — 같은 스트리밍 발상의 IETF 판, 레코드 구분자 방식.
- MDN — JSON.parse() — 오류를 내는 파서, 그리고 거기서 멈추는 이유.
고친 날 2026-09-05