티스토리 뷰

 이 포스팅은 사실, 하고싶은 다음 포스팅을 위한 밑밥이라고 보시면 됩니다.

 오랜만에 포스팅해보고 싶은 이야깃거리가 생겼는데, 거기서 불변성의 개념까지 설명하기엔 너무 주제를 벗어나는 느낌이기도하고 불변성(Immutability)이라는 개념 자체도 충분히 하나의 포스팅거리로 삼을법한 주제이기 때문에, 이 포스팅을 작성하게 되었습니다.


0. 변수인데 불변한다는게 무슨 말이야?

 처음 불변성이라는 용어를 Javascript를 공부하며 들었을때, 머릿속에 들었던 첫 번째 물음.

 우리는 개발을 하고 코드를 작성하며 수많은 변수를 사용한다. 변수라는 건 엄연히 변경이 가능한 수를 뜻하고, 변하지 않는 수라면 그건 상수라고 칭하면 될 텐데 굳이 불변성이라는 용어로 정의하면서까지 설명을 해놓는 이유가 뭘까.

 

1. 포인터

나는 개발입문을 C언어로 한 사람으로써, 포인터의 개념을 뼛속까지 깊이 새겨놓은 개발자 중에 한 사람이다. 철수와 영희네 집 주소부터 시작해서 집 명패가 어쩌구저쩌구 하면서 배웠던 바로 그 개념. 포인터의 가장 중요한 개념은 바로 모든 '값'은 메모리에 존재하며, 그 메모리에 적재된 값을 우리가 사용하기 위해 가리키는 지시자가 바로 '포인터'라는 것이다. 이러한 개념을 Call by reference, 라고도하는데 '참조의 형태로 값을 바라본다'라는 의미로 이해하면 될 것 같다. '포인트'라는 용어를 네이버 사전에서 찾아보면 여러가지 뜻이 나오지만, 여기에서의 개념과 가장 유사한 뜻은 '한 점'으로써, 값이 적재된 메모리의 한 지점을 '포인트'라고 생각했을때, 그 지점을 가리키는 주체에게 point + 'er'을 붙여서 pointer(포인터)라고 명명한 것이다. 즉, '메모리에 적재된 값'을 가리키는(참조하는) 주체가 바로 포인터인 것이다.

void main(){
 int num = 5;
 int *p = #
}

만약 위와 같은 코드로 작성이 되었다면, 아래와 같은 형태로 메모리와 메모리에 적재된 값이 구성되게 된다.

대략 이런 형태

num이라는 변수는 104번지의 메모리영역을 가리키는데, 104번지에는 int num = 5; 라는 코드를 통해 할당한 '5'라는 값이 정의되어있고 포인터 p가 가리키는 메모리영역인 200번지에는 &num을 통해 할당한 변수 num의 주소지인 104가 '값'으로 정의되어있다.

 

여기서 잠깐...C언어 문법을 모르시는 분들을 위한 설명을 곁들이자면, C언어에선 변수명 앞에 애스터리스크...그러니까 흔한 표현으로 별표(*)를 붙이면 해당 변수는 '포인터'라는 표현이며 해당 포인터 변수가 가리키는 주소지의 값을 의미한다.

그리고 변수앞에 앤드연산자인 '&'을 붙이면, &가 붙은 변수는 해당 변수가 가리키는 메모리 영역의 값이 아니라 그 변수가 가리키는 메모리의 주소값을 리턴한다.

 

따라서, p라고 명명된 변수가 실제 메모리에 가지고 있는 값은 104라는 주소지값이지만 애스터리스크를 붙인 *p의 형태로 활용되면 p가 가리키는 200번지 메모리의 값이 가리키는(참조하는) 104번지의 값인 5를 활용할 수 있게 되는 것이다.

 

2. Javascript Primitive Type

