직렬화(Serialization)란?
직렬화(Serialization)는 객체를 데이터 스트림으로 변환하는 과정을 말합니다. 이 과정을 통해 객체는 파일에 저장하거나 네트워크를 통해 전송될 수 있습니다. 주로 Java에서 많이 사용되며, 객체의 상태를 영속적으로 저장하거나 다른 시스템 간에 객체를 전송할 때 유용하게 활용됩니다.
사용 방법
- Java에서는 java.io.Serializable 인터페이스를 구현한 클래스만 직렬화할 수 있습니다. 이 인터페이스는 메소드를 가지지 않지만, 마킹 인터페이스로서 직렬화 가능하다는 표시를 합니다.
import java.io.Serializable;
public class Person implements Serializable {
private String name;
private int age;
// 생성자, getter, setter
}
직렬화의 과정
- 객체를 직렬화하기 위해서는 ObjectOutputStream 클래스를 사용합니다. 이 클래스는 객체를 출력 스트림으로 보내고, writeObject() 메소드를 사용하여 객체를 직렬화합니다.
import java.io.*;
public class SerializationExample {
public static void main(String[] args) {
Person person = new Person("Alice", 30);
try (FileOutputStream fos = new FileOutputStream("person.ser");
ObjectOutputStream oos = new ObjectOutputStream(fos)) {
oos.writeObject(person); // 객체 직렬화
System.out.println("Person 객체를 직렬화하여 저장했습니다.");
} catch (IOException e) {
e.printStackTrace();
}
}
}
역직렬화(Deserialization)란?
- 역직렬화는 직렬화된 데이터를 다시 객체로 변환하는 과정입니다. 이 과정을 통해 직렬화된 객체를 다시 메모리에 올릴 수 있습니다.
- Java에서는 ObjectInputStream 클래스를 사용하여 역직렬화를 수행합니다. readObject() 메소드를 사용하여 바이트 스트림에서 객체를 역직렬화합니다.
public class DeserializationExample {
public static void main(String[] args) {
try (FileInputStream fis = new FileInputStream("person.ser");
ObjectInputStream ois = new ObjectInputStream(fis)) {
Person person = (Person) ois.readObject(); // 객체 역직렬화
System.out.println("역직렬화된 Person 객체: " + person);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
주의사항
- 직렬화된 데이터는 파일에 저장되거나 네트워크를 통해 전송될 수 있습니다. 따라서 보안과 관련된 중요한 정보가 포함된 객체는 직렬화하지 않는 것이 좋습니다.
- 직렬화할 클래스는 Serializable 인터페이스를 반드시 구현해야 합니다. 이 인터페이스를 구현하지 않으면 java.io.NotSerializableException이 발생할 수 있습니다.
- 직렬화된 클래스의 필드가 변경되면 직렬화된 데이터와의 호환성 문제가 발생할 수 있습니다. 이를 방지하기 위해 직렬화 버전 UID(serialVersionUID)를 명시적으로 설정하는 것이 좋습니다.
private static final long serialVersionUID = 1L;
직렬화는 Java에서 객체를 파일에 저장하거나 네트워크를 통해 전송하는 등의 유연한 데이터 관리 기능을 제공합니다. 하지만 데이터의 보안, 버전 관리 등에 유의하여 사용해야 합니다.
직렬화 사용 이유 및 예시
직렬화(Serialization)는 다양한 이유로 사용되며, 주로 객체의 상태를 영속화하거나 네트워크를 통해 객체를 전송하는 데 유용합니다. 여기에 대한 몇 가지 주요 사용 예시를 소개합니다:
1. 객체의 영속화(Persistence)
일반적으로 메모리에 있는 객체는 프로그램이 종료되면 사라집니다. 하지만 객체를 직렬화하여 파일에 저장하면 프로그램이 종료되어도 객체의 상태를 유지할 수 있습니다. 이는 다음과 같은 경우에 유용합니다:
- 데이터베이스와의 연동: 객체를 데이터베이스에 저장할 때 직렬화된 형태로 저장하거나, 데이터베이스에서 객체를 가져올 때 역직렬화하여 메모리에 다시 올릴 수 있습니다.
- 설정 정보 저장: 프로그램 설정 정보를 파일에 저장하여 다음 실행 시에도 불러와 사용할 수 있습니다.
2. 네트워크 통신(Network Communication)
직렬화는 객체를 바이트 스트림으로 변환하여 네트워크를 통해 다른 시스템으로 전송할 수 있습니다. 이는 분산 시스템에서 중요한 역할을 합니다:
- 클라이언트-서버 통신: 서버에서 객체를 직렬화하여 클라이언트로 전송하거나, 클라이언트에서 서버로 직렬화된 객체를 전송하여 상호작용할 수 있습니다.
- 웹 서비스: 웹 서비스에서 객체를 XML이나 JSON 형식으로 직렬화하여 전송하는 경우가 많습니다.
// 객체 직렬화 및 네트워크 전송 예제
import java.io.*;
import java.net.*;
public class SerializationNetworkExample {
public static void main(String[] args) {
try {
// 서버 소켓 생성
ServerSocket serverSocket = new ServerSocket(12345);
System.out.println("서버가 시작되었습니다.");
// 클라이언트 접속 대기
Socket clientSocket = serverSocket.accept();
System.out.println("클라이언트가 접속했습니다.");
// 직렬화된 객체를 전송받아 역직렬화
ObjectInputStream ois = new ObjectInputStream(clientSocket.getInputStream());
Person receivedPerson = (Person) ois.readObject();
System.out.println("받은 객체: " + receivedPerson);
// 클라이언트 소켓 및 서버 소켓 닫기
ois.close();
clientSocket.close();
serverSocket.close();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
3. 객체 전송과 복제
직렬화를 사용하면 객체를 복제하거나 전송할 수 있습니다. 예를 들어, 한 시스템에서 생성된 객체를 직렬화하여 다른 시스템으로 전송하고, 그곳에서 역직렬화하여 동일한 객체를 사용할 수 있습니다.
- 클러스터링(Clustering): 여러 서버 사이에서 객체를 공유하거나 전송할 때 유용하게 사용됩니다.
- 분산 환경에서의 데이터 동기화: 분산 시스템에서 객체의 동기화를 위해 직렬화된 데이터를 사용할 수 있습니다.
// 객체 직렬화 및 복제 예제
public class ObjectCloningExample {
public static void main(String[] args) {
Person originalPerson = new Person("Alice", 30);
// 객체를 복제하기 위해 직렬화 후 역직렬화
Person clonedPerson = deserialize(serialize(originalPerson));
System.out.println("복제된 객체: " + clonedPerson);
}
// 객체 직렬화 메소드
private static byte[] serialize(Object obj) {
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos)) {
oos.writeObject(obj);
return bos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
// 객체 역직렬화 메소드
private static Object deserialize(byte[] data) {
try (ByteArrayInputStream bis = new ByteArrayInputStream(data);
ObjectInputStream ois = new ObjectInputStream(bis)) {
return ois.readObject();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
return null;
}
}
}
직렬화(Serialization)의 주요 장점
- 객체의 영속화(Persistence):
- 직렬화를 통해 객체를 파일에 저장하고, 나중에 필요할 때 다시 역직렬화하여 메모리에 로드할 수 있습니다. 이는 프로그램의 실행 상태를 영구적으로 저장할 수 있게 해줍니다.
- 네트워크 통신(Network Communication):
- 직렬화된 객체는 네트워크를 통해 전송할 수 있습니다. 이는 분산 시스템에서 다른 시스템 간에 객체를 주고받거나 공유하는 데 매우 유용합니다.
- 다양한 데이터 형식으로 변환:
- 직렬화를 통해 객체를 바이트 스트림으로 변환할 수 있기 때문에, 이를 다양한 형식(XML, JSON 등)으로 변환하여 사용할 수 있습니다. 예를 들어, 웹 서비스에서 JSON 형식으로 직렬화하여 클라이언트에게 전송할 수 있습니다.
- 객체 복제(Clone):
- 직렬화를 통해 객체를 복제할 수 있습니다. 객체를 직렬화한 후에 역직렬화하면 동일한 객체를 얻을 수 있습니다. 이는 객체의 깊은 복사(deep copy)를 구현하는 데 유용합니다.
- 다형성과 유연성:
- 직렬화를 사용하면 상속 계층 구조에서도 다형성을 유지하면서 객체를 전송하거나 저장할 수 있습니다. 즉, 상위 클래스 타입으로 여러 하위 클래스의 객체를 다룰 수 있습니다.
- 캐싱과 성능 향상:
- 직렬화된 데이터는 캐시에 저장하거나 전송하면서 성능을 향상시킬 수 있습니다. 특히 반복적인 데이터 전송이 필요한 시스템에서 유용합니다.
- 데이터의 보안성 향상:
- 직렬화된 데이터는 암호화하여 전송할 수 있습니다. 이는 데이터의 보안성을 높이는 데 도움을 줍니다.
이러한 장점들로 인해 직렬화는 객체 지향 프로그래밍에서 데이터 관리와 네트워크 통신을 효율적으로 처리하는 중요한 기술이 되고 있습니다.
'Programming > Java, Kotlin' 카테고리의 다른 글
[Java] Exception 예외처리란? 예외처리 종류, 예시, 장단점 (0) | 2024.06.22 |
---|---|
[Java] 컬렉션 프레임워크(Collection Framework), 동시성 컬렉션(concurrent collection) 이란? 장단점, 차이 (0) | 2024.06.22 |
[Java] OOPS란? 객체지향 프로그래밍(OOP, Object-Oriented Programming) 개념 (0) | 2024.06.22 |
[Java] Immutability(불변성)이란? Immutability 특징, 사용 예시, 장점 (0) | 2024.06.22 |
[Java] hashCode, equals 메소드 정의, 차이 (0) | 2024.06.22 |