자바스크립트에서 변수 선언 시 사용되는 키워드는 var, let, const가 있다. 이 세 가지는 조금은 다른 각각의 특징들이 있는데, 그 차이점에 대해 알아보도록 하겠다.
중복 선언, 할당이 가능하다. 즉, 같은 변수명으로 선언하고 새로운 값을 할당하는 것이 가능하다. 이 경우 여러 사람이 작업할 경우에 의도치 않은 값 변경으로 인한 오류를 발생시킬 여지가 있다. 이러한 문제를 해결하기 위해 ES6에 추가 된 문법이 let과 const이다.
var a = 1
var a = 2
var a = 3
console.log(a) // 3
재선언은 불가능하나, 재할당은 가능하다.
let a = 1
let a = 2 // Uncaught SyntaxError: Identifier 'a' has already been declared
console.log(a) // 1
a = 2
console.log(a) // 2
재선언과 재할당 모두 불가하다. 처음 할당한 값을 다른 값으로 재할당할 수 없기 때문에 보통 객체나 상수를 선언할 때 사용한다.
const a = 1
const a = 2 // Uncaught SyntaxError: Identifier 'a' has already been declared
a = 2 // Uncaught TypeError: Assignment to constant variable.
console.log(a) // 1
런타임 이전에 변수 선언과 초기화가 일어난다.
console.log(a) // undefined
var a = 1
console.log(a) // a
선언과 초기화 단계가 분리되어 진행된다. 자바스크립트 엔진에 의해 런타임 이전에 변수 선언이 이루어지지만 초기화는 스크립트를 실행시키며 초기화 단계에 이르기 전까지는 변수를 참조할 수 없다.
console.log(a) // ReferenceError: a is not defined
let a = 1
선언과 초기화가 동시에 이루어져야하며 초기화없이 선언문만 있을 경우 문법 에러가 발생한다.
const a // SyntaxError: Missing initializer in const declaration
let과 마찬가지로 호이스팅되기는 하지만 선언 및 초기화 구문을 만나기 전까지는 참조할 수 없다.
console.log(a) // ReferenceError: a is not defined
const a = 1
let과 const는 for, while, try/catch, if 문과 같이 모든 코드 블록을 지역 스코프로 삼는다. 즉 블록 레벨 스코프를 갖는다.
반면 var는 오직 함수의 코드블록만을 지역 스코프로 삼는 함수 레벨 스코프이다.
// var
var a = 1
console.log(a) // 1
if (true){
var a = 2
console.log(a) // 2
}
console.log(a) //2
// let
let b = 1
console.log(b) // 1
if (true){
let b = 2
console.log(b) // 2
}
console.log(b) // 1
위의 예제에서 var는 if를 지역 스코프로 인정하지 않기 때문에 if 문을 벗어나도 if문 내에서 선언한 값이 콘솔에 찍히고 있다.
반면 let은 if문을 지역 스코프로 보기 때문에 같은 변수명으로 재선언을 해줄 수 있으며 블록을 벗어났을 때는 전역에 선언된 변수 값이 콘솔에 찍힌다.
let의 재선언 가능 여부를 공부하려 크롬 개발자도구를 열어서 테스트를 해보려는데 아래 사진처럼 let으로 선언한 변수가 재선언이 되는 것을 확인하였다.

분명 let은 재선언이 안된다고 알고 있는데 왜 에러를 발생시키지 않는걸까싶어서 바로 구글링을 해본 결과 이는 개발자 도구 콘솔과 같은 REPL모드와 일반 스크립트의 차이점이라고 한다.
콘솔은 입력하는 한 줄 한 줄 마다 바로 실행이 되기 때문에 변수를 선언하다가 오타가 난 채로 선언을 해버리면 해당 변수명은 다시 쓸 수 없다. 따라서 let과 const의 경우 일반 스크립트 모드와는 다르게 다른 줄에 선언을 할 경우 같은 변수명이어도 재선언이 가능하다. (같은 줄일 경우 에러 발생)

흥미롭구랴..🤔
참고
The strange behavior of let and var in Javascript
var, let, const의 차이 ⏤ 변수 선언 및 할당, 호이스팅, 스코프