본문 바로가기

개발/javascript

원시 값과 객체의 비교02 - 문자열과 불변성

"원시 값과 객체의 비교"

 

1.2. 문자열과 불변성

자바스크립트에서는 문자열도 원시값이다. "데이터 타입에 의한 메모리 공산의 확보"에서 살펴보았듯이 메모리 공간을 확보할 때 데이터 타입이 필요하다. 원시 값을 저장하려면 먼저 확보해야 하는 메모리 공간의 크기를 결정해야 한다. 이를 위해 원시 타입 별로 메모리 공간의 크기가 미리 정해져 있다고 했다. 단, ECMAScript 사양에 문자열 타입(2byte)과 숫자 타입(8byte) 이외의 원시 타입은 크리를 명확히 규정하고 있지는 않아서 브라우저 제조사의 구현에 따라 원시 타입의 크기는 다를 수 있다.

 

원시 값인 문자열은 다른 원시 값과 비교할 때 독특한 특징이 있다. 문자열은 0개 이상의 문자(character)들로 이루어진 집합을 말하며 1개의 문자는 2byte의 메모리 공간에 저장된다. 따라서 문자열은 몇개의 문자로 이루어졌는지에 따라 필요한 메모리 공간의 크기가 결정된다. 숫자 값은 1도, 1000000도 동일한 8byte가 필요하지만 문자열의 경우, (실제와는 다르지만 단순하게 계산했을 때) 1개의 문자로 이루어진 문자열은 2byte, 10개의 문자로 이루어진 문자열은 20byte가 필요하다.

// 문자열은 0개 이상의 문자들로 이루어진 집합이다.
var str1 = '';		//  0개의 문자로 이루어진 문자열(빈 문자열)
var str2 = 'Hello';	// 5개의 문자로 이루어진 문자열

이와 같은 이유로 C는 하나의 문자를 위한 데이터 타입(char)만 존재할 뿐 문자열 타입이란 존재하지 않는다. C는 문자열을 문자들의 배열로 처리하고 java는 문자열을 String 객체로 처리한다.

 

하지만 자바스크립트는 개발자의 편의를 위해 원시 타입인 문자열 타입을 제공한다. 즉, 자바스크립트의 문자열은 원시 타입이며 변경 불가능하다. 이것은 생성된 이후 변경할 수 없다는 것을 의미한다.

var str = 'Hello';
str = 'world';

첫 번째 문이 실행되면 메모리에 문자열 'Hello'가 생성되고 식별자 str은 문자열 'Hello'가 저장된 메모리 셀 주소를 가리킨다. 그리고 두 번째 문이 실행되면 이전에 생성된 문자열 'Hello'을 수정하는 것이 아니라 새로운 문자열 'world'를 메모리에 생성하고 식별자 str은 이것을 가리킨다. 이때 문자열 'Hello'와 'world'는 모두 메모리에 존재하고 있다. 식별자 str은 문자열 'Hello'를 가리키고 있다가 문자열 'world'를 가리키도록 변경되었을 뿐이다.

 

문자열의 한 문자를 변경해 보자. 문자열은 유사 배열 객체이므로 배열과 유사하게 각 문자에 접근할 수 있다.

유사 배열 객체(Array-like Object)
유사 배열 객체는 마치 배열처럼 인덱스로 프로퍼티 값에 접근할 수 있고 length 프로퍼티를 갖는 객체를 말한다. 문자열은 마치 배열처럼 인덱스를 통해 각 문자에 접근할 수 있으며 length 프로퍼티를 갖기 때문에 유사 배열 객체이고 for 문으로 순회할 수 있다.
갑자기 원시값인 문자열이 객체일 수도 있다니 혼란스러울 수 있겠다. 아직 살펴보지 않았지만 원시값을 객체처럼 사용하면 원시 값을 감싸는 래퍼 객체로 자동 변환된다.
var str = 'string';

// 문자열은 유사 배열이므로 배열과 유사하게 인덱스를 사용하여 각 문자에 접근할 수 있다.
// 히지만 문자열은 원시 값이므로 변경할 수 없다. 이때 에러가 발생하지 않는다.
str[0] = 'S';

console.log(str);	// string

str[0] = 'S' 처럼 이미 생성된 문자열의 일부 문자를 변경해도 반영되지 않는다. 문자열은 변경 불가능한 값(immutable value)이기 때문이다. 이처럼 한번 생성된 문자열은 read only한 값으로서 변경할 수 없다. 원시 값은 어떤 일이 있어도 불변한다. 따라서 예기치 못한 변경으로부터 자유롭다. 이는 신뢰성을 보장한다.