직렬화(Serialization)와 역직렬화(Deserialization)

-·2023년 12월 8일
0

손 타이핑을 통한 학습용 글

출처: https://gruda.tistory.com/entry/serialization-

자바에서 객체를 파일에 저장하거나 네트워크 상에서 객체를 전송하는 데 유용합니다.

Q&A

Java에서 직렬화 및 역직렬화란 무엇입니까?

자바에서 Serialization(직렬화)란 객체를 데이터 스트림으로 변환하는 것이고, Deserialization(역직렬화)란 데이터 스트림을 객체로 다시 변환하는 것입니다. 직렬화는 객체를 전송하거나 저장할 때 유용하며, 자바에서는 Serializable 인터페이스를 구현하여 직렬화를 지원합니다. 하지만 보안상의 문제를 유발할 수 있기 때문에 주의하여 사용해야 합니다.

Java에서 직렬화 및 역직렬화를 구현하는 방법은 무엇입니까?

Serializable인터페이스를 구현하여 구현할 수 있습니다. 해당 인터페이스를 구현한 클래스의 객체는 ObjectOutputStream을 이용하여 직렬화하고, ObjectInputStream을 이용하여 역직렬화 할 수 있습니다. 이를 통해 객체를 데이터 스트림으로 변환하고 다시 객체로 변환하는 과정을 수행할 수 있습니다.

직렬화(Serialization)

직렬화란 객체를 연속적인 바이트 스트림(Byte Stream)으로 변환하는 것.
즉, 객체를 메모리 상에서 상태 정보와 함께 저장할 수 있는 형태로 변환하는 것.

Serializable 인터페이스를 통해 구현한다. 이를 상속받으면 직렬화가 가능한 객체가 되며, ObjectOutputStream 클래스를 이용하여 직렬화를 수행할 수 있다.

import java.io.*;
public class Serialization implements Serializable{

    private int num;
    private String str;

    public Serialization(int num, String str) {
        this.num = num;
        this.str = str;
    }

    public static void main(String[] args) {

        Serialization obj = new Serialization(10, "Hello");

        try {
            FileOutputStream fos = new FileOutputStream("object.ser");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(obj);
            oos.close();
            fos.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

ObjectoutputStream클래스를 이용해 Serialization 객체를 파일에 저장했다.

역직렬화(Deserialization)

직렬화된 바이트 스트림을 객체로 변환하는 것. ObjectInputStream 클래스를 이용하여 저장된 파일을 열어, 객체로 변환한다.

import java.io.*;

public class Deserialization implements Serializable {
    private int num;
    private String str;

    public Deserialization(int num, String str) {
        this.num = num;
        this.str = str;
    }

    public void printData() {
        System.out.println("num : " + num + ", str : " + str);
    }

    public static void main(String[] args) {
        try {
            FileInputStream fis = new FileInputStream("Object.ser");
            ObjectInputStream ois = new ObjectInputStream(fis);
            Deserialization obj = (Deserialization)ois.readObject();
            obj.printData();
            ois.close();
            fis.close();
        } catch (IOException | ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }
}

파일을 InputStream으로 읽어들인 후 객체의 정보 출력

직렬화, 역직렬화와 네트워크 통신

직렬화와 역직렬화는 네트워크 통신에서도 사용된다.
클라이언트와 서버가 통신할 때, 클라이언트가 보낸 객체를 서버에서 사용하려면 해당 객체를 역질렬화해야 한다.

public class NetworkCommunication implements Serializable {
    private int num;
    private String str;

    public NetworkCommunication(int num, String str) {
        this.num = num;
        this.str = str;
    }

    public void printData() {
        System.out.println("num : " + num + ", str : " + str);
    }

    public void server(){
//        ServerSocket
        try {
            ServerSocket server = new ServerSocket(1234);
            System.out.println("Server started");
            while(true){
                Socket socket = server.accept();
                ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
                NetworkCommunication obj = (NetworkCommunication) ois.readObject();
                obj.printData();
                ois.close();
                socket.close();
            }
        } catch (IOException | ClassNotFoundException e) {
            throw new RuntimeException(e);
        }

    }

    public void client{
        try {
            Socket socket = new Socket("localhost", 1234);
            ObjectOutputStream oss = new ObjectOutputStream(socket.getOutputStream());
            NetworkCommunication obj = new NetworkCommunication(10, "Hello");
            oss.writeObject(obj);
            oss.close();
            socket.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {

//        ServerSocket
    }
}

클라이언트 : 객체를 직렬화하여 서버로 전송
서버 : 전송된 직렬화된 객체를 역직렬화하여 객체 상태정보 이용

보안 문제

직렬화와 역직렬화는 보안 문제가 발생할 수 있다.
네트워크 전송 간 악의적인 조작이 일어날 수 있음.

이러한 문제를 해결하기 위해 Serializable 인터페이스에서 보안성을 높이는 기능을 제공.

  • transicient 선언을 통해 직렬화 대상에서 제외시킴 .
    -> 파일이나 네트워크를 통해 전송하지 않아 보안성을 높인다.
public class SecuredCommunication implements Serializable {
    private int num;
    private String str;
    private transient String password;

    public Transient(int num, String str, String password) {
        this.num = num;
        this.str = str;
        this.password = password;
    }

    private void writeObject(ObjectOutputStream oss) throws IOException {
        oss.defaultWriteObject();
        String encryptedPassword = encrypt(password);
        oss.writeObject(encryptedPassword);
    }

    private readObject(ObjectInputStream ois) {
        ois.defaultReadObject();
        String encryptedPassword = (String) ois.readObject();
        password = decrypt(encryptedPassword);
    }

    private String encrypt(String str){
        // 암호화 코드
    }

    private String decrypt(String str){
        //복호화 코드
    }


}

writeObject와 readObject는 객체를 직렬화하거나 역직렬화 할 때 호출되는 메소드들이다. writeObject는 객체를 직렬화하기 전에 호출되며, readObject는 객체를 역직렬화한 후 호출된다.
따라서, 디크립트 된 이후 객체를 저장한다.

profile
신입 개발자의 개인 공부 공간입니다

0개의 댓글