Java에서 Gson 스트리밍 API(Streaming API)를 사용하면 파일에 JSON 데이터를 효율적으로 읽고 쓸 수 있습니다. 이 API는 순차적(sequential) 방식으로 데이터를 처리하며, 대용량 JSON 문서를 다룰 때 메모리 사용량을 크게 줄여주는 것이 가장 큰 장점입니다.
스트리밍 API의 핵심 클래스는 두 가지입니다.
- JsonWriter: JSON 인코딩된 값을 스트림에 한 번에 하나의 토큰(token)씩 기록합니다. 문자열, 숫자, 불리언(boolean), null 같은 리터럴 값과 객체·배열의 시작(begin) 및 종료(end) 구분자(delimiter)를 모두 포함합니다.
- JsonReader: JSON 인코딩된 값을 토큰 스트림 형태로 읽어들입니다. 마찬가지로 리터럴 값과 객체·배열의 시작/종료 구분자를 포함하며, 토큰은 JSON 문서에 나타나는 순서대로 깊이 우선(depth-first) 방식으로 탐색됩니다.
JsonWriter로 파일에 쓰기
다음 예제는 JsonWriter를 사용하여 객체와 배열이 포함된 JSON 데이터를 파일에 작성하는 방법을 보여줍니다.
예제 코드
import java.io.*;
import com.google.gson.stream.*;
public class JsonWriterTest {
public static void main(String args[]) {
JsonWriter writer;
try {
writer = new JsonWriter(new FileWriter("input.json"));
writer.beginObject();
writer.name("name").value("Adithya");
writer.name("age").value(25);
writer.name("technologies");
writer.beginArray();
writer.value("Java");
writer.value("Scala");
writer.value("Python");
writer.endArray();
writer.endObject();
writer.close();
System.out.println("파일에 데이터가 성공적으로 저장되었습니다.");
} catch(Exception e) {
e.printStackTrace();
}
}
}실행 결과
파일에 데이터가 성공적으로 저장되었습니다.
위 코드는 beginObject()와 endObject() 사이에서 name() 메서드로 키를 지정하고 value()로 값을 기록합니다. 배열의 경우 beginArray()와 endArray()로 감싸서 여러 개의 값을 순차적으로 추가할 수 있습니다.
JsonReader로 파일 읽기
다음 예제는 JsonReader를 사용하여 앞서 작성한 JSON 파일을 토큰 단위로 순회하며 읽는 방법을 보여줍니다.
예제 코드
import java.io.*;
import com.google.gson.stream.*;
public class JsonReaderTest {
public static void main(String args[]) {
JsonReader reader;
try {
reader = new JsonReader(new FileReader("input.json"));
reader.beginObject();
while(reader.hasNext()) {
String name = reader.nextName();
if(name.equals("name")) {
System.out.println(reader.nextString());
} else if(name.equals("age")) {
System.out.println(reader.nextInt());
} else if(name.equals("technologies")) {
reader.beginArray();
while(reader.hasNext()) {
System.out.println(reader.nextString());
}
reader.endArray();
} else {
reader.skipValue();
}
}
reader.endObject();
reader.close();
} catch(Exception e) {
e.printStackTrace();
}
}
}실행 결과
Adithya 25 Java Scala Python
읽기 과정에서는 hasNext()로 다음 토큰의 존재 여부를 확인하고, nextName(), nextString(), nextInt() 등의 메서드로 각 값의 타입에 맞게 데이터를 추출합니다. 필요 없는 값은 skipValue()로 건너뛸 수 있어 유연한 파싱이 가능합니다.
정리
Gson 스트리밍 API는 DOM 기반 파싱(fromJson/toJson)과 달리 전체 문서를 메모리에 로드하지 않고 토큰 단위로 처리하기 때문에, 수백 MB 이상의 대용량 JSON 파일을 다룰 때 특히 유용합니다. JsonWriter로 순차적 쓰기를, JsonReader로 순차적 읽기를 구현하면 메모리 효율성과 성능을 모두 확보할 수 있습니다.