[JAVA] 불변객체(Immutable Object)

2025. 10. 13. 20:24·JAVA

기초 개념

불변객체란 무엇인가?

개념 정의

불변객체(Immutable Object)는 한 번 생성되면 내부 상태가 절대 변하지 않는 객체를 말함

개체가 만들어진 이후에는 속성값을 바꾸거나 수정할 수 없음

 

반대의 의미로는 Mutable Object(가변 객체)가 있으며 생성된 이후에도 내부 상태를 변경할 수 있는 객체를 말함

예를 들어 ArrayList 같은 클래스는 데이터를 추가하거나 수정할 수 있으므로 mutable한 객체

 

record

기존 클래스를 Record로 변환하기(JAVA 14+)

전통적인 불변 클래스 → Record 변환

변환 전

public final class Product {
    private final String id;
    private final String name;
    private final BigDecimal price;

    public Product(String id, String name, BigDecimal price) {
        this.id = id;
        this.name = name;
        this.price = price;
    }

    public String getId() { return id; }
    public String getName() { return name; }
    public BigDecimal getPrice() { return price; }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Product product = (Product) o;
        return Objects.equals(id, product.id) &&
               Objects.equals(name, product.name) &&
               Objects.equals(price, product.price);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, name, price);
    }

    @Override
    public String toString() {
        return "Product{id='" + id + "', name='" + name + "', price=" + price + "}";
    }
}

 

변환 후 (Record 사용)

public record Product(String id, String name, BigDecimal price) {
}

 

Compact Constructor에서 방어적 복사 다루기

왜 Compact Constructor에서 방어적 복사가 중요한가?

: Record도 불변 객체이므로, 가변 컬렉션을 참조할 때는 반드시 방어적 복사가 필요

 

불변객체의 장점

1. 스레드 안정성 (Thread Safety)

2. 예측 가능성과 신뢰성

3. 캐싱과 최적화

4. HashMap/HashSet의 Key로 안전

5. 방어적 복사 불필요

 

불변객체의 단점

1. 메모리 오버헤드

2. GC(Garbage Collection) 압박

3. 복잡한 객체 업데이트의 번거로움

4. 성능 민감한 상황에서 부적합

 

총정리

불변객체 설계 체크리스트

필수 체크사항

  1. 클래스를 final로 선언
  2. 모든 필드를 private final로 선언
  3. equals()와 hashCode() Override
  4. 생성자에서 모든 필드 초기화
  5. 가변 객체는 방어적 복사 수행

사용 가이드라인

불변객체가 적합한 경우

  • DTO, Value Object
  • 설정(Configuration) 객체
  • 멀티스레드 환경의 공유 데이터
  • Map/Set의 Key
  • 캐시 대상 객체

가변객체가 적합한 경우

  • 성능이 극도로 중요한 경우
  • 빈번하고 복잡한 상태 변경
  • 대용량 데이터 처리
  • 실시간 처리가 필요한 경우

Best Practice

  1. 기본적으로 불변으로 설계하기
    • 처음부터 불변으로 만들고, 정말 필요할 때만 가변으로 변경
    • 나중에 불변으로 바꾸는 것은 매우 어려움
  2. Java 14+ 환경이라면 Record 적극 활용
    • 20줄 코드를 1줄로 줄일 수 있음
    • 자동으로 생성자, getter, equals, hashCode, toString 제공
  3. 컬렉션 필드는 방어적 복사로 보호
    • 방어적 복사 : 외부에서 내부 데이터 변경 못하게 복사본 만들기
    • 생성자와 getter에서 new ArrayList<>(원본리스트) 사용

 

'JAVA' 카테고리의 다른 글

[JAVA] 다형성 파헤쳐보기  (0) 2025.10.15
[JAVA] 예외처리  (1) 2025.10.13
[JAVA Algorithm] 컬렉션 프레임워크  (0) 2025.10.02
[Java Algorithm] 2차원 배열  (0) 2025.10.02
[JAVA Algorithm] 배열 개념 정리  (0) 2025.10.01
'JAVA' 카테고리의 다른 글
  • [JAVA] 다형성 파헤쳐보기
  • [JAVA] 예외처리
  • [JAVA Algorithm] 컬렉션 프레임워크
  • [Java Algorithm] 2차원 배열
stark77
stark77
하마의 IT 자기개발 이모저모, 백엔드 개발자로 거듭나기
  • stark77
    하마의 개발자 성장일기
    stark77
  • 전체
    오늘
    어제
    • 분류 전체보기
      • 컴퓨터구조와 운영체제
        • 컴퓨터구조
        • 운영체제
      • SQL 기초
      • Spring
        • 백엔드 기초
        • Spring 실습
      • JAVA
        • Java 실습
      • HTML&CSS
        • HTML&CSS 실습
      • Git&GitHub
        • Git&GitHub 실습
      • 내배캠 끄적끄적
        • Today I Learned
      • 유용한 툴 및 사이트 정리
      • 취미
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    thymleaf
    웹소켓
    백엔드 기초다지기
    BEAN
    HTML&CSS
    MVC
    네트워크 기초
    SpringSecurity
    RestTemplate
    Til
    객체지향프로그래밍
    프로세스와 쓰레드
    String.format
    실시간 데이터 처리
    java
    WebSocket
    Java 문법기초
    Github
    for문
    객체지향
    Stomp
    백엔드 기초
    다형성
    Spring
    JPA
    git
    경합조건과 교착상태
    jsp
    algorithm
    Spriingboot
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
stark77
[JAVA] 불변객체(Immutable Object)
상단으로

티스토리툴바