자바스크립트에서 var, let, const의 차이점(중복 선언 허용, 스코프, 호이스팅 관점)

kwakjihoon·2025년 1월 22일
post-thumbnail

변수의 생성 과정은 다음과 같다.

  1. 선언
  2. 초기화
  3. 할당
let myName; // 선언
let age = 26 // 초기화
myName = 'jihoon'; //할당

자바스크립트에서는 var, let, const로 변수를 선언할 수 있다. 이 세 가지 타입은 어떤 차이점이 있을까?

선언과 할당 관점

var

var는 중복 선언이 가능하고, 재할당이 가능하다.

var jihoon1;
var jihoon1 = 1;
var jihoon1 = 2; //중복 선언

jihoon1 = 3; //값 재할당

console.log(jihoon1) // 3;

위와 같은 코드가 유동성이 높아 장점처럼 보일 수 있지만, var는 지양하는 것이 좋다.

프로젝트 볼륨이 커져 코드가 많아지면, 기존에 변수를 선언한 것을 잊어버려서 값을 재할당 하거나 재선언 하는 실수가 발생할 수 있다. 이러면 기존의 로직에 영향이 갈 수 있다.

let

let은 재할당은 가능하지만, var와는 달리 중복 선언이 불가능하다.

let jihoon1;
let jihoon1 = 1; // 중복 선언, error

jihoon1 = 3; //값 재할당은 가능

console.log(jihoon1) // 3;

const를 제외하고 let을 자주 사용한다.

const

var, let과 달리 중복 선언도, 값 재할당도 불가능하다. 그렇기에 반드시 값을 선언과 동시에 할당해야 한다.

const jihoon1 = 1; // 선언과 동시에 할당
const jihoon1 = 2; // 중복 선언, error

jihoon1 = 3; //값 재할당, error

console.log(jihoon1) // 1;

const는 constant(상수)를 의미한다. 상수란 변하지 않는 수를 의미하는데, 코드에서 변화하지 않을 변수에 대해 const로 선언한다.

스코프 관점

스코프(scope)란, 변수에 접근할 수 있는 범위를 뜻한다. 전체적으로 접근할 수 있는 전역 스코프와 특정 스코프에서만 접근할 수 있는 지역 스코프가 존재한다.

자바스크립트에서는 함수 스코프와 블록 스코프 2가지 타입이 존재한다.

var의 경우 함수 스코프로, 함수 내에 선언 된 변수는 접근이 가능하다.

letconst의 경우 블록 스코프로, 선언된 블록 안에서만 접근이 가능하다. 함수도 블록으로 정의하기에, 함수 스코프 안에서 변수를 선언했다면 매한가지로 접근 가능하다.

  • 함수 스코프(function scope)
function functionScope() {
  if (true) {
    var x = 10; 
  }
  console.log(x); // var는 함수 스코프로, 접근 가능
}

functionScope(); // Output: 10
  • 블록 스코프(block scope)
function blockScope() {
  if (true) {
    let y = 20;  
    const z = 30;  
    console.log(y); // 블록 스코프로 접근 가능, 20
    console.log(z); // 블록 스코프로 접근 가능, 30
  }
  console.log(y); // ReferenceError, 변수가 정의된 블록 스코프를 벗어나 접근 불가
  console.log(z); // ReferenceError, 변수가 정의된 블록 스코프를 벗어나 접근 불가
}

blockScope(); 

호이스팅(hoisting) 관점

호이스팅이 무엇일까?

MDN에선 아래와 같이 정의하고 있다.

JavaScript 호이스팅은 인터프리터가 코드를 실행하기 전에 함수, 변수, 클래스 또는 임포트(import)의 선언문을 해당 범위의 맨 위로 끌어올리는 것처럼 보이는 현상을 뜻합니다.

여기서 잘 봐야하는 것은 "끌어올려진 것처럼 보이는 현상"이다. 물리적으로 코드가 끌어올려진 것이 아니다.

자바스크립트 엔진이 전체적으로 코드를 읽고 실행 컨텍스트에 미리 기록을 하는데, 이 과정에서 함수나 변수의 선언부보다 위에 호출이 존재해도 error가 나지 않고 실행 되는 것이다.

💡 실행 컨텍스트란 실행 가능한 코드에 제공할 환경정보를 모아놓은 객체를 말한다. 실행 가능한 코드란 일반적으로 전역 코드와 함수 코드를 뜻한다.

아래의 예시 코드를 살펴보자.

hoisting_testFunction(); // 선언부보다 호출이 먼저 존재

const hoisting_testFunction = () => {
  console.log("호이스팅")
}

hoisting_testFunction(); 

첫 함수를 호출하는 코드는 함수 선언부보다 위에 존재한다. 원래 과정이라면 위에서 아래로 흘러가는 동작 구조로 실행되지 않아야 한다. 하지만 호이스팅 개념으로 인해 첫 hoisting_testFunction은 실행이 된다.

자, 그럼 이제 다시 var, let, const를 알아보자.

var

var는 변수 호이스팅이 발생한다.

console.log(age);  // undefined
var age = 26;
console.log(age);  // 10

원래라면 첫 console.log는 error가 나야하지만, 자바스크립트 엔진이 선언만 돼 있는 age에 대해 undefined로 초기화 해두었기 때문에 에러가 발생하지 않는다.

let, const

letconst도 마찬가지로 변수 호이스팅이 발생하는데, var와는 다른 방식으로 작동한다.

console.log(age);  // ReferenceError
let age = 26;
console.log(age); // 26

var와 동일한 코드지만, 이 사이에는 시간적 데드존(TDZ, Temporal Dead Zone)이 생성 된다. 그래서 이 기간 동안 변수에 엑세스를 하면 ReferenceError가 발생한다.

letconst로 변수를 선언하는 경우에는 초기화 과정이 변수 선언문을 만났을 때 수행한다. 따라서 값을 참조할 수 없기 때문에 호이스팅이 발생하지 않는 것처럼 보인다.

profile
딥다이브 습관화 하기 ☺️

0개의 댓글