직렬화 (Serialization)
프로그램 실행 중에 생성된 인스턴스(객체)들은 JVM 메모리(Heap)에만 존재하며, 프로그램이 종료되면 모두 사라집니다. 이러한 객체의 상태(필드에 저장된 값들)를 영구적으로 파일에 저장하거나, 네트워크를 통해 다른 서버의 JVM으로 전송하고 싶을 때 직렬화 를 사용합니다.
- 직렬화 (Serialization): 메모리에 있는 객체를 바이트(Byte) 스트림 형태로 연속된 데이터로 변환하는 과정
- 역직렬화 (Deserialization): 저장되거나 전송받은 바이트 스트림을 다시 원래의 객체 데이터로 복원하는 과정
1. Serializable 인터페이스 달기
객체를 직렬화하려면 반드시 해당 클래스가 java.io.Serializable 인터페이스를 구현(implements)해야 합니다. 이 인터페이스는 단지 "이 클래스는 직렬화가 허용됨"을 마킹하는 일종의 마커 인터페이스로, 구현해야 할 메서드는 없습니다.
import java.io.Serializable;
// 직렬화가 가능한 UserInfo 클래스
class UserInfo implements Serializable {
// 직렬화 버전 관리를 위한 고유값 (권장)
private static final long serialVersionUID = 1L;
String name;
// transient 키워드가 붙은 변수는 직렬화 대상에서 제외됩니다. (보안 목적 등)
transient String password;
int age;
public UserInfo(String name, String password, int age) {
this.name = name;
this.password = password;
this.age = age;
}
}
2. ObjectOutputStream / ObjectInputStream 사용
객체를 직접 입출력하기 위해 전용 보조 스트림인 ObjectOutputStream, ObjectInputStream 을 사용합니다.
import java.io.*;
public class SerialEx {
public static void main(String[] args) {
UserInfo u1 = new UserInfo("Alice", "1234", 30);
String fileName = "userinfo.ser";
// 1. 객체 직렬화하여 파일에 저장하기
try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(fileName))) {
out.writeObject(u1);
System.out.println("객체가 직렬화되어 파일에 저장되었습니다.");
} catch (IOException e) {
e.printStackTrace();
}
// 2. 파일에서 바이트를 읽어와 객체로 역직렬화하기
try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(fileName))) {
// writeObject()로 기록했으므로 readObject()로 읽어서 캐스팅합니다.
UserInfo readUser = (UserInfo) in.readObject();
System.out.println("복원된 이름: " + readUser.name);
System.out.println("복원된 나이: " + readUser.age);
System.out.println("비밀번호(transient): " + readUser.password); // null 출력됨!
} catch (Exception e) {
e.printStackTrace();
}
}
}
현대의 분산 서버 아키텍처나 웹 애플리케이션에서는 Java 직렬화 방식(보안 이슈 및 호환성 단점)을 직접 쓰기보다, JSON 형식으로 변환하여 통신하는 것이 일반적입니다. (예: Jackson이나 Gson 라이브러리 사용)