Java 클래스 직렬화 - serialVersionUID

devkev00·2025년 1월 17일

🔥 What I've Learned

목록 보기
5/9
post-thumbnail

최근에 자바를 공부하다가 뭔가 이상한 코드를 보게 되었다.

package com.mysite.sbb;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;

@ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "entity not found")
public class DataNotFoundException extends RuntimeException {
    private static final long serialVersionUID = 1L;

    public DataNotFoundException(String message) {
        super(message);
    }
}

해당 코드는 사용자 정의 예외처리 메서드인데, 잘 보면 serialVersionUID라는 변수를 선언해놓고 사용하지 않는 걸 볼 수 있다.

알고 보니 이는 객체를 직렬화하는 경우 버전 관리를 위해 필요한 일종의 버전 번호였다.

직렬화란?

직렬화란 객체를 "저장하거나 전송할 수 있는 형태"로 변환하는 것을 말한다.

이 과정에서 객체의 원본을 직접 저장하는 것이 아니기 때문에 복사가 이뤄지게 되는데, 복사된 객체의 버전이 어떤 버전인지 알아야 나중에 클래스 구조가 변경되거나, 다른 환경에서 작동을 시켜도 값이 변하지 않고 올바르게 작동한다.

만약 serialVersionUID를 명시하지 않으면, 컴파일러가 자동 생성하는데, 이럴 경우 클래스 구조 변경에 따라 값이 변할 수 있고 이는 역직렬화시 예상치 못한 오류를 발생시킬 수 있기 때문에,

serialVersionUID는 항상 명시적으로 설정해주는 것이 좋다.

참고로 역직렬화란 직렬화의 반대이다. 즉 저장/전송된 데이터를 다시 객체화시키는 것을 말한다.

직렬화는 왜 쓰나?

객체를 "다른 곳으로 옮기거나", "나중을 위해 저장"할 필요가 있을 때 사용한다. 실제 서비스로 예를 들자면

  • 사용자가 장바구니에 물건을 담고, 사용자가 브라우저를 껐다가 다시 돌아와도 유지
  • save 기능이 있는 게임의 경우 중간 저장할 때, 진행 상황을 직렬화하여 저장
  • 채팅 메시지를 전달할 때, 메시지 객체를 직렬화하여 전송

주로 캐시나 세션과 많이 같이 쓰인다.

직렬화가 필요한 객체들?

예외처리 클래스, DTO, 엔티티 클래스, 세션에 저장되는 객체, 캐시 객체 등이 있다.

@Serial

따라서 스프링부트에서는 이러한 직렬화와 관련된 경고를 제어할 수 있도록 @Serial 어노테이션을 통해 관리할 수 있도록 해 놓았다.
해당 어노테이션은,

  • serialVersionUID 선언 시,
  • 직렬화에 포함/제외할 필드 명시 시,
  • IDE나 컴파일러의 직렬화 관련 경고 제어 시,

주로 사용된다.

profile
Focusing on what I can change

0개의 댓글