티스토리 뷰

0. var가 let보다 빠르다고들 한다.

모 프로젝트로부터 헬퍼 요청이 있어서 2주 정도 단기로 투입됐을 때,

코드를 분석하며 의아했던 점 중에 하나는 대부분의 변수가 var로 선언되어있다는 것이었다.

 

코드를 살펴봤을 때, let을 두고 var를 사용할 이유가 없어보였기에

해당 로직을 개발하신 분께 여쭤봤더니 아래와 같은 답변을 들을 수 있었다.

"var가 let보다 빨라요"

 

사실 당시엔 그런가보다, 하고 넘겼다.

왜 var가 let보다 빠르다는건지에 대한 설명이 부족했지만,

오픈직전의 프로젝트에 헬퍼로 투입된 입장에서 이미 동작하고 있는 로직의 변수선언을 왜 var로 했는지 리뷰하며 수정을 요청드릴 정도로 정신머리가 있지는 았았다.

 

...물론, 급할수록 돌아가랬다고 변명이다. 개발자로써 직무유기랄까.

 

그러다 얼마전에 팀의 선배가 개발하던 것을 이어받게되어 코드 분석을 하고 있는데,
그 코드들에도 let보다는 var가 대부분의 변수 선언을 담당하고 있었다.

그리고 왜 let대신 var를 쓰셨냐는 질문에 돌아온 대답은 역시나,

"var가 let보다 빨라"

 

왜 아무도 왜 그런지 왜 말을 안 해주는거야, 왜에ㅠㅠㅠ

...그래서 왜 var가 let보다 빠르다고들 하는건지 직접 찾아보기 했다.

 

1. 구글은 정답을 알고있다.

이런 쪽으로의 궁금증은 개발자라면 누구나 품을 수 있는 거라고 생각한다.

그리고 그걸 반증하듯, 이미 Stack overflow에는 관련한 질문들이 여럿있었다.

예를 들어...why var declaration fast than let 와 같은 질문이라던가

let vs var performance in nodejs and chrome 라던가

Why is let slower than var in a for loop in nodejs? 라던가.

 

그리고 해당 질문들은, 본인들이 테스트해보니 아래와 같이 var가 let보다 빠르다는 명확한 기록을 남김으로써, 자신들의 주장에 신빙성을 더해주고 있었다.

각 질문들에 있는 데이터들. var가 let보다 빠른 것을 분명하게 알 수 있다.

예제를 바탕으로 실측된 위와 같은 값들을 바탕으로 var가 let보다 빠르다는 것을 확인할 수는 있었지만...궁극적으로 내가 찾던 답은 이게 아니었다. 내가 찾던 것은 '아, 진짜 빠르구나'라는 결론이 아니라 '그래서 왜 빠른가'에 대한 과정의 설득성이었고, 이에 가장 근접한 내용을 한 블로그에서 찾을 수 있었다.

A Lexical Environment is a specification type used to define the association of Identifiers to specific variables and functions based upon the lexical nesting structure of ECMAScript code. (중략) Usually a Lexical Environment is associated with some specific syntactic structure of ECMAScript code such as a FunctionDeclaration, a BlockStatement, or a Catch clause of a TryStatement and a new Lexical Environment is created each time such code is evaluated.

(발번역 주의) 렉시컬 환경은 ECMAScript 코드의 렉시컬 중첩구조를 기반으로 식별자(identifier)와 특정 변수 및 함수와의 연관성을 정의하기 위한 스펙 유형이다. 렉시컬 환경은 일반적으로 Function Declaration, Block Statement, try구문의 catch 절과 같은 ECMAScript 코드의 특정 구문 구조와 연결되며, 이러한 코드가 평가될 때마다 새로운 렉시컬 환경이 생성된다.                                    

  - 출처 : let과 var의 성능 비교

 

위 문구는 해당 블로거분이 ECMAScript2015 Specfication - Lexical Environments 에서 발췌한 것으로써, 친절하게 번역까지 해주신 내용을 가져온 것이다. 저기서 설명된 Lexical Environment는 예전에 내가 포스팅했던 [Javascript] class도 호이스팅이 되나요(feat. lexical environment) 에서도 언급됐던 내용인데, Javascript의 Execution Context(실행 컨텍스트)가 구축될 때 해당 영역에서 사용되는 변수 혹은 함수들이 선정의되는 자료구조라고 보면 된다.

 

그리고 당연하게도 이때 할당되는 변수나 함수들은 본인들의 scope를 기준으로 Lexical Environment에 할당이 될텐데...let과 const의 경우 Block scope를 가지고 있기 때문에 if나 for와 같이 지정된 Block 영역내에서 활용될 경우 새롭게 생성되는 Lexical Environment에서 시스템적인 비용이 발생한다는 것이다. 반면에 Functional Scope를 가지는 var는 이러한 비용적인 측면에서 자유롭기에, Block Scope를 가진 let/const보다 빠르다는 결론에 도달할 수 있는 것이다.

 

그리고, 실제로 결과로도 그러하다는 것을 Stackoverflow의 질문들과 위 포스팅에 첨부된 결과값으로 우리는 확인 할 수 있었다.

 

2. 끝날때까진, 끝난게 아니다.

