Skip to content

불변 객체(Immutable Object), 정말 언제나 좋을까? #2

@YehyeokBang

Description

@YehyeokBang

상황

불변 객체는 한 번 생성되면 내부 상태가 바뀌지 않는다.
자바에서는 final 필드와 생성자 주입을 통해 불변성을 유지하는 객체를 만들 수 있다.

public final class Money { // 상속 방지

    private final int amount; // 재할당 방지

    // constructor, getter..
}

나는 상태 변경에 따른 사이드 이펙트를 줄이기 위해 모든 객체를 불변으로 유지하려고 했다.
우테코 미션과 같이 작은 규모의 프로그램에서는 방식이 문제를 일으키지 않았고,
오히려 예측 가능성, 디버깅 편의성 등이 장점으로 느껴졌다.

그래서 가능한 모든 객체를 불변으로 만들자는 방향으로 구현을 진행했다.

레벨 인터뷰를 하며, 몇 가지 애매한 부분들을 발견했다.
다양한 상황에서는 어떤 선택을 할 것 같은지 의도적으로 고민해보려고 한다.
(단순히 불변 = 좋던데이라는 생각에서 벗어나, 기준을 명확히 하고 싶다.)

장단점

장단점을 한번 확인하고 고민하면 좋을 것 같다.

수정 전의 객체와 수정 후의 객체는 정말 ‘다른’ 객체일까?

불변이 주는 이점은 분명하지만, 어느 순간부터 이런 의문이 들었다.

수정 전의 객체와 수정 후의 객체는 정말 다른 객체일까?

예를 들어, 사람의 나이는 시간이 지나면서 자연스럽게 증가해야 한다.
이때도 불변을 고집하면 아래처럼 새 객체를 만들어야 한다.

public final class Person {

    private final String name;
    private final int age;

    // constructor, getter..

    public Person growOlder() {
        return new Person(name, age + 1);
    }
}
Person bello = new Person("Bello", 20);
Person olderBello = bello.growOlder();

olderBello는 bello의 나이만 1살 늘어난 버전이다.
분명히 같은 사람을 표현하고 있지만, 실제로는 서로 다른 인스턴스다.
bello == olderBellofalse를 반환한다.

물론 olderBello를 기존 bello 변수에 덮어씌우면 되지만, 이 과정은 꽤나 어색하게 느껴졌다.
객체는 분명 같은 실체를 표현하는데, 코드에서는 다른 인스턴스로 다뤄진다.

이처럼 상태가 변하는 게 자연스러운 도메인에서도, 불변 객체를 고집해야 할까?

불변 객체는 성능을 고려해야 한다?

불변 객체는 상태가 바뀔 때마다 새로운 인스턴스를 생성해야 한다.
덕분에 불변은 성능에 안 좋다는 이야기를 자주 들었다.

그러나 실제로는 불변 객체가 성능에 문제를 일으킨다고 체감한 적은 없다.
아마도 작은 미션 환경이라서 그런 것 같다.

규모가 커지고 객체 생성 비용이 누적된다면 어떤 일이 생길 수 있을까?

지금은 체감하지 못했지만, 이후 큰 서비스에서는 영향을 줄 수도 있다.
이 점도 한번 짚고 넘어가면 좋겠다고 느꼈다.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions