1. 직렬화(serialization)
- 자바 시스템 내부에서 사용되는 Object 또는 Data를 외부의 자바 시스템에서도 사용할 수 있도록 byte 형태로 데이터를 변환하는 기술.
- JVM(Jaava Virtual Machine 이하 JVM)의 메모리에 상주(힙 또는 스택)되어 있는 객체 데이터를 바이트 형태로 변환하는 기술
- 직렬화의 주된 목적은 객체를 상태 그대로 저장하고 필요할 때 다시 생성하여 사용하는 것이다.
2. 역직렬화(Deserialization)
- byte로 변환된 Data를 원래대로 Object나 Data로 변환하는 기술을 역직렬화(Deserialize)라고 부릅니다.
- 직렬화된 바이트 형태의 데이터를 객체로 변환해서 JVM으로 상주시키는 형태
3. 자바의 직렬화는 왜 사용하는가?
- 복잡한 데이터 구조의 클래스의 객체라도 직렬화 기본 조건만 지키면 큰 작업 없이 바로 직렬화, 역직렬화가 가능합니다.
- 데이터 타입이 자동으로 맞춰지기 때문에 관련 부분을 큰 신경을 쓰지 않아도 됩니다.
4. 주로 어디에 사용되는가?
서블릿 세션(Servlet Session)
- 세션을 서블릿 메모리 위에서 운용한다면 직렬화를 필요로 하지 않지만, 파일로 저장하거나 세션 클러스터링, DB를 저장하는 옵션 등을 선택하게 되면 세션 자체가 직렬화가 되어 저장되어 전달됩니다.
캐시(Cache)
- Ehcache, Redis, Memcached라이브러리 시스템을 많이 사용합니다.
자바 RMI(Remote Method Invocation)
- 원격 시스템 간의 메시지 교환을 위해서 사용하는 자바에서 지원하는 기술
5. 사용 시 주의사항
역직렬화시 클래스 구조 변경 문제
- 클래스의 멤버 변수 하나만 추가되어도 java.io.InvalidClassException 예외가 발생합니다.
- 예외 메시지를 읽어보면 serialVersionUID의 정보가 일치하지 않기 때문에 발생한 것을 알 수 있습니다.
- serialVersionUID 를 직접 기술하지 않아도 내부 적으로 serialVersionUID 정보가 추가되며,
내부 값도 자바 직렬화 스펙 그대로 자동으로 생성된 클래스의 해쉬 값을 이라는 것을 확인할 수 있었습니다.
즉, serialVersionUID 정보를 기술하지 않는다고 해서 사용하지 않는 것이 아니 다라는 것이 확인되었습니다.
직렬화 스펙
- SUID(serialVersionUID) 필수 값은 아니다.
- 호환 가능한 클래스는 SUID값이 고정되어 있다.
- SUID가 선언되어 있지 않으면 클래스의 기본 해쉬값을 사용한다.
(해쉬값 알고리즘은 링크에서 확인이 가능합니다.)
serialVersionUID 값이 동일할 때에도 문제가 발생할 수 있다.
- String -> StringBuilder, int -> long으로 변경해도 역직렬화에서 Exception이 발생한다.
- 자바 직렬화는 상당히 타입의 엄격하다는 것을 알 수있다.
- 멤버 변수가 빠지게 된다면 Exception대신 null 값이 들어간다.
용량문제
serializedMember (byte size = 146)
json (byte size = 62)
- 아주 간단한 객체의 내용도 2배이상의 차이를 확인할 수 있습니다.
- 일반적인 메모리기반의 Cache에서는 Data를 저장할 수 있는 용량의 한계가 있기 때문에 Json 형태와 같은 경량화된 형태로 직렬화하는 것도 좋은 방법입니다.
6. 마무리
- 외부 저장소로 저장되는 데이터는 짧은 만료시간의 데이터를 제외하고 자바 직렬화를 사용을 지양합니다.
- 역직렬화시 반드시 예외가 생긴다는 것을 생각하고 개발합니다.
- 자주 변경되는 비즈니스적인 데이터를 자바 직렬화을 사용하지 않습니다.
- 긴 만료 시간을 가지는 데이터는 JSON 등 다른 포맷을 사용하여 저장합니다.
Reference
728x90
반응형
LIST