Serialization & Deserialization

bearMin·2024년 7월 22일

들어가면서

데이터의 전송 방법에 대해서 공부를 했었는데, 그때 눈에 띈 단어가 있었다. 바로 직렬화이다. 이 직렬화가 무엇이고 왜 써야하는지에 대해서 알아보자!


직렬화(Serialization)란?

정의는?

메모리를 디스크에 저장하거나, 네트워크 통신에 사용하기 위한 형식으로 변환하는 것

조금 더 간단하게 말해보자면 내가 어떠한 데이터를 다른 곳에 저장하기 위해서 그에 맞는 형식으로 반환을 해주는 것이다.


필요한 이유는?

정의에서 이해가 조금 안되는 것들이 있을 것이다. 다른 곳에 그대로 저장하면 되는 거 아닌가? 왜 꼭 형식을 바꿔서 저장을 해야하지? 라는 의문들이 있을텐데 지금부터 하나씩 설명을 해보겠다.


우리가 개발을 할 때 사용하는 메모리의 구조는 크게 2가지이다.

첫번째로는 값 형식 데이터이다. 이 값 형식 테이터는 int, char 등 스택에 메모리가 쌓이고 직접 접근이 가능하다. 때문에 디스크에 저장하거나 통신을 할 때 직접적으로 사용이 가능하다.

그렇다면 그냥 저장하면 되는 것이 아닌가? 라는 생각을 할 수 있지만 우리의 메모리 구조는 전부 값 형식 데이터가 아니다.


두번째로는 참조 형식 데이터이다. 우리가 직렬화를 사용해야하는 이유는 바로 이 참조 형식 데이터 때문이다.

참조 형식 데이터는 실제 데이터 값이 아닌 힙이라는 동적 메모리 공간에 할당되어 있는 메모리 번지 주소를 가지고 있기 때문에 저장을 하거나 통신을 할 때 사용이 불가능하다.


불가능한 이유는 주소값을 파일에 저장하기 때문인데, 이 주소값을 넘겨준다고 해서 다른 pc에서 똑같은 주소에 같은 메모리가 존재하지 않으며 프로그램을 종료하고 재시작 할 경우 사라지는 휘발성의 성질을 가지고 있기 때문이다.

따라서 우리는 직렬화라는 과정을 통해서 참조 형식 데이터를 저장 또는 통신을 하고 유의미한 데이터가 되도록 한다!


역직렬화(Deserialization)란?

정의는?

디스크에 저장한 데이터를 읽거나, 네트워크 통신으로 받은 데이터를 메모리에 쓸 수 있도록 변환하는 것

위에서 열심히 설명한 직렬화에 대해 감을 잡았다면 사실 역직렬화는 크게 설명할 것이 없다. 직렬화를 반대로 한 과정이 역직렬화이기 때문이다. 직렬화와 역직렬화는 암호화와 복호화처럼 하나의 과정을 반대로 한다고 생각하면 된다.

즉, 열심히 직렬화를 해서 데이터를 저장하거나 통신을 했다면 데이터를 가져와서 읽거나 통신해서 데이터를 받았을 때 읽을 수 있도록 데이터를 원래 상태로 변환하는 것을 의미한다.


직렬화의 종류는?

사람이 읽을 수 있는 형태?

직렬화를 해도 사람이 읽을 수 있는 형태가 있고 읽을 수 없는 형태가 있다. 그 중 읽을 수 있는 형태에 대해서 먼저 설명을 해보겠다.

우선 예시로는 CSV, XML, JSON이 있다. XML과 JSON이 바로 여기서 나온다..!

이러한 방식의 직렬화는 저장공간의 효율성이 떨어진다. 때문에 데이터의 양이 적을 경우 주로 사용을 하게 된다.

추가로, 최근에는 JSON 형태를 통해 데이터를 직렬화한다고 한다. JSON의 장점을 알아보고 싶다면 여기로


사람이 읽을 수 없는 형태?

직렬화를 해서 사람이 읽을 수 없는 형태의 예시로는 Binary가 있다.

이는 저장공간을 효율적으로 사용할 수 있으며 데이터의 양이 많을 때 주로 사용이 된다.


Java 직렬화?

