SlideShare a Scribd company logo
1 of 47
Download to read offline
ECMA2015 INSIDE
우아한형제들
이준호
ECMA 2015
• 2015년 6월 17일
• Be a Better Language
• ECMA 스펙의 가장 큰 변화
• ES5의 완벽한 상위 집합
New features
• Classes
• Modules
• New methods for strings and Arrays
• Promises
• Maps, Sets
• Generators
• Proxies
• WeakMaps
• Lexical block scoping
• Iterators
• Destructuring patterns
Contents
• Promise
• Generator
• Generator + Promise
비동기 제어 ( Promise + Generator )
function *main() {
const r1 = yield request('sample1.txt');
const r2 = yield request('sample2.txt');
console.log(r1);
console.log(r2);
}
run(main);
Promise
new Promise, Promise.resolve, Promise.reject,
Promise.all, Promise.race, 비동기 제어, Job Queue
new Promise
const p = new Promise(function(resolve, reject) {
// ...
if (success) {
resolve('success');
} else {
reject('error');
}
});
p.then(resoved, rejected);
Promise.resolve
const resolved = {
then(resolve) { resolve(42); }
};
const rejected = {
then(resolve, reject) { reject('error'); }
};
const p1 = Promise.resolve(resolved);
const p2 = Promise.resolve(rejected);
p1.then(function(value) { console.log(value); }); // 42
p2.catch(function(value) { console.log(value); }); // error
Promise.reject
const p1 = new Promise(function(resolve, reject) {
reject('error');
});
const p2 = Promise.reject('error');
Promise
Promise
.then(reject)
.catch(reject)
.then(resolve)
Promise
Promise.all
const p1 = Promise.resolve(42);
const p2 = Promise.resolve('JSCON');
const p3 = Promise.reject('error');
Promise.all([p1, p2, p3]).catch(function(error) {
console.log(error); // error
});
Promise.all([p1, p2]).then(function(value) {
console.log(value); // [42, 'JSCON']
});
Promise.race
const p1 = Promise.resolve(42);
const p2 = Promise.resolve('JSCON');
const p3 = Promise.reject('error');
Promise.race([p1, p2, p3]).then(function(value) {
console.log(value); // 42
});
비동기 제어
const p = Promise.resolve(21);
p.then(function(v) {
return new Promise(function(resolve) {
setTimeout(function() {
resolve(v * 2);
}, 100 );
});
}).then(function(v) { console.log( v ); /* 42 */ } );
비동기 제어
request('sample1.txt').then(function(value) {
console.log(value);
return request('sample2.txt');
}).then(function(value) {
console.log(value);
return request('sample3.txt');
}).catch(function(value) {
console.log(value);
});
Job Queue
setTimeout(function() {
console.log('A');
}, 0);
Promise.resolve().then(function() {
console.log('B');
}).then(function() {
console.log('C');
});
Event Queue & Job Queue
setTimeout(func1, 0)
Promise.resolve()
.then(func2)
func2
func1
Job Queue
Promise.resolve('A').then(function(val) {
console.log(val); // 1
Promise.resolve('a').then(function(v) {
console.log(v); // 2
return Promise.resolve('b');
}).then(function(v) {
console.log(v); // 4
return Promise.resolve('c');
}).then(function(v) {
console.log(v); // 6
});
return Promise.resolve('B');
})
.then(function(val) {
console.log(val); // 3
return Promise.resolve('C');
})
.then(function(val) {
console.log(val); // 5
});
// A, a, B, b, C, c
Promise의 한계
예외처리, 단일귀결, 취소 불가
예외처리
const p = foo().then(function() {
// ...
}).then(function() {
// ...
});
p.catch(function() { /* ... */ });
단일귀결
const p = new Promise(function(resolve, reject) {
addEventListener('click', resolve);
});
p.then(function(event) {
const id = event.target.id;
return request(`http://json.io/?id=${id}`);
}).then(function(value) { /* ... */ });
단일귀결
addEventListener('click', function(event) {
const id = event.target.id;
request(`http://jscon.io/?id=${id}`)
.then(function(value) {
// ...
});
});
취소 불가
const p = foo(42);
p.then(function() {
// ...
}).catch(function() {
// ...
});
p.then(function() {
// ...
});
Generator
Iterable / Iterator, yield, yield*, yeild + next, return, throw
Iterable / Iterator
const iterable = {
count: 0,
[Symbol.iterator]() { return this; },
next() {
if (this.count < 10) {
return { value: this.count++ };
} else {
return { done: true };
}}};
for (const count of iterable[Symbol.iterator]()) {
console.log(count);
}
Iterable / Iterator
const arr = [1,3,5,7,9];
const it = arr[Symbol.iterator]();
it.next().value; // 1
it.next().value; // 3
it.next().value; // 5
Generator
function *Gen(){
yield 1;
}
const it = Gen();
console.log(it.next()); // {value: 1, done: false }
console.log(it.next()); // {value: undefined, done: true }
yield
function *gen(val) {
while (true) {
yield val++;
}}
const it = gen(10);
console.log(it.next().value); // 10
console.log(it.next().value); // 11
console.log(it.next().value); // 12
yield*
function *foo() {
yield 2;
yield 3;
}
function *bar() {
yield 1;
yield *foo();
}
const it = bar();
console.log(it.next().value); // 1
console.log(it.next().value); // 2
console.log(it.next().value); // 3
Generator
Generator
// …
yield
const it = Gen();
it.next();
it.next();
// …
yield
// …
2
4
yield + next
function *foo(x) {
const y = x * (yield);
return y;
}
const it = foo(6);
it.next();
const res = it.next(7);
console.log(res.value); // 42
return 예외처리
function *gen(val) {
try {
while (true) { yield val++; }
} finally { console.log('end'); }
}
const it = gen(10);
console.log(it.next()); // 10
console.log(it.return()); // end, ..
throw 예외처리
function foo() {
request('http://jscon.io', function(err, data) {
if (err) it.throw(err);
else it.next(data);
}); }
function *main() {
try {
const text = yield foo();
} catch (err) { console.error(err); } }
const it = main();
it.next();
throw 예외처리
function *gen() {
var x = yield "Hello JSCON";
}
const it = gen();
it.next();
try {
it.throw('error');
} catch (error) { console.error(error); /* error */ }
Generator + Promise
request, 비동기 제어, Generator 실행기, main, *sub, Promise.all
request Promise
function request(url) {
return new Promise(function(res, rej) {
const request = new XMLHttpRequest();
request.onload = function() {
if (this.status == 200) {
res(this.response);
} else {
rej(new Error(this.statusText));
}
};
request.onerror = function() {
reject(new Error(this.statusText));
};
request.open('GET', url);
request.send();
})
}
Example
• Preview
http://goo.gl/us2cKJ
• Code
http://goo.gl/94rtQR
• JSFiddle
• http://goo.gl/qa9icN
비동기 제어 Generator + Promise
function foo() {
return request('http://jscon.io');
}
function *main() {
try {
const text = yield foo();
console.log(text);
} catch (err) {
console.error(err);
}
}
const it = main();
const p = it.next().value;
p.then(function(text) {
it.next(text);
},
function(err) {
it.throw(err);
}
);
Generator 실행기
function run(gen, ...args) {
var it = gen.apply(this, args);
return Promise.resolve()
.then(function handleNext(value) {
var next = it.next(value);
return (function handleResult(next) {
if (next.done) {
return next.value;
} else {
return Promise.resolve(next.value)
.then(handleNext, function
handleError(error) {
return Promise.resolve(
it.throw(error))
.then(handleResult);
});
}
})(next);
});
}
main
function *main() {
const r1 = yield request('sample1.txt');
const r2 = yield request('sample2.txt');
console.log(r1);
console.log(r2);
}
run(main);
Example
• Preview
http://goo.gl/Lmxklf
• Code
http://goo.gl/6Wq1WY
• JSFiddle
http://goo.gl/t4zqrP
*sub
function *sub() {
const r2 = yield request('sample2.txt');
const r3 = yield request('sample3.txt');
return [r2, r3];
}
function *main() {
const url = yield request('sample1.txt');
const [data1, data2] = yield *sub();
alert(`${url}/?data1=${data1}&data2=${data2}`);
}
run(main);
Example
• Preview
http://goo.gl/Pi3nKc
• Code
http://goo.gl/Ft84I1
• JSFiddle
http://goo.gl/jA3FRx
Promise.all
function bar(url1, url2) {
return Promise.all([request(url1), request(url2)]);
}
function *foo() {
var [r1, r2] = yield bar('sample1.txt', 'sample2.txt' );
var r3 = yield request(`sample3.txt/?r1=${r1}&r2=${r2}`);
console.log(r3);
}
run(foo);
Example
• Preview
http://goo.gl/3FKeUA
• Code
http://goo.gl/K66dDd
• JSFiddle
http://goo.gl/w0iE9o
Further reading
Github
compatibility table,
ECMAScript 6 — New Features: Overview & Comparison
HACKS-웹기술블로그
Further reading
• Github
https://github.com/shallaa/async
• compatibility table
http://kangax.github.io/compat-table/es5/
• ECMAScript 6 — New Features: Overview & Comparison
http://es6-features.org/
• HACKS-웹기술블로그
http://hacks.mozilla.or.kr/category/es6-in-depth/
끗
수고하셨습니다.

