혹시 리스트나 객체를 다른 변수에 할당했다가, 원본 데이터까지 엉뚱하게 바뀌어버린 버그를 경험한 적이 있으신가요?
let a = [1-3];
let b = a;
b.push(4);
console.log(a); // 결과는? [1-4]
// "어라? 난 b만 바꿨는데 왜 a가 바뀌지?"
우리는 프로그래밍을 처음 배울 때 "변수(Variable)는 값을 저장하는 상자"라고 배웁니다. 하지만 이 설명은 '반만 맞는' 이야기입니다. 이 '상자 모델'만 믿고 코딩을 하다가는 위와 같은 참조(Reference) 관련 버그 앞에서 속수무책이 될 수밖에 없습니다.
오늘은 주니어 개발자가 가장 많이 오해하는 변수, 참조, 그리고 메모리의 진짜 관계를 파헤쳐 보겠습니다. 이 글을 다 읽고 나면, 더 이상 알 수 없는 데이터 변경 버그로 고생하지 않게 될 것입니다.
--------------------------------------------------------------------------------
1. 변수의 진짜 정체: 상자가 아니라 '이름표'
우리가 흔히 듣는 "변수는 물건(값)을 담는 상자"라는 비유는 직관적이지만, 객체(Object)나 배열(Array) 같은 복잡한 데이터를 다룰 때 오류를 범하게 만듭니다.
메모리 관점에서 변수의 진짜 정의는 다음과 같습니다.
"변수는 값이 위치한 메모리 주소를 가리키는 '이름표(Label)'입니다."
이미지로 상상해보기
• 기존의 오해 (상자 모델): a라는 상자 안에 이라는 리스트가 꽉 차게 들어있다.
• 실제 작동 (이름표 모델): 이라는 리스트는 저 멀리 메모리 창고(Heap) 어딘가에 있고, 변수 a는 그 창고의 위치(주소, 예: 0x1234)가 적힌 포스트잇(이름표)일 뿐입니다.
즉, let b = a라는 코드는 상자 안의 물건을 복사해서 새 상자에 넣는 것이 아니라, a가 보고 있는 주소가 적힌 포스트잇을 하나 더 복사해서 b에게 주는 것과 같습니다. 결국 a와 b는 같은 대상(객체)을 가리키게 되는 것이죠.
--------------------------------------------------------------------------------
2. 메모리: 대형 물류 창고와 선반 번호
컴퓨터의 메모리는 거대한 물류 창고와 같습니다.
1. 메모리(RAM): 거대한 물류 창고 바닥입니다.
2. 주소(Address): 물건이 놓인 선반 번호(예: 1001번, 2004번)입니다.
3. 값(Value): 선반에 실제 놓인 물건입니다.
4. 변수(Variable): "1001번 선반을 보라"고 적힌 작업 지시서입니다.
Stack vs Heap: 물건의 크기에 따른 저장 방식
웹 자료에 따르면 현대 언어(Java, JS, Python 등)는 메모리를 크게 두 영역으로 나누어 관리합니다.
• 스택(Stack): 정해진 크기의 작고 간단한 데이터(정수, 불리언 등 기본형)를 저장합니다. 접근 속도가 매우 빠릅니다. 이곳에는 값 자체가 저장될 수 있습니다.
• 힙(Heap): 크기가 수시로 변할 수 있는 복잡한 데이터(객체, 배열, 클래스 인스턴스)를 저장합니다. 이곳은 정리되지 않은 자유 공간이므로, 반드시 주소(참조)를 통해 찾아가야 합니다.
우리가 변수에 객체를 담을 때, 실제 객체는 힙에 저장되고, 스택에 있는 변수에는 힙의 주소만 저장됩니다.
--------------------------------------------------------------------------------
3. 기본형(Primitive) vs 참조형(Object)
왜 숫자는 복사해도 서로 영향을 안 주는데, 리스트는 영향을 줄까요?
기본형 (Primitive Type)
숫자나 문자 같은 기본형은 불변(Immutable)입니다. a = 10에서 a = 20으로 바꾸면, 10을 20으로 고치는 게 아니라 새로운 메모리 공간에 20을 만들고 변수가 가리키는 방향을 바꿉니다. 즉, 주소가 달라집니다.
참조형 (Reference Type)
리스트나 객체는 가변(Mutable)입니다.
• 집 주소를 철수와 영희가 동시에 알고 있다고 가정해 봅시다. (a와 b가 같은 주소 참조)
• 철수가 그 집에 들어가서 벽지를 뜯어내면(내부 데이터 변경), 나중에 영희가 들어왔을 때 뜯겨진 벽지를 보게 됩니다.
• 이것이 바로 Aliasing(별칭) 버그의 원인입니다.
핵심: 변수 간 대입 연산자(=)를 사용할 때, 객체는 값이 복사되는 것이 아니라 '참조(위치)'가 연결되는 것입니다. 이를 막으려면 얕은 복사(Shallow Copy)나 깊은 복사(Deep Copy)를 통해 새로운 집을 지어야(새 메모리 할당) 합니다.
--------------------------------------------------------------------------------
4. 함수에 값을 전달할 때 일어나는 일 (Call by Sharing)
함수에 변수를 인자로 넘길 때도 마찬가지입니다.
function changeName(person) {
person.name = "New Name"; // (1) 내부 속성 변경
person = { name: "Another Object" }; // (2) 재할당
}
let user = { name: "Original" };
changeName(user);
console.log(user.name); // 결과: "New Name"
많은 분들이 여기서 혼란을 겪습니다. "참조가 전달됐다면 (2)번에서 아예 새 객체로 바뀌어야 하는 거 아니야?"라고요.
여기서 중요한 개념은 Call by Sharing(공유에 의한 호출)입니다.
1. 함수를 호출할 때, 변수 user가 가진 주소값(참조)이 복사되어 매개변수 person에 전달됩니다. (마치 복사된 열쇠를 주는 것과 같습니다.)
2. (1)번 상황: 복사된 열쇠로 문을 열고 들어가 가구(속성)를 바꾸면, 원본 집의 가구도 바뀝니다.
3. (2)번 상황: person = ...은 person이라는 이름표를 **새로운 집(새 객체)**에 다시 붙이는 행위입니다. 원본 user가 가진 열쇠에는 아무런 영향을 주지 않습니다.
--------------------------------------------------------------------------------
5. 이 개념을 이해하면 무엇이 달라질까요?
변수를 '상자'가 아닌 '이름표와 주소'로 이해하는 순간, 개발자의 시야는 완전히 달라집니다.
1. 디버깅 속도 향상: "왜 값이 바뀌었지?"라는 의문이 들 때, 누가 같은 주소를 공유(참조)하고 있는지 추적할 수 있습니다.
2. 프레임워크 이해도 증가: React나 Vue 같은 최신 라이브러리가 왜 불변성(Immutability)을 강조하며, 상태 변경 시 왜 spread operator(...) 등을 써서 객체를 새로 만드는지 이해하게 됩니다. (참조가 바뀌어야 변경을 감지하니까요!)
3. 메모리 누수 방지: 더 이상 쓰지 않는 객체의 연결(참조)을 끊어주어 가비지 컬렉터(GC)가 청소하게 만드는 원리를 알게 됩니다.
--------------------------------------------------------------------------------
📝 요약
• 변수는 값을 담는 상자가 아니라, 값이 있는 곳을 가리키는 이름표(참조)입니다.
• 메모리는 거대한 물류 창고이며, 객체는 힙(Heap) 영역에 저장되고 변수는 그 주소만 가집니다.
• = 연산자는 객체를 복사하는 게 아니라, 주소를 복사하여 연결하는 것입니다.
• 함수에 객체를 넘길 때는 참조값(주소)의 복사본을 넘기는 것입니다.
이제 코드를 짤 때 머릿속에 상자 대신 화살표와 지도를 그려보세요. 훨씬 더 명확한 데이터 흐름이 보일 것입니다.

반응형
'프로그래밍 개발 공부' 카테고리의 다른 글
| [개발 트렌드] 프레임워크 먼저 배워도 될까? 기술 학습 순서의 소멸과 롱런하는 개발자의 생존 전략 (0) | 2026.03.09 |
|---|---|
| [개발 실무] 자료구조 기초 - 배열과 연결 리스트는 왜 속도가 다를까? (1) | 2026.03.06 |
| [개발 트렌드] 1인 개발 전성시대, 어떻게 혼자서 유니콘을 만들 수 있을까? (1) | 2026.03.02 |
| [개발 실무] 함수는 단순한 코드 묶음이 아니다: 클린 코드와 설계의 본질 (0) | 2026.02.27 |
| [개발 트렌드] 코드를 작성하는데 개발자는 왜 필요한가? 생성형 AI 시대 개발자의 역할 변화 (0) | 2026.02.23 |