직렬화(Serialization) 와 transient 키워드

# Serialization

직렬화 (Serialization)으로 검색해서 나온 정보들은 종합해 보면 대부분 같습니다.

직렬화란 오브젝트를 데이터스트림에 쓰기 위해 연속적인(serial) 바이트로 변환 하는것을 말한다.

Java에서 직렬화가 가능한 것은

  1. 원시타입 객체
  2. Serializable 인터페이스를 implements 한 오브젝트
  3. Serializable 인터페이스를 implements 한 클래스나 인터페이스를 상속/구현 한 오브젝트

개념이 좀 안잡히니 예를 들어보겠습니다.
내가 생성한 User 객체를 Disk에 저장하려고 합니다.
User.java에는 String type의 _username_과 password 를 정의했습니다.

usernamepassword 를 파일로 저장하고 싶으면 간단히 파일을 열고 해당값을 저장하는 프로그램을 작성하면 됩니다.

하지만 usernamepassword 의 값이 포함된 상태의 User ** 객체 자체 ** 를 저장하고 싶다면 어떻게 해야 할까요?

상식적으로 생각해봐도 파일에 User 객체를 쓰기는 쉽지 않을것 같은데 이렇게 객체를 데이터 스트림에 쓰기 위한 작업을 ** 직렬화 ** 라는 과정을 통해 가능하게 만들어 주는것 입니다.

Q : 그렇다면 transient 키워드는 무엇인가요?

A : transient 키워드를 붙인 변수는 직렬화 대상에서 제외 됩니다.

어렵게 생각할 필요가 없습니다. 데이터를 디스크에 저장하거나 디비에 저장하거나 http request를 통해 보내거나 할때 민감한 데이터(개인정보등)은 제외하고 싶으면 transient를 붙이면 되는것 입니다.
(참고로 JPA (or hibernate)의 도메인(모델) 에는 @transient 라는 어노테이션을 붙이게 되면 DB의 값과 맵핑시키지 않습니다.)

아래 예제는 User 클래스를 객체로 만들고 직렬화/역직렬화 해보는 예제 입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

public class User implements Serializable {

private static final long serialVersionUID = 1000000000000001L;

private String username;
private transient String password;

public User(String username, String password){
this.username = username;
this.password = password;
}

public String getUsername() {
return username;
}

public String getPassword() {
return password;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

public class UserTest {

@Test
public void transientField() throws IOException, ClassNotFoundException {
final User user = new User("Rafael", "secret321");

final FileOutputStream fos = new FileOutputStream("/tmp/user");
final ObjectOutputStream oos = new ObjectOutputStream(fos);

oos.writeObject(user);
oos.flush();
oos.close();
fos.close();

final FileInputStream fis = new FileInputStream("/tmp/user");
final ObjectInputStream ois = new ObjectInputStream(fis);

final User deserialized = (User) ois.readObject();

assertEquals("Rafael", deserialized.getUsername());
assertNull(deserialized.getPassword()); //password는 transient 키워드가 붙어있으므로 넘어오지 않았음.
}
}
Share