들어가면서
얼마 전, 이펙티브 자바 스터디를 하면서 불변 객체에 대한 토론을 하게 되었습니다.
그리고 준팍, 아벨 등을 비롯한 크루분들도 불변 객체에 관한 고민을 많이 하고 있는 것 같았습니다.
그 과정에서 '불변 객체의 본질은 무엇인가?'에 대한 아이디어를 얻어 글을 작성해보려고 합니다.
불변객체를 구글에 검색해보면, 비용을 제외한 단점이 없는 것 같아 보입니다.
하지만 불변객체의 장/단점만으로는 적용 시점을 결정할 수 없는 것 같습니다.
불변 객체에 대해 검색하다보면, 아래와 같은 고민들이 당연히 피어날 수 밖에 없습니다.
- 무엇을 불변객체로 결정해야 할까?
- 언제가 비용을 지불하면서도 불변객체를 사용할 때일까?
하지만 불변객체 사용 시점은 단편적으로 결정할 수 있는 부분이 아니라고 생각합니다.
예를 들어서 자동차 경주 미션에서 무엇을 불변 객체로 설정할 것인지 결정한다고 해봅시다.
이동 거리, 자동차, 혹은 자동차 경주 게임.. 무엇을 불변 객체로 설정할까요?
명확한 판단을 내릴 수 없는 것 같습니다.
즉, 불변객체 사용 시점은 문맥에 따라 결정되며, 이는 설계 관점에서 바라볼 수 밖에 없음을 의미합니다.
따라서 불변 객체란 무엇인지부터 어떻게 사용 시점을 결정할 수 있는지에 대한 저만의 생각을 작성해보려 합니다.
학습을 위한 아티클이기에, 틀린 부분은 존재할 수 있고 지적해주시면 감사하겠습니다 :)
설계 관점에서의 불변 객체란
불변 객체란 말 그대로 불변한 객체를 의미합니다.
장단점은 이미 많은 분들이 작성해주셨기에 따로 작성하지 않겠습니다.
따라서 불변 객체를 사용한다는 것의 의미가 설계 관점에서 무슨 의미를 가지는지를 알아보려 합니다.
자동차 경주 미션을 예로 들어보겠습니다.
자동차 경주 미션에는 자동차 객체가 존재하고, 자동차는 위치 정보를 가집니다.
코드로 한번 표현해볼게요.
Car 객체와 Position 객체가 각각 존재할 것 같습니다.
public class Car {
private final Position position;
public Car(final Position position) {
this.position = position;
}
}
public class Position {
private final int value;
public Position(final int value) {
this.value = value;
}
}
위처럼 표현할 수 있을 것 같습니다.
그러면 Position 객체의 불변을 보장하면서도 자동차가 이동할 수 있는 기능을 추가해볼게요.
public class Position {
private final int value;
public Position(final int value) {
this.value = value;
}
public Position add(final int distance) {
return new Position(value + distance);
}
}
public class Car {
private Position position; // final을 붙일 수 없다.
public Car(final Position position) {
this.position = position;
}
public void move(final int distance) {
position = position.add(distance);
}
}
불변 객체를 사용했을 때의 특이점이 보이는 것 같습니다.
Position 객체가 불변객체이기에 move라는 책임을 수행하기 위해서는 Position 객체를 항상 갈아 끼워야합니다.
그렇다면 비슷한 접근 방법으로 Car도 불변으로 만들면 안될까요?
public class Car {
private final Position position;
public Car(final Position position) {
this.position = position;
}
public Car move(final int distance) {
return new Car(position.add(distance));
}
}
이렇게 하면 Car 객체까지도 불변으로 만들 수 있습니다.
하지만 또 같은 문제가 반복되는 것 같습니다. Car를 호출하는 다른 클래스가 또 한번 영향을 받습니다.
이처럼, 불변 객체를 어디까지 적용할 것인지는 어디까지 갈아끼우는 것을 허용할 것인지와 동일한 맥락이라고 생각합니다.
따라서 저는 불변 객체는 비용의 관점에서 바라보아야 한다는 판단에 이르렀습니다.
불변은 가변 상태에서의 하나의 스냅샷입니다.
Position은 0 ~ 100까지의 값을 가질 수 있다고 해보겠습니다.
그렇다면 Position을 불변 객체로 설정한다면, 자동차 객체마다 최대 100번 갈아끼울 수 있다는 의미입니다.
불변은 한 순간에 하나의 상태밖에 표현할 수 없으니까요..!
따라서 불변 객체가 무조건 좋다, 나쁘다가 아닌, 설계 그리고 비용 관점에서 불변을 바라보아야 할 것 같다는 생각이 듭니다.
타협지점을 찾는 것이 목표
결국은 비용 vs. 유지보수성 + 성능이라고 생각합니다.
불변은 하나의 문맥을 표현할 수 밖에 없습니다.
예를 들어서, 자동차 경주 게임에서 자동차를 불변 객체로 설정한다면,
해당 객체는 '특정 A라는 위치의 자동차'라는 문맥만 제공합니다.
따라서 문맥의 개수, 객체의 비용 등 모든 상황을 종합적으로 고려해야
불변 객체를 어디까지 사용할 것인지에 대한 타협점을 찾을 수 있는 것이 아닐까 생각이 듭니다.
마찬가지로 'VO를 불변 객체로 설정해라'라고 하는 이유도 VO는 시스템을 트리 구조로 본다면 가장 말단 노드에 위치하고, 갈아끼우는 비용이 당연히 적기 때문에 그런 것이 아닐까 생각이 듭니다.
적은 비용으로도 안정성을 제공할 수 있으니까요.
하지만 VO라도 값비싼 객체라면(정보를 매우 많이 담고 있다면) 불변을 보장해야 할지는 고려해봐야 한다고 생각합니다.
마지막으로
이번에는 불변 객체에 대해 알아보았습니다.
사실 아직 불변 객체가 언제 유용하게 사용될 수 있는지, 왜 유용한지는 경험해보지 못했던 것 같습니다.
따라서 이 글만으로는 불변 객체의 모든 것을 이해하기 어렵다고는 생각합니다.
그래도 정리하면서 저 자신의 나름의 기준을 확립할 수 있는 시간이었어서 만족합니다.
'우테코 5기' 카테고리의 다른 글
레벨 1 레벨로그 (1) | 2023.03.30 |
---|---|
[레벨 1 미션] 체스 미션 회고 (1) | 2023.03.29 |
getter는 금기가 아니다 (3) | 2023.03.25 |
[레벨 1 미션] 블랙잭 게임 미션 회고 (7) | 2023.03.22 |
[레벨 1 미션] 사다리 타기 미션 회고 & 학습기록 (1) | 2023.03.12 |