기록 전체보기/JavaScript

const 키워드로 변수에 객체를 할당한 경우 왜 재할당이 되는가?

Kyoo130 2022. 7. 10. 16:13
본 게시글은 개인 공부를 하면서 기록 목적으로 작성하였습니다.
잘못된 내용이 있다면 제보 부탁드립니다. 감사합니다.🙇‍♂️

 

1.  개 요

JavaScript를 공부하다가 const로 선언한 변수의 값은 재할당을 할 수 없는데, 그 동안 프로젝트를 만들었던 코드를 보면
"const 키워드로 변수에 객체를 할당한 경우 왜 재할당이 되는 거지?" 라는 것에 의문이 생겨 자료를 찾아보게 되었다.

먼저, 이 글을 통해 JavaScript 변수 선언 방법 기초적인 내용부터 하나씩 기록을 남겨 보고자 한다.

 

2. 변수 선언

  • JavaScript는 느슨한 타입을 가진 언어이기 때문에 데이터 타입을 따로 명시하지 않고 변수를 선언할 수 있다.
  • 변수를 선언할 때 타입을 명시하지 않는 것일 뿐, 느슨한 타입이라고 해서 타입이 존재하지 않는 것이 아니라,
    내부적으로는 데이터의 종류에 따른 변수의 타입을 가진다.
  • JavaScript 에서는 var, let, const 를 통해 변수를 선언할 수 있다.

var

  • var는 ES6(ES2015)에서 let과 const가 등장하기 전까지 변수를 선언할 수 있는 유일한 방법이었다.
  • var로 선언된 변수는 기존에 선언된 변수의 값을 덮어쓰며, 함수 스코프를 기준으로 동작한다.
     
  • 스코프란?
    • 스코프는 어떤 변수들에 접근할 수 있는지 정의한 범위를 말한다.
  • 함수 스코프를 기준으로 동작한다는 것은?
    • 변수를 선언한 함수 몸체 안에서만 해당 변수에 접근할 수 있다는 의미를 말한다.
       
  • var로 선언한 변수는 스코프 내에 이미 동일한 식별자를 가진 변수가 존재한다면 해당 변수에 값을 재할당한다.
{
 var a = 1;
}
console.log(a); // 1

var a = 2;
console.log(a); // 2

 

let 과 const

  • let 과 const는 ES6(ES2015)에서 등장한 변수 선언 키워드로 var와 달리 재선언을 허용하지 않는다.
  • let 과 const는 블록 스코프를 가지고 있어 변수를 둘러싼 블록({})에서만 해당 변수에 접근할 수 있다.
  • let은 값을 재할당 하는 것이 가능하지만, const는 값을 재할당 하는 것이 불가하다.
// 블록 레벨
{
 let a = 1;
 console.log(a); // 1
}
console.log(a); // Uncaught ReferenceError: a is not defined


// 재선언
{
 let b = 1;
 let b = 2; // Uncaught SyntaxError: Identifier 'b' has already been declared
}


// 재할당
}
 let c = 1;
 c = 2;
 console.log(c); // 2
}

 

3. 원시 값과 객체

원시 타입 (Primitive Type)

  • JavaScript에서 원시 타입은 7가지가 존재한다.
    • number
    • string
    • boolean
    • null
    • undefined
    • Symbol
    • BigInt (ES2020에서 추가)
  • 원시 타입의 값은 읽기 전용으로 변경할 수 없으며, 변수에 할당하면 그 변수에는 실제 값이 저장된다.

객체 (참조형)

  • JavaScript에서 원시 타입이 아닌 모든 값은 객체이다.
  • 객체는 key: value 형태로 여러 값을 포함하는 컨테이너이며, 내부의 값은 얼마든지 변경할 수 있다.
  • 객체를 변수에 할당하면 변수에는 참조 값이 저장된다.

 

