[Java] 불변 객체란 무엇일까

hyunoi·2024년 11월 11일
0

Java

목록 보기
6/20
post-thumbnail

불변 객체(Immutable Object)


불변 객체는 객체 생성 이후 재할당은 가능하지만 내부 상태가 변하지 않는, 변경할 수 없는 객체이다.
String, Integer, Boolean 등이 있다.

String str = "a";
str = "ab"

이런 식으로 사용하면 '객체의 모양이 바뀌는 것이니 불변성이 아닌 것 아니냐?' 생각할 수 있는데
이것은 str이 처음 참조하고 있는 "a"의 객체를 "ab"로 바꾸는 것이 아닌 "ab"라는 새로운 객체를 만들고 이 객체를 str이 참조하게 만드는 것이다.

재할당을 한 것이고, 내부 상태를 바꾼 것이 아니라는 것이다.

가변 객체를 만드는 규칙

  1. Setter 메소드 사용하지 않기
  2. 모든 필드를 private, final로 선언하기
  3. 클래스를 final로 선언하기
    이는 하위 클래스의 오버라이딩을 방지하기 위함
    오버라이딩이 행해지면 변화가 생김
  4. 객체 생성을 위한 생성자 또는 정적 팩토리를 추가하기
    객체 생성 시에 값 고정을 위해
    생성 시점에 모든 필드를 초기화하고, 이후에 필드 값 변경 방법을 제공하지 않아야 함
  5. 불변 객체 사용시 방어적 복사 고려하지 않아도 됨

불변 객체를 만드는 코드이다.

public final class Person {
    private final String name;
    private final int age;

    // 생성자에서 필드 초기화
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // Getter 메서드만 제공 (Setter 없음)
    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

장점

Thread-Safe하여 병렬 프로그래밍에서 유용하고 따로 동기화를 고려하지 않아도 된다.

멀티 스레드에서 주로 발생하는 공유 자원에 대해 서로 변경을 하다보니 값이 덮어씌워지는 문제가 있다.
하지만 불변 객체는 항상 동일한 값을 보장하기 때문에 동기화 신경 안 써도 된다.

내부의 변경이 없기 때문에 Cache, Map, Set 등의 요소로 활용하기 적합하다.

위 세 개는 내부 요소가 변경되면 갱신 작업이 꼭 필요하지만, 불변 객체의 경우 저장 이후 부가적인 작업이 필요 없다.

외부에서 객체에 대해 변경할 수 없기 때문에 안정적이다.

가변 객체는 값을 변경하는 set 메소드가 있다면 객체의 값을 항상 파악해야 하고, 이 파악하는 것도 어렵다.
하지만 불변 객체는 값 변경 걱정이 없기 때문에 객체의 신뢰성이 높다.

가비지 컬렉션의 성능을 높일 수 있다.

불변 객체의 경우 상태 변경이 필요 하면 또 새로운 객체를 만들어서 참조를 바꿔주어야 한다.
객체가 계속 늘어난다.

이 부분에서 성능이 떨어지는가? 오라클에서는 아니라고 답했다.

'객체 생성하는 비용이 과대평가되고 있고, 불변 객체를 이용하는 이점이 그 비용을 충분히 상쇄할 수 있다'

  • 새롭게 생성된 객체는 짧은 생명 주기를 가지고 이는 가비지 컬렉션에 부담이 되지 않는다.
  • 불변 객체는 상태가 변하지 않기 때문에 가비지 컬렉션은 이에 대해 신경을 쓰지 않아도 된다. 참조 관계가 바뀔 일이 없으니 관심 꺼도 된다는 것
  • 가변 객체의 경우 상태가 변하면 내부의 참조 관계가 변할 수 있으니 신경을 써야 한다. 그러므로 가변객체보다는 불변객체가 가비지 컬렉션의 스캔 범위와 빈도를 줄이는데 도움을 준다.

정리하자면,
불변 객체를 사용하면 가변 객체보다 생성 비용이 더 들지만
가비지 컬렉션의 스캔 범위와 빈도가 줄어든다
이것이 더 큰 효율을 가져오기 때문에 성능 상 유리하다.

0개의 댓글