HwangHub
[Java] 문자열은 왜 불변 객체로 설계되었나요? 본문
String name = "Hwang";
String anotherName = "Hwang";
name = "Jack";
name에 "Hwang"을 할당했다가 "Jack"을 할당할 수 있으니 불변 객체가 아니지 않냐고?
만약 이런 의문이 들고 있다면 참조 변수와 객체에 대하여 먼저 알아봐야 한다.
이러한 질문은 들지 않는 상태라고 가정하고 시작한다.
name에는 "Hwang"이 할당될 때, Hwang이라는 데이터를 가진 문자열 데이터가 JVM 메모리 구조 중 Heap에 생성되어 저장되었을 것이다. name이라고 하는 변수는 그저 heap 영역에 생성된 "Hwang"이라는 문자열 객체를 가리키고 있을 뿐이다.
그럼 이제 anotherName을 보자. 이 변수에도 "Hwang"이라는 문자열 객체를 참조하도록 하였다. 그렇다면 Heap에는 "Hwang"이라는 값을 갖는 문자열 객체가 두 개 생성된 것일까?
다행이게도, "Hwang"이라는 하나의 객체를 name 과 anotherName 둘 다 참조하고 있게 된다. 자바에서는 String pool을 heap 영역 중 일부로 할당하여, 문자열 객체를 변수에 할당할 때 해당 String pool을 체크하여 동일한 내용의 문자열이 있는지 체크하는 과정을 거친다. 이를 통해 동일한 의미를 갖는 객체들이 불필요하게 중복 생성되지 않을 수 있어서, 효율적으로 메모리를 활용할 수 있도록 해 준다.
이게 왜 불변 객체랑 관련이 있냐고? 위의 상황에서 다시 생각해보자. 만약 불변 객체가 아니게 설계된다면 name과 anotherName 에 "Hwang"을 할당한 뒤 name에 "Jack"을 할당한 상황에서, 개발자는 anotherName도 "Jack"이 되길 원하고 있을까? 10에 9은 아닐 것이다. 즉, 문자열이 불변 객체가 아니라면 anotherName은 "Hwang"을 가지고 있어야 하기 때문에 별도의 "Hwang" 객체로 애초에 할당해야 하는 것이다.(== 애초에 같은 객체를 바라보고 있어서는 안된다는 것이다.)
따라서 불변 객체가 아니게 설계된다면 메모리를 효율적으로 사용하려고 하는 String pool이라는 구역은 의미가 없게 된다.
String name = "Hwang";
String antoherName = "Hwang";
String otherName = new String("Hwang");
System.out.println(name == anotherName); // true
System.out.println(name == otherName); // false
이제 이 상황을 가정해보자. String도 객체인데, 왜 지금껏 우리는 new 키워드를 사용하지 않았는지 이해하여야 한다.
new 키워드는 일반적인 객체를 생성할 때 사용하는 자바 키워드이다. 하지만 자바 철학 속에서, 문자열은 정말 많이 사용될 데이터 중 하나라고 보았기 때문에 기본적으로 String pool이라는 영역을 별도로 이용하여 효율적으로 관리하려고 하는 것이다. 하지만 new 키워드를 사용하게 되면, 이를 일반적인 객체라고 인식하여 String pool 외부의 heap 영역을 할당하여 객체를 저장하게 된다.
아시다시피 ==는 객체가 저장된 메모리 주소를 비교함으로써 완전히 동일한 객체를 가리킬 때 동일하다는 결과를 반환한다. 따라서 name과 anotherName은 완전히 동일한 "Hwang"이라는 String pool 내에 존재하는 문자열 객체를 가리키고 있으므로 true를 반환한다.
하지만 name과 otherName은 전혀 다른 객체를 바라보고 있다. otherName이 바라보는 "Hwang"이라는 문자열 객체는 string pool 외부에 별도로 존재하는 전혀 다른 문자열 객체이므로 name == otherName이 false일 수 밖에 없다.
그 외에 문자열이 불변 객체이기 때문에 얻는 장점으로써는, 변하지 않기 때문에 이를 이용하여 보안성이 필요한 로직에 활용될 수 있다는 것이다. 또한 불변 객체의 잘 알려진 특징 중 하나인 thread-safe는 당연하다.
'workspace > 아티클' 카테고리의 다른 글
[OAuth] 동작 원리 (0) | 2023.12.07 |
---|---|
[Java] String, StringBuilder, StringBuffer의 차이에 대한 고리타분한 이야기 (0) | 2023.12.07 |
[cloudfront] 재배포 시 뭐 하면 되나? (0) | 2023.11.27 |
[트러블슈팅] AWS S3 : NoSuchKey 이슈 (1) | 2023.11.26 |
[Java] Garbage Collection (1) | 2023.11.24 |