프로그래밍 언어/JAVA

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

구루다 2023. 3. 9. 08:09
반응형

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

자바(Java) 프로그래밍 언어는 객체 지향(Object-Oriented) 언어로써 객체를 직렬화(Serialization)하거나 역직렬화(Deserialization)하는 기능을 제공합니다. 이 기능은 자바에서 객체를 파일에 저장하거나 네트워크 상에서 객체를 전송하는 데 유용합니다.

 

JAVA 10-3
JAVA 10-3

 

직렬화(Serialization)

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

자바에서 직렬화를 하려면 Serializable 인터페이스를 구현해야 합니다. Serializable 인터페이스를 구현하면 직렬화가 가능한 객체가 되며, ObjectOutputStream 클래스를 이용하여 직렬화를 수행할 수 있습니다.

import java.io.*;

class MyClass implements Serializable {
    private int num;
    private String str;

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

public class Main {
    public static void main(String[] args) {
        MyClass obj = new MyClass(10, "Hello");

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

 

위 코드에서 MyClass 클래스는 Serializable 인터페이스를 구현하고 있습니다. main 메소드에서는 MyClass 객체를 생성하고 ObjectOutputStream 클래스를 이용하여 MyClass 객체를 파일에 저장하고 있습니다.

 

반응형

 

역직렬화(Deserialization)

역직렬화(Deserialization)란 직렬화된 바이트 스트림을 객체로 변환하는 것입니다. 자바에서 역직렬화를 하려면 ObjectInputStream 클래스를 이용하여 저장된 파일을 열어 객체로 변환해야 합니다.

import java.io.*;

class MyClass implements Serializable {
    private int num;
    private String str;

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

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

public class Main {
    public static void main(String[] args) {
        try {
            FileInputStream fis = new FileInputStream("object.ser");
            ObjectInputStream ois = new ObjectInputStream(fis);
            MyClass obj = (MyClass) ois.readObject();
            obj.printData();
            ois.close();
            fis.close();
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

 

위 코드에서 main 메소드에서는 파일에서 MyClass 객체를 읽어들인 후 printData() 메소드를 호출하여 객체의 상태 정보를 출력하고 있습니다.

 

300x250

 

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

직렬화와 역직렬화는 네트워크 통신(Network Communication)에서도 사용됩니다. 클라이언트(Client)와 서버(Server)가 통신할 때, 클라이언트가 보낸 객체를 서버에서 사용하려면 해당 객체를 역직렬화해야 합니다.

import java.io.*;
import java.net.*;

class MyClass implements Serializable {
    private int num;
    private String str;

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

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

public class Server {
    public static void main(String[] args) {
        try {
            ServerSocket serverSocket = new ServerSocket(1234);
            System.out.println("Server started");
            while (true) {
                Socket socket = serverSocket.accept();
                ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
                MyClass obj = (MyClass) ois.readObject();
                obj.printData();
                ois.close();
                socket.close();
            }
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

public class Client {
    public static void main(String[] args) {
        try {
            Socket socket = new Socket("localhost", 1234);
            ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
            MyClass obj = new MyClass(10, "Hello");
            oos.writeObject(obj);
            oos.close();
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

 

위 코드에서 Server 클래스는 1234번 포트를 열어서 클라이언트의 접속을 대기하고 있습니다. 클라이언트가 접속하면 ObjectInputStream 클래스를 이용하여 객체를 역직렬화하고 객체의 상태 정보를 출력하고 있습니다.

Client 클래스에서는 Socket 클래스를 이용하여 서버에 접속하고 ObjectOutputStream 클래스를 이용하여 객체를 직렬화하여 서버로 전송하고 있습니다.

 

 

보안 문제

직렬화와 역직렬화는 강력한 기능이지만, 보안 문제(Security Concerns)가 발생할 수 있습니다. 직렬화된 객체는 파일이나 네트워크를 통해 전송될 수 있기 때문에 악의적인 사용자가 객체를 수정하거나 조작할 수 있습니다.

이러한 문제를 해결하기 위해 자바에서는 Serializable 인터페이스를 이용하여 객체를 직렬화하거나 역직렬화할 때 보안성을 높일 수 있는 기능을 제공하고 있습니다.

import java.io.*;

class MyClass implements Serializable {
    private int num;
    private String str;
    private transient String password;

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

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

 

위 코드에서 MyClass 클래스에는 password 필드가 추가되었는데, 이 필드는 transient 키워드를 사용하여 직렬화 대상에서 제외되었습니다. 이렇게 함으로써 password 필드는 직렬화되지 않아 파일이나 네트워크를 통해 전송되지 않아 보안성을 높일 수 있습니다.

또한 MyClass 클래스에는 writeObject 메서드와 readObject 메서드가 추가되었는데, 이 메서드들은 객체를 직렬화하거나 역직렬화할 때 호출되는 메서드입니다. writeObject 메서드는 객체를 직렬화하기 전에 호출되며, readObject 메서드는 객체를 역직렬화한 후에 호출됩니다.

 

import java.io.*;

class MyClass implements Serializable {
    private int num;
    private String str;
    private transient String password;

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

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

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

    private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
        ois.defaultReadObject();
        String encryptedPassword = (String) ois.readObject();
        password = decrypt(encryptedPassword);
    }

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

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

 

위 코드에서 writeObject 메서드는 defaultWriteObject 메서드를 호출한 후 password 필드를 암호화하여 출력합니다. readObject 메서드는 defaultReadObject 메서드를 호출한 후 암호화된 password 값을 복호화하여 password 필드에 저장합니다.

이렇게 함으로써 password 필드는 직렬화되지 않아 보안성이 높아지고, 암호화된 password 값을 역직렬화하여 복호화해야만 실제 값을 알아낼 수 있기 때문에 악의적인 사용자가 객체를 조작하는 것을 방지할 수 있습니다.

 

 

Q&A

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

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

 

Java에서 직렬화 및 직렬화 해제가 필요한 이유는 무엇입니까?

자바에서 Serialization(직렬화)은 객체를 데이터 스트림으로 변환하고, Deserialization(역직렬화)은 데이터 스트림을 객체로 다시 변환합니다. 이 기능은 객체를 전송하거나 저장할 때 유용하며, 자바에서는 Serializable 인터페이스를 구현하여 직렬화를 지원합니다. 이를 통해 객체를 안전하게 전송하고 저장할 수 있습니다.

 

직렬화 및 역직렬화가 사용되는 이유는 무엇입니까?

직렬화와 역직렬화는 객체를 데이터 스트림으로 변환하고 다시 객체로 변환하는 과정입니다. 이 기능은 객체를 전송하거나 저장할 때 유용하며, 자바에서는 Serializable 인터페이스를 구현하여 직렬화를 지원합니다. 이를 통해 객체를 안전하게 전송하고 저장할 수 있습니다. 또한, 직렬화된 데이터를 암호화하거나 서명하여 보안성을 높일 수 있습니다.

 

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

자바에서 Serialization(직렬화)과 Deserialization(역직렬화)은 Serializable 인터페이스를 구현하여 간단하게 구현할 수 있습니다. Serializable 인터페이스를 구현한 클래스의 객체는 ObjectOutputStream 클래스를 이용하여 직렬화하고, ObjectInputStream 클래스를 이용하여 역직렬화할 수 있습니다. 이를 통해 객체를 데이터 스트림으로 변환하고 다시 객체로 변환하는 과정을 수행할 수 있습니다.

 

 

마무리

자바에서는 객체를 직렬화하고 역직렬화하는 기능을 제공합니다. 이 기능을 이용하면 객체를 파일이나 네트워크를 통해 전송하거나 저장할 수 있습니다. 하지만 직렬화와 역직렬화는 보안 문제가 발생할 수 있기 때문에 신중하게 사용해야 합니다. 보안성을 높이기 위해 transient 키워드나 Serializable 인터페이스의 readObject와 writeObject 메서드를 이용하여 직접 제어할 수 있습니다. 또한, 직렬화된 데이터를 암호화하거나 서명하여 보안성을 높일 수 있습니다.

직렬화와 역직렬화는 자바에서 매우 유용한 기능입니다. 하지만 이 기능은 보안상의 문제를 유발할 수 있기 때문에 신중하게 사용해야 합니다. 민감한 정보를 가지고 있는 필드는 transient 키워드를 사용하여 제외하고, 객체를 직렬화하거나 역직렬화할 때는 보안성을 고려하여 readObject와 writeObject 메서드를 이용하여 데이터를 제어해야 합니다. 이렇게 함으로써 객체를 안전하게 전송하고 저장할 수 있습니다.

 

자바의 Byte Stream과 Character Stream

 

자바에서 예외(Exception) 생성 및 처리하기

 

 

자바: Checked와 Unchecked 예외(Exceptions)란?

자바: Checked와 Unchecked 예외(Exceptions)란? 자바(Java) 프로그래밍 언어에서 예외(Exception)란 실행 중에 발생할 수 있는 프로그램 오류를 의미합니다. 이 예외들은 일반적으로 프로그래머가 예상 가능

gruda.tistory.com

 

Try-Catch-Finally 블록의 활용 방법

Try-Catch-Finally 블록의 활용 방법 자바 프로그래밍에서 예외 처리는 중요한 역할을 합니다. 예외란 프로그램 실행 중 발생할 수 있는 오류로, 이를 처리하지 않으면 프로그램이 비정상적으로 종료

gruda.tistory.com

 

320x100
728x90