More Related Content

What's hot

RxSwift 예제로 감잡기
RxSwift 예제로 감잡기RxSwift 예제로 감잡기
RxSwift 예제로 감잡기Yongha Yoo
 
EJEMPLOS DESARROLLADOS
EJEMPLOS DESARROLLADOSEJEMPLOS DESARROLLADOS
EJEMPLOS DESARROLLADOSDarwin Durand
 
Java Script - Object-Oriented Programming
Java Script - Object-Oriented ProgrammingJava Script - Object-Oriented Programming
Java Script - Object-Oriented Programmingintive
 
4.2. trasformers-filters-y-adapters
4.2. trasformers-filters-y-adapters4.2. trasformers-filters-y-adapters
4.2. trasformers-filters-y-adaptersxavazque2
 
Practical JavaScript Programming - Session 3/8
Practical JavaScript Programming - Session 3/8Practical JavaScript Programming - Session 3/8
Practical JavaScript Programming - Session 3/8Wilson Su
 
Второй экрана для “Еды". Владимир Павликов. Kelnik. 29.01.2014
Второй экрана для “Еды". Владимир Павликов. Kelnik. 29.01.2014Второй экрана для “Еды". Владимир Павликов. Kelnik. 29.01.2014
Второй экрана для “Еды". Владимир Павликов. Kelnik. 29.01.2014SPECIA
 
