자바 직렬화(Serialization)에서 객체 그래프(Object Graph)는 매우 중요한 개념입니다. 객체 그래프란 하나의 객체가 다른 객체를 참조하고 있을 때, 참조 관계로 연결된 객체들이 하나의 네트워크처럼 묶여 있는 구조를 말합니다.
핵심 규칙은 다음과 같습니다. 어떤 객체를 직렬화하면, 그 객체가 참조하고 있는 다른 객체들 역시 JVM이 자동으로 함께 직렬화합니다. 즉, 개발자가 일일이 내부 객체를 직렬화할 필요 없이 최상위 객체만 직렬화하면, 참조로 연결된 모든 객체가 한꺼번에 처리됩니다.
객체 그래프 직렬화 예제 코드
아래 예제는 세 개의 클래스가 서로를 참조하는 구조에서, 최상위 객체 하나만 직렬화했을 때 어떻게 동작하는지 보여줍니다.
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
class One implements Serializable {
Two s2 = new Two();
}
class Two implements Serializable {
Three s3 = new Three();
}
class Three implements Serializable {
int i = 34;
int j = 67;
}
public class Demo_Serialize {
public static void main(String args[]) throws Exception {
One s1 = new One();
// 객체 직렬화 (파일에 저장)
FileOutputStream my_fos = new FileOutputStream("abc.ser");
ObjectOutputStream my_oos = new ObjectOutputStream(my_fos);
my_oos.writeObject(s1);
my_oos.close();
my_fos.close();
// 객체 역직렬화 (파일에서 복원)
FileInputStream my_fis = new FileInputStream("abc.ser");
ObjectInputStream my_ois = new ObjectInputStream(my_fis);
One my_obj = (One) my_ois.readObject();
my_ois.close();
my_fis.close();
System.out.println("직렬화 후 i의 값: " + my_obj.s2.s3.i);
System.out.println("직렬화 후 j의 값: " + my_obj.s2.s3.j);
}
}실행 결과
Value of i after it is serialized is 34 Value of j after it is serialized is 67
코드 상세 분석
먼저 One 클래스는 Serializable 인터페이스를 구현하여 직렬화 가능한 클래스가 됩니다. 이 클래스 내부에는 Two 타입의 인스턴스 변수 s2가 선언되어 있으며, Two 클래스 역시 Serializable을 구현하고 있습니다.
Two 클래스 내부에는 또 다른 클래스인 Three 타입의 인스턴스 s3가 존재합니다. Three 클래스에는 두 개의 정수형 변수 i와 j가 정의되어 있으며, 마찬가지로 Serializable을 구현합니다. 결국 One → Two → Three로 이어지는 참조 체인, 즉 객체 그래프가 형성됩니다.
메인 클래스인 Demo_Serialize의 main 메서드에서는 먼저 One 객체를 생성합니다. 이후 FileOutputStream과 ObjectOutputStream을 사용해 abc.ser 파일에 객체를 기록(writeObject)하고, 스트림을 닫아 직렬화를 완료합니다.
다음으로 FileInputStream과 ObjectInputStream을 사용해 저장된 파일을 읽어 들여(readObject) 원래 객체로 복원하는 역직렬화를 수행합니다. 복원된 객체에서 my_obj.s2.s3.i, my_obj.s2.s3.j처럼 내부 객체의 필드에 접근하면, 직렬화 전의 값 34와 67이 그대로 유지되고 있음을 확인할 수 있습니다.
주의 사항: 직렬화 불가능한 객체가 포함된 경우
객체 그래프에 포함된 모든 객체가 반드시 Serializable을 구현해야 합니다. 만약 참조 체인 중 단 하나의 클래스라도 직렬화를 지원하지 않으면, 실행 시점에 NotSerializableException이 발생하며 직렬화에 실패합니다. 따라서 객체 그래프를 설계할 때는 참조되는 모든 클래스의 직렬화 가능 여부를 확인하는 것이 좋습니다.