[JavaScript] var 쓰지마 제발!!

ButterFlakes·2022년 7월 2일
2
post-thumbnail

아무튼 쓰지 말라면 쓰지 마!


물론 이유 없이 쓰지 말라고 하는 건 아니다

그런데 코드에다 var를 쓰지 말라는 것 치고는 var로 작성된 예제는 많고 인터넷에도 매우 흔해빠졌다

그런데 왜 많은 사람들이 var를 쓰지 말라고 하는 것일까?
그럼 var의 대체제로 거론되는 let, const와 var의 차이는 무엇일까?

var를 쓰면 안되는 이유 1

시나리오를 한 번 가정해보자

내가 참여한 프로젝트가 하나 있는데 이 프로젝트가 너무 거대해졌다. 그래서 어디서 어떤 이름을 갖다 썼는지 기억하기도 힘들 정도가 돼버렸다

그래서 아래와 같은 경우가 발생했다고 가정해보자

var url = 'https://velog.io/@wksh229'
console.log(url)

/* 아무튼 엄청나게 긴 코드의 여백*/

var url = 'https://www.google.com' // ??
console.log(url)

딱 봐도 에러를 띄울 것 같은 코드이다. 똑같은 url 이란 이름의 변수가 2번이나 선언되었으니까

그런데 의외로 이 코드의 실행결과는 아래와 같다

https://velog.io/@wksh229
https://www.google.com

같은 이름의 변수가 2번이나 선언되었는데 아무런 에러도 일으키지 않고 멀쩡히 작동한다

아니 이게 왜 오류가 안뜸?

아직 안끝났다. 이제 아래와 같은 코드를 보자

console.log(fruit)
var fruit = 'banana'
console.log(fruit)

누가 봐도 에러가 생기는게 맞는 코드이다. 근데 이 코드도 아래와 같이 실행된다

undefined
banana

아니 왜 오류 안떠!

이제 왜 저 버그코드들이 오류가 안뜨고 실행되는지 알아보자

var는 변수 생성 시에 생성된 변수를 맨 위로 올리는 호이스팅(Hoisting)을 진행해서 코드 초반부에 변수를 선언해 놓은 것과 같은 효과가 나타난다

그래서 자바 스크립트에서 아래와 같이 변수를 선언하면

var nickname = 'ButterFlakes'
console.log(nickname)
var velog = 'velog.io/@wksh229'
console.log(velog)

호이스팅이 진행되어서 아래와 같이 코드를 작성해놓은 것과 같은 효과가 나타난다

var nickname
var velog
nickname = 'ButterFlakes'
console.log(nickname)
velog = 'velog.io/@wksh229'
console.log(velog)

그렇다 보니 아래와 같은 문제 있어 보이는 코드도

console.log(nickname)
var nickname = 'ButterFlakes'

내부적으로는 아래와 같이 취급되어 일단은 동작하는 것이다

var nickname
console.log(nickname) // undefined
nickname = 'ButterFlakes'

당연하겠지만 이런 코드는 어떤 동작을 일으킬지 알 수가 없다. 그러니까 위험한 코드라는 이야기이다

하지만 var를 쓰면 안되는 이유는 한가지가 더 있다

var를 쓰면 안되는 이유 2

var에는 더 골때리는 문제가 하나 더 있다

아래와 같은 코드를 작성하고 실행해보자

function novar(){
  console.log(n)
  for(var n = 0; n < 5; n++){
    console.log(n)
  }
  console.log(n)
}

novar()

하지만 이번에는 뭔가 오류를 일으킬 것 같기도 하다. 왜냐하면 var n 은 for문 내부에 선언되어 있으니까

그러나 이 코드도 문제없이 실행되는데 무려 아래와 같은 결과를 보인다

아마 정신이 더더욱 아득해지지 않을까 싶은데 undefined까진 그렇다고 치자. 근데 마지막 줄의 5는 도대체 왜 출력되는 것인지 이해가 안되는 사람들이 많을 것이다

이건 var가 block scope가 아닌 function scope단위 변수이기 때문이다

그렇다보니 위의 코드는 아래와 같이 해석된다

function novar(){
  var n
  console.log(n)
  for(n = 0; n < 5; n++){
    console.log(n)
  }
  console.log(n)
}
novar()

여기서 생기는 치명적인 문제가 있는데 위와 같이 함수 내부에 선언한 var는 그나마 함수의 실행이 끝나면 사라지지만 아래의 코드를 보자

for(var i = 0; i < 5; i++){
  console.log(i)
}

이렇게 전역에 var를 선언해놓으면 해당 var는 그냥 전역변수가 되어버리고 만다. 내가 전역으로 사용하는 것을 의도하지 않았더라도 그냥 전역 사용이 가능해지는 것이다

이렇게 전역으로 선언된 var는 함수 내부에 선언해놓은 것과 달리 프로그램이 종료되기 전까지 계속 살아있게 된다. 만일 아래와 같은 코드가 작성되어 있다면

for(var i = 0; i < 5; i++){
  console.log(i)
}

function func1(){
  i++
}

어떤 동작을 일으킬지 예측하기가 더더욱 힘들어진다. 디버깅 난이도가 극강으로 높아지는 것은 덤으로 따라오고 말이다

그러니까 var는 쓰면 안된다

이외에도 var는 여러 문제가 많지만 가장 크리티컬한 문제 3개는 위에서 언급한 3개와 같다

  1. 같은 이름의 변수를 중복으로 선언 가능
  2. 나중에 선언된 변수가 호이스팅으로 인해 사용 가능
  3. function scope라 같은 함수 내부에 있다면 선언 위치에 상관 없이 사용이 된다

하나같이 골때리는데다 치명적인 문제들이라 요새는 var를 거의 쓰지 않는 추세로 가고 있다. var의 대체품으로 let과 const가 있으니 let과 const를 사용하도록 하자

var의 대용품 1: let

let은 var와 가장 유사하다. 한 번 할당된 값을 언제든지 변경할 수 있다. 다만 var처럼 같은 이름의 변수를 중복으로 선언할 수 있다던가, 나중에 선언한 변수의 이름을 미리 쓸 수 있다던가, function scope라던가 하는 문제는 없다

let name = 'ButterFlakes'
console.log(name)

name = 'who' // 한 번 할당된 값을 변경가능함
console.log(name)

let name = 'Shinosuke' // error, 동일한 이름의 변수를 중복으로 선언할 수 없음

console.log(fruit) // error, 나중에 선언된 변수를 미리 사용할 수 없음
let fruit = 'Apple'

for(let i = 0; i < 5; i++){
  console.log(i)
}
console.log(i) // error, 블록 내부에 선언된 변수를 블록 밖에서 사용할 수 없음

var의 대용품 2: const

const는 C를 배운 사람이라면 어떤 역할을 하는 변수인지 쉽게 유추할 수 있을 것이다. const로 변수 선언시에는 반드시 변수 선언과 동시에 값을 할당해 주어야 한다

const 변수로 클래스의 인스턴스를 선언해도 인스턴스 내부의 프로퍼티의 값은 변경이 가능하다. 그렇기 때문에 보통 한 번 할당하고 나면 프로퍼티의 값만 변경이 이루어지고 참조가 변하는 일이 거의 없는 인스턴스가 const로 많이 선언된다

const name // error, 변수 선언과 동시에 값을 할당해야함
const name = 'ButterFlakes' // OK
name = 'who?' // error, 한 번 할당된 값을 변경할 수 없음

결론

그러므로 var는 쓰지 말자. var 써서 잔소리 들었다면 반은 당신 잘못이다

그러니까 var 쓰지마!!

0개의 댓글