Serializable
์ง๋ ฌํ๋ผ๋ ์ฉ์ด์ ๋ํด์ ๋ค์ด๋ง ๋ณด๊ณ ๊ณต๋ถํด๋ณธ ์ ์ ์๋๋ฐ ์ด๋ฒ ๊ธฐํ์ ์ ๋ฆฌ๋ฅผ ํ๊ฒ ๋์์ต๋๋ค,, ์ด๋ฒ ๊ธ์์๋ ์ง๋ ฌํ
์ ๋ํด์ ์์๋ณด๊ฒ ์ต๋๋ค.
public interface Serializable {
}
Serializable
์ ์ธํฐํ์ด์ค๋ฅผ ๋ณด๋ฉด ๋ฉ์๋๊ฐ ํ๋๋ ์๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค. ์๋ฌด๋ฐ ๊ตฌํํด์ผ ํ ๋ฉ์๋๋ ์๋ ์ด ์ธํฐํ์ด์ค๊ฐ ๋๋์ฒด ์ ์๋ ๊ฒ์ผ๊น์?
๊ฐ๋ฐ์ ํ๋ค ๋ณด๋ฉด ์๋์ ๊ฐ์ ๊ฒฝ์ฐ๊ฐ ์กด์ฌํฉ๋๋ค.
์์ฑํ ๊ฐ์ฒด๋ฅผ ํ์ผ๋ก ์ ์ฅํ ์ผ์ด ์์ ์๋ ์์ต๋๋ค.
์ ์ฅํ ๊ฐ์ฒด๋ฅผ ์ฝ์ ์ผ์ด ์๊ธธ ์๋ ์์ต๋๋ค.
๋ค๋ฅธ ์๋ฒ์์ ์์ฑํ ๊ฐ์ฒด๋ฅผ ๋ฐ์ ์ผ๋ ์๊ธธ ์ ์์ต๋๋ค.
์ด๋ด ๋ ๊ผญ ํ์ํ ๊ฒ์ด Serializable
์
๋๋ค. ์ฐ๋ฆฌ๊ฐ ๋ง๋ ํด๋์ค๊ฐ ํ์ผ์ ์ฝ๊ฑฐ๋ ์ธ ์ ์๋๋ก ํ๊ฑฐ๋, ๋ค๋ฅธ ์๋ฒ๋ก ๋ณด๋ด๊ฑฐ๋ ๋ฐ์ ์ ์๋๋ก ํ๋ ค๋ฉด ๋ฐ๋์ ์ด ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํ
ํด์ผ ํฉ๋๋ค.
Serializable ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๋ฉด JVM์์ ํด๋น ๊ฐ์ฒด๋ ์ ์ฅํ๊ฑฐ๋ ๋ค๋ฅธ ์๋ฒ๋ก ์ ์กํ ์ ์๋๋ก ํด์ค๋ค.
๊ทธ๋์ ์ง๋ ฌํ๊ฐ ๋ฌด์์ธ๊ฐ?
๊ทธ๋์ ์ง๋ ฌํ๊ฐ ๋ฌด์์ธ๊ฐ?
์๋ฐ ์ง๋ ฌํ๋ ์๋ฐ ์์คํ ๋ด๋ถ์์ ์ฌ์ฉ๋๋ ๊ฐ์ฒด ๋๋ ๋ฐ์ดํฐ๋ฅผ ์ธ๋ถ์ ์๋ฐ ์์คํ ์์๋ ์ฌ์ฉํ ์ ์๋๋ก ๋ฐ์ดํธ(byte) ํํ๋ก ๋ฐ์ดํฐ ๋ณํํ๋ ๊ธฐ์ ๊ณผ ๋ฐ์ดํธ๋ก ๋ณํ๋ ๋ฐ์ดํฐ๋ฅผ ๋ค์ ๊ฐ์ฒด๋ก ๋ณํํ๋ ๊ธฐ์ (์ญ์ง๋ ฌํ)์ ์์ธ๋ฌ์ ์ด์ผ๊ธฐํฉ๋๋ค.
์์คํ ์ ์ผ๋ก ์ด์ผ๊ธฐํ์๋ฉด JVM(Java Virtual Machine ์ดํ JVM)์ ๋ฉ๋ชจ๋ฆฌ์ ์์ฃผ(ํ ๋๋ ์คํ)๋์ด ์๋ ๊ฐ์ฒด ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ดํธ ํํ๋ก ๋ณํํ๋ ๊ธฐ์ ๊ณผ ์ง๋ ฌํ๋ ๋ฐ์ดํธ ํํ์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ฒด๋ก ๋ณํํด์ JVM์ผ๋ก ์์ฃผ์ํค๋ ํํ๋ฅผ ๊ฐ์ด ์ด์ผ๊ธฐํฉ๋๋ค.
์ฌ๊ธฐ ์์ ์ฐธ๊ณ ํ ์ ์์ ๋๋ค.
Serializable
์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ ํด๋์ค๋ค์ ๋ณด๋ฉด serialVersionUID
๋ผ๋ ๊ฐ์ ์ง์ ํด์ฃผ๋ ๊ฒ์ ๋ณธ ์ ์ด ์์ ๊ฒ์
๋๋ค.
public class HashMap<K,V> extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable {
private static final long serialVersionUID = 362498820763181265L;
}
์๋ฅผ๋ค์ด, HashMap
ํด๋์ค๋ฅผ ๋ณด๋ฉด ์์ ๊ฐ์ ๋ณ์๋ฅผ ๋ณผ ์ ์์ต๋๋ค. ์ด๋ ๊ฒ Serializable
์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ ํ์๋ ์์ ๊ฐ์ด serialVersionUID
๋ผ๋ ๊ฐ์ ์ง์ ํด ์ฃผ๋ ๊ฒ์ ๊ถ์ฅํฉ๋๋ค.
(๋ง์ฝ ๋ณ๋๋ก ์ง์ ํ์ง ์์ผ๋ฉด, ์๋ฐ ์์ค๊ฐ ์ปดํ์ผ๋ ๋ ์๋์ผ๋ก ์๊น๋๋ค.)
static final long serialVersionUID = 1L;
์์ ๊ฐ์ด ๋ฐ๋์ static final long
์ผ๋ก ์ ์ธํด์ผ ํ๋ฉฐ, ๋ณ์๋ช
๋ serialVersionUID
๋ก ์ ์ธํด ์ฃผ์ด์ผ ์๋ฐ์์ ์ธ์์ ํ ์ ์์ต๋๋ค.
๊ทธ๋ฌ๋ฉด ์ด ๊ฐ์ ์ด๋์ ์ฌ์ฉ๋๊ณ ์ด๋ค ๊ฐ์ ๋ฃ์ด์ผ ํ ๊น์?
๊ทธ๋ฌ๋ฉด ์ด ๊ฐ์ ์ด๋์ ์ฌ์ฉ๋๊ณ ์ด๋ค ๊ฐ์ ๋ฃ์ด์ผ ํ ๊น์?
๊ฐ์ ์๋ฌด๋ฐ ๊ฐ์ด๋ ์ง์ ํด์ฃผ๋ฉด ๋ฉ๋๋ค.
๊ฐ์ ์๋ฏธ๋ ํด๋น ๊ฐ์ฒด์ ๋ฒ์ ์ ๋ช
์ํ๋ ๋ฐ ์ฌ์ฉํฉ๋๋ค.
์๋ฅผ๋ค์ด ๋ณด๊ฒ ์ต๋๋ค.
A๋ผ๋ ์๋ฒ์์ B๋ผ๋ ์๋ฒ๋ก SerialDTO๋ผ๋ ํด๋์ค์ ๊ฐ์ฒด๋ฅผ ์ ์กํ๋ค๊ณ ๊ฐ์ ํ๊ฒ ์ต๋๋ค. ์ ์กํ๋ A ์๋ฒ์ SerialDTO๋ผ๋ ํด๋์ค๊ฐ ์์ด์ผ ํ๊ณ , ์ ์ก๋ฐ๋ B ์๋ฒ์๋ SerialDTO๋ผ๋ ํด๋์ค๊ฐ ์์ด์ผ๋ง ํฉ๋๋ค. ๊ทธ๋์ผ๋ง ๊ทธ ํด๋์ค์ ๊ฐ์ฒด์์ ์๊ณ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ ์ ์์ต๋๋ค.
๊ทธ๋ฐ๋ฐ ๋ง์ฝ A ์๋ฒ๊ฐ ๊ฐ๊ณ ์๋ SerialDTO์๋ ๋ณ์๊ฐ 3๊ฐ ์๊ณ , B ์๋ฒ์ SerialDTO์๋ ๋ณ์๊ฐ 4๊ฐ ์๋ ์ํฉ์ด ๋ฐ์ํ๋ฉด ์ด๋ป๊ฒ ๋ ๊น์? ์ด๋ฌ๋ฉด ์๋ฐ์์๋ ์ ๋๋ก ์ฒ๋ฆฌ๋ฅผ ๋ชปํ๊ฒ ๋ฉ๋๋ค. ๋ฐ๋ผ์ ๊ฐ ์๋ฒ๊ฐ ์ฝ๊ฒ ํด๋น ๊ฐ์ฒด๊ฐ ๊ฐ์์ง ๋ค๋ฅธ์ง๋ฅผ ํ์ธํ ์ ์๋๋ก ํ๊ธฐ ์ํด์๋ serialVersionUID๋ก ๊ด๋ฆฌ๋ฅผ ํด์ฃผ์ด์ผ๋ง ํฉ๋๋ค.
์ฆ ํด๋์ค ์ด๋ฆ์ด ๊ฐ๋๋ผ๋ ์ด ID๊ฐ ๋ค๋ฅด๋ฉด ๋ค๋ฅธ ํด๋์ค๋ผ๊ณ ์ธ์ํฉ๋๋ค. ๊ฒ๋ค๊ฐ, ๊ฐ์ UID๋ผ๊ณ ํ ์ง๋ผ๋, ๋ณ์์ ๊ฐ์๋ ํ์ ๋ฑ์ด ๋ค๋ฅด๋ฉด ์ด ๊ฒฝ์ฐ๋ ๋ค๋ฅธ ํด๋์ค๋ก ์ธ์ํฉ๋๋ค.
๊ธ๋ง ๋ด์๋ ์ฝ์ง๊ฐ ์์๋ฐ ์์ธํ ๋ด์ฉ์ ์กฐ๊ธ๋ง ์๋ค๊ฐ ๋ค์ ๋ ์์๋ณด๊ฒ ์ต๋๋ค.
๊ฐ์ฒด๋ฅผ ์ ์ฅํด๋ณด๊ธฐ
๊ฐ์ฒด๋ฅผ ์ ์ฅํด๋ณด๊ธฐ
import java.io.Serializable;
public class SerialDTO implements Serializable {
private String booName;
private int bookOrder;
private boolean bestSeller;
private long soldPerDay;
public SerialDTO(String booName, int bookOrder, boolean bestSeller, long soldPerDay) {
this.booName = booName;
this.bookOrder = bookOrder;
this.bestSeller = bestSeller;
this.soldPerDay = soldPerDay;
}
@Override
public String toString() {
return "SerialDTO{" +
"booName='" + booName + '\'' +
", bookOrder=" + bookOrder +
", bestSeller=" + bestSeller +
", soldPerDay=" + soldPerDay +
'}';
}
}
DTO ํด๋์ค๋ฅผ ์ ์ฅํด๋ณด๋ ์์ ๋ฅผ ํด๋ณด๊ฒ ์ต๋๋ค.
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
public class ManageObject {
public static void main(String[] args) {
ManageObject manage = new ManageObject();
String fullPath = "/Users/choejeong-gyun/Documents/test.md";
SerialDTO dto = new SerialDTO("God of Java", 1, true, 100);
manage.saveObject(fullPath, dto);
}
public void saveObject(String fullPath, SerialDTO dto) {
FileOutputStream fos = null;
ObjectOutputStream oos = null;
try {
fos = new FileOutputStream(fullPath);
oos = new ObjectOutputStream(fos);
oos.writeObject(dto);
System.out.println("Write Success");
} catch (Exception e) {
e.printStackTrace();
} finally {
if (oos != null) {
try {
oos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (fos != null) {
try {
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
์๋ฐ์์๋
ObjectOutputStream
ํด๋์ค๋ฅผ ์ฌ์ฉํ๋ฉด ๊ฐ์ฒด๋ฅผ ์ ์ฅํ ์ ์์ต๋๋ค.ObjectInputStream
์ ์ฌ์ฉํ๋ฉด ์ ์ฅํด๋์ ๊ฐ์ฒด๋ฅผ ์ฝ์ ์ ์์ต๋๋ค.์์ ์ฝ๋์์๋
FileOutputStream
๊ฐ์ฒด๋ฅผ ๋ง๋ ํ์ObjectOutputStream
์ ๋งค๊ฐ๋ณ์๋ก ๋๊ฒผ์ต๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ํด๋น ๊ฐ์ฒด๋ ํ์ผ์ ์ ์ฅ๋ฉ๋๋ค.writeObject()๋ฅผ ํตํด์ ๋งค๊ฐ๋ณ์๋ก ๋์ด์จ ๊ฐ์ฒด๋ฅผ ์ ์ฅํฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ ํ์ผ์ ํ์ธํด๋ณด๋ฉด ํ์ผ์ ๊ฐ์ฒด๊ฐ ์ ์ฅ์ด ๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.
๊ฐ์ฒด๋ฅผ ์ฝ์ด๋ณด๊ธฐ
๊ฐ์ฒด๋ฅผ ์ฝ์ด๋ณด๊ธฐ
import java.io.*;
public class ManageObject {
public static void main(String[] args) {
ManageObject manage = new ManageObject();
String fullPath = "/Users/choejeong-gyun/Documents/test.md";
manage.loadObject(fullPath);
}
public void loadObject(String fullPath) {
FileInputStream fis = null;
ObjectInputStream ois = null;
try {
fis = new FileInputStream(fullPath);
ois = new ObjectInputStream(fis);
Object obj = ois.readObject();
SerialDTO dto = (SerialDTO)obj;
System.out.println(dto);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (ois != null) {
try {
ois.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
if (fis != null) {
try {
fis.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
SerialDTO{booName='God of Java', bookOrder=1, bestSeller=true, soldPerDay=100}
๊ทธ๋ฌ๋ฉด ์์ ๊ฐ์ด ํ์ผ์ ์ ์ฅ๋ ๊ฐ์ฒด ์ ๋ณด๋ฅผ ์ฝ์ ์ ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ด๋ฒ์ SerialDTO
ํด๋์ค์ ํ๋๋ฅผ ํ๋ ์ถ๊ฐํ ํ์ ์์ ์ฝ๋๋ฅผ ๋ค์ ์คํํด๋ณด๊ฒ ์ต๋๋ค.
java.io.InvalidClassException: FileIO.SerialDTO; local class incompatible: stream classdesc serialVersionUID = -358710248991570103, local class serialVersionUID = 1424372278057927306
at java.base/java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:689)
at java.base/java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1982)
at java.base/java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1851)
at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2139)
at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1668)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:482)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:440)
at FileIO.ManageObject.loadObject(ManageObject.java:49)
at FileIO.ManageObject.main(ManageObject.java:12)
๊ทธ๋ฌ๋ฉด ์์ ๊ฐ์ ๊ฒฐ๊ณผ๊ฐ ๋์ต๋๋ค. ์์์ ๋ณผ ์ ์๋ฏ์ด serialVersionUID
๊ฐ์ด ๋ค๋ฅด๋ค๋ ์๋ฌ ๋ฉ์ธ์ง๊ฐ ์ถ๋ ฅ๋ฉ๋๋ค. ์ด๋ ๊ฒ ๊ฐ์ฒด ํํ๊ฐ ๋ณ๊ฒฝ๋๋ฉด ์ปดํ์ผ์ serialVersionUID๊ฐ ๋ค์ ์์ฑ๋๊ธฐ ๋๋ฌธ์ ์ด๋ฌํ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๊ฒ ๋ฉ๋๋ค.
transient๋ผ๋ ์์ฝ์ด๋ Serializable๊ณผ ๋จ์ด์ง ์ ์๋ ๊ด๊ณ
transient๋ผ๋ ์์ฝ์ด๋ Serializable๊ณผ ๋จ์ด์ง ์ ์๋ ๊ด๊ณ
transient private int bookOrder;
SerialDTO ํด๋์ค์ transient
๋ผ๋ ์์ฝ์ด๋ฅผ ์ถ๊ฐํ ํ์ ๋ค์ ๊ฐ์ฒด๋ฅผ ํ์ผ์ ์ ์ฅํ๊ณ ์ฝ์ด์ค๋ ์ฝ๋๋ฅผ ์คํํด๋ณด๊ฒ ์ต๋๋ค.
Write Success
SerialDTO{booName='God of Java', bookOrder=0, bestSeller=true, soldPerDay=100}
๊ทธ๋ฌ๋ฉด ๊ฐ์ฒด๋ฅผ ์์ฑํ ๋ bookOrder์ 1์ ๋ฃ์์ง๋ง ๊ฒฐ๊ณผ์๋ 0์ด ๋์ค๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.
0์ด ๋์ค๋ ์ด์ ๊ฐ ๋ฌด์์ผ๊น์?
๊ฐ์ฒด๋ฅผ ์ ์ฅํ๊ฑฐ๋, ๋ค๋ฅธ JVM์ผ๋ก ๋ณด๋ผ ๋, transient ์์ฝ์ด๋ฅผ ์ฌ์ฉํ์ฌ ์ ์ธํ ๋ณ์๋ Serializable์ ๋์์์ ์ ์ธ๋ฉ๋๋ค.
๊ทธ๋ฌ๋ฉด ๋ญํ๋ฌ ์ด๊ฒ์ ์ฌ์ฉํ๋ ์ถ์ ์ ์์ง๋ง, ํจ์ค์๋์ ๊ฐ์ด ๋ณด์์ ์ค์ํ ๋ณ์๋ ๊ผญ ์ ์ฅํด์ผ ํ ํ์๊ฐ ์๋ ๋ณ์์ ๋ํด์๋ transient
๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ง๋ ฌํ ์ฐธ๊ณ ํ๊ธฐ
์ง๋ ฌํ ์ฐธ๊ณ ํ๊ธฐ
public class SuperUserInfo implements Serializable {
String name;
String password;
}
public class UserInfo extends SuperUserInfo {
int age;
}
์ด๋ฌํ ์์ ๊ด๊ณ๊ฐ ์์ ๋, SuperUserInfo
ํด๋์ค๋ฅผ ์ง๋ ฌํ ํ์ง๋ง, ํ์ ํด๋์ค์ธ UserInfo
ํด๋์ค๋ ์ง๋ ฌํ๊ฐ ๊ฐ๋ฅํ๊ฒ ๋ฉ๋๋ค.
UserInfo๋ฅผ ์ง๋ ฌํํ๋ฉด ๋ถ๋ชจ ํด๋์ค์ name, password๋ ๊ฐ์ด ์ง๋ ฌํ๊ฐ ๋ฉ๋๋ค.
public class SuperUserInfo {
String name;
String password;
}
public class UserInfo extends SuperUserInfo implements Serializable {
int age;
}
ํ์ง๋ง ์์ ๊ฐ์ด ๋ถ๋ชจ ํด๋์ค๊ฐ ์ง๋ ฌํ๋ฅผ ๊ตฌํํ์ง ์์๋ค๋ฉด ์์ ํด๋์ค์์ ์ง๋ ฌํํ ๋ name, password๋ ์ง๋ ฌํ ๋์์์ ์ ์ธ๋ฉ๋๋ค.
public class UserInfo implements Serializable {
int age;
Object object = new Object(); // Object ๊ฐ์ฒด๋ ์ง๋ ฌํํ ์ ์๋ค.
}
์์ ์ฝ๋์์ UserInfo ํด๋์ค๋ Serializable์ ๊ตฌํํ๊ณ ์์ด์ ์ง๋ ฌํ ํ ์ ์๋ค๊ณ ์๊ฐํ ์ ์์ง๋ง ์ง๋ ฌํ๋ฅผ ์๋ํ๋ฉด java.io.NotSerializableException
์ด ๋ฐ์ํฉ๋๋ค.
์ด์ ๊ฐ ๋ฌด์์ผ๊น์?
๋ฐ๋ก Object ๊ฐ์ฒด ๋๋ฌธ์
๋๋ค. ์์ ์์ ์์ ๋ณด์๋ฏ์ด ๋ถ๋ชจ ํด๋์ค์์ Serializable์ ๊ตฌํํ๊ณ ์๋ค๋ฉด ์์ ํด๋์ค๋ ์ง๋ ฌํ๊ฐ ๊ฐ๋ฅํ์ต๋๋ค.
Object๋ ๋ชจ๋ ํด๋์ค์ ์ต๊ณ ์กฐ์์ด๊ธฐ ๋๋ฌธ์ ์ด ํด๋์ค๊ฐ Serializable์ ๊ตฌํํ๋ค๋ฉด ๋ชจ๋ ํด๋์ค๋ค์ด ์ง๋ ฌํ๊ฐ ๊ฐ๋ฅํ์ ๊ฒ์ ๋๋ค.
๊ทธ๋ ๊ธฐ ๋๋ฌธ์ Object ํด๋์ค๋ Serializable์ ๊ตฌํํ์ง ์์ ์ง๋ ฌํ๋ฅผ ํ ์ ์์ต๋๋ค.
public class UserInfo implements Serializable {
int age;
Object object = new String("abc");
}
ํ์ง๋ง ์์ ๊ฐ์ด ๋คํ์ฑ์ ์ด์ฉํ ์ฝ๋๋ ์ง๋ ฌํ๋ฅผ ํ ์ ์์ต๋๋ค. ์ธ์คํด์ค ๋ณ์์ ํ์ ์ Object์ ํ์ ์ด์ง๋ง ์ค์ ๋ก ์ ์ฅ๋ ๊ฐ์ฒด๋ ์ง๋ ฌํ๊ฐ ๊ฐ๋ฅํ String ์ธ์คํด์ค์ด๊ธฐ ๋๋ฌธ์ ์ง๋ ฌํ๊ฐ ๊ฐ๋ฅํฉ๋๋ค.
์ธ์คํด์ค ๋ณ์์ ํ์
์ด ์๋ ์ค์ ๋ก ์ฐ๊ฒฐ๋ ๊ฐ์ฒด์ ์ข
๋ฅ์ ์ํด์ ๊ฒฐ์ ๋๋ค๋ ๊ฒ์ ์์๋๋ฉด ์ข์ ๊ฒ ๊ฐ์ต๋๋ค.
Reference
Reference
์๋ฐ์ ์
Last updated