ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [ JAVA ] 내가 생각하는 직렬화. 왜 직렬화를 사용하는 걸까?
    PROGRAMMING/JAVA 2022. 12. 22. 02:10

    하루입니다.

     


     

     

    자바의 입출력을 다루다가 '직렬화' 를 배웠다. 정확히는 객체를 출력하기 위해서는 ObjectOutputStream을 사용하고, 이를 위해서는 객체를 직렬화해야 한다고 한다. 

     

    직렬화가 뭔데?

     

    정말 간단히 말하자면 객체를 바이트로 변환하는 것이다.

     

    왜?

     

    자바에서 객체 내부 내용을 파일에 저장하거나 네트워크를 통해 전송하기 위해서는 일일히 바이트로 분해하는 작업이 필요하기 때문이다. (직렬화객체 Stream들이 그 역할을 대신 해 주는 거고)

     

    왜?

     

    왜 객체 내부 내용을 바로 보내면 안 되는데?

     

    이에 대한 답을 오키의 누군가가 적어주셨다.

     

     


     

     

    - 데이터의 메모리 구조는 크게 값과 오브젝트 두 가지로 나뉜다.

    - 은 integer 이런 거. Stack 영역에 직접 값을 가지고 있다.

    - object(reference) 형식 데이터는 메모리 주소를 가진다. 자바에서 class의 인스턴스는 해당 프로세스의 메모리 상에서만 유효한 번지 주소를 가지는 object(reference) 데이터이다. Heap 영역의 객체 주소 Stack 영역에 갖고 있다.

    - 이 중, '저장/전송 가능한 데이터' 는 값 형식 데이터이다. 생각해보면 당연한 게(물론 당연한 건 없지만) 메모리 번지 주소를 참조하는 참조 형식 데이터를 저장하면 ... 누굴 참조할 거고 ... 네트워크 전송시키면 참조를 또 어떻게 할 것이고 ... 
    - 만약 class A의 instance를 만들고 그 참조값을 강제로 같이 저장/전달한다고 하자. 그 파일을 열었을 때 참조값을 다시 읽어와도 instance는 부활할 수 없는 쓰레기값이다.

    - 네트워크 전송 역시 마찬가지이다. 물리적으로 사용중인 메모리 공간이 일치하지 않기 때문이다.

     

    - 자바는 내부적으로 오브젝트(또는 Reference) 형식의 데이터를 많이 한다. 그리고 오브젝트의 주소 메모리 번지 값 접근/편집을 일반적인 JAVA 코딩에 쓰지 않는다. (언어 차원에서 내부적으로 해결 해 줌) 생각해보니까 굳이굳이 메모리값을 편집하는 일은 없었다. 해시코드도 주소값이 아닌 메모리 번지를 사용해 알고리즘을 돌린 정수값이니까, 직접 주소값을 조회하는 게 아니다.
    - 또한 자바는 객체 내부 객체가 가능하다. 이는 오브젝트 안에 다른 오브젝트를 참조할 수 있는 주소값이 담긴 것을 의미한다.

    - 이 주소값의 실체를 다 끌어와서 Primitive(원시) 한 값 형식 데이터로 전부 변조하는 작업을 바로 직렬화(Serialization)라고 한다.
    - 그리고 직렬화 된 데이터 형식은 언어에 따라 텍스트로 된 데이터 또는 바이너리 등의 모양을 띄게 된다. (어차피 텍스트든 바이너리든 결국 둘 다 Primitive 한 값들의 집합임) (약간 추상화 개념인가?)

    - 결국 직렬화가 된 데이터는 최종적으로 오브젝트 타입이 없다. 모든것이 Primitive 한 값 형식의 데이터 묶음이며, 이것은 파일 저장이나 네트워크 전송시 파싱 할 수 있는 유의미한 데이터가 된다. (데이터 중복을 줄이기 위한 테이블화가 일어나는지는 확인 필요. 어차피 이 부분은 언어마다, 규약마다 다를 것)


    - 그리고 또하나 특징은 현존하는 컴퓨터 머신들의 메모리 설계상 큰 데이터 덩어리를 순차적으로 읽어 오는 것이 가장 빠르기 때문에 직렬화 된 데이터는 RDBMS 구조랑은 완전 다르게, 일직선의 연속적인 값들의 집합인 형태를 띄게 된다. (이것도 언어/규약 마다 다를 수 있다)

    - 그래서 이렇게 전송/저장 가능한 데이터를 만드는 행위에 '직렬화(Serialization)' 라는 이름이 붙게 되었습니다.

    - 정리하면 직렬화는 보통 파일 저장이나, 패킷 전송시에 '파싱할 수 있는 데이터를 만들기 위해' 사용됩니다.

    +@ 로 프로세스 간에 데이터 전송에도 직렬화된 데이터가 사용 되는 이유는
    대부분의 OS 가 현재 가상메모리를 운영 중이며 대부분의 OS 의 프로세스 구현은 서로 다른 가상메모리주소공간(Virtual Address Space, VAS) 를 갖기 때문에 역시 마찬가지로 오브젝트 타입의 참조값(결국 주소값)데이터 인스턴스를 직접 줄 수 없어서 직렬화된 데이터로의 교환을 주로 사용한다.

     

     

     


     

    위 게시글의 또다른 답변

     

     서버가 다중화(여러개존재) 되어 있고 세션 클러스터링을 통해 세션관리를 하는 환경에서 도메인 객체가 세션에 저장이 될때 도메인 객체에 Serializable 인터페이스 클래스를 구현하기(implements) 해야지 정상적으로 세션에 저장하고 꺼내올수 있기 때문입니다.

     

     도메인 객체가 세션에 저장하지 않는 단순한 데이터 집합이고 컨트롤러에서 생성되어서 뷰에서 소멸하는 데이터의 전달체라면 객체 직렬화는 고려하지 않아도 되는 부분입니다. 그리고 중간에 패턴 이야기가 나왔는데 메멘토 나 프록시 패턴에서 사용하는 객체는 도메인 객체의 성격보다는 메소드와 데이터를 포함하는 일반적인 객체 형태라서 질문하신 도메인 객체의 직렬화와 다른 내용인것 같아서 덧 붙입니다. 그런 점에서 보면 생각하지 않고 다른 코드에 적용되어 있으니 관습적으로 Serializable 를 구현한 도메인 객체를 많이 보시게 될거에요.

     

     

     


     

     

    배달의 민족 : 자바 직렬화, 그것이 알고 싶다

    • 자바 직렬화란 자바 시스템 내부에서 사용되는 객체 또는 데이터를 외부의 자바 시스템에서도 사용할 수 있도록 바이트(byte) 형태로 데이터 변환하는 기술과 바이트로 변환된 데이터를 다시 객체로 변환하는 기술(역직렬화)을 아울러서 이야기합니다.
    • 시스템적으로 이야기하자면 JVM(Java Virtual Machine 이하 JVM)의 메모리에 상주(힙 또는 스택)되어 있는 객체 데이터를 바이트 형태로 변환하는 기술과 직렬화된 바이트 형태의 데이터를 객체로 변환해서 JVM으로 상주시키는 형태를 같이 이야기합니다.
    • 자바 직렬화 형태의 데이터 교환은 자바 시스템 간의 데이터 교환을 위해서 존재한다.

     

     

    자바 직렬화의 장점

    • 자바 직렬화는 자바 시스템에서 개발에 최적화되어 있습니다.
    • 복잡한 데이터 구조의 클래스의 객체라도 직렬화 기본 조건만 지키면 큰 작업 없이 바로 직렬화를 가능합니다. 물론 역직렬화도 마찬가지입니다.
    • 데이터 타입이 자동으로 맞춰지기 때문에 관련 부분을 큰 신경을 쓰지 않아도 됩니다. 그렇게 역직렬화가 되면 기존 객체처럼 바로 사용할 수 있게 됩니다. 

     

     

    자바 직렬화의 단점

    • 외부(DB, 캐시 서버, NoSQL 서버 등)에 장기간 저장될 정보는 자바 직렬화 사용을 지양해야 합니다. 역직렬화 대상의 클래스가 언제 변경이 일어날지 모르는 환경에서 긴 시간 동안 외부에 존재했던 직렬화된 데이터는 쓰레기(Garbage)가 될 가능성이 높습니다. 언제 예외가 발생할지 모르는 지뢰 시스템이 될 수도 있습니다.
    • 개발자가 직접 컨트롤이 가능한 클래스의 객체가 아닌 클래스의 객체에 대해서는 직렬화를 지양해야 합니다
    • 긴 시간 동안 외부에 저장하는 의미 있는 데이터들은 자바 직렬화를 사용하지 않아야 합니다.
    • 기본적으로 타입에 대한 정보 등 클래스의 메타 정보도 가지고 있기 때문에 상대적으로 다른 포맷에 비해서 용량이 큰 문제가 있습니다.
    • 자바 직렬화를 사용할 때에는 될 수 있으면 자주 변경되는 클래스의 객체는 사용 안 하는 것이 좋습니다. 변경에 취약하기 때문에 생각지도 못한 예외사항들이 발생할 가능성이 높습니다. 특히 역직렬 화가 되지 않을 때와 같은 예외처리는 기본적으로 해두는 것을 추천합니다.

     

     

    자바 직렬화는 언제(when) 어디서(where) 사용되나요?

    • JVM의 메모리에서만 상주되어있는 객체 데이터를 그대로 영속화(Persistence)가 필요할 때 사용됩니다.
      시스템이 종료되더라도 없어지지 않는 장점을 가지며 영속화된 데이터이기 때문에 네트워크로 전송도 가능합니다.
      그리고 필요할 때 직렬화된 객체 데이터를 가져와서 역직렬 화하여 객체를 바로 사용할 수 있게 됩니다.
      그런 특성을 살린 자바 직렬화는 많은 곳에서 이용됩니다. 많이 사용하는 부분 몇 개만 이야기해보겠습니다.

     

    • 서블릿 세션 (Servlet Session)
      서블릿 기반의 WAS(톰캣, 웹로직 등)들은 대부분 세션의 자바 직렬화를 지원하고 있습니다. 물론 단순히 세션을 서블릿 메모리 위에서 운용한다면 직렬화를 필요로 하지 않지만, 파일로 저장하거나 세션 클러스터링, DB를 저장하는 옵션 등을 선택하게 되면 세션 자체가 직렬화가 되어 저장되어 전달됩니다. (그래서 세션에 필요한 객체는 java.io.Serializable 인터페이스를 구현(implements) 해두는 것을 추천합니다.) 

     

    • 캐시 (Cache)
       DB를 조회한 후 가져온 데이터 객체 같은 경우 실시간 형태로 요구하는 데이터가 아니라면 메모리, 외부 저장소, 파일 등을 저장소를 이용해서 데이터 객체를 저장한 후 동일한 요청이 오면 DB를 다시 요청하는 것이 아니라 저장된 객체를 찾아서 응답하게 하는 형태를 보통 캐시를 사용한다고 합니다. 캐시를 이용하면 DB에 대한 리소스를 절약할 수 있기 때문에 많은 시스템에서 자주 활용됩니다. 이렇게 캐시 할 부분을 자바 직렬화된 데이터를 저장해서 사용됩니다. 물론 자바 직렬 화만 이용해서만 캐시를 저장하지 않지만 가장 간편하기 때문에 많이 사용됩니다.

     

    • 자바 RMI(Remote Method Invocation)
      자바 RMI는 원격 시스템 간의 메시지 교환을 위해서 사용하는 자바에서 지원하는 기술이다. 보통은 원격의 시스템과의 통신을 위해서 IP와 포트를 이용해서 소켓통신을 해야 하지만 RMI는 그 부분을 추상화하여 원격에 있는 시스템의 메서드를 로컬 시스템의 메서드인 것처럼 호출할 수 있습니다. 원격의 시스템의 메서드를 호출 시에 전달하는 메시지(보통 객체)를 자동으로 직렬화 시켜 사용됩니다. 그리고 전달받은 원격 시스템에서는 메시지를 역직렬화를 통해 변환하여 사용됩니다.

    결론

    장점 많지만 단점 보완이 힘들다. 작성자님은 아래의 원칙을 따르신다고 한다.

    1. 외부 저장소로 저장되는 데이터는 짧은 만료시간의 데이터를 제외하고 자바 직렬화를 사용을 지양합니다.
    2. 역직렬화시 반드시 예외가 생긴다는 것을 생각하고 개발합니다.
    3. 자주 변경되는 비즈니스적인 데이터를 자바 직렬화을 사용하지 않습니다.
    4. 긴 만료 시간을 가지는 데이터는 JSON 등 다른 포맷을 사용하여 저장합니다.

     

     


     

     

    내가 생각한 결론

    • 직렬화는 JVM의 메모리에 상주하는 객체를 바이트 형식으로 바꾸거나, 혹은 그 반대의 것을 뜻한다. 
    • 객체는 참조하는 값이 있다. 컴퓨터마다 물리적으로 사용 중인 데이터 공간이 다르기에 참조값을 강제로 줘봤자 다른 곳에서는 사용이 불가한 쓰레기 값이다. (그런데 파일로 저장할 때는 내 컴퓨터고 내 공간인데도 다른 걸까?)
    • 그래서 객체를 바이트 형태로 바꾸어서 보낸다. ( 내 생각 : 원시값이기에 각각의 컴퓨터에 깔린 OS나 IDE가 알아서 실행 가능하지 않을까? 추상화처럼?)
    • 객체를 파싱하기 위해 직렬화한다!!! 

     

     

     

     

    틀린 정보 지적 환영!!!

     

    감사합니다!!!

     

     


     

     

     

    출처 (참고자료)

    자바의 정석 기초

    선생님의 강의자료

     

    https://zeroco.tistory.com/17

     

    [JAVA] 객체의 직렬화, ObjectOutputStream, ObjectInputStream

    직렬화(Serialize) 란? 자바 시스템 내부에서 사용되는 Object 또는 Data를 외부의 자바 시스템에서도 사용할 수 있도록 byte 형태로 데이터를 변환하는 기술. JVM(Java Virtual Machine 이하 JVM)의 메모리에 상

    zeroco.tistory.com

     

    https://techblog.woowahan.com/2550/

     

    자바 직렬화, 그것이 알고싶다. 훑어보기편 | 우아한형제들 기술블로그

    {{item.name}} 자바의 직렬화 기술에 대한 대한 이야기입니다. 간단한 질문과 답변 형태로 자바 직렬화에 대한 간단한 설명과 직접 프로젝트를 진행하면서 겪은 경험에 대해 이야기해보려 합니다.

    techblog.woowahan.com

     

    https://docs.oracle.com/javase/8/docs/platform/serialization/spec/serial-arch.html

     

    Java Object Serialization Specification: 1 - System Architecture

    CONTENTS | PREV | NEXT Java Object Serialization Specification version 6.0 System Architecture <!-- --> CHAPTER 1 Topics: The ability to store and retrieve JavaTM objects is essential to building all but the most transient applications. The key to storing

    docs.oracle.com

    https://j.mearie.org/post/122845365013/serialization

     

    직렬화

    며칠 전 해커뉴스에서 “인터넷은 디버깅 모드로 돌아가고 있다"는 글을 보았다. 아, 원래 글을 읽을 필요는 없다. 글의 내용이라는 게 JSON이나 XML은 텍스트 포맷인데 바이너리 포맷보다 오버헤

    j.mearie.org

     

    특히 많은 도움을 주신 아래 링크의 댓글님들!

    https://okky.kr/articles/224715

     

    OKKY - 직렬화 하는 이유가?

    자바책에는 객체를 파일에 저장하거나 파일에서 꺼내오기 위해서 또는 객체를 네트워크를 통해 전송하기 위해서는 미리 객체를 직렬화해야한다고 되어 있네요. 웹 어플 소스 분석하다보면 서

    okky.kr

     

     

    https://okky.kr/articles/690377

     

    OKKY - 직렬화는 꼭 필요할까요?

    rest api의 entity 클래스에서직렬화는 꼭 필요할까요?직렬화를 알게 되고 사용 필요성도 어느정도 이해된 상태인데find한 객체를 그대로 리턴하는 작업, 다른 가공없이 바로 save하는 엔티티에서도

    okky.kr

     

Designed by Tistory.