이 글은 Adrian Mejia의 Overview of JavaScript ES6 features (a.k.a ECMAScript 6 and ES2015+)을 번역한 글입니다. 오타나 오역 제보는 언제나 환영입니다!
자바스크립트는 지난 몇 년간 꽤 많은 변화가 있었습니다. 지금 당장 쓸 수 있는 새로운 12가지 기능은 다음과 같습니다.
1. JavaScript History
이번에 자바스크립트에 추가된 기능을 ECMAScript 6 이라고 부릅니다. ES6 나 ES2015+ 라고도 불리죠.
1995년 자바스크립트 개념이 도입된 이래로, 자바스크립트는 서서히 진화해 오고 있었습니다. 기능을 추가하는 작업은 몇 년에 한번씩 일어나곤 했습니다. ECMAScript는 자바스크립트의 이러한 방향을 바로 잡기 위해 1997년에 등장했습니다. ECMAScript는 ES3, ES5, ES6 등과 같은 버젼을 발표해 왔습니다.
보시다시피, ES3, ES5 와 ES6은 각각 10년과 6년의 간격이 있습니다. 새 모델은 매년 작고 점진적인 변화를 만드는 것입니다. ES6 처럼 한 번에 엄청난 변화를 하는것 대신에요.
2. Browsers Support
모든 현대 브라우저와 환경은 ES6를 이미 지원하고 있습니다!

