Yomni's TIL Help

아이템 17. 불변 객체로 만들어라

1. 불변 객체란 무엇인가?

  • 불변 객체(Immutable Object) 는 상태가 한 번 설정되면 절대 바뀌지 않는 객체이다.

  • 즉, 필드 값이 생성 시점 이후에는 절대 변경되지 않는다.

2. 불변 객체의 장점

  • 안정적이고 단순하다. 상태가 변하지 않으므로 동기화 없어도 스레드 안전(Thread-safe) 하다.

  • 예측 가능하고 버그가 적다 외부에서 상태를 변경할 수 없으므로 사이드 이펙트가 없다.

  • 캐싱, 공유, 재사용이 안전하다. 여러 곳에서 동시에 사용해도 부작용이 없다.

  • 방어적 복사(defensive copy) 가 필요 없다.

  • 불변 객체는 좋은 키(Key) 가 된다. Map 이나 Set 에 사용할 때 안정적이다.

3. 불변 객체를 만드는 다섯가지 규칙

3-1. 객체의 상태를 변경하는 메서드(변경자, setter)를 제공하지 말 것

// no Setter public class Money { private final int amount; }

3-2. 클래스를 final 로 선언해서 하위 클래스에서 확장하지 못하게 할 것

public final class Money { }

3-3. 모든 필드를 final 로 선언할 것

private final String currency;

3-4. 모든 필드를 private 으로 선언해서 외부 접근을 막을 것

3-5. 자기 자신의 참조를 외부로 노출하지 말 것

  • 가변 객체를 참조하는 경우, 방어적 복사로 반환해야 한다.

public Date getDate() { return new Date(date.getDate()); }

4. 대표적인 불변 클래스 예시

public final class Complex { private final double re; private final double im; public Complex(double re, double im) { this.re = re; this.im = im; } public double realPart() { return re; } public double imaginaryPart() { return im; } public Complex plus(Complex c) { return new Complex(re + c.re, im + c.im); } // equals, hashCode, toString 등도 구현 }
  • 내부 상태를 변경하지 않고, 새로운 인스턴스를 반환하는 방식으로 동작한다.

5. 단점과 해결 전략

  • 성능과 메모리 비용이 증가할 수 있다.

    • ex) 매 연산마다 객체가 새로 생성되는 경우 (BigInteger 연산)

  • 복잡한 객체 상태 변경이 필요한 경우

    • Builder 패턴이나 가변 동반 클래스(mutability companion) 를 함께 사용할 수 있다.

public final class Person { private final String name; private final int age; private Person(String name, int age) { ...} public static class Builder { private String name; private int age; public Builder setName(String name) { this.name = name; return this; } public Builder setAge(int age) { this.age = age; return this; } public Person build() { return new Person(name, age); } } }

6. 결론

  • 가능한 한 모든 객체는 불변으로 설계해야 한다.

  • 불변 객체는 단순하고 안전하며, 동기화 문제 없이 여러 환경에서 활용할 수 있다.

  • 반드시 불변일 수 없는 경우가 아니라면 기본값은 불변으로 생각해야 한다.

  • 특히 여러 스레드에서 객체를 공유하거나, 콜렉션의 키로 사용할 때는 불변성이 매우 중요하다.

Last modified: 09 April 2025