성장일기

내가 보려고 정리하는 공부기록

언어/자바

[JAVA] 자바의 직렬화, 역직렬화 (Serializable 인터페이스)

와나나나 2024. 6. 19. 00:54
728x90

이번 게시글에서는 자바의 직렬화와 역직렬화에 대해 다루어보려고 한다. 평소에 코딩테스트를 위한 자바의 라이브러리나 문법에 대해서만 야매로 공부했었는데, 부트캠프에서 직렬화라는 개념을 접하게 되어서 이참에 정리할 생각이다.

 

자바의 직렬화 ? 역직렬화 ?

자바 직렬화란 자바 시스템 내부의 객체나 데이터를 외부의 자바시스템에서도 사용할 수 있게 바이트 형태로 변환하는 기술을 의미한다.

반대로 자바 역직렬화는 바이트로 변환된 데이터를 다시 객체로 변환하는 기술이다.

 

참고로 해당 객체는 JVM의 메모리 (힙이나 스택)에 상주되어있다고 한다.

 

 

자바 직렬화는 어떻게 쓰는데 ?

자바 직렬화를 사용하려면, 직렬화를 원하는 객체가 Serializable 인터페이스를 상속받도록 해주어야 한다.

 

java.io.Serializable 인터페이스는 현재 객체의 직렬화가 제공되어야 함을 JVM에게 알려주는 역할을 한다.

 

 

직렬화를 하는 방법java.io.ObjectOutputStream 객체를 사용하는 것이다. 

try(ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("c_object.dat"))) {
			// 직렬화 안 하면 에러 발생
            oos.writeObject(new Member("hong", "123", "홍길동", 30, '남', 324.45)); 


        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);

        } catch (IOException e) {
            throw new RuntimeException(e);
        }

 

 

필자는 파일형태로 객체를 변환하기 위해서 ObjectOutputStream 의 인자로 FileOutputStream을 주었는데, 만약 바이트배열의 형태를 원한다면 ByteArrayOutputStream을 사용할 수도 있고, 그 외에도 다른 객체를 사용할 수 있다.

 

직렬화를 진행한 저 멤버 객체는 파일형태로 c_object.dat에 저장된다.

 

transient

필드를 생성할 때, 해당 예약어를 넣어주면 직렬화 대상에서 제외된다. 

비밀번호처럼 보안상 중요한 변수나 꼭 저장할 필요 없는 변수에 대해서는 해당 예약어를 사용할 수 있다.

=> null로 들어간다!

 

 

자바 역직렬화는 어떻게 쓰는데 ?

 

역직렬화를 사용하기 위해서는 다음 조건을 만족해야 한다.

  • 직렬화 대상인 객체의 클래스가 클래스 패스에 존재해야 한다. 
    • 클래스패스 (Class Path)소스 코드(.java)를 컴파일하면 바이트코드(.class)로 변환되고 JVM이 바이트코드로 된 파일을 실행하려면 찾아야 하는데 이 바이트코드까지의 경로를 의미한다.
    • 여기서 직렬화와 역직렬화를 진행하는 시스템이 다를 수 있다
  • 자바 직렬화 대상 객체는 동일한 serialVersionUID를 갖는다.

 

여기서 serialVersionUID에 들어가는 숫자는 뭐든 상관없다. 다만 상수로 설정해주어야한다! (static final을 사용한다)

 

 

역직렬화 하는 방법java.io.ObjectInputStream 객체를 사용하는 것이다.

try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("c_object.dat"))) {

            Member member = (Member) ois.readObject();
            System.out.println(member);

        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }

 

파일의 데이터를 객체화 시킬 것이기 때문에 마찬가지로 FileInputStreamObjectInputStream의 인자로 생성해 주었다.

 

 

직렬화 / 역직렬화를 사용하는 이유

데이터를 직렬화 하는 방법으로는 자바 직렬화 외에도 CSV나 JSON이 있다. 특히 JSON은 최근에 많이 사용하고 있는 것 같다!

 

csv나 json 등은 시스템 고유의 특성과 상관없는 시스템에서의 데이터 교환시 많이 사용한다고 한다. 

이런 방법들이 있는데 자바 직렬화를 왜 사용할까 ?

 

정답은 없다고 한다. ... 음 ? 즉 목적에 따라 알아서! 적절히! 사용해야 하는데,, 

장점과 단점을 알고있으면 판단에 도움이 될 것이다

 

장점

자바 직렬화는 자바 시스템 개발에 최적화 되어있다. 기본 직렬화 조건만 지킨다면 복잡한 데이터 구조의 클래스도 직렬화가 가능하다.

 

데이터 타입 또한 자동으로 맞춰줘서 신경쓰지 않아도 된다. 그래서 역직렬화시 바로 기존 객체처럼 사용할 수 있게 된다.

 

 

단점

  • 특별한 문제가 없다면 serialVersionUID 값은 개발자가 직접! 관리해야한다. 
    • 이 값이 동일하면 멤버 변수, 메소드 추가는 큰 문제 없다. 다만 삭제하거나 이름을 바꾸면 데이터가 누락될 수 있다.
  • 역직렬화 대상 클래스의 멤버 변수 타입 변경 지양해야한다
  • 외부에 장기간 저장되는 정보는 언제 변경될지 모르는 긴 시간동안 외부에 존재해야 하기 때문에 직렬화 사용 지양해야한다
  • 직접 컨트롤 할 수 없는 개체에서는 직렬화를 지양해야한다.
    • 프레임워크, 라이브러리에서 제공하는 객체들

 

-> 즉 자주 바뀌는 클래스의 객체는 직렬화를 사용하지 말자. 예외가 언제 발생할지 모른다.

 

 

이런 자바 직렬화는 JVM 메모리에서만 상주되어있는 객체 데이터를 그대로 영속화 해야할 때 사용한다. 

시스템이 종료되어도 사라지지 않고, 네트워크 전송도 가능하게 된다!

 

 

 

레퍼런스

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

 

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

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

techblog.woowahan.com

https://techblog.woowahan.com/2551/

 

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

{{item.name}} 자바의 직렬화 기술에 대한 대한 두 번째 이야기입니다. 실제 자바 직렬화를 실무에 적용해보면서 주의해야 할 부분에 대해 이야기해보려고합니다. 자바 직렬화 실제 업무에서 사용

techblog.woowahan.com