1. ์ง๋ ฌํ ๊ฐ๋ ๐
์ง๋ ฌํ(Serialization)๋ ๊ฐ์ฒด๋ฅผ ๋ฐ์ดํฐ ์คํธ๋ฆผ์ผ๋ก ๋ง๋๋ ๊ฒ์ ๋งํ๋ค. ์ฆ, ํ์ฌ ๋ฐ์ดํฐ(structure, object)์ ์ํ๋ฅผ ์์์ ์ผ๋ก ์ ์ฅํ๊ฑฐ๋ ๋ค๋ฅธ ํ๊ฒฝ์ผ๋ก ์ ๋ฌ(๋คํธ์ํฌ ํต์ ๋ฑ) ํ๊ธฐ ์ํด ์ด๋ ํ ์ ํด์ง ํฌ๋งท์ผ๋ก ๋ณํํ๋ ๊ณผ์ ์ด๋ค. ๋ณํ๋ ๋ฐ์ดํฐ๋ฅผ ๋ค์ ์๋ ๋ฐ์ดํฐ๋ก ๋ณํํ๋ ๊ณผ์ ์ ์ญ์ง๋ ฌํ(Deserialization)์ด๋ผ๊ณ ํ๋ค.
// ์ง๋ ฌํ๋ฅผ ํ์ง ์์ ๊ฒฝ์ฐ
public class User{
private String name;
private String id;
String password;
public User(String name, String id, String password) {
this.name = name;
this.id = id;
this.password = password;
}
@Override
public String toString() {
return "User [name=" + name + ", id=" + id + ", password=" + password + "]";
}
}
public class Main {
private static File target = new File("C:" + File.separator + "Amenable" + File.separator + "User.dat");
public static void main(String[] args) throws IOException {
write();
}
private static void write() {
User user = new User("์ด๋ฐ๋ค", "Amenable", "1234");
try(ObjectOutputStream objOut = new ObjectOutputStream(new FileOutputStream(target))){
objOut.writeObject(user); // Error
System.out.println("์ ์ฅ ์๋ฃ");
} catch (IOException e) {
e.printStackTrace();
}
}
private static void read() {
try(ObjectInputStream objIn = new ObjectInputStream(new FileInputStream(target))){
Object obj = objIn.readObject();
if(obj instanceof User) {
User user = (User) obj;
System.out.println(user);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
์์ ์ฝ๋๋ ์ง๋ ฌํ๋ฅผ ์งํํ์ง ์๊ณ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ ์ฝ๋์ด๋ค. ์คํ์์ผ ๋ณด๋ฉด, "java.io.NotSerializableException"๋ผ๋ ์๋ฌ๋ฉ์์ง๊ฐ ๋์จ๋ค. ์ฆ, ๊ฐ์ฒด๋ฅผ ํต์ ๋ฐ ์ ์ฅํ๊ธฐ ์ํด์ ๋ฐ๋์ ์ง๋ ฌํ๋ฅผ ๊ตฌํํด์ผ ํ๋ค.
2. ์ง๋ ฌํํ๋ ๋ฐฉ๋ฒ ๐ธ
์ง๋ ฌํ๋ฅผ ํ๋ ๋ฐฉ๋ฒ์ ๊ฐ๋จํ๋ค. ์ง๋ ฌํํ๊ณ ์ ํ๋ ํด๋์ค๊ฐ java.io.Serializable์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๋๋ก ํ๋ฉด ๋๋ค. ๋ง์ฝ ๋ณด์์ ์ง๋ ฌํํ๋ฉด ์ ๋๋ ๊ฐ์ด ์๋ค๋ฉด transient๋ฅผ ๋ถ์ผ ์ ์๋ค. ๊ทธ๋ฌ๋ฉด ์ธ์คํด์ค๋ณ์์ ๊ฐ์ ๊ทธ ํ์ ์ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ์ง์ ๋๋ค.
// ์ง๋ ฌํ๋ฅผ ํ ๊ฒฝ์ฐ
public class User implements Serializable {
private String name;
private String id;
transient String password; // ํ์
์ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ์ง๋ ฌํ ์งํ
public User(String name, String id, String password) {
this.name = name;
this.id = id;
this.password = password;
}
@Override
public String toString() {
return "User [name=" + name + ", id=" + id + ", password=" + password + "]";
}
}
public class Main {
private static File target = new File("C:" + File.separator + "Amenable" + File.separator + "User.dat");
public static void main(String[] args) throws IOException {
write();
read();
}
private static void write() {
User user = new User("์ด๋ฐ๋ค", "Amenable", "1234");
try(ObjectOutputStream objOut = new ObjectOutputStream(new FileOutputStream(target))){
objOut.writeObject(user);
System.out.println("์ ์ฅ ์๋ฃ");
} catch (IOException e) {
e.printStackTrace();
}
}
private static void read() {
try(ObjectInputStream objIn = new ObjectInputStream(new FileInputStream(target))){
Object obj = objIn.readObject();
if(obj instanceof User) {
User user = (User) obj;
System.out.println(user);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
// ์ ์ฅ ์๋ฃ
// User [name=์ด๋ฐ๋ค, id=Amenable, password=null]
๋ง์ฝ Serializable์ ๊ตฌํํ ํด๋์ค๋ฅผ ์์๋ฐ๋๋ค๋ฉด Serializable์ ๊ตฌํํ์ง ์์๋ ๋๋ค.
public class User implements Serializable {
int id;
String name;
}
public class SubUser extends User {
int country;
}
์ง๋ ฌํํ๊ณ ์ ํ๋ ํด๋์ค์ ์ง๋ ฌํ๋์ง ์์ ๊ฐ์ฒด๊ฐ ์๋ค๋ฉด ์ฃผ์๊ฐ ํ์ํ๋ค. ๊ฐ๋จํ๊ฒ๋ ์์์ ์ดํด๋ณธ ๊ฒ์ฒ๋ผ transient๋ฅผ ์ฌ์ฉํด์ ์ง๋ ฌํ ๋์์์ ์ ์ธ๋ฅผ ํ๋ฉด ๋๋ค. ํ์ง๋ง ํด๋น ๊ฐ์ฒด ๋ํ ์ ์ฅํด์ผ ํ๋ ๊ฐ์ด๋ผ๋ฉด ํด๋น ๊ฐ์ฒด๋ Serializable์ ๊ตฌํํด์ผ ํ๋ค.
// ๋ฐฉ๋ฒ1
public class User implements Serializable {
private String name;
transient SubUser subUser = new SubUser();
}
// ๋ฐฉ๋ฒ2
public class User implements Serializable {
private String name;
SubUser subUser = new SubUser();
}
public class SubUser implements Srializable {
private String id;
}
3. ์ง๋ ฌํ๊ฐ๋ฅํ ํด๋์ค์ ๋ฒ์ ๊ด๋ฆฌ ๐พ
์์ ์์ ์์ User์ ๊ตญ๊ฐ(country)๋ฅผ ์ถ๊ฐํ๋ค๊ณ ์๊ฐํด ๋ณด์.
public class User implements Serializable {
private String name;
private String id;
transient String password;
private String country;
public User(String name, String id, String password, String country) {
this.name = name;
this.id = id;
this.password = password;
this.country = country;
}
@Override
public String toString() {
return "User [name=" + name + ", id=" + id + ", password=" + password + ", country=" + country + "]";
}
}
๊ทธ ํ, read()๋ฅผ ํตํด์ ๊ฐ์ ์ฝ์ด์ค๋ฉด ์ด๋ป๊ฒ ๋์ด์ผ ํ ๊น? ์ผ๋จ name, id, password(๊ธฐ๋ณธ๊ฐ์ด๋ผ๋ ๊ฐ์ด ์๋ค๊ณ ์๊ฐํ์)์ ์ด์ ์ ์ ์ฅํด ๋์์ผ๋๊น ๊ทธ๊ฑธ ๋ถ๋ฌ์ค๋ฉด ๋๊ณ , country๋ ์์ง ์ ์ฅํ์ง ์์์ผ๋๊น null๋ก ์จ๋ค๊ณ ์๊ฐ๋๋ค. ํ์ง๋ง ์ค์ ์คํ์์ผ ๋ณด๋ฉด
"java.io.InvalidClassException: test.User; local class incompatible: stream classdesc serialVersionUID = 2429090748191540600, local class serialVersionUID = 2845618176141831242"
์ด ๋์ค๊ฒ ๋๋ค. serialVersionUID๊ฐ ์ผ์นํ์ง ์๋๋ค๋ ๊ฒ์ด๋ค. ํด๊ฒฐ์ฑ
๋ถํฐ ๋จผ์ ๋งํ์๋ฉด serialVerisonUID๋ฅผ ์ค์ ํด์ฃผ์ด์ผ ํ๋ค.
serialVersionUID๋ ํด๋์ค์ ๋ณ๊ฒฝ ์ฌ๋ถ๋ฅผ ํ์ ํ๊ธฐ ์ํ ์ ์ผ ํค์ด๋ค. ์ง๋ ฌํ๋๋ ๊ฐ์ฒด์ serialVersionUID๊ฐ ์ค์ ๋์ง ์์์ ๊ฒฝ์ฐ ์ปดํ์ผ๋ฌ๊ฐ ์๋์ผ๋ก ์์ฑํ๋ค. ์์ ์์์๋ country๋ก ์ธํ ๋ณ๊ฒฝ์ผ๋ก ์ธํด ์ปดํ์ผ ์์ ์๋์ผ๋ก ์๋ก์ด serialVersionUID๋ฅผ ํ ๋น๋ฐ์๋ค.
๊ทธ๋์ ์ง๋ ฌํ๋๋ ๊ฐ์ฒด์ ๋ํด์ serialVersionUID๋ฅผ ์ค์ ํด ์ค๋ค๋ฉด ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋๋ค.
// serialVersionUID๋ฅผ ์ค์ ํ๊ณ write()๋ฅผ ํตํด ์ ์ฅ
public class User implements Serializable {
private static final long serialVersionUID = 2429090748191540600L;
private String name;
private String id;
transient String password;
public User(String name, String id, String password) {
this.name = name;
this.id = id;
this.password = password;
}
@Override
public String toString() {
return "User [name=" + name + ", id=" + id + ", password=" + password + "]";
}
}
public class Main {
private static File target = new File("C:" + File.separator + "Amenable" + File.separator + "User.dat");
public static void main(String[] args) throws IOException {
write();
}
private static void write() {
User user = new User("์ด๋ฐ๋ค", "Amenable", "1234");
try(ObjectOutputStream objOut = new ObjectOutputStream(new FileOutputStream(target))){
objOut.writeObject(user);
System.out.println("์ ์ฅ ์๋ฃ");
} catch (IOException e) {
e.printStackTrace();
}
}
}
// Userํด๋์ค์ country ์ถ๊ฐ
public class User implements Serializable {
private static final long serialVersionUID = 2429090748191540600L;
private String name;
private String id;
transient String password;
private String country;
public User(String name, String id, String password, String country) {
this.name = name;
this.id = id;
this.password = password;
this.country = country;
}
@Override
public String toString() {
return "User [name=" + name + ", id=" + id + ", password=" + password + ", country=" + country + "]";
}
}
public class Main {
private static File target = new File("C:" + File.separator + "Amenable" + File.separator + "User.dat");
public static void main(String[] args) throws IOException {
read();
}
private static void read() {
try(ObjectInputStream objIn = new ObjectInputStream(new FileInputStream(target))){
Object obj = objIn.readObject();
if(obj instanceof User) {
User user = (User) obj;
System.out.println(user);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
// User [name=์ด๋ฐ๋ค, id=Amenable, password=null, country=null]
serialVersionUID๋ฅผ ์ค์ ํ ํ ํด๋์ค๊ฐ ๋ณ๊ฒฝ๋๋ฉด ์ฐ๋ฆฌ๊ฐ ์์ํ ๊ฒ์ฒ๋ผ ๊ฐ์ ๊ฐ์ ธ์ฌ ์ ์๋ค.(User [name=์ด๋ฐ๋ค, id=Amenable, password=null, country=null])
๊ทธ๋ฌ๋ static๋ณ์๋ ์์ ๋๋ transient๊ฐ ๋ถ์ ์ธ์คํด์ค ๋ณ์๊ฐ ์ถ๊ฐ๋๋ ๊ฒฝ์ฐ์๋ ์ง๋ ฌํ์ ์ํฅ์ ๋ฏธ์น์ง ์๊ธฐ ๋๋ฌธ์ ํด๋์ค์ ๋ฒ์ ์ ๋ค๋ฅด๊ฒ ์ธ์ํ๋๋ก ํ ํ์๋ ์๋ค.
ํด๋น ๊ธ์ ๋จ๊ถ ์ฑ๋์ Java์ ์ ์์ ์ฝ๊ณ ์์ฑํ ๊ฒ์ ๋๋ค.
'๐ JAVA > ์ฃผ์ ๊ฐ๋ ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๋ง์ปค ์ธํฐํ์ด์ค (Marker Interface) (0) | 2023.03.09 |
---|---|
Parsing(ํ์ฑ) - CSV, XML, JSON (0) | 2023.01.30 |
์ ์ถ๋ ฅ(I/O)(1) - ๋ ธ๋ ์คํธ๋ฆผ, ๋ณด์กฐ ์คํธ๋ฆผ (0) | 2023.01.29 |
๋๋ค์(Lambda Expression) - (2) (0) | 2023.01.29 |
๋๋ค์(Lambda Expression) - (1) (0) | 2023.01.29 |