프로그래밍백엔드 개발자

자바에서 Serializable 인터페이스는 어떻게 구성되어 있으며, 그 필요성과 직렬화 가능한 클래스를 설계할 때 고려해야 할 주요 세부사항은 무엇인가요?

Hintsage AI 어시스턴트로 면접 통과

답변.

질문 배경

자바가 처음 등장한 이래로, 애플리케이션 세션 간에 객체를 저장하는 문제가 발생했습니다. 네트워크를 통해 전송하거나 데이터베이스 또는 디스크에 기록하는 등의 작업을 위해 Serializable 인터페이스가 고안되어 객체를 바이트 스트림으로 변환하고 다시 변환할 수 있게 되었습니다 (직렬화 및 역직렬화).

문제점

클래스가 Serializable 인터페이스를 구현하지 않으면, 해당 인스턴스를 직렬화하려 할 때 예외가 발생합니다. 더군다나, 직렬화는 필드 값뿐만 아니라 그 상태도 저장하므로 잘못된 구현은 예기치 않은 취약성, 객체 복구 오류, 데이터 손실을 초래할 수 있습니다.

해결책

Serializable 인터페이스는 마커 인터페이스입니다. 즉, 메서드를 포함하지 않습니다. 올바른 직렬화를 위해서는 serialVersionUID를 명시적으로 선언하고, 직렬화되지 않아야 할 필드에 대해 transient 키워드를 사용하는 것이 좋습니다.

코드 예시:

import java.io.Serializable; public class User implements Serializable { private static final long serialVersionUID = 1L; private String username; private transient String password; // 직렬화되지 않음 public User(String username, String password) { this.username = username; this.password = password; } }

주요 특징:

  • 마커 인터페이스로 메서드 구현이 필요 없음
  • 객체를 바이트 스트림으로 직렬화할 수 있음
  • transient 사용으로 특정 필드의 직렬화를 방지

함정 질문.

serialVersionUID를 반드시 명시적으로 선언해야 하나요?

아니요, 필수는 아니지만 선언하지 않으면 자동으로 생성됩니다. 그러나 클래스에 변경이 있을 경우 이전 직렬화된 버전을 복구하는 과정에서 InvalidClassException이 발생할 수 있습니다. 따라서 이 필드는 항상 명시적으로 선언하는 것이 좋습니다.

정적 필드는 직렬화되나요?

아니요, 정적 필드는 직렬화되지 않고, 인스턴스 필드만 직렬화됩니다. 정적 필드는 클래스에 속하며, 객체에 속하지 않기 때문에 직렬화 및 역직렬화 시 값이 저장되거나 복구되지 않습니다.

Serializable을 구현하지 않는 필드를 가진 객체를 직렬화할 수 있나요?

아니요, 비정적 필드 중 하나라도 직렬화되지 않거나 transient로 선언되어 있지 않으면 직렬화 시 NotSerializableException 예외가 발생합니다.

일반적인 실수 및 반패턴

  • serialVersionUID 미 선언으로 인한 객체 버전 불일치
  • transient 없이 민감한 데이터 직렬화 (예: 비밀번호)
  • 불안정하며 빠르게 변경되는 클래스 구조를 가진 객체의 직렬화

실제 사례

부정적인 경우

사용자 캐시 애플리케이션에서 serialVersionUID를 명시하지 않고, 코드 수정을 통해 User 클래스의 구조를 변경했습니다. 애플리케이션 시작 시 InvalidClassException이 발생하고 모든 직렬화된 데이터가 손실되었습니다.

장점:

  • 개발 속도

단점:

  • 캐시된 데이터 손실
  • 코드 호환성 문제

긍정적인 경우

유사한 프로젝트에서 항상 serialVersionUID를 명시하고 직렬화되지 않는 모든 필드를 transient로 설정했습니다. 이 덕분에 구조가 미세하게 변경된 후에도 직렬화된 객체가 성공적으로 로드되었습니다.

장점:

  • 직렬화된 데이터와의 신뢰성 있는 작업
  • 안전한 사용

단점:

  • 추가 설계 필요
  • 클래스 수정을 위한 규율 요구