source: https://kangax.github.io/compat-table/es6/
Chrome, MS Edge, Firefox, Safari, Node와 많은 다른 환경에서 이미 자바스크립트 ES6의 기본적인 기능을 지원합니다. 그래서 당신이 이제 배울 모든 튜토리얼은 당장 사용해 볼 수 있습니다.
ECMAScript 6를 시작해봅시다!
3. Core ES6 Features
브라우저 콘솔에서 모든 코드들을 테스트 할 수 있습니다.
그러니 글만 읽지 말고 ES5와 ES6 예제를 테스트 해보길 바랍니다. 어서 해보죠 💪
3.1 Block scope variables
ES6에서 변수를 선언하기 위해 var 대신 let/const를 사용합니다.
var에 무슨 문제가 있었을까요?
var의 문제는 for문이나 if문과 같은 코드 블록에서 변수가 누출되는 것입니다.
ES5
1 | var x = 'outer'; |
test(false)에서 outer가 반환되길 기대했지만, undefined를 얻었습니다.
왜 일까요?
왜냐하면 if 블록이 실행되지 않더라도 네째 줄의 var x가 호이스트(hoisted)되기 때문입니다.
var 호이스팅:
var는 함수 범위(scope)입니다. 이것은 선언되기 전에도 전체 함수에서 사용할 수 있습니다.- 선언(Declarations)은 호이스트(Hoisted)됩니다. 그래서 선언되기 전에도 변수를 사용할 수 있습니다.
- 초기화(Initializations)는 호이스트되지 않습니다. 만약
var를 사용한다면 항상 맨 위에 변수를 선언하세요.- 호이스팅 규칙을 적용해 본 후에 무슨 일이 일어났는지 더 잘 이해할 수 있습니다.
ES5
1
2
3
4
5
6
7
8
9
10> var x = 'outer';
> function test(inner) {
> var x; // HOISTED DECLARATION
> if (inner) {
> x = 'inner'; // INITIALIZATION NOT HOISTED
> return x;
> }
> return x;
> }
>
ECMAScript 2015가 도와주러 왔습니다:
ES6
1 | let x = 'outer'; |
var를 let으로 변경하면 예상대로 작동합니다. if 블록이 호출되지 않는다면, 변수 x는 블록 밖으로 호이스트되지 않습니다.
호이스팅(hoisting) 과 “temporal dead zone”
- ES6에서
let은 블록의 맨 위로 호이스트 됩니다.(ES5 처럼 함수의 맨위가 아닌)- 그러나, 변수가 선언되기 전에 블록에서 변수를 참조하는 것은
ReferenceError를 초래합니다.let은 차단된 스코프를 가집니다. 선언되기 전에 사용할 수 없습니다.- “Temporal dead zone”은 블락의 처음부터 변수가 선언되기 전까지의 영역입니다.
IIFE
IIFE를 설명하기 전에 예제를 봅시다. 여길 봐주세요:
ES5
1 | { |
보시다시피, private은 유출됩니다. 그것을 감싸기 위해 IIFE (immediately-invoked function expression)을 사용할 필요가 있습니다:
ES5
1 | (function(){ |
jQuery/lodash 나 다른 오픈소스 프로젝트를 살펴보면 그것들은 전역 환경의 오염을 피하기위해 IIFE를 사용하고, 단지 _, $ 및 jQuery만 전역으로 정의합니다.
ES6에서 더 깔끔합니다. 블록과 let을 사용하면 더이상 IIFE를 사용할 필요가 없습니다.
ES6
1 | { |
Const
변수를 전혀 변경하지 않는다면 const를 사용할 수 있습니다.
밑줄:
var를 버리고let과const로.
- 모든 참조에
var의 사용을 피하고const를 사용하세요.- 만약 참조를 재 정의해야 한다면
const대신let을 사용하세요
3.2 Template Literals
템플릿 리터럴을 사용하면 더이상 중첩된 연결을 하지 않아도 됩니다. 여길 보세요:
ES5
1 | var first = 'Adrian'; |
이제 우린 역 따옴표( ` )와 문자열 보간 ${}을 사용할 수 있습니다:
ES6
1 | const first = 'Adrian'; |
3.3 Multi-line strings
아래처럼 더이상 문자열과 \n을 연결하지 않아도 됩니다.
ES5
1 | var template = '<li *ngFor="let todo of todos" [ngClass]="{completed: todo.isDone}" >\n' + |
ES6에서 역 따옴표를 사용하여 이를 해결할 수 있습니다.
ES6
1 | const template = `<li *ngFor="let todo of todos" [ngClass]="{completed: todo.isDone}" > |
두 코드는 정확히 똑같은 결과를 가지게 됩니다.
3.4 Destructuring Assignment
ES6 비구조화(Destructuring)은 매우 유용하고 중요합니다. 아래 예제를 보세요:
배열에서 요소 가져오기
ES5
1 | var array = [1, 2, 3, 4]; |
다음과 같습니다:
ES6
1 | const array = [1, 2, 3, 4]; |
값 치환
ES5
1 | var a = 1; |
다음과 같습니다:
ES6
1 | let a = 1; |
여러 반환 값에 대한 비구조화
ES5
1 | function margin() { |
세째 줄에서, 다음과 같은 배열로 리턴할 수도 있습니다.
1 | return [left, right, top, bottom]; |
하지만 호출자(caller)는 반환된 데이터의 순서에 대해 생각해볼 필요가 있습니다.
1 | var left = data[0]; |
ES6에서, 호출자는 필요한 데이터만 설택할 수 있습니다. (여섯째 줄):
ES6
1 | function margin() { |
Notice: 셋째 줄에서, 우리는 ES6의 새로운 기능을 사용하고 있습니다. { left: left }를 { left }로 줄일 수 있습니다. ES5 버젼과 비교하면 얼마나 간결한지 보이시죠. 멋지지 않나요?
일치하는 매개변수에 대한 비구조화
ES5
1 | var user = {firstName: 'Adrian', lastName: 'Mejia'}; |
다음과 같습니다.(하지만 더 간결한)
ES6
1 | const user = {firstName: 'Adrian', lastName: 'Mejia'}; |
Deep Matching
ES5
1 | function settings() { |
다음과 같습니다.(하지만 더 간결한)
ES6
1 | function settings() { |
이것은 객체 비구조화라고도 불립니다.
보시다시피, 비구조화는 매우 유용하고 좋은 코딩 스타일을 가지게 합니다.
모범 사례:
- 배열 비구조화를 사용하여 요소를 가져오거나 값을 바꾸길 바랍니다. 임시 참조를 만들지 않아도 되게 도와줍니다.
- 여러 값을 반환할 때 배열 비구조화를 사용하는 대신 객체 비구조화를 사용하세요.
3.5 Classes and Objects
ECMAScript 6에서, “constructor functions” 🔨 대신 “classes” 🍸 를 사용합니다.
자바스크립트에서 모든 단일 객체는 또 다른 객체인 프로토타입을 가지고 있습니다. 모든 자바스크립트 객체는 그들의 프로토타입의 메서드와 프로퍼티를 상속받습니다.
ES5에서, 우리는 다음과 같이 객체를 생성하기 위해 생성자 함수를 사용하여 객체 지향 프로그래밍(OOP)를 했습니다.
ES5
1 | var Animal = (function () { |
ES6에는 몇가지 달콤한 문법이 존재합니다. 우리는 적은 보일러 플레이트와 새로운 키워드인 class와 constructor 를 사용해 같은 작업을 수행할 수 있습니다. 또한 우리가 constructor.prototype.speak = function () 와 speak() 메서드를 얼마나 명확하게 정의했는지 확인해보세요:
ES6
1 | class Animal { |
보시다시피, 두 스타일 (ES5/6)은 동일한 결과를 만들어 내고 같은 방식으로 사용됩니다.
모범 사례:
- 항상 클래스 문법을 사용하고 프로토 타입을 직접 조작하는 것을 피하세요. 왜냐구요? 왜냐하면 코드가 더 간결해지고 이해하기도 더 쉬워지기 때문입니다.
- 빈 생성자를 가지는 것을 피하세요. 클래스는 생성자가 지정되지 않았다면 기본 생성자를 가집니다.
3.6 Inheritance
이전 Animal클래스를 기반으로 진행하겠습니다. 우리는 그것을 확장하여 Lion 클래스를 정의하기를 원합니다.
ES5에서, 이것은 프로토 타입 상속과 조금 더 관련이 있습니다.
ES5
1 | var Lion = (function () { |
모든 디테일한 사항들을 검토하지 않을겁니다:
- 셋째 줄에서 우리는
Animal생성자를 매개변수와 함께 명시적으로 호출합니다. - 7-8 줄에서
Lion프로토 타입을Animal의 프로토 타입으로 지정했습니다. - 11 줄에서 부모 클래스인
Animal에서speak메서드를 호출합니다.
ES6에서 새 키워드인 extends와 super가 있습니다.
ES6
1 | class Lion extends Animal { |
이 ES6 코드가 같은 동작을 하는 ES5 코드와 비해 얼마나 읽기 쉬운지 보세요. 승리!
모범 사례:
- 상속을 위해 내장되어 있는
extends를 사용하세요
3.7 Native Promises
콜백 헬(Callback Hell) 👹 대신 프러미스(Promise) 🙏 를 사용합니다.
ES5
1 | function printAfterTimeout(string, timeout, done){ |
우리는 done일 때 실행하기 위해 콜백을 받는 함수를 가지고 있습니다. 우리는 두번씩 차례대로 실행해야 합니다. 그것이 콜백에서 printAfterTimeout를 두 번째로 호출한 이유입니다.
이것은 세 번째나 네 번째 콜백이 필요할 경우 매우 빨리 동작하게 됩니다. promise가 어떻게 동작하는지 봅시다:
ES6
1 | function printAfterTimeout(string, timeout){ |
보시다시피, promise를 사용하면 다른 함수가 완료된 후에 무언가를 하기 위해 then을 사용할 수 있습니다. 더이상 중첩 함수를 사용할 필요가 없어집니다.
3.8 Arrow functions
ES6는 함수 표현식을 제거하지 않았지만, 화살표 함수(arrow functions)라고 불리는 것을 새로 추가했습니다.
ES5에서 this의 문제가 몇가지 있었습니다:
ES5
1 | var _this = this; // need to hold a reference |
함수를 내부에서 참조하거나 bind를 사용하기 위해 임시로 this를 사용해야만 합니다. 하지만 ES6에서 화살표 함수를 사용할 수 있습니다.
ES6
1 | // this will reference the outer one |
3.9 For…of
for나 forEach 대신 for...of를 사용합니다.
ES5
1 | // for |
ES6 for...of 또한 반복 작업을 수행할 수 있습니다.
ES6
1 | // for ...of |
3.10 Default parameters
변수가 정의되었는지 확인하는 것 대신 default parameters로 값을 지정할 수 있습니다. 전에 이렇게 한 적이 있나요?
ES5
1 | function point(x, y, isFlag){ |
아마도 변수가 값을 가지고 있는지 확인하거나 기본 값을 할당하는 일반적인 패턴입니다. 그러나 몇 가지 문제가 있는 것을 확인하세요:
- 여덟째 줄,
0, 0을 넘겨주고0, -1을 받게됩니다. - 아홉째 줄,
false를 넘겨주고true를 받게됩니다.
기본 매개변수로 부울 값을 갖거나 값을 0으로 설정한다면 작동하지 않습니다. 왜 그런지 아시나요? ES6 예를 들어 설명해 드리겠습니다. ;)
ES6를 사용하면 더 적은 코드로 더 좋게 할 수 있습니다!
ES6
1 | function point(x = 0, y = -1, isFlag = true){ |
다섯째 줄과 여섯째 줄은 예상대로 결과를 얻었습니다. ES5 예제는 동작하지 않았었죠. 우리는 false, null, undefined 과 0 은 거짓 값이므로 undefined를 먼저 확인해야 합니다. 숫자는 잊을 수 있습니다.
ES5
1 | function point(x, y, isFlag){ |
undefined를 확인할 때 비로소 예상대로 동작하게 됩니다.
3.11 Rest parameters
매개변수에서 나머지 매개변수와 전개 연산자로 왔습니다.
ES5에서 매개변수에서 임의의 변수를 얻는 것은 어렵습니다.
ES5
1 | function printf(format) { |
우리는 나머지 매개변수 ...를 사용하여 동일한 작업을 수행할 수 있습니다.
ES6
1 | function printf(format, ...params) { |
3.12 Spread operator
우리는 apply()대신 전개 연산자를 사용합니다. 우리는 다시 ...의 도움을 받습니다:
주의사항: 우리는 배열을 전달인자의 목록으로 바꾸기 위해
apply()를 사용합니다. 예를 들어,Math.max()는 전달인자의 목록을 취하지만 배열인 경우apply를 사용하여 동작하게 합니다.
먼저 보았듯이, apply를 사용해 전달인자의 목록을 배열로 넘겼습니다.
ES5
1 | Math.max.apply(Math, [2,100,1,6,43]) // 100 |
ES6에서는 전개 연산자를 사용할 수 있습니다.
ES6
1 | Math.max(...[2,100,1,6,43]) // 100 |
또한 우리는 concat 대신 전개 연산자를 사용할 수 있습니다.
ES5
1 | var array1 = [2,100,1,6,43]; |
ES6에서 전개 연산자를 사용해 중첩된 배열을 병합 할 수 있습니다:
ES6
1 | const array1 = [2,100,1,6,43]; |
4. Conclusion
자바스크립트는 많은 변화를 겪었습니다. 이 글은 모든 자바스크립트 개발자가 알아야 할 중심 기능을 다뤘습니다. 또한 코드를 보다 간결하고 쉽게 이해할 수 있는 모범 사례를 제공했습니다.
만약 꼭 알아야할 다른 기능이 있다면 아래 댓글로 알려주세요. 저는 이 글을 업데이트할 것 입니다.
5. 역자 후기
매번 ES6를 공부 해야지 생각만 하다가 좋은 글을 발견하여 읽게되었다.
읽는 도중에 영어가 막혀서 한글로 번역해서 보고 싶다고 생각했다.
그것이 나의 첫 번역이었다.
역시 영어가 서툰 나에게는 글 내용 자체를 이해하기도 힘들었다.
그래서 번역을 할 때 단어가 의미하는 것이 정확이 무엇인지 조사하고 그에 맞는 적절한 단어를 선택할 수 밖에 없었는데, 그 점이 오히려 나의 이해를 도운것 같다.



