참조 타입 — 주소가 복사되는 것들
객체·배열·함수는 변수에 값이 아니라 주소가 담긴다. 복사해도 같은 것을 가리켜서 한쪽을 고치면 둘 다 바뀐다.
Seobway · · 7분
복사한 객체를 고쳤는데 왜 원본까지 바뀌는가
원시 타입은 값이 복사되어 서로 독립적이었다. 객체는 다르다.
const original = { name: "서브웨이" };
const copy = original;
copy.name = "바뀜";
console.log(original.name); // "바뀜" ← 원본까지 바뀐다
복사한 것은 객체가 아니라 객체를 가리키는 주소이기 때문이다.
참조 타입은 무엇인가
참조 타입은 변수에 값이 아니라 메모리 주소(참조)가 저장되는 타입이다.
원시 타입 7가지가 아닌 것은 전부 참조 타입이다.
- 객체
{} - 배열
[] - 함수
function () {} - 그 밖에
Date·Map·Set·RegExp등
변수에 담기는 것은 실제 데이터가 아니라 "그 데이터가 어디 있는지" 다.
그래서 두 변수에 같은 주소가 들어가면 둘은 같은 하나를 본다.
인터랙티브 다이어그램: 참조 타입은 주소가 복사된다 (단계별로 재생할 수 있다)
- const original = { name: "서브웨이" } — 객체가 어딘가에 만들어진다.
- original 에는 객체가 아니라 그 객체의 주소가 담긴다.
- const copy = original — 복사되는 것은 주소다. 객체는 그대로 하나다.
- copy.name 을 고치면 주소를 따라가 그 하나뿐인 객체를 고친다.
- original 로 읽어도 같은 객체라 바뀐 값이 보인다.
비교도 주소로 한다
=== 는 참조 타입에서 내용이 같은지가 아니라 같은 객체인지를 본다.
{ a: 1 } === { a: 1 } // false — 내용은 같지만 서로 다른 객체
[1, 2] === [1, 2] // false
const x = { a: 1 };
const y = x;
x === y // true — 같은 주소
내용을 비교하려면 직접 비교하거나 JSON.stringify 같은 우회를 써야 한다
(중첩·순서·함수 때문에 완전하지는 않다).
직접 확인
같은 객체를 가리키는지, 따로인지 눈으로 확인해라.
const original = { name: "서브웨이", tags: ["js"] };
const alias = original; // 주소 복사 — 같은 객체
const shallow = { ...original }; // 얕은 복사 — 겉만 새 객체
alias.name = "별칭이 바꿈";
console.log("1:", original.name); // 바뀐다
shallow.name = "복사본이 바꿈";
console.log("2:", original.name); // 안 바뀐다
// 그런데 중첩된 배열은 여전히 공유된다
shallow.tags.push("ts");
console.log("3:", original.tags); // 같이 바뀐다!
console.log("같은 객체?", original === alias, original === shallow);
3번이 핵심이다. { ...original } 은 최상위 속성만 새로 만들고, 그 안의 배열은
주소만 복사한다. 이것이 얕은 복사와 깊은 복사가 갈리는 지점이다.
흔한 실수
한 줄 정리
참조 타입은 변수에 주소가 저장되는 타입(객체·배열·함수)이다. 대입·인자 전달은
주소를 복사하므로 여러 변수가 같은 하나를 가리키고, === 도 내용이 아니라 주소를 비교한다.
-
const객체의 속성을 바꿀 수 있는 이유를 설명할 수 있다 -
{a:1} === {a:1}이false인 이유를 안다 - 스프레드로 복사해도 중첩된 값이 공유되는 이유를 안다
참고
- [1] JavaScript data types and data structures — MDN Web Docs
- [2] Object — MDN Web Docs
- [3] The Object Type — ECMAScript 사양
관련 글
- javascript
- 타입
- 참조타입
- 객체