4. var, let 값의 재할당

  • var, let 키워드로 선언한 변수는 값을 재할당 할 수 있다.
    • 재할당이란, 현재 변수에 저장된 값을 버리고 새로운 값을 저장할 수 있는 것을 말한다.
  • 아래 예제와 같이 변수에 값을 재할당하면 이전 값 20이 저장되어 있던 메모리 공간을 지우고 그 메모리 공간에
    재할당 값 30을 저장하는 것이 아니라, 새로운 메모리 공간을 확보하고 그 메모리 공간에 숫자 값 30을 저장한다.
  • age 변수의 값이 30으로 재할당 되면서 이전 값인 20은 어떤 식별자와도 연결되어 있지 않기에 이러한 불필요한 값들은
    가비지 콜렉터에 의해 메모리에서 자동 해제된다. (※ 단, 메모리에서 언제 해제될지는 예측할 수 없다.)
let age = 20;
console.log(age); // 20

age = 30;
console.log(age); // 30

 

가비지 콜렉터란?

  • 어플리케이션이 할당한 메모리 공간을 주기적으로 검사하여 어떤 식별자도 참조하지 않은 메모리를 해제하는 기능을 말한다.
  • JavaScript는 가비지 콜렉터를 내장하고 있는 매니지드 언어로서 더 이상 사용되지 않는 메모리를 해제하여 메모리 누수를 방지한다.

 

5. const 값의 재할당

  • const 키워드로 선언된 변수에 원시 값을 할당한 경우 원시 값은 불변성을 갖기에 변경할 수 없다.
const fruit = "apple";
fruit = "peach"; // Uncaught TypeError: Assignment to constant variable.

 

  • 하지만, const 키워드로 선언된 변수에 객체를 할당한 경우 메모리에 저장되어 있는 참조 값을 통해 실제 객체에 접근한다.
  • 객체는 변경이 가능한 값으로 객체를 할당한 변수는 재할당 없이 동적으로 프로퍼티의 값을 추가하고 삭제할 수 있다.
const user = {name: "kyoo"};
console.log(user); // {name: "kyoo"};

user.name = "dromy";
console.log(user); // {name: "dromy"};

 

6. 결 론

const 키워드로 선언된 변수에 원시 값을 할당할 경우 불변성을 갖기에 변경할 수 없다.

하지만, const 키워드로 객체를 할당할 경우 객체는 변경 가능한 값이므로 메모리에 저장된 객체를 직접 수정할 수 있다.
이 때 객체를 할당한 변수에 재할당을 하지 않았으므로 객체를 할당한 변수의 참조 값은 변경되지 않는다.

이에, 위 "1. 개요"에서 언급한 const 키워드로 변수에 객체를 할당한 경우 재할당이 가능한 것이었다.


지금까지 프로젝트에서 기능을 구현하는 것 위주로 공부만 하다보니 내가 작성하고 있는 코드가 맞는 것인지
이게 왜 이렇게 작동되는 것인지에 대한 원리도 모르는 채 코드를 작성하고 있었다는 것을 깨닫게 된 계기가 되었다.

이번 공부를 통해 JavaScript에 대해 조금 더 상세히 알 수 있었고, 궁금했던 의문이 풀렸지만,
추가적으로 Call By Value와 Call By Reference, 참조에 의한 객체 복사에 대해 궁금증이 생겼다.

공부를 할 수록 알아가는 것도 많고 알아야 할 것도 많지만 하나씩 차근차근 공부하며, 기록을 남기는 습관을 가져볼 것이다.

 

 


참 고

 

모던 자바스크립트 Deep Dive (이웅모)
기초부터 완성까지, 프런트엔드 (이재성, 한정)

https://zeebeck.tistory.com/3

 

Const 키워드를 사용 해도 값의 재할당이 일어날 수 있을까?

자바스크립트엔 여덟 가지 자료형(숫자형, bigint형, 문자형, 불린형, 객체형, Null형, Undefined형, 심볼형)이 있다. 이 중 일곱 개는 오직 하나의 데이터(문자열, 숫자 등)만 담을 수 있어 '원시형(primit

zeebeck.tistory.com