본문 바로가기

Javascript

JavaScript 객체와 불변성

자바스크립트 내에서 데이터 타입은 크게 두 가지로 분류된다.

 

기본형 데이터와 참조형 데이터

 

기본형데이터 (Primitive Data)
참조형데이터 (Reference Type)
number
string
null
undefined
boolean
symbol
객체 
배열
함수
날짜
정규표현식
Map
Set

 

참조형데이터는 기본형데이터를 제외한 모든 객체라고 생각하면 되겠다.

데이터 타입을 나누는 이유는 복사를 할 때, 작동하는 방식이 완전히 다르다.

일단 가변성이라는 기준을 두고 보았을 때,

 

기본형데이터 = 불변

참조형데이터 = 가변

 

 

 

그렇다면 가변성이 복사를 할 때에, 어떠한 차이를 만드는 지 아래를 보며 생각해보자.

let a = 10
let b = 10

console.log(a===b)
//결과 True

let a1 = {name: "paul"}
let b1 = {name: "paul"}

console.log(a1===b1)
//결과 False

숫자로 같은 값을 부여했을 때와, 객체로 같은 값을 부여했을 때 다른 결과가 나오는 것을 알 수 있다.

이와 같이, 불변하는 데이터는 변수에 값을 할당하였을 때 같은 value를 가지지만

가변하는 데이터, 즉 객체타입은 겉으로 보기에는 같아보이지만 a1의 {name: "paul"}와는 또다른 위치에 {name: "paul"}라는 값을 가지게 된다.

이것을 통하여 우리는 변수를 복사할 때 일어나는 문제점을 생각해볼 수 있다.

let a = 10
let b = 10
let c = a

c = 20

console.log(a,c)
//결과 10 20

let a1 = {name: "paul"}
let b1 = {name: "paul"}
let c1 = a1

c1.name = "jessy"

console.log(a1,c1)
//결과 {name: 'jessy'} {name: 'jessy'}

 

위에서는 세번째 변수값에 불변하는 데이터를 넣으니, a값에 영향을 주지 않았다. 따라서 a=10이고, c=20이 된다.

하지만, 아래에서 세번쨰 변수값에 또다른 객체(가변하는 데이터)를 넣으니, a1값 또한 변하는 것을 알 수 있다.

c1 = a1 을 통해, c1과 a1이 같은 밸류를 공유하고 있는 도중, c1의 밸류를 바꾸니 a1과 c1이 공유하고 있는 밸류가 통째로 바뀌는 상황이 발생한 것이다.

 

그렇다면, 가변하는 데이터는 같은 값을 서로 다른 위치에서 가지게 할 수는 없을까?

let a1 = {name: "paul"}
let b1 = {name: "paul"}
let c1 = Object.assign({},a1)

c1.name = "jessy"


console.log(a1,c1)
//결과 {name: 'paul'} {name: 'jessy'}

 

Object.assign({}, 변수) 를 통하여, 서로 다른 위치에서 같은 값을 가지게 할 수 있다.

 

 

 

위의 상황을 해결했으나, 위의 방법에는 또 다른 문제점이 있다.

바로 객체 내에서 또다른 객체를 데이터에 포함할 경우이다.

let a1 = {name: "paul", pet: ["dog"]}
let c1 = Object.assign({},a1)

c1.pet = c1.pet.push("cat")


console.log(a1.pet,c1.pet)
//결과 ['dog', 'cat'] ['dog', 'cat']

 

Object.assign({}, 변수)를 했음에도 불구하고, 객체 내의 객체가 동시에 변하고 있음을 알 수 있다.

결국 Object.assign()은 얕게 복사될 뿐, 객체 내의 객체까지 침투되고 있지 못함을 알 수 있다. (객체 내의 객체는 같은 위치에서 공유하고 있음)

그렇다면, 어떠한 방식으로 객체 내의 객체까지 다른 위치에 값을 가지게 할 수 있을까?

.concat()을 이용해보자

let a1 = {name: "paul", pet: ["dog"]}
let c1 = Object.assign({},a1)

c1.pet = c1.pet.concat("cat")


console.log(a1.pet,c1.pet)
//결과  ['dog']  ['dog', 'cat']

.concat을 이용하여 값을 집어넣으니, 객체 내의 객체 값이 아까와 다르게 c1에서만 변경된 것을 알 수 있다.


처음에 이해하기 꽤나 복잡한 내용이였던 것 같다. 그래도 유튜브 "생활코딩"의 JavaScript immutability 강의를 듣고,
쉽게 이해할 수 있었던 것 같다.

데이터타입에 대해 궁금한 사람들은 위 유튜브에 한 번 들려보시길 권장한다.