여기서 아름답게, var가 let보다 빠르구나! 라고 박수치고 끝났으면 참 좋았을텐데.

 

끝날때까진, 끝난 게 아니다.

앞서 Stackoverflow와 let과 var의 성능 비교 블로그의 설명을 바탕으로, 나는 설득을 당했고.

이 포스팅을 마무리지으려고 했었다. 그렇게 마무리됐다면 참 좋았을텐데...

이게 또 Stackoverflow와 블로그에서 실측되는 예제 코드를 봤으니, 보는걸로 끝맺는게 아니라 실제로 동작시켜보는게 개발자로써의 인지상정 아니겠는가. 그리고, 해당 코드 스니펫들을 동작시켜보는순간...

왜, 나는 별 차이가 없어...??

다시 이 짤을 쓰는 순간이 오게 될 줄이야.

심지어, 내가 설득당했던 let과 var의 성능 비교 블로그의 예제코드도 돌려보니...

Edge, Chrome, Firefox에서의 결과

케이스별로 크게 차이가 나지 않음은 물론이고 일부 구간에선 let이 var보다 빠른 결과를 보이고 있었다.

 

그러다 나는 이쯤에서 재밌는 Issue 하나를 발견하게 되었다.

Issue 4762: Low performance when use "let" in "for" loop

 

이와 관련된 사항이 2016년에 Javascript V8 엔진쪽에 issue로 올라왔고...

결론적으로 2021년인 현시점엔 fix된 Issue였던 것이다.

 

...그러니까, 황망하게도 결론을 짓자면 삽질 끝에 광명찾은 그런 느낌이긴한데

var가 let보다 빠르다, 라는 건 옛날 이야기라는거다.

 

let과 const는 ES6(2015)때 등장했고, 이듬해인 2016년까지는 브라우저 엔진들이 최적화를 이뤄내지 못 하고 불안정한 시기를 보냈을 것이다. 그리고 그 때쯤 let과 var을 혼용해서 사용했던 이들...그러니까 stackoverflow에 질문을 던진 이들과 내가 링크한 블로거, 내게 'var가 let보다 빨라'라는 말을 했던 팀선배나 프로젝트 개발자분까지. 그들은 그때 본인들이 실증한 경험을 가지고 있기에 맞는 말이었던 것이다.

 

다만, 현시점에서의 브라우져 엔진들은 결국 최적화를 위해 계속해서 개선해나가고 있으며,

내가 실측한 데이터와 같이 var와 let의 성능적 격차는 거의 없는 것으로 확인되었다.

그리고 일부 케이스에선 let이 빠르지만, 또 일부케이스에선 var가 빠르다는 것도 우리는 확인할 수 있었는데, 이는 결국 앞서 언급했던 Scope와 Lexical Environment간의 관계의 차이에서 오는 격차일 것이다.

 

3. 자, 그렇다면 결론은?

변수를 선언함에 있어서 어떤 키워드를 쓸지는, 사실 개인 취향이라고해도 할 말은 없지만...

var보단 let을 쓰는 게 훨씬 좋다고 생각한다.

 

var는,

선언하지 않은 시점에도 해당 변수를 마치 선언한 것처럼 사용할 수 있게 해주며 이는 마치 해당 변수가 전역으로 활용되는 착각을 불러일으킬 수 있고, 변수의 명확한 선언 위치를 혼동하기 쉬우며 동일한 변수명에 대해 중복 선언도 가능하다. 또한 C언어를 비롯한 수많은 언어들이 변수에 대해 Block scope를 가지는 것과 이질적인 경향이 있기 때문에, 개발시 혼란스러움을 가중시켜주는 단점을 가지고 있다.

 

물론, 위와 같은 점들을 장점이라고 바라보는 시선도 있다.

어디서든 변수를 부담없이 필요할 때마다 사용할 수 있고, 사용코자하는 변수명의 재차사용이 가능하며 Scope에 대해 깊게 생각지않고 쉬운 코딩을 할 수 있다는...관점에서 말이다(대학생때 알고리즘을 가르치던 교수님께서, Javascript의 이런 작태를 보고 "근본이 없는 언어같지 않은 언어"라고 말씀하셨던 게 문득 떠오른다)

 

이제는 학생때 하던 과제 프로젝트 수준이 아니라 대규모 서비스를 개발해야하는 개발자라면, 쉽게 사용할 수 있지만 가독성 및 정립성 관점에서 복잡도를 가중시키는 var는 지양하는게 맞다고 생각한다. 몇년전과 같이 var가 let보다 성능이 5배, 10배 정도 좋았던 환경이라면, let보다 var를 사용하는 것을 동의하는 바였겠지만(물론, 그렇다고 var를 여기저기 막 쓰는 것까지 동의하는 건 아니다) 오늘 확인한 바에 따르면 성능적인 격차는 브라우져 엔진들의 최적화로 현격히 줄어들었고, 그렇다면 let보다 var를 선호해야 할 이유가 없다고 생각한다.

 


참고사이트

1. 자바스크립트 코드를 리팩토링 하는 방법 ' ES2015'

2. let과 var의 성능 비교

 

댓글
최근에 올라온 글
Total
Today
Yesterday