직렬화(Serialization)는 Java 객체를 객체의 데이터와 함께 객체 타입 및 저장된 데이터의 타입 정보까지 포함하는 바이트 스트림 형태로 저장하는 과정입니다. 즉, 직렬화는 Java 객체의 값과 상태를 바이트로 변환하여 네트워크를 통해 전송하거나 파일로 저장할 수 있도록 해줍니다. 반대로 역직렬화(Deserialization)는 이렇게 저장된 바이트 코드를 다시 원래의 Java 객체로 복원하는 과정입니다.
transient(임시) 변수는 직렬화 과정에서 그 값이 저장되지 않는 변수입니다. 따라서 역직렬화를 수행하면 해당 변수에는 저장 당시의 값이 아닌 타입별 기본값(default value)이 할당됩니다.
transient 변수가 직렬화되지 않는 이유
- 보안상의 이유: 비밀번호, 카드 번호 등 민감한 정보가 파일이나 네트워크를 통해 외부로 노출되는 것을 방지할 수 있습니다.
- 파생 가능한 값: 다른 필드로부터 다시 계산할 수 있는 값이라면 굳이 저장하지 않고, 역직렬화 후 재계산하여 복원할 수 있습니다.
- 직렬화 불가능한 참조: Serializable을 구현하지 않은 객체를 필드로 가질 때 발생하는 NotSerializableException을 피할 수 있습니다.
문법
private transient <멤버_변수>;
예제
import java.io.*;
class EmpInfo implements Serializable {
String name;
private transient int age;
String occupation;
public EmpInfo(String name, int age, String occupation) {
this.name = name;
this.age = age;
this.occupation = occupation;
}
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("Name:"+"\n");
sb.append(this.name+"\n");
sb.append("Age:"+ "\n");
sb.append(this.age + "\n");
sb.append("Occupation:" + "\n");
sb.append(this.occupation);
return sb.toString();
}
}
// 메인 클래스
public class TransientVarTest {
public static void main(String args[]) throws Exception {
EmpInfo empInfo = new EmpInfo("Adithya", 30, "Java Developer");
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("empInfo"));
oos.writeObject(empInfo);
oos.close();
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("empInfo"));
EmpInfo empInfo1 = (EmpInfo)ois.readObject();
System.out.println(empInfo1);
}
}
출력 결과
Name: Adithya Age: 0 Occupation: Java Developer
위 실행 결과를 보면, 객체 생성 시 age 값을 30으로 설정했음에도 불구하고 역직렬화 후에는 0이 출력되는 것을 확인할 수 있습니다. 이는 age 필드가 transient로 선언되어 직렬화 대상에서 제외되었고, 따라서 역직렬화 시 int 타입의 기본값인 0이 할당되었기 때문입니다. 반면 name과 occupation 필드는 일반 필드이므로 저장 당시의 값이 그대로 복원된 것을 볼 수 있습니다.