π€ 1. μλ° μ§λ ¬νλ?
μλ° μ§λ ¬ν(Java Serialization)μ, κ°μ²΄μ μνλ₯Ό μμν νλ 맀컀λμ¦μ λλ€.
μμνλ, μꡬμ μΌλ‘ μμ±μ μ μ₯νλ κ²μ μλ―Ένλ―λ‘, μ½κ² νμ΄μ μ€λͺ νλ©΄ κ°μ²΄λ₯Ό λ€λ₯Έ νκ²½μ μ μ₯νλ€κ° λμ€μ μ¬κ΅¬μ±ν μ μλ κ²μ΄ 곧 μλ° μ§λ ¬νμ μλ―Έμ λλ€.
λ¨μν μ μ₯μ΄λΌκ³ νννμ§λ§, μΌλ°μ μΌλ‘ μ°λ¦¬κ° μκ°νλ λ°μ΄ν°λ² μ΄μ€ μ μ₯, νμΌμ ννλ‘ μ μ₯λ ν΄λΉμ΄ λμ§λ§, λ©λͺ¨λ¦¬ λ° μΊμμ μ μ₯νλ κ² μμ μ§λ ¬νλΌκ³ ννν μ μμ΅λλ€.
μλ° μ§λ ¬νλ₯Ό ν΅ν΄ κ°μ²΄λ₯Ό μ¨μ ν λ€λ₯Έ κ³³μ μ μ₯νκ³ , λ€μ μ¨μ ν κ°μ²΄λ‘ μ¬κ΅¬μ±ν μ μμ΅λλ€. μ΄λ₯Ό ν΅ν΄ μ½κ² λΆμ° κ°μ²΄ μμ±μ΄ κ°λ₯ν΄μ‘μ΅λλ€. μλ° μ§λ ¬νμμ μ μ₯νλ λ°©μμ, κ°μ²΄λ₯Ό λ°μ΄νΈ μ€νΈλ¦Όμ ννλ‘ λ§λ€μ΄ μ΄λ₯Ό μ μ₯ν©λλ€.
π€ 2. μλ° μ§λ ¬νλ μΈμ μ°λμ?
κ°μ²΄μ μνλ₯Ό μμ(μ΄λκ°μ μꡬμ μΌλ‘ μ μ₯)ν΄μΌ ν λ μ¬μ©ν©λλ€.
κ°μ²΄λ‘ μ¬κ΅¬μ±ν μ μλ€λ μ μμ, λ€λ₯Έ VMμκ² κ°μ²΄μ μ 보λ₯Ό μ λ¬ν΄μΌ ν λ μ¬μ©νκΈ°λ ν©λλ€. (Remote Method Invocation νΉμ Socketμ μ¬μ©ν΄μ.)
μ¬μ©νλ λ°©λ²μ λ¨μν©λλ€.
package java.io;
public interface Serializable {}
public class MyObject implemets Serializable{
public int value;
public MyObject(final int value){
this.value = value;
}
}
μμ μ½λμμ λ³Ό μ μλ―μ΄ Serializable μΈν°νμ΄μ€λ κ³΅κ° APIκ° μλ λ¨μν λ§μ»€ μΈν°νμ΄μ€μ λλ€.
νμ§λ§ μ΄ Serializable μΈν°νμ΄μ€λ₯Ό implements ν΄μ£Όλ κ²λ§μΌλ‘λ ν΄λΉ κ°μ²΄λ μ§λ ¬ν κ°λ₯ν κ°μ²΄λ‘ λ³μ νκ² λ©λλ€!
λ§μ½ Serializable μΈν°νμ΄μ€λ₯Ό implementsνμ§ μλ κ°μ²΄λ₯Ό μ§λ ¬ν νλ €κ³ νλ€λ©΄, NotSerializableExceptionμ΄ λ°λ°νκ² λλ―λ‘ μ£Όμκ° νμν©λλ€!
byte[] serailizedObject;
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream)) {
MyObject myObject = new MyObject(1);
objectOutputStream.writeObject(myObject);
serializedObject = byteArrayOutputStream.toByteArray();
}
μ§λ ¬νλ₯Ό νλ κ²μ java.io.ObjectOutputStreamμ μ¬μ©ν©λλ€. try-with-resource λ¬Έμ μ¬μ©ν΄ byteArrayOutputStreamκ³Ό ObjectOutputStreamμ μμ±ν λ€, writeObject λ©μλμ toByteArray λ©μλλ₯Ό μ¬μ©ν΄ μ§λ ¬νλ₯Ό ν μ μμ΅λλ€.
λ°λλ‘ μμ§λ ¬νλ java.io.ObjectInputStreamλ₯Ό μ¬μ©ν©λλ€.
μμ§λ ¬νλ, λ°μ΄νΈ μ€νΈλ¦ΌμΌλ‘ μ μ₯λ λ°μ΄ν°λ₯Ό κ°μ²΄λ‘ μ¬κ΅¬μ±νλ κ²μ μλ―Έν©λλ€.
byte[] serializedObject = getSerializedObject();
try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(serializedObject);
ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream)){
MyObject myObject = (MyObject) objectInputStream.readObject();
}
κ·Έλ¦¬κ³ ObjectInputStreamμ readObject λ©μλμ νμ μΊμ€ν μ ν΅ν΄ μμ§λ ¬νλ₯Ό μ§νν΄ κ²°κ΅, κ°μ²΄λ₯Ό μ¨μ ν μ¬κ΅¬μ±ν μ μκ² λ©λλ€.
μ 체μ μΈ νλ‘μ°λ μμ κ°μ΅λλ€.
π€ 3. SerialVersionUIDμ μ©λλ 무μμΌκΉ?
Serializationμ implementsνλ κ°μ²΄λ€μ, ν΄λμ€μ λ²μ κ΄λ¦¬λ₯Ό μν΄ serialVersionUID λ³μλ₯Ό μ¬μ©νκ² λ©λλ€.
μ΄ serialVersionUID λ³μλ κ°λ°μκ° μ§μ μ μνμ§ μμΌλ©΄, μ»΄νμΌλ¬κ° μμμ λΆμ¬νκ² λ©λλ€.
μ΄ serialVersionUIDλ μ§λ ¬ν ν λ κ°μ΄ μ μ₯λκ² λκ³ , μμ§λ ¬νλ₯Ό ν λμλ κ·Έ κ°μ 체ν¬νλ μ©λλ‘ μ¬μ©νκ² λ©λλ€.
μλ₯Ό λ€μ΄ serialVersionUID κ°μ 1Lλ‘ μ€μ ν ν μ§λ ¬νλ₯Ό νμ΅λλ€. κ·Έ μ΄ν, ν΄λΉ ν΄λμ€μ serialVersionUID κ°μ 2Lλ‘ λ³κ²½ν λ€, μμ§λ ¬νλ₯Ό μλνλ©΄ invalidClassExceptionμ΄ λ°μνκ² λ©λλ€. μ¦ λ²μ κ΄λ¦¬λ₯Ό κ°λ₯μΌ νλ κ²μ΄μ£ .
SerialVersionUIDλ κ°λ°μκ° μ§μ μ€μ νλ κ²μ κΆμ₯ν©λλ€. κ·Έ μ΄μ λ μ»΄νμΌλ¬μ μμ λΆμ¬μ μμ΅λλ€. JVMμ λ΄λΆ μκ³ λ¦¬μ¦μ μν΄ ν΄λΉ κ°μ΄ κ²°μ λκ² λλλ°, λ¬Έμ λ μ΄λ€ JVMμ μ¬μ©νλμ§μ λ°λΌμ μ΄ κ°μ΄ λ¬λΌμ§κ² λ©λλ€.
λ°λΌμ Clientκ° Windows, μλ²κ° LinuxμΈ κ²½μ° μλ‘ λ€λ₯Έ JVMμ μ¬μ©νκ² λμ΄ μ΄ κ°μ΄ λ¬λΌμ Έ μμ§λ ¬νλ₯Ό μ§νν λ Exceptionμ΄ λ°μν μ¬μ§κ° μμ΅λλ€.
π€ 4. μ μλ° μ§λ ¬νλ μ μ μ°κ² λλ κ±ΈκΉ?
μ΄ μ§λ ¬νλΌλ κ°λ μ λ§μ΄ λ€μ΄λ³΄κΈ΄ νμΌλ μ€λ¬΄ κ²½νμ΄ λΆμ‘±ν λ΄κ²λ μ μ°μ΄μ§ μλλ€λ λλμ λ°μμ΅λλ€.
μ§λ ¬νλ₯Ό κΈ°νΌνλ μ΄μ λ 보μ λ¬Έμ , μ μ§ λ³΄μμ±, ν μ€νΈ λ±μμ 볡μ‘ν¨μ΄ μμ΄μ κ·Έλ λ€κ³ ν©λλ€.
μλ₯Ό λ€μ΄ νμΈν΄λ΄ μλ€.
1) 보μ λ¬Έμ
μ§λ ¬νλ λ°μ΄νΈ μ€νΈλ¦Όμ μμ§λ ¬ν ν λμλ readObject λ©μλκ° νΈμΆλκ² λ©λλ€. κ·Όλ° μ΄κ² μμ²΄κ° νλμ μμ±μμ λ€λ₯Όκ² μμ΅λλ€. μ¦, 보μ΄μ§ μλ μμ±μμ λ¬Έμ κ° μκΈ°κ² λ©λλ€.
μ΄κ² μ λ¬Έμ κ° λ°μνλλ©΄, λ°μ΄νΈ μ€νΈλ¦Όμ λ°°μ΄ λ΄λΆμ κ°μ μ§μ μ κ·Όν΄ μμ μ΄ κ°λ₯ν©λλ€.
μ΄ μνλ‘ objectInputStreamμ μμ±νκ³ , readObjectλ₯Ό νλ€λ©΄ κ·Έλλ‘ μμ±μ΄ λ©λλ€. κΈ°μ‘΄μ μμ±μμμλ validationλ‘μ§μ λ£μ΄μ κ°μ μ ν¨μ±μ νλ¨νμ§λ§, readObjectλ₯Ό ν΅ν΄ λ§λ€μ΄μ§ κ°μ²΄λ 보μ΄μ§ μλ λ€λ₯Έ μμ±μλ₯Ό μ¬μ©νκ² λμ΄λ²λ¦½λλ€.
μ΄λ₯Ό λ°©μ΄νλ λ°©λ²μΌλ‘λ, 컀μ€ν μ§λ ¬νλ₯Ό μ¬μ©νλ λ°©λ²μ΄ μμ΅λλ€. readObjectλ₯Ό μλ‘κ² μ μνλ λ°©μμΌλ‘, κΈ°μ‘΄μ objectInputStream.defaultReadObject() λ©μλλ₯Ό ν΅ν΄ κΈ°μ‘΄μ μμ§λ ¬ν κ³Όμ μ μν€κ³ , μΆκ°μ μΈ validation μ½λλ₯Ό μ¬κΈ°μ μ½μ ν΄μ£Όλ©΄ μ΄λ¬ν λ¬Έμ λ₯Ό ν΄κ²°ν μ μμ΅λλ€.
private void readObject(ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException {
objectInputStream.defaultReadObject(); // κΈ°λ³Έμ μΈ μμ§λ ¬ν κ³Όμ
// μλ΅, μΆκ°μ μΈ validation μ½λ.
}
2) μ±κΈν€ λ¬Έμ
μ±κΈν€ ν¨ν΄μΌλ‘ μ΄λ ν ν΄λμ€λ₯Ό λ§λ€κ³ , μ΄λ₯Ό μ§λ ¬ν κ°λ₯νλλ‘ Serializable μΈν°νμ΄μ€λ₯Ό ꡬννλ€κ³ ν©μλ€.
μ±κΈν€ κ°μ²΄λ₯Ό λ€μ μμ§λ ¬ν νλ©΄, μ±κΈν€μ νΉμ±μ μμ΄λ²λ¦¬κ² λ©λλ€. readObjectκ° νΈμΆλλ©΄ λ€λ₯Έ κ°μ²΄κ° μμ±λκ² λ©λλ€. μ±κΈν€μ λ¨ νλμ κ°μ²΄λ§ μ‘΄μ¬ν΄μΌ νλ€λ κ²μ νμ μ μ§νλλ° μ΄λ₯Ό κΉ¨λ²λ¦¬κ² λλ€λ κ²μ΄μ£ .
μ΄λ¬ν μ±κΈν€ λ¬Έμ λ₯Ό ν΄κ²°νλ €λ©΄ readResolve()λ₯Ό μ μνλ©΄ λ©λλ€. readResolve() λ©μλλ readObject()κ° νΈμΆλ μ΄νμ νΈμΆλκ² λ©λλ€. μμ§λ ¬νλ₯Ό κ±°μΉ κ°μ²΄λ₯Ό μ¬μ©νμ§ μκ³ , readResolve()μμ λ°ννλ κ°μ²΄λ₯Ό μ¬μ©νκ² λκΈ° λλ¬Έμ, μ±κΈν€ λ¬Έμ λ₯Ό ν΄κ²°ν μ μμ£ .
λ€λ§ μ΄ κ²½μ°, ν΄λμ€μ νλ μ€μ, μΈμ€ν΄μ€ λ³μκ° μ‘΄μ¬νλ κ²½μ°μλ μ§λ ¬ν/μμ§λ ¬νκ° λμ§ μν λ‘ transient ν€μλλ₯Ό λΆμ¬μΌ ν©λλ€. κ·ΈλμΌ μ°Έμ‘°νλμ μμκ°μ νμ³μ€λ νμλ₯Ό λ§μ μ μλ€κ³ ν©λλ€. μ΄ λΆλΆμ μΆνμ 곡λΆλ₯Ό λ ν΄λ΄μΌκ² μ΅λλ€.
λͺ¨λ μΈμ€ν΄μ€ λ³μμ μ¬μ©ν΄μΌ νκ³ , μ΄λ₯Ό κ°κ³Όνλ€λ©΄ 보μ λ¬Έμ κ° λ°μν μ μμ΅λλ€.
μ±κΈν€κ°μ΄ κ°μ²΄ κ°―μ ν΅μ ν΄μΌ νλ μν©μλ readResolveλ₯Ό μ¬μ©νλ κ²μ΄ κ΅μ₯ν λΆνΈνκ² λ©λλ€.
μλ° μ§λ ¬νλ μκ°ν κ²μ΄ λ§μ κΈ°μ μ΄μμ΅λλ€. μλ¬΄λ° μκ° μμ΄ μ¬μ©νλ€κ°λ μ¬λ¬ λ¬Έμ κ° λ°μν μ¬μ§κ° μμμ΅λλ€.
κ·Έλμ 10λΆ ν μ½ν‘μμλ μ¬λ§νλ©΄ μ¬μ©νμ§ μλ κ²μ κΆμ₯νμ΅λλ€. μλ‘μ΄ μμ€ν μ λ°μ΄νΈ μ€νΈλ¦ΌμΌλ‘ λ³ννλ μ’μ 맀컀λμ¦μ΄ λ§κΈ° λλ¬Έμ λλ€.
μλ₯Ό λ€μ΄, ν¬λ‘μ€ νλ«νΌμ μ ν©ν λ°μ΄ν° ννμΌλ‘ JSON, CSV, νλ‘ν μ½ λ²νΌ λ±μ μ¬μ©νλ κ²μ κΆμ₯νλ€κ³ νλ€μ.
μ΄νν°λΈ μλ°μμλ μ§λ ¬ν ννΈμμ λ§μ λ΄μ©μ λ€λ£¨κ³ μλ€λ, μΆκ° νμ΅μ ν΄λ³΄λλ‘ νκ² μ΅λλ€.
π μΆμ²
[λ§ν¬] https://blog.naver.com/kkson50/220564273220 (SerialVersionUID)
[λ§ν¬] https://www.youtube.com/watch?v=3iypR-1Glm0 (10λΆ ν μ½ν‘ : μλ° μ§λ ¬ν)