Функциональное реактивное программирование
Функциональное реактивное программированиеФункциональное реактивное программирование
Функциональное реактивное программированиеDmitriy Kiriyenko
 
Comprendre la programmation fonctionnelle, Blend Web Mix le 02/11/2016
Comprendre la programmation fonctionnelle, Blend Web Mix le 02/11/2016Comprendre la programmation fonctionnelle, Blend Web Mix le 02/11/2016
Comprendre la programmation fonctionnelle, Blend Web Mix le 02/11/2016Loïc Knuchel
 
HTTP Interceptors com AngularJS
HTTP Interceptors com AngularJSHTTP Interceptors com AngularJS
HTTP Interceptors com AngularJSRodrigo Branas
 
Алексей Кутумов, C++ без исключений, часть 3
Алексей Кутумов,  C++ без исключений, часть 3Алексей Кутумов,  C++ без исключений, часть 3
Алексей Кутумов, C++ без исключений, часть 3Platonov Sergey
 
Sinopsis kafilah kabupaten buton
Sinopsis kafilah kabupaten butonSinopsis kafilah kabupaten buton
Sinopsis kafilah kabupaten butonWijaya Tac
 
C# Starter L01-Intro and Warm-up
C# Starter L01-Intro and Warm-upC# Starter L01-Intro and Warm-up
C# Starter L01-Intro and Warm-upMohammad Shaker
 
ECMAScript 6 im Produktivbetrieb
ECMAScript 6 im ProduktivbetriebECMAScript 6 im Produktivbetrieb
ECMAScript 6 im ProduktivbetriebSebastian Springer
 
Aller plus loin avec Doctrine2
Aller plus loin avec Doctrine2Aller plus loin avec Doctrine2
Aller plus loin avec Doctrine2André Tapia
 
JQuery应用开发
JQuery应用开发JQuery应用开发
JQuery应用开发chevionlu
 

What's hot (20)

RxSwift 예제로 감잡기
RxSwift 예제로 감잡기RxSwift 예제로 감잡기
RxSwift 예제로 감잡기
 
EJEMPLOS DESARROLLADOS
EJEMPLOS DESARROLLADOSEJEMPLOS DESARROLLADOS
EJEMPLOS DESARROLLADOS
 
