원시값 vs 객체: 메모리 저장 방식의 차이 (cc.객체 재할당?)

    728x90
    반응형
    SMALL

    원시값 vs 객체: 메모리 저장 방식의 차이

    변수에 값을 할당할 때 원시값과 객체는 메모리에 저장되는 방식이 다릅니다.

    원시값 - 값 자체를 저장

    let a = 10;
    let b = a;
    
    환경 레코드          메모리
    ┌───┬────────┐
    │ a │ 0x1000 │ ──→ [0x1000]: 10
    │ b │ 0x2000 │ ──→ [0x2000]: 10 (값 복사)
    └───┴────────┘
    

    특징:

    • 변수마다 독립적인 메모리 공간
    • 값 자체를 직접 저장
    • 복사하면 새 메모리에 값 복사

    재할당 시

    a = 20;
    
    환경 레코드          메모리
    ┌───┬────────┐
    │ a │ 0x3000 │ ──→ [0x1000]: 10 (b가 사용 중)
    │ b │ 0x2000 │ ──→ [0x2000]: 10 (그대로)
    └───┴────────┘      [0x3000]: 20 (새로 생성)
    
    console.log(a);  // 20
    console.log(b);  // 10 (독립적)
    
    • 새 메모리 생성 후 재바인딩
    • 각 변수는 독립적

    객체 - 참조값(주소)을 저장

    let obj1 = { value: 1 };
    
    환경 레코드      스택              힙
    ┌──────┬─────┐
    │ obj1 │ 0x1 │ ─→ [0x1]: 0x5000 ─→ [0x5000]: { value: 1 }
    └──────┴─────┘    (참조 저장)        (실제 객체)
    

    특징:

    • 2단계 메모리 사용 (스택 + 힙)
    • 스택: 힙 메모리 주소(참조값) 저장
    • 힙: 실제 객체 저장

    객체 복사 - 참조 공유

    let obj1 = { value: 1 };
    let obj2 = obj1;  // 참조값 복사
    
    환경 레코드      스택              힙
    ┌──────┬─────┐
    │ obj1 │ 0x1 │ ─→ [0x1]: 0x5000 ─┐
    │ obj2 │ 0x2 │ ─→ [0x2]: 0x5000 ─┴→ [0x5000]: { value: 1 }
    └──────┴─────┘    (같은 참조)         (같은 객체)
    
    • obj1, obj2는 다른 스택 메모리 사용
    • 하지만 같은 힙 주소 저장
    • 같은 객체를 참조

    객체 수정 - 내용만 변경

    obj1.value = 2;
    
    환경 레코드      스택              힙
    ┌──────┬─────┐
    │ obj1 │ 0x1 │ ─→ [0x1]: 0x5000 ─┐
    │ obj2 │ 0x2 │ ─→ [0x2]: 0x5000 ─┴→ [0x5000]: { value: 2 }
    └──────┴─────┘                         (내용만 수정)
    
    console.log(obj1.value);  // 2
    console.log(obj2.value);  // 2 (같은 객체 참조)
    
    • 힙 주소는 그대로 (0x5000)
    • 객체 내용만 변경
    • 모든 참조에 영향

    비교 예시

    // 원시값 - 값 복사
    let a = 10;
    let b = a;
    a = 20;
    console.log(b);  // 10 (독립적)
    
    // 객체 - 참조 복사
    let obj1 = { value: 10 };
    let obj2 = obj1;
    obj1.value = 20;
    console.log(obj2.value);  // 20 (같은 객체)
    

    메모리 사용 차이

    원시값: 1단계
    변수 → 메모리 → 값
    
    객체: 2단계
    변수 → 스택 → 힙 → 실제 객체
    

    객체는 메모리를 한 번 더 사용합니다:

    • 스택: 참조값 저장 (작은 크기)
    • 힙: 실제 객체 저장 (큰 크기 가능)

    핵심 정리

      원시값 객체
    저장 값 직접 저장 참조(주소) 저장
    복사 값 복사 (독립적) 참조 복사 (공유)
    변경 새 메모리 + 재바인딩 같은 메모리, 내용만 수정
    메모리 1단계 (직접) 2단계 (스택 + 힙)
    // 원시값: 값으로 평가
    let x = 10;  // x → 10
    
    // 객체: 참조로 평가  
    let obj = { value: 1 };  // obj → 주소 → { value: 1 }
    

    기억하기:

    • 원시값: 값 자체를 저장 📦
    • 객체: 주소(참조)를 저장 🏠📍

     

     

     

     

     

     

    객체 재할당? - 새 객체, 새 주소

    let obj = { value: 1 };
    
    환경 레코드      스택              힙
    ┌─────┬─────┐
    │ obj │ 0x1 │ ─→ [0x1]: 0x5000 ─→ [0x5000]: { value: 1 }
    └─────┴─────┘
    
    // 새 객체로 재할당
    obj = { value: 2 };
    
    환경 레코드      스택              힙
    ┌─────┬─────┐
    │ obj │ 0x1 │ ─→ [0x1]: 0x6000 ─→ [0x5000]: { value: 1 } (GC 대상)
    └─────┴─────┘    (새 참조)          [0x6000]: { value: 2 } (새 객체)
    

    동작:

    1. 힙에 새 객체 생성 (0x6000)
    2. 스택의 참조값을 새 주소로 변경
    3. 기존 객체 (0x5000)는 GC 대상

    프로퍼티 수정 vs 객체 재할당

    프로퍼티 수정 - 같은 주소

    let obj = { value: 1 };
    obj.value = 2;  // 같은 객체, 내용만 수정
    
    환경 레코드      스택              힙
    ┌─────┬─────┐
    │ obj │ 0x1 │ ─→ [0x1]: 0x5000 ─→ [0x5000]: { value: 2 }
    └─────┴─────┘    (주소 그대로)       (내용 변경)
    

    객체 재할당 - 새 주소

    let obj = { value: 1 };
    obj = { value: 2 };  // 새 객체
    
    환경 레코드      스택              힙
    ┌─────┬─────┐
    │ obj │ 0x1 │ ─→ [0x1]: 0x6000 ─→ [0x5000]: { value: 1 } (GC)
    └─────┴─────┘    (주소 변경)        [0x6000]: { value: 2 } (새 객체)
    

    참조 공유 시 차이

    let obj1 = { value: 1 };
    let obj2 = obj1;
    
    // 1. 프로퍼티 수정
    obj1.value = 2;
    console.log(obj2.value);  // 2 (같은 객체)
    
    // 2. 객체 재할당
    obj1 = { value: 3 };
    console.log(obj2.value);  // 2 (다른 객체)
    

    그림으로 보면:

    프로퍼티 수정 후:
    obj1 → [0x1]: 0x5000 ─┐
    obj2 → [0x2]: 0x5000 ─┴→ [0x5000]: { value: 2 }
                               (같은 객체, 내용만 변경)
    
    객체 재할당 후:
    obj1 → [0x1]: 0x6000 ──→ [0x6000]: { value: 3 } (새 객체)
    obj2 → [0x2]: 0x5000 ──→ [0x5000]: { value: 2 } (기존 객체)
    

    정리

    프로퍼티 수정 (obj.value = 2):

    • 힙 주소 그대로
    • 객체 내용만 변경
    • 모든 참조에 영향

    객체 재할당 (obj = { ... }):

    • 힙에 새 객체 생성
    • 스택의 참조값 변경
    • 다른 참조에 영향 없음
    // 수정
    obj.value = 2;     // 같은 메모리, 내용 변경
    
    // 재할당
    obj = { value: 2 }; // 새 메모리, 주소 변경
    

    말씀하신 대로, 재할당하면 힙에 새 객체 생성 + 새 메모리 주소로 재바인딩입니다! 🎯

    728x90
    반응형
    LIST

    댓글