직렬화와 역직렬화 + 쓰레드풀과 싱글톤

MINJU·2022년 3월 20일
0

Java

목록 보기
1/7

Spring MVC를 공부하면서 이해가 부족했던 부분을 추가 공부한 내용입니다.

직렬화와 역직렬화

참조1
참조2
참조3

: Java의 I/O 처리는 정수, 문자열, 바이트 단위의 처리만 지원합니다. 따라서 복잡한 객체의 내용을 네트워크상으로 전송하기 위해서는 객체의 내용을 I/O가 처리할 수 있는 형태로 변환해주어야 합니다.

: 따라서 자바에서의 객체 직렬화는 자바의 객체를 외부로 저장/복원하거나 네트워크상으로 전송할 수 있도록 바이트 형태로 변환하는 기술을 의미합니다.
: 직렬화가 된 데이터는 언어에 따라서 텍스트 또는 바이너리 등의 형태가 되는데, 이러한 형태가 되었을 때 저장하거나 통신할 때 파싱이 가능한 유의미한 데이터가 됩니다.

: 반대로 역직렬화는 직렬화를 통해 변환된 바이트 형태를 다시 원상태인 객체로 변환시키는 기술을 의미합니다.

직렬화 조건

: java.io.Serializale 인터페이스를 상속받은 객체는 직렬화할 수 있습니다.
: java.io.ObjectOutputStream을 사용하여 직렬화를 진행합니다.

역직렬화 조건

: 직렬화 대상이 된 객체의 클래스가 클래스 패스에 존재해야하며 import 되어있어야 합니다.
: 여기서 중요한 점은 ! 직렬화와 역직렬화를 진행하는 시스템이 서로 다를 수 있다는 것입니다.
: 자바 직렬화 대상 객체는 동일한 serialVersionUID를 가지고 있어야합니다. 모델의 버전간의 호환성을 유지하기 위해서이기 때문입니다.
: 따라서 역직렬화시 반드시 예외가 생긴다는 것을 알고 개발해야합니다.
: 그래서 자주 변경되는 비즈니스적인 데이터를 자바 직렬화를 사용하지 않고, 긴 만료시간을 가지는 데이터는 json등 다른 포맷을 사용하여 저장합니다.
: 외부저장소로 저장되는 데이터는 짧은 만료시간의 데이터를 제외하고는 직렬화 사용을 지양합니다.

쓰레드풀과 싱글톤

: 쓰레드풀 내부에서 여러 쓰레드가 동작하는데 객체를 싱글톤으로 관리한다는 것이 무슨 의미인지..! 접목이 잘 안됐는데 기냥 멀티 쓰레드가 하나의 객체에 접근한다는 뜻이었습니다~... 그래서 공유변수를 조심하라고 하시는거였음

: 쓰레드 풀에서 각각의 쓰레드가 싱글톤 객체에 어떻게 접근하는지?에 대한 방법에 대한 것은 찾지 못했지만
: 직접적으로 스프링이 thread-safe한지에 대해 코드로 구현해놓은 참조 블로그를 찾았습니다.
: 이 코드를 통해 싱글톤에서 공유 변수를 주의하라는 말에 대해 다시금 이해할 수 있게 되었습니다.
참조 블로그

public class Singleton {
    private static Singleton singleton = new Singleton();
    private Singleton(){}

    public static Singleton getInstance(){
        return singleton;
    }

    public int add(int num){
        return ++num;
    }
}

class AddTest{
    public static void main(String[] args) {
        Singleton instance = Singleton.getInstance();
        int array[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
        for (int i : array) {
            new Thread(()->{
                System.out.println(instance.add(i));
            }).start();
        }
    }
}

결과는 다음과 같습니다. 순서는 다르지만 빠짐없이 출력되었음을 확인할 수 있습니다.

하지만 전역변수가 있는 싱글톤 객체를 이용한다면

public class Singleton {
    int num;
    private static Singleton singleton = new Singleton();
    private Singleton(){}

    public static Singleton getInstance(){
        return singleton;
    }

    public int add(){
        return ++num;
    }
}

class AddTest{
    public static void main(String[] args) {
        Singleton instance = Singleton.getInstance();
        int array[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
        for (int i : array) {
            new Thread(()->{
                System.out.println(instance.add());
            }).start();
        }
    }
}


다음과 같이 결과에 문제가 생김을 확인할 수 있습니다. 이 경우엔 Thread-safe하지 못하다고 할 수 있습니다.

결론적으로 스프링 빈을 상태를 변경할 수 있도록 세팅한다면 thread-safe하지 않다고 볼 수 있습니다.

0개의 댓글