Simulacion - Algoritmo congruencial cuadratico
Simulacion - Algoritmo congruencial cuadraticoSimulacion - Algoritmo congruencial cuadratico
Simulacion - Algoritmo congruencial cuadratico
 
Java Script - Object-Oriented Programming
Java Script - Object-Oriented ProgrammingJava Script - Object-Oriented Programming
Java Script - Object-Oriented Programming
 
4.2. trasformers-filters-y-adapters
4.2. trasformers-filters-y-adapters4.2. trasformers-filters-y-adapters
4.2. trasformers-filters-y-adapters
 
Practical JavaScript Programming - Session 3/8
Practical JavaScript Programming - Session 3/8Practical JavaScript Programming - Session 3/8
Practical JavaScript Programming - Session 3/8
 
Второй экрана для “Еды". Владимир Павликов. Kelnik. 29.01.2014
Второй экрана для “Еды". Владимир Павликов. Kelnik. 29.01.2014Второй экрана для “Еды". Владимир Павликов. Kelnik. 29.01.2014
Второй экрана для “Еды". Владимир Павликов. Kelnik. 29.01.2014
 
Функциональное реактивное программирование
Функциональное реактивное программированиеФункциональное реактивное программирование
Функциональное реактивное программирование
 
Comprendre la programmation fonctionnelle, Blend Web Mix le 02/11/2016
Comprendre la programmation fonctionnelle, Blend Web Mix le 02/11/2016Comprendre la programmation fonctionnelle, Blend Web Mix le 02/11/2016
Comprendre la programmation fonctionnelle, Blend Web Mix le 02/11/2016
 
Ngaji NodeJs
Ngaji NodeJsNgaji NodeJs
Ngaji NodeJs
 
HTTP Interceptors com AngularJS
HTTP Interceptors com AngularJSHTTP Interceptors com AngularJS
HTTP Interceptors com AngularJS
 
Sockets java
Sockets javaSockets java
Sockets java
 
Алексей Кутумов, C++ без исключений, часть 3
Алексей Кутумов,  C++ без исключений, часть 3Алексей Кутумов,  C++ без исключений, часть 3
Алексей Кутумов, C++ без исключений, часть 3
 
Sinopsis kafilah kabupaten buton
Sinopsis kafilah kabupaten butonSinopsis kafilah kabupaten buton
Sinopsis kafilah kabupaten buton
 
Dart und JavaScript
Dart und JavaScriptDart und JavaScript
Dart und JavaScript
 
JavaScript Dynamic Loading
JavaScript Dynamic LoadingJavaScript Dynamic Loading
JavaScript Dynamic Loading
 
C# Starter L01-Intro and Warm-up
C# Starter L01-Intro and Warm-upC# Starter L01-Intro and Warm-up
C# Starter L01-Intro and Warm-up
 
ECMAScript 6 im Produktivbetrieb
ECMAScript 6 im ProduktivbetriebECMAScript 6 im Produktivbetrieb
ECMAScript 6 im Produktivbetrieb
 
Aller plus loin avec Doctrine2
Aller plus loin avec Doctrine2Aller plus loin avec Doctrine2
Aller plus loin avec Doctrine2
 
JQuery应用开发
JQuery应用开发JQuery应用开发
JQuery应用开发
 

Viewers also liked

HTML5 관점에서 본 2015년 웹개발 트렌드 및 인사이트
HTML5 관점에서 본 2015년 웹개발 트렌드 및 인사이트HTML5 관점에서 본 2015년 웹개발 트렌드 및 인사이트
HTML5 관점에서 본 2015년 웹개발 트렌드 및 인사이트Jun Ho Lee
 
JavaScript Full-Stack Development Course Session 01
JavaScript Full-Stack Development Course Session 01JavaScript Full-Stack Development Course Session 01
JavaScript Full-Stack Development Course Session 01Basir Jafarzadeh
 
Nodejs Production 적용기
Nodejs Production 적용기Nodejs Production 적용기
Nodejs Production 적용기JeongHun Byeon
 
11 different types of blog posts - to avoid boring your readers!
11 different types of blog posts - to avoid boring your readers! 11 different types of blog posts - to avoid boring your readers!
11 different types of blog posts - to avoid boring your readers! Top Left Design
 
Compressed Larry Cantwell Resume
Compressed Larry Cantwell ResumeCompressed Larry Cantwell Resume
Compressed Larry Cantwell Resumelarrymcantwell
 