사실 Java 직렬화를 얘기하기 위해서 이렇게 먼 길을 돌아왔다.. 미안하다 이거 보여주고 싶어서 어그로 끌었..

Java의 직렬화에 대해서는 아래서 더 자세하게 알아보자!


Java 직렬화란?

정의는?

Java 시스템 내부에서 사용되는 객체 또는 데이터를 외부의 Java 시스템에서도 사용할 수 있도록 Byte 형태로 데이터를 변환하는 기술이다.

Java에서 입출력은 Stream이라는 통로를 통해 이동을 하게 된다. 하지만 객체는 Byte형이 아니기 때문에 Stream을 통해서 파일에 저장을 하거나 전송을 할 수 없다.

따라서 객체를 Stream을 통해 입출력을 하려면 Byte 배열로 변환을 하게 되는데, 이를 Java 직렬화라고 한다!

그렇다면 역직렬화는 무엇일까? 맞다. Byte 배열을 원래 객체로 되돌리는 과정역직렬화라고 한다!


왜 사용할까?

위에서 얘기했지만 직렬화에는 여러 종류가 있다. 그런데 Java 직렬화를 써야하는 이유는 무엇일까?

그 이유는 Java 직렬화의 장점과도 연관이 있는데, Java 시스템 간의 직렬화 형태의 데이터 교환을 위해서 라고 볼 수 있다.

이게 무슨 뜻이냐하면 CSV나 XML, JSON의 형식을 사용해서 데이터를 교환할 경우 그 값들을 Java 객체로 변환하는 과정이 필요하다. 단순 JSON 만으로 Java에서는 사용을 못하기 때문이다. 하지만 Byte 배열로 전달이 된다면 역직렬화를 했을 때 기존의 객체처럼 바로 사용이 가능하다!

데이터의 타입이 맞춰지며 관련에 대해서 크게 신경을 쓰지 않아도 되기 때문에 개발자의 입장에서는 매우 편해지게 된다!


주의할 점은?

그렇다면 Java 직렬화와 역직렬화를 사용하면서 생각을 해야할 부분은 무엇일까?

  1. 용량이 큼
    직렬화는 객체에 저장된 데이터값 뿐만 아니라 타입 등 메타 데이터를 가지고 있어 용량을 많이 차지하게 된다. 때문에 너무 큰 객체는 직렬화를 사용하지 않는 것이 좋다.

  2. 엄격한 타입 체크
    객체의 변수명은 동일하지만 변수의 타입이 달라지면 타입 예외가 발생한다. 직렬화한 데이터의 객체 변수 타입을 도중 바꾼다면 역직렬화가 불가능해진다.

  3. 클래스 구조의 변경
    모델의 버전 간의 호환성을 유지하는 SUID를 정의해야한다. 이 값이 동일할 경우 직렬화와 역직렬화에 문제가 없다.

    💡 SUID(SerialVersionUID)란?
    Java 직렬화 대상의 객체는 동일한 SerialVersionUID를 가지고 있어야하며, 이를 선언하지 않을 경우 
    내부적으로 클래스의 구조 정보를 이용하여 자동으로 생성된 해시값이 할당된다.

    이때, 클래스의 멤버 변수가 변경이 되면 SUID가 달라지고 에러가 발생한다.

  4. 외부 저장소로 저장되는 데이터는 사용을 지양
    외부 저장소에 오랫동안 저장이 될 경우 이 직렬화된 데이터는 결국 쓰레기값이 될 가능성이 있으며, 이는 시스템에 오류를 발생시킬 수 있다. 이와 비슷하게 긴 만료 시간을 가지는 데이터라면 JSON 등 다른 포맷을 사용하여 저장하는 것이 좋다.


이외에도 여러가지 단점이 있다. 사실 사용을 안하는데에는 다 이유가 있다. 특히 이 기술의 단점은 보완하기 힘든 형태로 되어있어 사용시 많은 제약들이 걸린다..

때문에 다른 대안이 있다면 그 대안을 사용하고 최대한 Java 직렬화와 역직렬화는 사용을 피하는 것이 좋다.


정리하자면

직렬화데이터를 저장하거나 통신을 하기 위해 정해진 포맷으로 변경하는 것이다!

Java 직렬화는 최대한 사용을 피하자!

profile
소소한 공부기록

0개의 댓글