데이터 타입

김영재·2024년 3월 31일
0

데이터

타입

데이터 타입 관련 글을 보기 전 아래의 상황을 공유하겠습니다.

let a = 10
let b = a
let address = { location:"서울특별시", detail:"1XX동 XXX호"}
let newAddress = address

b = 20
newAddress.location = "대구광역시"

console.log(a === b) // false
console.log(address === newAddress) // true

console.log(a === b) 의 결과는 누구나 쉽게 납득을 할 수있으나 두번째의 경우는 의아할 수 있다.
실제 현업에서 주소록관련 컴퍼넌트를 제작하면서 겪었던 경험이 있다. 기존 address를 newAddress로 수정하면서 address와 newAddress가 다른 경우만 해당 데이터 변경을 위한 api요청을 시도 하려했으나 비교시 일치한다는 결과가 출력되어 api요청을 하지 않았던 적이 있었다

분명 코드상 newAddress의 location의 값만 변경하였는데 address의 location마저 영향을 미치게되었다. 이유가 뭔지 또 이런경우 어떻게 해결을 해야할지 보겠습니다.

데이터 할당

위의 상황에서 자바스크립트가 어떻게 데이터 할당을 하는지 확인하겠습니다.

변수 영역주소1001100210031004
변수 영역데이터이름: a
값:@5001이름:b
값:@5001이름:address
값:@5002이름:newAddress
값:@5002
데이터 영역주소5001500250035004
데이터 영역데이터10@7103 ~ ?“서울 특별시”"1XX동 XXX호"
객체 @5002의 변수영역주소71037104
객체 @5002의 변수영역데이터이름:location
값: @5003이름: detail
값: @5004

기본형 데이터, 참조형 데이터 모두 복사시 같은 주소를 봅니다. 여기서 기본형과 참조형의 차이는 참조형은 객체 프로퍼티 영역이 따로 존재한다는 점입니다. 이제 문제의 상황인 복사한 변수에 값을 재할당 하려하는 경우 어떤 일이 생기는지 확인하면 아래와 같습니다.

변수 영역주소1001100210031004
변수 영역데이터이름: a
값:@5001이름:b
값:@5001 → @5006이름:address
값:@5002이름:newAddress
값:@5002
데이터 영역주소500150025003500450055006
데이터 영역데이터10@7103 ~ ?“서울 특별시”"1XX동 XXX호"“대구 광역시”20
객체 @5002의 변수영역주소71037104
객체 @5002의 변수영역데이터이름:location
값: @5003 → @5005이름: detail
값: @5004

변수 a와 b는 서로 다른 주소를 바라보게되었고 이로 인해 console.log(a === b) 가 false가 됩니다. 반면 address와 newAddress는 여전히 같은 객체를 바라보고있기에 위와 같은 문제가 발생하였습니다.

이로인해 해당 문제는 기본형은 주솟값을 복사하는 과정이 한번, 참조형은 한단계 더 거쳐 복사하기에 문제가 생긴다는것을 알았습니다.

불변객체

결론적으로 위와 같이 전달받은 객체에 변경을 가해도 원본 객체는 변하지 말아야하는경우의 문제 해결을 위해선 불변객체가 필요합니다. 여기서 주의 할 점은 참조형 데이터의 가변성은 내부 프로퍼티를 변경할 때 성립합니다. 즉, 새로운 객체를 return해야합니다. 그리고 이과정에서 얕은 복사, 깊은 복사 개념이 나옵니다.

위의 상황의 객체가 아닌 중첩객체의 경우 프로퍼티에 참조형 데이터가 또 할당이 되어 있는경우는 객체는 바로 아래 단계의 값만 복사하는 얕은 복사가 아닌 내부의 모든 값을 하나하나 복사하는 깊은 복사를 해야만 원하는 결과값을 얻을 수 있습니다.

간단하게 위의 문제를 해결하기 위해 깊은 복사를 통해 해결해 보겠습니다.

let a = 10
let b = a
let address = { location: "서울특별시", detail: "1XX동 XXX호" }
let newAddress = JSON.parse(JSON.stringify(address))

b = 20
newAddress.location = "대구광역시"

console.log(a === b) // false
console.log(address === newAddress) // false
profile
[ frontend-developer ]

0개의 댓글