#UKGovChat Presentation at Modern Governor's #GovernorLive unconference event...
#UKGovChat Presentation at Modern Governor's #GovernorLive unconference event...#UKGovChat Presentation at Modern Governor's #GovernorLive unconference event...
#UKGovChat Presentation at Modern Governor's #GovernorLive unconference event...Elaine Walton
 
Cool Business Tool – это универсальный сервис для подбора бизнес-тренеров и к...
Cool Business Tool – это универсальный сервис для подбора бизнес-тренеров и к...Cool Business Tool – это универсальный сервис для подбора бизнес-тренеров и к...
Cool Business Tool – это универсальный сервис для подбора бизнес-тренеров и к...Fert
 
デブサミ東北Lt「itで日本を元気に!」
デブサミ東北Lt「itで日本を元気に!」デブサミ東北Lt「itで日本を元気に!」
デブサミ東北Lt「itで日本を元気に!」Developers Summit
 
デブサミ2014 個人スポンサー募集要項
デブサミ2014 個人スポンサー募集要項デブサミ2014 個人スポンサー募集要項
デブサミ2014 個人スポンサー募集要項Developers Summit
 
Структура сайта салона красоты: что должно быть обязательно, а от чего стоит ...
Структура сайта салона красоты: что должно быть обязательно, а от чего стоит ...Структура сайта салона красоты: что должно быть обязательно, а от чего стоит ...
Структура сайта салона красоты: что должно быть обязательно, а от чего стоит ...Fert
 
Digipak and Magazine advert
Digipak and Magazine advertDigipak and Magazine advert
Digipak and Magazine advertpirforo
 
Business angel: Entrevista a Jose Tesan
Business angel: Entrevista a Jose TesanBusiness angel: Entrevista a Jose Tesan
Business angel: Entrevista a Jose Tesanekonomistak
 
『シーエー・モバイルのスマートフォンへの取組』シーエー・モバイル山口氏
『シーエー・モバイルのスマートフォンへの取組』シーエー・モバイル山口氏『シーエー・モバイルのスマートフォンへの取組』シーエー・モバイル山口氏
『シーエー・モバイルのスマートフォンへの取組』シーエー・モバイル山口氏Developers Summit
 
AmbrosiaLab UniFe - Integratori gjav 2014 ita v02
AmbrosiaLab UniFe - Integratori gjav 2014 ita v02AmbrosiaLab UniFe - Integratori gjav 2014 ita v02
AmbrosiaLab UniFe - Integratori gjav 2014 ita v02GJAV
 
Brief sampling of works done.
Brief sampling of works done.Brief sampling of works done.
Brief sampling of works done.carloslarua
 

Viewers also liked (20)

HTML5 관점에서 본 2015년 웹개발 트렌드 및 인사이트
HTML5 관점에서 본 2015년 웹개발 트렌드 및 인사이트HTML5 관점에서 본 2015년 웹개발 트렌드 및 인사이트
HTML5 관점에서 본 2015년 웹개발 트렌드 및 인사이트
 
Es2015 training material-syedawase
Es2015 training material-syedawaseEs2015 training material-syedawase
Es2015 training material-syedawase
 
ECMA 入门
ECMA 入门ECMA 入门
ECMA 入门
 
JavaScript Full-Stack Development Course Session 01
JavaScript Full-Stack Development Course Session 01JavaScript Full-Stack Development Course Session 01
JavaScript Full-Stack Development Course Session 01
 
Nodejs Production 적용기
Nodejs Production 적용기Nodejs Production 적용기
Nodejs Production 적용기
 
Leidraad green lease
Leidraad green leaseLeidraad green lease
Leidraad green lease
 
11 different types of blog posts - to avoid boring your readers!
11 different types of blog posts - to avoid boring your readers! 11 different types of blog posts - to avoid boring your readers!
11 different types of blog posts - to avoid boring your readers!
 
Compressed Larry Cantwell Resume
Compressed Larry Cantwell ResumeCompressed Larry Cantwell Resume
Compressed Larry Cantwell Resume
 
CAS 2 Treball
CAS 2 TreballCAS 2 Treball
CAS 2 Treball
 
#UKGovChat Presentation at Modern Governor's #GovernorLive unconference event...
#UKGovChat Presentation at Modern Governor's #GovernorLive unconference event...#UKGovChat Presentation at Modern Governor's #GovernorLive unconference event...
#UKGovChat Presentation at Modern Governor's #GovernorLive unconference event...
 
