Python에서 JSONL: 읽기, 쓰기 & 파싱
Python에서 JSONL(JSON Lines) 파일을 다루는 완전 가이드. 내장 모듈, pandas 및 고성능 라이브러리를 사용하여 JSONL 데이터를 읽고, 쓰고, 파싱하고, 스트리밍하는 방법을 알아보세요.
최종 업데이트: 2026년 2월
왜 Python으로 JSONL을 다루나요?
Python은 JSONL 파일 작업에 가장 인기 있는 언어이며, 그럴만한 이유가 있습니다. 내장된 json 모듈이 JSON 파싱을 기본적으로 처리하고, 파일 반복이 기본적으로 메모리 효율적이며, pandas와 orjson 같은 강력한 라이브러리가 전문 워크플로우를 위해 제공됩니다. 머신러닝 데이터셋, 애플리케이션 로그 또는 API 응답을 처리하든, Python은 JSONL 처리를 간단하게 만들어 줍니다.
JSONL(JSON Lines)은 줄당 하나의 JSON 객체를 저장하여 스트리밍, 추가 전용 로깅, 전체를 메모리에 로드하지 않고도 대용량 데이터셋을 처리하는 데 이상적입니다. Python의 줄 단위 파일 읽기는 이 형식과 완벽하게 일치합니다. 이 가이드에서는 JSONL을 읽는 세 가지 방법, 쓰는 두 가지 방법, 그리고 메모리에 맞지 않는 파일을 처리하는 방법을 배웁니다.
Python에서 JSONL 파일 읽기
Python에서 JSONL 파일을 읽는 여러 방법이 있으며, 각각 다른 사용 사례에 적합합니다. 표준 json 모듈은 대부분의 시나리오에서 작동하고, pandas는 표 형식 분석에 편리하며, 제너레이터는 대용량 파일에 가장 적합합니다.
가장 간단한 방법은 Python의 내장 json 모듈을 사용하는 것입니다. 파일을 열고, 줄 단위로 반복하며, 각 줄을 json.loads()로 파싱합니다. 이렇게 하면 모든 레코드가 메모리의 리스트에 로드됩니다.
import jsonrecords = []with open('data.jsonl', 'r', encoding='utf-8') as f:for line in f:line = line.strip()if line: # Skip empty linesrecords.append(json.loads(line))print(f'Loaded {len(records)} records')print(records[0])
JSONL 데이터가 표 형식(모든 레코드에 동일한 키)인 경우, pandas가 단일 함수 호출로 직접 DataFrame으로 읽을 수 있습니다. 구조화된 JSONL 데이터 분석을 시작하는 가장 빠른 방법입니다.
import pandas as pd# Read entire file into a DataFramedf = pd.read_json('data.jsonl', lines=True)print(df.head())print(f'Shape: {df.shape}')# For large files, read in chunkschunks = pd.read_json('large.jsonl', lines=True, chunksize=10000)for chunk in chunks:# Process each chunk (DataFrame)print(f'Chunk shape: {chunk.shape}')
메모리에 맞지 않는 대용량 파일의 경우, 제너레이터 함수를 사용하세요. 한 번에 하나의 레코드만 생성하여 파일 크기에 관계없이 메모리 사용량을 일정하게 유지합니다. 프로덕션 데이터 파이프라인에 권장되는 패턴입니다.
import jsonfrom typing import Iterator, Anydef read_jsonl(path: str) -> Iterator[dict[str, Any]]:"""Read a JSONL file lazily, yielding one record at a time."""with open(path, 'r', encoding='utf-8') as f:for line_num, line in enumerate(f, 1):line = line.strip()if not line:continuetry:yield json.loads(line)except json.JSONDecodeError as e:print(f'Skipping invalid JSON at line {line_num}: {e}')# Process records one at a timefor record in read_jsonl('large_data.jsonl'):process(record) # Only one record in memory at a time
Python에서 JSONL 파일 쓰기
JSONL 파일 쓰기는 간단합니다: 각 레코드를 JSON 문자열로 직렬화하고 줄바꿈 문자를 추가합니다. 핵심 규칙은 줄당 하나의 JSON 객체이며, 후행 쉼표나 감싸는 배열이 없어야 합니다.
json.dumps()를 사용하여 각 레코드를 직렬화한 다음 줄바꿈을 뒤에 붙여 씁니다. 출력에서 중국어, 일본어 또는 이모지와 같은 유니코드 문자를 보존하려면 ensure_ascii=False를 설정하세요.
import jsonrecords = [{"id": 1, "name": "Alice", "age": 30},{"id": 2, "name": "Bob", "age": 25},{"id": 3, "name": "Charlie", "age": 35},]with open('output.jsonl', 'w', encoding='utf-8') as f:for record in records:f.write(json.dumps(record, ensure_ascii=False) + '\n')print(f'Wrote {len(records)} records to output.jsonl')
데이터가 이미 pandas DataFrame에 있는 경우, to_json()을 orient='records'와 lines=True로 사용하여 직접 JSONL로 내보낼 수 있습니다. 이는 pd.read_json()에 lines=True를 사용한 것의 역연산입니다.
import pandas as pddf = pd.DataFrame([{"id": 1, "name": "Alice", "age": 30},{"id": 2, "name": "Bob", "age": 25},{"id": 3, "name": "Charlie", "age": 35},])# Write DataFrame to JSONLdf.to_json('output.jsonl', orient='records', lines=True, force_ascii=False)print(f'Wrote {len(df)} records to output.jsonl')
JSONL용 Python 라이브러리
Python은 성능 특성이 다른 여러 JSON 파싱 라이브러리를 제공합니다. 파일 크기와 성능 요구 사항에 따라 적합한 것을 선택하세요.
json (stdlib)
내장Python의 내장 json 모듈은 설치가 필요 없으며 어디서나 작동합니다. 대부분의 JSONL 작업에 충분하며 모든 표준 JSON 타입을 지원합니다. 수백 MB 이하의 파일에는 성능이 적절합니다.
orjson
최고 속도orjson은 Rust로 작성된 가장 빠른 Python JSON 라이브러리입니다. 표준 json 모듈에 비해 2~10배 빠른 파싱과 직렬화를 제공합니다. 문자열 대신 바이트를 출력하며, dataclass, datetime, numpy, UUID 타입을 기본적으로 지원합니다.
ujson
빠름ujson(UltraJSON)은 C 기반 JSON 라이브러리로 표준 json 모듈보다 2~5배 빠릅니다. API가 내장 json 모듈과 거의 동일하여 드롭인 대체제로 사용할 수 있습니다. 호환성과 속도 사이의 좋은 중간점입니다.
대용량 JSONL 파일 스트리밍
기가바이트 크기의 JSONL 파일을 처리할 때는 데이터를 배치로 읽고, 변환하고, 쓰는 스트리밍 접근 방식이 필요합니다. 이렇게 하면 메모리 사용량이 일정하게 유지되고 진행 상황을 추적할 수 있습니다.
import jsonimport sysdef process_large_jsonl(input_path: str,output_path: str,batch_size: int = 1000) -> int:"""Stream-process a large JSONL file in batches."""processed = 0batch: list[dict] = []with open(input_path, 'r') as fin, \open(output_path, 'w') as fout:for line in fin:line = line.strip()if not line:continuerecord = json.loads(line)# Transform the recordrecord['processed'] = Truebatch.append(record)if len(batch) >= batch_size:for r in batch:fout.write(json.dumps(r) + '\n')processed += len(batch)batch.clear()print(f'\rProcessed {processed} records...', end='')# Write remaining recordsfor r in batch:fout.write(json.dumps(r) + '\n')processed += len(batch)print(f'\nDone. Processed {processed} records total.')return processed# Usageprocess_large_jsonl('input.jsonl', 'output.jsonl', batch_size=5000)
이 패턴은 고정 크기 배치로 레코드를 처리하여 일정한 메모리를 사용합니다. batch_size 매개변수는 메모리 사용량과 I/O 효율성 사이의 균형을 제어합니다. 대부분의 시스템에서 1,000~10,000개 레코드의 배치가 잘 작동합니다. 진행 표시기는 장기 실행 작업을 모니터링하는 데 도움이 됩니다.
무료 JSONL 도구를 사용해 보세요
코드를 작성하고 싶지 않으신가요? 무료 온라인 도구를 사용하여 브라우저에서 바로 JSONL 파일을 보고, 검증하고, 변환하세요.