개요
실제 개발 현장에서는 다양한 편의 기능을 위해 데이터를 파싱해야 하는 요구가 자주 발생합니다. 그러나 하드웨어 자원, 특히 메모리의 용량이 한정되어 있어, 대용량 JSON 파일을 ObjectMapper로 한 번에 읽어들일 경우 OutOfMemoryError가 발생할 수 있습니다.
이러한 문제를 해결하는 방법 중 하나는 Jackson의 Streaming API, 특히 JsonParser를 활용하는 것입니다. 본 글에서는 JsonParser를 이용해 대용량 JSON 파일을 스트리밍 방식으로 파싱하고, 필요한 데이터만 추출하여 텍스트(.txt) 파일로 저장하는 과정을 정리합니다.
Jackson Streaming API란?
- Tree Model (
JsonNode
) - Data Binding (
ObjectMapper
) - Streaming API ✅ (
JsonParser
,JsonGenerator
)
Streaming 방식은 이벤트 기반으로 JSON 데이터를 토큰 단위로 읽고 처리합니다. 대용량 JSON을 빠르고 메모리 효율적으로 처리할 수 있습니다.
구분 | ObjectMapper | JsonParser |
방식 | 데이터 전체를 메모리에 로딩 후 파싱 | 한 줄씩 토큰 단위로 스트리밍 처리 |
메모리 사용량 | 크고 예측하기 어려움 | 매우 적고 안정적 |
속도 | 작은 데이터에 유리 | 대용량에서 효율적 |
구조 | 내부 객체 매핑 (DTO 필요) | 직접 토큰 단위 파싱 필요 |
사용 예 | REST API 응답 파싱, 간단한 JSON 변환 | 로그 분석, 빅데이터 전처리 등 |
예제 상황
- 입력: data.json (대용량 JSON 배열)
- 출력: output.txt (필요한 필드만 추출하여 텍스트 파일 저장)
{
"result": [
{ "id": 1, "name": "test" },
{ "id": 2, "name": "test2" },
...
]
}
예제 코드
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import java.io.File;
import java.io.IOException;
public class JsonResultParser {
public static void main(String[] args) {
JsonFactory factory = new JsonFactory();
try (JsonParser parser = factory.createParser(new File("input.json"))) {
while (!parser.isClosed()) {
JsonToken token = parser.nextToken();
if (JsonToken.FIELD_NAME.equals(token) && "result".equals(parser.getCurrentName())) {
// "result": [ ... ] 까지 왔음
token = parser.nextToken(); // START_ARRAY
while (parser.nextToken() == JsonToken.START_OBJECT) {
// 배열 내부 객체 파싱
String name = null;
int id = -1;
while (parser.nextToken() != JsonToken.END_OBJECT) {
String fieldName = parser.getCurrentName();
parser.nextToken(); // move to value
switch (fieldName) {
case "name":
name = parser.getText();
break;
case "id":
id = parser.getIntValue();
break;
default:
parser.skipChildren(); // 예외 필드는 무시
}
}
System.out.println("Parsed name: " + name + ", id: " + id);
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
주요 메서드 설명
parser.nextToken()
: 다음 JSON 토큰으로 이동parser.getCurrentName()
: 현재 필드 이름 가져오기parser.getText()
: 현재 값 텍스트로 가져오기parser.skipChildren()
: 객체/배열 건너뛰기
주의사항
- 필요한 필드만 추출하면 훨씬 빠르고 효율적입니다.
- 파일 인코딩이 필요하면
OutputStreamWriter
로 처리할 수 있습니다.
실제 적용 예
- 로그 데이터를 날짜별로 분리하여 저장
- 대용량 API 응답을 실시간으로 분석 및 요약
- IoT 디바이스 JSON 로그 정제
마무리
ObjectMapper 대신 JsonParser를 활용하면, 대용량 데이터를 처리할 때 메모리 효율성과 속도를 모두 잡을 수 있습니다. 대용량 Json을 파싱하는데 효율적이며
'개발새발 > Java' 카테고리의 다른 글
Java의 핵심 키워드: volatile, transient, synchronized (1) | 2025.06.16 |
---|---|
Java 키워드 정리 – final, static, this, super 차이와 사용법 (1) | 2025.06.13 |
Java의 메모리 영역 (0) | 2024.05.26 |
인터페이스 vs 추상클래스 (0) | 2024.05.26 |