Cool Business Tool – это универсальный сервис для подбора бизнес-тренеров и к...
Cool Business Tool – это универсальный сервис для подбора бизнес-тренеров и к...Cool Business Tool – это универсальный сервис для подбора бизнес-тренеров и к...
Cool Business Tool – это универсальный сервис для подбора бизнес-тренеров и к...
 
Malmberg en Beeld en Geluid 070411
Malmberg en Beeld en Geluid 070411Malmberg en Beeld en Geluid 070411
Malmberg en Beeld en Geluid 070411
 
デブサミ東北Lt「itで日本を元気に!」
デブサミ東北Lt「itで日本を元気に!」デブサミ東北Lt「itで日本を元気に!」
デブサミ東北Lt「itで日本を元気に!」
 
デブサミ2014 個人スポンサー募集要項
デブサミ2014 個人スポンサー募集要項デブサミ2014 個人スポンサー募集要項
デブサミ2014 個人スポンサー募集要項
 
Структура сайта салона красоты: что должно быть обязательно, а от чего стоит ...
Структура сайта салона красоты: что должно быть обязательно, а от чего стоит ...Структура сайта салона красоты: что должно быть обязательно, а от чего стоит ...
Структура сайта салона красоты: что должно быть обязательно, а от чего стоит ...
 
Digipak and Magazine advert
Digipak and Magazine advertDigipak and Magazine advert
Digipak and Magazine advert
 
Business angel: Entrevista a Jose Tesan
Business angel: Entrevista a Jose TesanBusiness angel: Entrevista a Jose Tesan
Business angel: Entrevista a Jose Tesan
 
『シーエー・モバイルのスマートフォンへの取組』シーエー・モバイル山口氏
『シーエー・モバイルのスマートフォンへの取組』シーエー・モバイル山口氏『シーエー・モバイルのスマートフォンへの取組』シーエー・モバイル山口氏
『シーエー・モバイルのスマートフォンへの取組』シーエー・モバイル山口氏
 
AmbrosiaLab UniFe - Integratori gjav 2014 ita v02
AmbrosiaLab UniFe - Integratori gjav 2014 ita v02AmbrosiaLab UniFe - Integratori gjav 2014 ita v02
AmbrosiaLab UniFe - Integratori gjav 2014 ita v02
 
Brief sampling of works done.
Brief sampling of works done.Brief sampling of works done.
Brief sampling of works done.
 

More from Jun Ho Lee

우아한오픈소스
우아한오픈소스우아한오픈소스
우아한오픈소스Jun Ho Lee
 
WebGL 20150428
WebGL 20150428WebGL 20150428
WebGL 20150428Jun Ho Lee
 
WebGL 20150406
WebGL 20150406WebGL 20150406
WebGL 20150406Jun Ho Lee
 
스타일 객체 활용
스타일 객체 활용스타일 객체 활용
스타일 객체 활용Jun Ho Lee
 
지금까지 상상한 Web 표현의한계를넘자 WebGL
지금까지 상상한 Web 표현의한계를넘자 WebGL지금까지 상상한 Web 표현의한계를넘자 WebGL
지금까지 상상한 Web 표현의한계를넘자 WebGLJun Ho Lee
 
WebGL의 무궁무진한 가능성
WebGL의 무궁무진한 가능성 WebGL의 무궁무진한 가능성
WebGL의 무궁무진한 가능성 Jun Ho Lee
 

More from Jun Ho Lee (6)

우아한오픈소스
우아한오픈소스우아한오픈소스
우아한오픈소스
 
WebGL 20150428
WebGL 20150428WebGL 20150428
WebGL 20150428
 
WebGL 20150406
WebGL 20150406WebGL 20150406
WebGL 20150406
 
스타일 객체 활용
스타일 객체 활용스타일 객체 활용
스타일 객체 활용
 
지금까지 상상한 Web 표현의한계를넘자 WebGL
지금까지 상상한 Web 표현의한계를넘자 WebGL지금까지 상상한 Web 표현의한계를넘자 WebGL
지금까지 상상한 Web 표현의한계를넘자 WebGL
 
WebGL의 무궁무진한 가능성
WebGL의 무궁무진한 가능성 WebGL의 무궁무진한 가능성
WebGL의 무궁무진한 가능성
 

ECMA2015 INSIDE