직렬화(Serializable)

윤재열·2023년 3월 9일
1

Java

목록 보기
71/71
post-custom-banner

자바의 직렬화 & 역직렬화

  • 직렬화(Serialize) 란 자바 언어에서 사용되는 Object 또는 Data를 다른 컴퓨터의 자바 시스템어서도 사용할 수 있도록 바이트 스트림(Stream of Bytes) 형태로 연속적인 (Serial) 데이터로 변환하는 포맷 변환 기술을 말합니다.
  • 역직렬화(Deserialize)는 바이트로 변환된 데이터를 원래대로 자바 시스템의 Object 또는 Data로 변환하는 기술입니다.
  • 이를 시스템적으로 살펴보면, JVM의 힙(heap) 혹은 스택(stack) 메모리에 상주하고 있는 객체 데이터를 직렬화를 통해 바이트 형태로 변환하여 DB나 파일 같은 외부 저장소에 저장해두고, 다른 컴퓨터에서 이 파일을 가져와 역직렬화를 통해 자바 객체로 변환해서 JVM 메모리에 적재하는 것으로 보면 됩니다.

바이트스트림(stream of bytes)란?
스트림은 클라이언트나 서버 간에 출발지, 목적지로 입출력하기 위한 데이터가 흐르는 통로를 말합니다.
자바는 스트림의 기본 단위를 바이트로 두고 있기 때문에, 네트워크, 데이터베이스로 전송하기 위해 최소 단위인 바이트 스트림을 변환하여 처리합니다.

직렬화 사용처

  • 직렬화를 응용한다면 휘발성이 있는 캐싱 데이터를 영구 저장이 필요할 때 사용할 수도 있습니다.
  • 예를들어 JVM의 메모리에서만 상주되어있는 객체 데이터가 시스템이 종료되더라도 나중에 다시 재사용이 될수 있을 때 영속화(Persistence)를 해두면 좋습니다.
  • 이러한 특성을 살린 자바 직렬화는 실제로도 여러곳에 응용됩니다.

서블릿 세션 (Servlet Session)

  • 단순히 세션을 서블릿 메모리 위에서 운용한다면 직렬화를 필요로 하지 않지만, 단일 세션 데이터를 저장 & 공유가 필요할 때 직렬화를 사용합니다.
  • 세션 데이터를 데이터베이스에 저장할 때
  • 톰켓의 세션 클러스터링을 통해 각 서버간에 데이터 공유가 필요할 때

캐시 (Cache)

  • 이터베이스로부터 조회한 객체 데이터를 다른 모듈에서도 필요할 떄 다시 DB를 조회하는 것이 아닌, 객체를 직렬화하여 메모리나 외부 파일에 저장해 두었다가 역직렬화하여 사용하는 캐시 데이터로서 이용이 가능합니다.
  • 자바 직렬화를 이용해서만 캐시를 저장할 수 있는 것은 아니지만 자바시스템에서 만큼은 구현이 가장 간편하기 때문에 많이 사용한다고 보면 됩니다.
  • 하지만 요즘은 앞서 포스팅한 Redis나, Memcached 와 같은 캐시 DB를 많이 사용하는편입니다.

자바 RMI (Remote Method Invocation)

  • 자바 RMI는 원격 시스템 간의 메시지 교환을 위해서 사용하는 자바에서 지원하는 기술입니다.
  • 이 메시지에 객체 데이터를 직렬화하여 송신하는 것입니다.
  • 최근에는 소켓을 사용하는 편이므로 안쓰이는 기술입니다.

직렬화 vs JSON 비교

  • 이처럼 자바 직렬화는 외부 파일이나 네트워크를 통해 클라이언트 간에 객체 데이터를 주고 받을 때 사용됩니다.
  • CSV, JSON이라는 훌륭한 데이터 포멧이 있는데 굳이 직렬화가 필요하다는 점입니다.
    • 실제로 JSON은 웹 뿐만 아니라 게임 쪽에서도 설정 파일로 쓰이거나 데이터를 교환할때 많이 사용됩니다.
    • 그리고 직렬화를 오로지 자바 프로그램에서만 사용이 가능하지만, JSON 형태로 객체 데이터를 저장해두면 Phyton,JS 에서도 범용적으로 사용이가능합니다.
  • 그렇다면 그냥 JSON을 이용하면 되는데 굳이 직렬화,역직렬화를 사용하는 이유에 대해서 공부해 봅니다!

자바 직렬화 사용에 대한 장점