느닷없이 Javascript의 불변성(Immutability)을 포스팅하면서 왜 갑자기 C언어의 포인터까지 언급을 했냐면, 변수의 메모리 할당적인 관점을 먼저 이해하면 불변성을 이해하기 좀 더 쉽기 때문이다(내가 그랬으니까)

 

자, 그럼 이제 본격적으로...Javascript에서 불변성을 띄는 대표적인 것들은 Primitive Type으로 분류되는 것들이다.

 

  • boolean
  • number
  • bigint
  • string
  • undefined
  • null
  • symbol

이렇게 7종세트가 Primitive Type(원시타입)으로써, Javascript에선 Immutability하다고 표현을 한다. 그 외에 모든 값은 객체(Object) 타입으로 분류되며, 객체 타입은 Mutable로써 변경이 가능한 값이다.

 

3. 이제 Immutability에 대해서 설명해보자

자...아주 간단한 예시를 들어보자. 우리는 흔하게 아래와 같은 코드를 쓴다.

let str = "hello";
str = "world";

어, 뭔가 이상하다.

 

Javascript에서 string은 분명 Primitive Type으로써 불변성을 가진다고 했는데,

str의 값이 "hello"에서 "world"로 변경됐다. 이러면, 값이 변한게 아닌가?

...라는 생각을 나도 처음에 했었다. 누가봐도 '코드'로 활용된 형태를 본다면 그렇게 생각 할 수 있으니까.

 

자, 질문을 하나 던져보겠다.

위의 2줄짜리 코드에서 '값'은 변했을까?

 

이 질문에 대한 답은 당연하게도 '값은 변하지 않았다'이다. 변한 것은 str이라는 변수가 가리키는 '값'이지, 기존에 가리키던 "hello"라는 순수한 값이 변경된 것은 아니다.

 

그러니까, 약식으로 그려보자면 다음과 같달까.

메모리에 적재된 "hello"는 여전히 그대로이고, str이 가리키는 곳이 "world"로 변경되었을 뿐이다.

즉, 변수 str이 가리키는 메모리의 위치가 바뀐 것이지, 실제 메모리에 있는 '값'이 변경된 건 아닌것이다.

Primitive Type의 string은 이렇게 불변성을 지키게 되는 것이다.

 

이와 마찬가지로 나머지 Primitive Type인 number나 boolean등도 불변성을 지키게 된다.

여기에 덫붙이고자 Stack overflow에서 무려 9년전에 올라온 재미난 질문이 있어서 덫붙여본다.

https://stackoverflow.com/questions/10648367/is-number-in-javascript-immutable

 

4. Object는 Mutable하다, Obejct는 참조(reference)하기 때문이다. 

이와 같이, Javascript의 Primitive Type들은 '불변성'을 지키는데반해 나머지 '값'을 지칭하는 객체(Object)들은 변경이 가능한(Mutable) 형태로 활용된다. 왜 객체는 Mutable 할까? 

 

자바스크립트의 객체는 키(key)과 값(value)으로 구성된 프로퍼티(Property)들의 집합이다.
                                                                                                                               - poiemaweb

이 질문에 대한 답은 이미 1. 포인터에서 언급한 것이나 마찬가지다.

위 인용구와 같이 Javascript의 Object는 키(key)와 값(value)으로 구성된 프로퍼티의 집합이고, 이로인해 객체의 모든 연산은 참조하고 있는 '값'을 바탕으로 실행되게 된다. 

 

즉, C언어의 포인터와 같이 Call-by-reference의 개념으로서 바라보면, Object로써 선언한 객체를 Primitive Type에서처럼 값을 '변경'하는 듯한 코드를 작성한다하더라도, 새로운 메모리 영역에 새로운 '값'을 할당하고 그 값을 변수가 바라보는 형태로써 불변성이 지키는 게 아니라...객체가 참조하는 메모리 영역의 '값'을 변경하는 것이기에 객체는 Mutable하다고 정의하는 것이다.

 


참고 사이트 : https://poiemaweb.com/js-object

댓글
최근에 올라온 글
Total
Today
Yesterday