문자열은 값형식이 아닌 참조형식으로 heap 메모리에 실제 값을 저장한다.
string str1 = "안녕하세요";
string str2 = str1;
str2 에 str1 의 참조주소를 할당하였고
str2 또한 str1의 "안녕하세요"라는 데이터를 가리키게 된다.
이때 만약 str1의 문자를 변경하면 어떻게 될까
string str1 = “안녕하세요”;
string str2 = str1;
str1 = "abc";
일반 참조타입과 다른방식으로 작동하게 된다.
일반적인 참조타입의 경우 가변객체의 특성으로 heap 영역의 데이터가 변경되어도
참조는 그대로 유지하며 데이터만 변경된다.
하지만 위의 그림과 같이 문자열은 heap 영역의 데이터를 변경하는 경우
다시 새로운 메모리를 할당하게 된다.
이러한 성질을 불변성이라 하며, 문자열은 불변성(Immutable) 객체라고 한다.
반대로 일반적인 객체는 가변성(Mutable) 객체라 한다.
가변성과 다른 불변성이란 객체가 생성된 이후 내부 상태가 변하지 않는 것을 의미한다.
고로, 위처럼 "안녕하세요" 라는 데이터를 변경하려 했지만
기존의 데이터는 그대로 두며 아예 새로운 데이터를 만들어버리게 되는것이다.
그럼 문자열은 왜 불변성이라는 방식을 사용할까?
1. 문자열이 불변성객체인 첫번째 이유는 String Pool 때문이다.
String pool 은 동일한 문자열을 프로그램 내에 재사용하는 메모리 최적화 기법이다.
str1 = "abc";
str2 = "abc";
str3 = "abc";
...
str100 = "abc";
위의 코드처럼 100개의 문자열 객체가 있다고 가정해보자
문자열객체가 100개가 존재하는데, 내부 데이터는 전부 "abc" 라는 값으로 동일하다면
이 모든 문자열을 개별적으로 둘 필요가 없다.
만약 "abc" 라는 값은 전부 동일하므로 하나의 데이터 값을 가리키게 된다면
99개의 메모리 공간을 절약할 수 있게 되는 셈이다.
이러한 문제를 해결하기 위한 기술이 StringPool 기법이다.
평소처럼 문자열을 선언해보면
string str1 = "abc";
라고 선언하게 된다.
참조 타입 객체이지만 (C# 기준) new 키워드를 사용하지 않는다.
new 키워드를 사용해서 선언해보자!
string str2 = new string("abc");
별 문제없이 문자열이 생성되며, 별반 다른게 없어보이지만, 이는 바로 위 str1 과 다른 방식으로 문자열을 생성한다.
첫번째 if 문은 StringPool 문자열 리터럴로 인해 하나의 영역을 가리키게 된다.
두번째 if 문 str3 는 new 키워드를 통해 아예 새로운 heap 영역을 만들기 때문에 참조가 일치하지 않는다.
마지막 if 문 str4 는 string의 Intern 이라는 메서드를 통해 문자열을 생성하게 된다.
결과값은 StringPool 의 같은 메모리 영역을 가리키는 것을 알 수 있다.
Intern 이라는 메서드 작동박식은 StringPool 내부에 해당 문자열이 있는지 확인하고,
만약 같은 문자열이 있다면 그대로 반환하게 되고,
해당 문자열이 없다면 새로운 리터럴을 StringPool에 넣어주게 된다.
문자열 리터럴 생성방식은 전부 이 Intern 메서드를 통해 생성하게 된다.
사용자의 편의성을 제공하기 위해 str1 = "abc" 처럼 간단하게 구현할 수 있게 되었다.
이렇게 문자열을 리터럴 하는방식으로 heap 영역의 StringPool을 통해
중복되는 문자열 데이터를 재사용하여 메모리측면으로 효율성을 높일 수 있게 된다.
이러한 이유로 StringPool 을 이용하기 위해 한번 생성된 문자열은 불변성을 지켜줘야한다.
2. 문자열이 불변성객체인 두번째 이유는 보안성 때문이다.
사용자의 이름이나, 비밀번호 처럼 중요한 데이터 형식은 주로 문자열로 구성된다.
만일 해커가 접근하여 이러한 데이터정보를 수정하려 할 때
문자열이 가변성객체라면 해커의 의도대로 데이터가 변경되어버리게 된다.
반면 문자열은 불변성객체이기에 해커의 공격에도 값이 변경되는 문제를 예방할 수 있게된다.
3. 문자열이 불변성객체인 세번째 이유는 동기화 때문이다.
위의 두번째 이유, 외부의 접근으로 인해 값이 변경되는 상황을 방지할 수 있다고 했다.
이러한 상황을 프로그램 내부의 측면에서 볼때 외부 접근요소를 멀티 스레드로 볼 수 있다.
다른 스레드에서 문자값을 변경하려 해도 불변성객체이기에 값이 바뀔 위험이 낮아진다.
'CS' 카테고리의 다른 글
컴파일러 Compiler (0) | 2025.02.10 |
---|---|
DI & DIP 의존성주입과 의존관계 역전원칙 (0) | 2024.12.11 |
2의 보수 (0) | 2024.07.14 |
컴퓨터의 사칙연산 (보수법의 필요성) (0) | 2024.07.14 |
고정 소수점, 부동 소수점 (0) | 2024.07.09 |