본문으로 건너뛰기
Advertisement

직렬화 (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 라이브러리 사용)

Advertisement