1. 직렬화는 자바의 고유 기술인 만큼 당연히 자바 시스템에서 개발에 최적화 되어있습니다.
2.자바의 레퍼런스 타입에 대해 제약 없이 외부에 내보낼 수 있다는 것
  • 예를들어 primitive type이나 array 같은 타입들은 웬만한 프로그래밍 언어가 공통적으로 사용하는 타입이기에 이러한 값들은 JSON만으로도 충분히 사용 이용이 가능합니다.

  • 하지만 자바의 collection이나 클래스,인터페이스,임의의 객체 같은 타입들은 단순 파일 포맷으로는 타입 개수가 한계가 있습니다.
    그래서 이들을 외부로 내보내기 위해서는 각 데이터를 매칭시키는 별도의 파싱(parsing)이 필요합니다.

  • 그에 반해, 직렬화를 이용하면 파이썬이나 자바스크립트 같은 다른 시스템에서는 사용하지는 못할지라도, 직렬화 기본 조건만 지킨다면 별도의 작업없이 그냥 바로 외부에 보낼 수 있습니다.

  • 그리고 역직렬화를 통해 읽어들이면 데이터 타입이 자동으로 맞춰지기 때문에 자바 클래스의 기능들을 곧바로 다시 이용 할 수 있습니다.

  • 그래서 직렬화된 문자열을 DB에 저장해두고 꺼내 쓰기도 합니다.

  • 요즘은 범용적인 JSON을 이용하는 추세가 점점 늘고 있다. 따라서 JSON 이냐 직렬화 이냐 에 대한 명확한 정답은 없고 '목적에 따라 적절히 써야 한다' 정도로 정리할 수 있을 것 같다.

자바 직렬화 사용법

객체 직렬화 & 역직렬화 하기

Serializable Interface

  • Serializable 인터페이스는 아무런 내용도 없는 마커 인터페이스 입니다.

ObjectOutputStream 객체 직렬화

  • 직렬화(스트림에 객체를 출력) 에는 ObjectOutputSream을 사용합니다.
  • 객체가 직렬화될때 오직 객체의 인스턴스 필드값 만을 저장합니다.
    static 필드나 메서드는 직렬화하여 저장되지 않습니다.
  • 아래 코드는 외부 파일에 객체를 직렬화하여 저장하는 예제입니다.
  • 코드를 실행하면 SerializeObject.obj 파일이 생성됩니다.
    그리고 파일 내용을 보면 해독이 불가능한 문자 형태로 문자 형태로 되어있는 것을 볼 수 있습니다.

ObjectInputStream 객체 역직렬화

  • 역직렬화(스트림으로부터 객체를 입력)에는 ObjectInputStream을 사용합니다.
  • 단, 역직렬화 할 때 주의사항이 있는데, 직렬화 대상이 된 객체의 클래스가 외부 클래스라면 , 클래스 경로에 존재해야하며 import된 상태여야 합니다.

  • 이렇게 역직렬화를 이용하게 되면, 직렬화된 외부 파일만 있다면 생성자로 객체 초기화 없이 바로 객체의 정보를 가져와 인스턴스화 하여 사용할 수 있게 됩니다.

직렬화 TIP!

  • 만약 여러개의 객체를 직,역직렬화할때는 역직렬화할 때도 직렬화 떄의 순서와 일치해야 합니다.

직렬화 요소 제외

  • 객체의 모든 인스턴스를 직렬화 하기에는 너무 무겁거나 혹은 중요한 정보는 외부에 노출시키고 싶지 않은 경우, 직렬화할 요소를 직접 선택할수 있습니다.

  • 위의 2개를 실행후 console 창을 보면 변수 정의문 앞에 trnsient 키워드를 명시해주면 직렬화 대상에서 제외 시킬 수 있습니다.
    • transient가 붙은 인스턴스 변수의 값은 그 타입의 기본값으로 직렬화 됩니다.
      • Primitive Type : 각 타입의 Default
      • Reference Type : null
  • 단, 직렬화 대상에서 제외하는데 있어 그 데이터가 객체에 실제로 필요가 없는지, 제외하였을 경우에 서비스 장애에 이상이 없는지에 대한 고려를 해야합니다.

직렬화의 단점

  • 직렬화는 용량이 크다.
    • 직렬화는 객체에 저장된 데이터 뿐만아니라, 타입정보, 클래스 메타정보를 가지고 있으므로 생각보다 용량을 많이 차지합니다.
    • 따라서 DB, Cache 같이 외부에 저장할때, 장기간 동안 저장되는 정보는 직렬화를 지양해야 합니다.
  • 역직렬화는 위험합니다.
    • 직렬화 설정 자체는 문제 없지만, 남이 만든 것을 역직렬화 과정에서 공격받을 위험성이 있습니다.
    • 역직렬화 과정에서 호출되어 잠재적으로 위험한 동작을 수행하는 메서드를 가젯이라고 부릅니다.
profile
블로그 이전합니다! https://jyyoun1022.tistory.com/
post-custom-banner

0개의 댓글