본문 바로가기
개발&프로그래밍

[JAVA] 직렬화(Serializable)와 역직렬화

by 재아군 2024. 11. 3.

[JAVA] 직렬화(Serializable)와 역직렬화 

[JAVA] 직렬화(Serializable)와 역직렬화

 

직렬화란?

자바 직렬화는 객체를 바이트 스트림으로 변환하는 과정이다. 역직렬화는 그 반대로, 바이트 스트림을 객체로 복원하는 과정이다.

주로 다음과 같은 상황에서 사용한다:

  • 객체를 파일로 저장할 때
  • 네트워크로 객체를 전송할 때
  • 캐시할 때
  • 클립보드에 복사할 때

 

기본 사용법

직렬화 가능한 클래스 만들기

public class User implements Serializable {
    private String name;
    private int age;
    private String email;

    // 생성자, getter, setter 생략
}

 

객체 직렬화하기

User user = new User("John", 30, "john@example.com");

// 파일로 저장
try (ObjectOutputStream out = new ObjectOutputStream(
        new FileOutputStream("user.ser"))) {
    out.writeObject(user);
}

 

역직렬화하기

try (ObjectInputStream in = new ObjectInputStream(
        new FileInputStream("user.ser"))) {
    User user = (User) in.readObject();
}

 

serialVersionUID 역할과 중요성

serialVersionUID는 직렬화된 객체의 버전 관리에 사용되는 식별자다. 클래스 구조가 변경될 때 버전 불일치를 감지할 수 있다.

 

명시적 정의

public class User implements Serializable {
    private static final long serialVersionUID = 1L;

    private String name;
    private int age;
    private String email;
}

 

IDE 자동 생성

IntelliJ IDEA에서는 Alt + Insert (맥에서는 ⌘ + N)를 눌러 자동 생성할 수 있다.

 

직렬화 제어

transient 키워드

직렬화에서 제외할 필드를 지정한다.

public class User implements Serializable {
    private static final long serialVersionUID = 1L;

    private String name;
    private int age;
    transient private String password; // 직렬화에서 제외
}

 

커스텀 직렬화

public class User implements Serializable {
    private static final long serialVersionUID = 1L;
    private String name;
    private int age;

    private void writeObject(ObjectOutputStream out) throws IOException {
        out.defaultWriteObject();
        // 추가적인 데이터 직렬화
        out.writeObject(name.toUpperCase());
    }

    private void readObject(ObjectInputStream in) 
            throws IOException, ClassNotFoundException {
        in.defaultReadObject();
        // 추가적인 데이터 역직렬화
        String upperName = (String) in.readObject();
    }
}

 

보안 고려사항

잠재적 위험

  1. 역직렬화 공격
  2. 민감한 데이터 노출
  3. 버전 관리 문제

 

보안 강화 예제

public class SecureUser implements Serializable {
    private static final long serialVersionUID = 1L;

    private String name;
    private transient String password; // 민감한 정보는 제외

    // 역직렬화 시 유효성 검사
    private Object readResolve() {
        // 기본적인 유효성 검사
        if (name == null || name.isEmpty()) {
            throw new IllegalStateException("Invalid user data");
        }
        return this;
    }
}

 

대안과 권장사항

JSON 직렬화

// Jackson 라이브러리 사용
ObjectMapper mapper = new ObjectMapper();

// 직렬화
String json = mapper.writeValueAsString(user);

// 역직렬화
User user = mapper.readValue(json, User.class);

 

Protocol Buffers 사용

message User {
    string name = 1;
    int32 age = 2;
    string email = 3;
}

 

직렬화 대신 권장되는 방법들

  1. REST API 사용
    • JSON/XML 기반 통신
    • 더 나은 버전 관리
    • 플랫폼 독립적
  2. 데이터베이스 저장
    • JPA/Hibernate 사용
    • 구조화된 데이터 관리
    • 더 나은 보안

 

적용 사례

캐시 시스템 구현

public class CacheEntry implements Serializable {
    private static final long serialVersionUID = 1L;

    private final Object data;
    private final long timestamp;
    private final long expiryTime;

    public boolean isExpired() {
        return System.currentTimeMillis() > timestamp + expiryTime;
    }
}

 

분산 시스템에서의 사용

public class DistributedMessage implements Serializable {
    private static final long serialVersionUID = 1L;

    private final String messageId;
    private final String content;
    private final long timestamp;

    // 메시지 무결성 검사
    private void readObject(ObjectInputStream in) 
            throws IOException, ClassNotFoundException {
        in.defaultReadObject();
        validateMessage();
    }

    private void validateMessage() {
        if (messageId == null || content == null) {
            throw new IllegalStateException("Invalid message");
        }
    }
}

 

 

 

자바 직렬화는 강력한 기능이지만, 신중하게 사용해야 한다. 다음 사항들을 기억하자:

  1. serialVersionUID는 항상 명시적으로 선언
  2. 민감한 데이터는 transient로 선언
  3. 가능하면 JSON 같은 표준 포맷 사용
  4. 커스텀 직렬화 메서드로 추가 보안 구현
  5. 역직렬화 시 항상 유효성 검사 수행

 

댓글