불변(Immutable) 개념에 대한 혼란

Java에서 프리미티브(Primitive) 타입 및 String 객체는 불변 속성이 있다.

음... String 객체는 알겠는데, 프리미티브 타입도 불변하다고 말할 수 있는건가? 하는 의문이 들었고 이것부터 짚고 넘어가고자 한다.

불변(Immutable)의 개념

최초 생성 이후로는 상태(속성)를 변경할 수 없는 성질

String 클래스를 예로 들어보자. Java에서 String은 불변하게 구현되어 있기 때문에 + 연산을 하더라도 초기 생성 이후로는 객체를 수정할 수 없다.

String str = "a";
str += "b";

초기 상태. String str = "a"
재할당. str += "b"

기존에 0xAB에 있던 String에 "b"를 추가하는게 아니라 새로운 "ab" 객체를 만들고 str이 해당 객체를 참조하도록 레퍼런스를 변경하고 있다.

Java에서 불변 속성을 이야기 할 때는 객체에 대한 것이고. 객체가 아닌 프리미티브 타입에 대해선 불변(Immutable)인가 아닌가를 이야기 하기가 어렵다.

왜 프리미티브 타입에 대해선 불변 속성을 따지기가 어려운가

프리미티브 타입은 레퍼런스로 참조되지 않고 변수에 직접 값을 가지고 있다.
int 연산을 예로 들면, 다음과 같다.

불변하다는 것은 어떤 것(Identity)의 속성을 바꿀 수 없는 것을 말하는데, int a에는 속성이랄게 없다.
객체는 명확히 속성이 있다. String 객체는 자신의 char[] 속성을 가지고 있고, 이 char[]을 변경할 수 없기에 immutable 하다고 한다.
int a는 속성이 없다. a는 그 자체로 값이다. 다시 말해 Identity가 곧 value이다. 새로운 연산이 일어날 때 마다 새로운 값(새로운 Identity)로 교체된다. Immutable은 Identity와 속성의 구분이 있어야 적용할 수 있는 개념으로 생각된다.

왜 불변 속성이 필요한 걸까?

우선 왜 Java에서 String을 불변하게 구현했는지 부터 찾아봤다.

  1. 메모리 절약
    String은 광범위하게 사용되는 객체이다. 같은 값을 갖는 경우 기존 객체를 재사용하여 힙 메모리 공간을 절약할 수 있다.

    String str1 = "hello world";
    String str2 = "hello world";

    String이 불변하지 않다면 str1, str2 각각 객체를 생성해야겠지만, 불변하기 때문에 같은 객체를 바라봐도 무방하다.

    String str1 = "a";
    while(...) {
        str1 += "a";
    }

    그러나 위 코드와 같이 String값을 변경하는 연산이 많은 경우, 10만번 연산을 한다고하면, 10만개의 객체가 생성되므로 이런 경우에는 주의해야 한다. 이 경우엔 StringBuffer를 사용하는 것이 좋다. StringBuffer는 불변이 아닌, 힙에 할당된 버퍼의 크기를 늘이거나 줄이면서 동작하기 때문에 실제 메모리에 객체가 1개만 생성된다.

  2. 성능 향상
    String은 매우 자주 사용되는 객체이고, HashMap, HashTable, HashSet 등에서 해시코드 계산도 그만큼 많을 것이다.
    String의 불변 속성으로 인해 최초 한번간 hashCode() 연산이 수행되고 이후에는 캐싱된 값을 리턴하게 되어 성능에서 이득이 있다.

  3. Thread-safe
    상태를 가지는 객체가 여러 스레드에 의해 공유될 때 문제가 생긴다. 이럴 때 사용하는 동기화 기법이 여러가지가 있는데, 예를 들면 lock을 건다던가 등이다. 불변 속성은 동기화 기법은 아니지만 객체를 Read-only로만 제공함으로써 상태를 변경하는 행위를 원천적으로 차단한다. 쓰기 기능을 포기하는 대신 Thread-safe 장점을 얻어간다고 볼 수 있다. 

여기까지가 String 클래스의 불변속성이었다. 

 

레퍼런스

https://stackoverflow.com/questions/18037082/are-java-primitives-immutable

https://www.baeldung.com/java-string-immutable

+ Recent posts