[Javasciprt] ES6์๋์ JavaScript
์๋ ํ์ธ์. ์ฌ์์ฌ์ ๋ถ์ ๋ง๋ฃจ์ผ๋ง@h13i32maru์ ๋๋ค. ์ต๊ทผ์ Web ํ๋ก ํธ์๋์ ๋ณํ๋ ๋งค์ฐ ๊ฒฉ๋ ฌํด์, ์กฐ๊ธ ๋์ ๋ ์ฌ์ด์ ์ ์ ์๋ก์ด ๊ฒ์ด ๋์ค๊ณ ์๋๋ผ๊ตฌ์. ๊ทธ๋ฐ ๊ฒฉ๋ ฌํ ๋ณํ์ค ํ๋๊ฐ ES6์ด๋ผ๋ ์ฐจ์ธ๋ JavaScript์ ์ฌ์์ ๋๋ค. ์ด ES6๋ ํ์ฌ ์ฌ์ ์ค์ผ๋ก ์งํ์์ ์์๋ Draft Rev31์ด ๊ณต๊ฐ๋์ด์์ต๋๋ค.
JavaScript๋ ECMAScript(ECMA262)๋ผ๋ ์ฌ์์ ๊ธฐ๋ฐ์ผ๋ก ๊ตฌํ๋์ด์์ต๋๋ค. ํ์ฌ ๋ชจ๋ํ Web ๋ธ๋ผ์ฐ์ ๋ ECMAScript 5.1th Edition์ ๊ธฐ๋ฐ์ผ๋ก ํ JavaScript์คํ ์์ง์ ํ์ฌํ๊ณ ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋ค์ ๋ฒ์ ์ธ ECMAScript 6th Edition์ด ํ์ฌ ์ฌ์ ์ค์ผ๋ก, ์ฝ์นญ์ผ๋ก ES6์ด๋ผ๋ ๋ช ์นญ์ด ์ฌ์ฉ๋๊ณ ์์ต๋๋ค.
์ด ๋ฒ์, ๋ค๋ฅธ ์ธ์ด์ ์๊ณ JavaScript์๋ ์์ผ๋ฉด ํ๋ ๊ธฐ๋ฅ๊ณผ, JavaScript์์ ์ ๋์ค๋ ํจํด์ ํตํฉ์ ์ผ๋ก ์ ์ ์ ์๋ ๊ธฐ๋ฅ์ ์ค์ฌ์ผ๋ก ์๊ฐํ๊ฒ ์ต๋๋ค.
Class
JavaScript๋ โํ๋กํ ํ์
๊ธฐ๋ฐ์ OOPโ๋ผ ๋ถ๋ฆฌ๊ณ ์๋ ๊ฒ ์ฒ๋ผ, Java๋ Ruby๋ฑ์ โํด๋์ค ๊ธฐ๋ฐ์ OOPโ์๋ ์กฐ๊ธ ๋ค๋ฆ
๋๋ค. ํ์ง๋ง ํ๋กํ ํ์
๋ฒ ์ด์ค์ ๊ธฐ๋ฅ์ ํจ๊ณผ์ ์ผ๋ก ์ฌ์ฉํ๋ค๋ ๊ฒ์ ์ฌํ๊น์ง ๋ณ๋ก ์์๋ค๊ณ ์๊ฐํฉ๋๋ค. ์คํ๋ ค ๊ฐ์ง ํด๋์ค ๊ธฐ๋ฅ์ ๊ตฌํํ๋๊ฐ, ํด๋์ค๋ฅผ ์คํํ๊ธฐ ์ํด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํด ํ๋ก๊ทธ๋๋ฐ์ ์ ๋ ๊ฒ์ด ๋ง์ ๊ฒ์
๋๋ค. ์ด๊ฒ์ npm์์ class
๋ก ๊ฒ์ํ๋ฉด ๋ง์ ํจํค์ง๊ฐ ๋์ค๋ ๊ฒ๋ง ์๊ฐํด๋ ์์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ์ฌ๊ธฐ์ ES6์์๋ ํด๋์ค ๊ธฐ๋ฅ์ ๋์
ํด์, ํด๋์ค๋ฅผ ๊ฐ๋จํ ์ทจ๊ธํ ์ ์๊ฒ ๋์์ต๋๋ค.
// ES5
'use strict';
function User(name) {
this._name = name;
}
User.prototype = Object.create(null, {
constructor: {
value: User,
},
say: {
value: function () {
return 'My name is ' + this._name;
},
},
});
function Admin(name) {
User.apply(this, arguments);
}
Admin.prototype = Object.create(User.prototype, {
constructor: {
value: Admin,
},
say: {
value: function () {
var superClassPrototype = Object.getPrototypeOf(this.constructor.prototype);
return '[Administrator] ' + superClassPrototype.say.call(this);
},
},
});
var user = new User('Alice');
console.log(user.say()); // My name is Alice
var admin = new Admin('Bob');
console.log(admin.say()); // [Administrator] My name is Bob
// ES6
'use strict';
class User {
constructor(name) {
this._name = name;
}
say() {
return 'My name is ' + this._name;
}
}
class Admin extends User {
say() {
return '[Administrator] ' + super.say();
}
}
var user = new User('Alice');
console.log(user.say()); // My name is Alice
var admin = new Admin('Bob');
console.log(admin.say()); // [Administrator] My name is Bob
Function Arguments
JavaScript์์ ํจ์์ ๋ํดํธ ์ธ์๋ ๊ฐ๋ณ๊ธธ์ด ์ธ์๋ฅผ ์ฌ์ฉํ๊ณ ์ถ๋ค๊ณ ์๊ฐํด๋ ์ธ์ด์์ ์ง์ ์ ์ธ ๋ฐฉ๋ฒ์ด ์์๊ธฐ ๋๋ฌธ์, ||
๋ฅผ ์ฌ์ฉํ ๋ง๋ฒ๊ฐ์ ๋ฐฉ๋ฒ์ด๋ arguments
์ ์ฌ์ฉํ ๋ฉํํ๋ก๊ทธ๋๋ฐ๊ฐ์ ๋ฐฉ๋ฒ์ ์ฐ๊ณ ์์์ต๋๋ค. ์ฌ๊ธฐ์ ES6๋ ํจ์์ ๊ฐ ์ธ์์ ์ ์ธ ๋ฐฉ๋ฒ์ด ๊ฐํ๋์ด, ์์ฐ์ค๋ฝ๊ฒ ์ ์ ์ ์๊ฒ ๋์์ต๋๋ค. ์ด๊ฒ์ ๋์ค์ ํ๋ก๊ทธ๋จ์ ์ฝ์ ๋์, ์๊ทธ๋์ณ๋ง์ผ๋ก ๋ณด๋ฉด ๊ทธ ํจ์๊ฐ ๊ธฐ๋ํ๋ ์ธ์๋ฅผ ์ด๋์ ๋ ์ ์ ์๊ฒ ๋์๋ค๋ ํจ๊ณผ๊ฐ ์์ต๋๋ค.
// ES5
'use strict';
function loop(func, count) {
count = count || 3;
for (var i = 0; i < count; i++) {
func();
}
}
function sum() {
var result = 0;
for (var i = 0; i < arguments.length; i++) {
result += arguments[i];
}
return result;
}
loop(function () {
console.log('hello');
}); // hello hello hello
console.log(sum(1, 2, 3, 4)); // 10
// ES6
'use strict';
function loop(func, count = 3) {
for (var i = 0; i < count; i++) {
func();
}
}
function sum(...numbers) {
return numbers.reduce(function (a, b) {
return a + b;
});
}
loop(function () {
console.log('hello');
}); // hello hello hello
console.log(sum(1, 2, 3, 4)); // 10
์ค์ ๋ก ์ด ๋ํดํธ ์ธ์๋ ๊ฐ๋ณ ๊ธธ์ด ์ธ์๋ ํจ์์ ๋ฐ์ธ์๋ถ๋ถ๋ง์ผ๋ก ์ฌ์ฉํ์ง๋ ์๊ณ , ๋ณ์์ ๋์ ์ฒ๋ฆฌ์ ๋ฐ์ด ๊ฐํ๋ ๊ฒ์ ์ผ๋ถ๋ถ์ด ๋ฉ๋๋ค. ES6์์ ๋ณ์์ ๋์ ์ฒ๋ฆฌ์ ๊ดํด์๋ Destructuring and parameter handling in ECMAScript 6์์ ์ํ์ ํฌํจํ ๋ค์ํ ํจํด์ด ์๊ฐ๋์ด ์์ต๋๋ค.
Arrow Function
JavaScript์์๋ ์ด๋ฒคํธ ๊ตฌ๋์ ์ฒ๋ฆฌ๋ฅผ ์์ฃผ ์ ์ต๋๋ค. ์๋ฅผ๋ค์ด DOM์ด ํด๋ฆญ๋๋ฉด ๋ญ๊ฐ ์ฒ๋ฆฌํ๊ฑฐ๋, XHR ๋ฆฌํ์คํธ๊ฐ ์๋ฃ๋๋ฉด ๋ญ๊ฐ ์ฒ๋ฆฌํ๋ ๊ฒฝ์ฐ์
๋๋ค. ์ด๋ฐ ์ฒ๋ฆฌ๋ฅผ JavaScript์์ ๊ตฌํํ๋ ค๋ฉด, ์ฝ๋ฐฑ ํจ์๋ ์ด๋ฒคํธ๋ฆฌ์ค๋๋ผ๊ณ ๋ถ๋ฆฌ๋ ๊ฒ์ ๋์ ๊ฐ์ฒด(DOM์ด๋ XHR)์ ์ค์ ํฉ๋๋ค. ์ด ์ฝ๋ฐฑํจ์๋ฅผ ๋ฑ๋กํ๋ ์์ ์์ this
์ ์ฝ๋ฐฑ ํจ์์์ ์ต์ธ์คํ๊ณ ์ถ์ ๊ฒฝ์ฐ๋ ์์ฃผ ์์ต๋๋ค๋ง, ์ฌํ๊น์ง๋ ํด๋ก์ ธ๋ฅผ ์ฌ์ฉํด this
๋ฅผ ๋ณด์กดํ๋๊ฐ, Function.prototype.bind
๋ฅผ ์ฌ์ฉํด this
๋ฅผ ์๋ฐํ๊ฑฐ๋ ํ์ต๋๋ค. ES6์์๋ Arrow Function๋ผ๊ณ ๋ถ๋ฆฌ๋ ์๋ก์ด ํจ์ ์ ์ ์์ด ๋์
๋์ด, ์ด this
์ ๊ดํ ๋ฒ๊ฑฐ๋ก์์ ํด์ํ๊ณ ์์ต๋๋ค.
// ES5
'use strict';
var ClickCounter = {
_count: 0,
start: function (selector) {
var node = document.querySelector(selector);
node.addEventListener(
'click',
function (evt) {
this._count++;
}.bind(this),
);
},
};
ClickCounter.start('body');
// ES6
'use strict';
var ClickCounter = {
_count: 0,
start: function (selector) {
var node = document.querySelector(selector);
node.addEventListener('click', (evt) => {
this._count++;
});
},
};
ClickCounter.start('body');
Promise
์ฌํ๊น์ง XHR๋ฑ์ ๋น๋๊ธฐ์ฒ๋ฆฌ๋ ์์์ ์ ์ฝ๋ฐฑํจ์๋ฅผ ์ ์ํด์, ๋น๋๊ธฐ์ฒ๋ฆฌ๊ฐ ๋๋๋ฉด ๊ทธ ์ฝ๋ฐฑํจ์๊ฐ ํธ์ถ๋๋ ๊ฒ์ด ์ผ๋ฐ์ ์ด์์ง๋ง, ์ฌ๋ฌ ์ฝ๋ฐฑํจ์์ ์ค์ ๋ฐฉ๋ฒ์ด ์์์ต๋๋ค. ์๋ฅผ๋ค์ด, ๋น๋๊ธฐ์ฒ๋ฆฌ์ ํจ์์ ์ฝ๋ฐฑ ํจ์๋ฅผ ์ธ์๋ก ๋๊ธฐ๊ฑฐ๋(setTimeout
์ด๋ setInterval
), ๋น๋๊ธฐ์ฒ๋ฆฌ๋ฅผ ํํ๋ ๊ฐ์ฒด์ ์ฝ๋ฐฑ ํจ์๋ฅผ ๋ฑ๋กํ๊ฑฐ๋(XHR
๋ WebWorker
), ๋น๋๊ธฐ์ฒ๋ฆฌ์ ๋ฐํ๊ฐ์ ์ฝ๋ฐฑ ํจ์๋ฅผ ๋ฑ๋กํ๊ฑฐ๋(IndexedDB
)๋ฑ์ด ์์ต๋๋ค.
์ด๋ฐ ์ฌ๋ฌ ๋ฐฉ๋ฒ์ด ์๊ธฐ ๋๋ฌธ์, ์ฌ์ฉํ๋ ์ธก์์๋ ๊ฐ๊ฐ์ ๋ฐฉ๋ฒ์ ๋๋ ์ ์ฌ์ฉํ ํ์๊ฐ ์์ต๋๋ค. ์ฌ๊ธฐ์ ES6์์๋ Promise๋ผ๋ ๋น๋๊ธฐ์ฒ๋ฆฌ๋ฅผ ์ข
ํฉ์ ์ผ๋ก ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ด ์ธ์ด๋ ๋ฒจ์์ ์ฌ๊ณต๋๊ฒ ๋์์ต๋๋ค. ์ฌ์ฉ๋ฒ์, ๋น๋๊ธฐ์ฒ๋ฆฌ๋ฅผ ํํ๋ ํจ์๋ Promise๋ฅผ ๋ฐํ๊ฐ์ผ๋ก ๋ฐํํด, ๋ถ๋ฅธ ์ชฝ์์๋ Promise์ ์ฝ๋ฐฑ ํจ์๋ฅผ ๋ฑ๋กํ๋ค๋ ๊ฒ์
๋๋ค.
// ES5
'use strict';
function sleep(callback, msec) {
setTimeout(callback, msec);
}
sleep(function () {
console.log('wake!');
}, 1000);
// ES6
'use strict';
function sleep(msec) {
return new Promise(function (resolve, reject) {
setTimeout(resolve, msec);
});
}
sleep(1000).then(function () {
console.log('wake!');
});
๋ ๋น๋๊ธฐ ์ฒ๋ฆฌ์์๋ ์์ธ์ฒ๋ฆฌ๊ฐ ๋ฌธ์ ๊ฐ ๋ฉ๋๋ค. ๋จ์ํ try-catch
๋ก ๊ฐ์ธ๋ ๋น๋๊ธฐ์์ ์์ธ๊ฐ ์ผ์ด๋๋ฉด ๋ณด์ถฉํ ์ ์์ต๋๋ค. ์ฌ๊ธฐ์ Promise์์๋ ๋น๋๊ธฐ ์ฒ๋ฆฌ์ ์์ธ์ฒ๋ฆฌ๋ ์ข
ํฉ์ ์ผ๋ก ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ด ์ ๊ณต๋๊ณ ์์ต๋๋ค. ์ด Promise์ ๊ดํด์๋ Web์์ ๋ฌด๋ฃ๋ก ์ฝ์ ์ ์๋ JavaScript Promiseใฎๆฌ(๋ฒ์ญ)์ด ๋ฌด์ฒ ์ฐธ๊ณ ๊ฐ ๋ฉ๋๋ค.
Generator
๋ง์ง๋ง์ผ๋ก Generator์ ๊ดํด ์๊ฐํ๊ฒ ์ต๋๋ค. ์ฌ๊ธฐ๊น์ง๋ JavaScript์์ ์์ง๋ง ์ฌ์ฉํ๊ธฐ ํ๋ค๊ฑฐ๋, ํต์ผ๋์ง ์์๋ ๊ฒ์ ๊ฐ์ ํ ๊ธฐ๋ฅ์ด์ง๋ง, ์ด Generator๋ผ๋ ๊ฒ์ ์์ ์๋ก์ด ๊ฐ๋ ์ผ๋ก ES6์ ๋์ ๋์์ต๋๋ค.1 Generator๋ ํจ์ ์ฒ๋ฆฌ์์ ์์์ ์ฅ์์์ ์ฒ๋ฆฌ๋ฅผ ์ค๋จ/์ฌ๊ฐํ ์ ์๋ ๊ตฌ์กฐ๋ฅผ ์ ๊ณตํ๋ ๊ฒ์ ๋๋ค. ์ด ๊ตฌ์กฐ๋ ์ผ๋ฐ์ ์ผ๋ก ์ฝ๋ฃจํด(co-rutine)์ด๋ผ ๋ถ๋ฆฝ๋๋ค. ์ฝ๋ฃจํด์ ์ฌ์ฉํ๋ฉด ๋ฌดํ ๋ฆฌ์ค๋๋ ์ดํฐ๋ ์ดํฐ๋ฑ์ ๊ตฌํ์ ํ ์ ์์ต๋๋ค. ์ด Generator์ Promise๋ฅผ ์กฐํฉํด์ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ๋๊ธฐ์ฒ๋ฆฌ์ฒ๋ผ ์ง๋ ฌ๋ก ์ ์ ์ ์๊ฒ ๋์์ต๋๋ค. ๊ธฐ๋ณธ์ ์ธ ์๊ฐ ๋ฒ์ โ๋น๋๊ธฐ ์ฒ๋ฆฌ๊ฐ ๊ฐ์๋๋ฉด ์ฒ๋ฆฌ๋ฅผ ์ค๋จํด, ๋น๋๊ธฐ์ฒ๋ฆฌ๊ฐ ์๋ฃ๋๋ฉด ์ฒ๋ฆฌ๋ฅผ ์ฌ๊ฐํ ๋ค ์ฐ๊ฒฐ ์ฒ๋ฆฌ๋ฅผ ์ฑํํด ๋๊ฐโ์ ๋๋ค. ์๊น, Promise ์ ์์ ์๊ฐํ ์ํ ์ฝ๋๋ฅผ Generator๋ฅผ ์ฌ์ฉํด ์ง๋ ฌ๋ก ์ ์ด ๋ณด๊ฒ ์ต๋๋ค. ๋ฐ์ ์ํ์ฝ๋์์๋ Generator์ Promise๋ฅผ ์ฌ์ฉํด ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ์ง๋ ฌ๋ก ์ ์์ ์๊ฒ ๋๋ co๋ผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๊ณ ์์ต๋๋ค.
// ES6
'use strict';
co(function* () {
console.log('sleep...');
yield sleep(1000);
console.log('wake!');
});
์ด๋ฒ์๋ co๋ฅผ ์ฌ์ฉํด ํด์คํ์ง๋ง, co๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ๋น๋๊ธฐ์ฒ๋ฆฌ๋ฅผ ์ง๋ ฌ๋ก ์ ๋ ๊ตฌ์กฐ๋ก async/await๋ผ๋๊ฒ์ด ES7์์๋ ์ ๊ณต๋๊ณ ์์ต๋๋ค.2 Generator์ ๊ดํด์๋ ์ ์ ๋ธ๋ก๊ทธ์์ ES6 Generatorใไฝฟใฃใฆasync/awaitใๅฎ่ฃ ใใใกใข๋ก ํด์ค ํ๊ณ ์์ต๋๋ค. ํฅ๋ฏธ๊ฐ ์์ผ์๋ฉด ๋ด์ฃผ์ธ์.
๊ฒฐ๋ก
์ด๋ฒ์๋ JavaScript์์ ์ํ๊น์ ๋ ๊ณณ์ด ES6์์ ์ด๋ป๊ฒ ๋ณํ๋๊ฐ๋ฅผ ์ค์ฌ์ผ๋ก ์ค๋ช ํ์ต๋๋ค. ์ฌ๊ธฐ์ ์๊ฐํ๋ ๋ด์ฉ์ ES6์ ์ผ๋ถ๋ก, ์ด์ธ์๋ Modules, Symbol, Data Structures, Proxy, Template String๋ฑ ์ฌ๋ฌ ๊ธฐ๋ฅ์ด ์ถ๊ฐ๋์ด ์์ต๋๋ค. ํ์์ ์์๋ ES6๋ก ์ ์ ์ฝ๋๋ฅผ ๊ทธ๋๋ก ๋ธ๋ผ์ฐ์ ธ๋ node์์ ์คํํ๋ ๊ฒ์ ์ด๋ ค์ด ์ํฉ์ ๋๋ค๋ง, ES6๋ฅผ ES5๋ก ํธ๋์ค์ปดํ์ผํ๋ ํด๋ก traceur-compiler๋ 6to5๊ฐ ์์ผ๋ฏ๋ก ๊ฐ๋ณ๊ฒ ์ํํด ๋ณด์ค ์ ์์ต๋๋ค. ๋ ๊ฐ ๋ธ๋ผ์ฐ์ ธ๋ ํด์ด ES6์ ์ด๋ ๊ธฐ๋ฅ์ ๋์ํ๊ณ ์๋์ง๋ ECMAScript compatibility table์ด ์ฐธ๊ณ ๊ฐ ๋ฉ๋๋ค. ES6์๋์ JavaScript๋ฅผ ์ค๋นํด์ ์ง๊ธ๋ถํฐ ์กฐ๊ธ์ฉ ๊ฑด๋๋ ค ๋ณด์๋ฉด ์ด๋จ๊น์?
- Firefox์์๋2006๋ ์ฏค์ ์ด๋ฏธ ๊ตฌํ๋์ด ์์ต๋๋ค.
- C#์ async/await์ ๊ฐ์ ๊ฒ