SlideShare a Scribd company logo
책에서는 맛 볼 수 없는
HTML5 Canvas
이야기
Name : Jinho Bang
E-Mail : zino@chromium.org
http://bit.ly/deview_canvas
목차 (http://bit.ly/deview_canvas)
● Canvas의 역사
● 브라우저는 어떻게 그림을 그리나?
● Canvas는 어떻게 그림을 그리나?
● Canvas Animation의 문제점
● 기존의 Canvas Animation 개선안들
● 새로운 API의 도입 OffscreenCanvas
● How to use Offscreen Canvas
● 사례 연구 및 그 밖의 실험
1.
CANVAS의 역사
WebCore/html/HTMLCanvasElement.h
/*
* Copyright (C) 2004-2017 Apple Inc. All rights reserved.
* Copyright (C) 2007 Alp Toker <alp@atoker.com>
* Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
*
* ...
*
*/
이후 <canvas>를 도입한 브라우저들
Ian Hickson’s
WHATWG
2.
브라우저는
어떻게 그림을 그리나?
https://www.naver.com |
Rendering
Engine
Javascript
Engine
Graphics
Library
<body>
<button>Hello</button>
<canvas></canvas>
</body>
<body>
<button>Hello</button>
<canvas></canvas>
</body>
Rendering
Engine
<body>
<button>Hello</button>
<canvas></canvas>
</body>
<head>
<html>
<body>
. . . <button> <canvas>
Parsing DOM (어떤 모양을 그릴지 결정)
<head>
<html>
<body>
. . . <button> <canvas>
LayoutBlock
LayoutBlock
LayoutButton
LayoutCanvas
Parsing CSS (어떤 모양을 그릴지 결정)
LayoutBlock
LayoutBlock
LayoutButton
LayoutCanvas
<body>
<button>
<canvas>
(0, 0, 800, 400)
(50, 0, 300, 150)
(0, 0, 50, 20)
Layouting (위치와 사이즈를 결정)
RedPaintLayer
PurplePaintLayerGreenPaintLayer
BluePaintLayer
z-index: 2
z-index: -1
z-index: 0
z-index: 1
Layerization (그리는 순서를 결정)
Rendering Engine에 의해 그리는 방법 결정
LayoutCanvas
Root
PaintLayer
PaintLayer
LayoutBlock
LayoutBlock
LayoutButton
Rendering
Engine
Rendering Engine에 의해 그리는 방법 결정
LayoutCanvas
Root
PaintLayer
PaintLayer
LayoutBlock
LayoutBlock
LayoutButton
Rendering
Engine
중요한 것은 어떤 모양으로,
어느 위치에 어느정도 크기로,
어떤 순서로 그릴지를 결정
Rendering Engine에 의해 그리는 방법 결정
Root
PaintLayer
LayoutBlock
LayoutBlock
LayoutButton
Graphics
Library
Hello
drawRoundRect();
drawText();
어떻게 그림을 그릴지에 대한 정보가 담겨있다
여기서 중요한 것은 Rendering Engine이
<button></button>을 어떻게 그릴지를 알고있다
3.
CANVAS는
어떻게 그림을 그리나?
<canvas></canvas>도 HTML Element이다
DOM을 그릴 때와 동일한 방법으로 그린다
Graphics
Library
LayoutCanvas
PaintLayer
내부를 어떻게 채울지에 대한 정보가 없다 비어있는 Canvas
<canvas></canvas>의 내부를 어떻게 그릴지는
개발자의 손에 달려있다
Canvas Rendering은 Javascript로..
const canvas = document.getElementById('canvas');
const context = canvas.getContext('2d');
context.drawRect(...);
context.drawText(...);
Javascript
Engine
Rendering
Engine
Graphics
Library
Javascript
Engine
Rendering
Engine
Graphics
Library
<script></script>
Javascript
Engine
Rendering
Engine
Graphics
Library
const canvas = document.getElementById('canvas');
const context = canvas.getContext('2d');
context.drawRect(...);
context.drawText(...);
Javascript
Engine
Rendering
Engine
Graphics
Library
const canvas = document.getElementById('canvas');
const context = canvas.getContext('2d');
context.drawRect(...);
context.drawText(...);
Javascript
Engine
Rendering
Engine
Graphics
Library
const canvas = document.getElementById('canvas');
const context = canvas.getContext('2d');
context.drawRect(...);
context.drawText(...);
drawRoundRect();
drawText();
<canvas></canvas>의 내부를 어떻게 그릴지는
개발자의 Javascript 코드에 달려있다
4.
CANVAS
ANIMATION의 문제점
<canvas></canvas>의 목적은 무엇인가?
다이나믹하게 변하는 그래픽을 처리
즉, Animation
16.7 ms
V-Sync timeline
참고1: “브라우저는 VSync를 어떻게 활용하고 있을까?”, 데뷰 2015, 홍영기
- https://deview.kr/2015/schedule#session/87
참고2: “웹 성능 최적화에 필요한 브라우저의 모든 것”, 데뷰 2018, 이형욱
- https://deview.kr/2018/schedule/252
16.7 ms
V-Sync timeline
Rendering
Engine
Javascript
Engine
Graphics
Library
16.7 ms
PaintingDOM
V-Sync timeline
Javascript Idle
Render Loop
function draw() {
requestAnimationFrame(draw);
// draw something in 16.7ms
}
requestAnimationFrame(draw);
Canvas Render Loop
function draw() {
requestAnimationFrame(draw);
for (let i = 0; i < 10000000000; i++)
context.drawRect(randomX, randomY, randomWidth, randomHeight);
}
requestAnimationFrame(draw);
16.7 ms
PaintingDOM
V-Sync timeline의 현실
Javascript
Main thread가 하는 일이 너무 많아서
16.7ms 동안 그림을 그리기가 힘들다
5.
기존의 CANVAS
ANIMATION 개선안들
브라우저 관점에서의 개선
16.7 ms
PaintingDOM
V-Sync timeline의 현실
Javascript
여러분이 만약 화가라면..
PaintLayer
PaintLayer
Recording
(Main Thread)
drawRect();
drawText();
...
drawRect();
...
그림 그리는 일을 남에게 미루자
PaintLayer
PaintLayer
Recording
(Main Thread)
drawRect();
drawText();
...
drawRect();
... <canvas>
<button>
Playback
(Raster Threads)
drawRect();
drawText();
...
그림 그리는 일을 남에게 미루자
PaintLayer
drawRect();
drawText();
...
<body>
<button>
<canvas>
PaintLayer <canvas>
Recording
(Main Thread)
Playback
(Raster Threads)
Compositing
(Compositor Thread)
drawRect();
...
<button>
그림 그리는 일을 남에게 미루자
참고1: “Accelerated compositing in WebKit: Now and in the future”, 데뷰 2015, 황광윤
- https://deview.kr/2015/schedule#session/75
참고2: “WebKit의 GPU 렌더링”, 데뷰 2012, 황동성
- https://deview.kr/2012/xe/index.php?mid=track&document_srl=374&time_srl=265
참고3: “웹 성능 최적화에 필요한 브라우저의 모든 것”, 데뷰 2018, 이형욱
- https://deview.kr/2018/schedule/252
16.7 ms16.7 ms
Req
Raster
Canvas
JavascriptMain thread
Req
Raster
Canvas
Javascript
GPU Process
Raster
Raster Raster
Raster
Raster Raster
GPU 가속 Canvas의 Rendering
웹 개발자 관점에서의 개선
개선안1:
Fullscreen Canvas로 Rendering 하기
개선안2:
WebGL로 Rendering 하기
개선안3:
Background Canvas
Normal Canvas VS Background Canvas
backContext.drawRect();
backContext.drawOval();
backContext.drawTriangle();
context.drawImage(backCanvas);
drawImage()를 활용한 Rendering 개선
const presentationCanvas = document.getElementById('canvas');
const presentationContext = presentationCanvas.getContext('2d');
drawImage()를 활용한 Rendering 개선
const presentationCanvas = document.getElementById('canvas');
const presentationContext = presentationCanvas.getContext('2d');
const backgroundCanvas = document.createElement('canvas');
const backgroundContext = backgroundCanvas.getContext('2d');
drawImage()를 활용한 Rendering 개선
const presentationCanvas = document.getElementById('canvas');
const presentationContext = presentationCanvas.getContext('2d');
const backgroundCanvas = document.createElement('canvas');
const backgroundContext = backgroundCanvas.getContext('2d');
drawComplexObject(backgroundContext);
presentationContext.drawImage(backgroundCanvas, ...);
6.
새로운 API의 도입
OFFSCREEN CANVAS
많은 개선 방법에도 불구하고..
● Javascript Engine과 Rendering Engine 사이의 Binding Overhead
● GPU 가속을 사용하더라도 Skia 내부의 Overhead
● DOM Rendering을 처리하기에도 벅찬 Main-thread
16.7 ms16.7 ms
Req
Raster
Canvas
JavascriptMain thread
Req
Raster
Canvas
Javascript
GPU Process
Raster
Raster Raster
Raster
Raster Raster
이상적인 GPU 가속 Canvas의 Rendering
16.7 ms16.7 ms
Main thread
Javascript
Overhead
Skia
Overhead
DOM
Overhead
GPU Process
Raster
Raster Raster
Raster
Raster Raster
다시 참혹한 현실..
새로운 방법이 필요하다
● Javascript의 부하를 줄이기 위해 다른 thread에서 실행할 수 있으면 좋겠다
● 그리 크진 않지만 Skia의 부하를 줄이기 위해 다른 thread에서 실행하면 좋겠다
● DOM Rendering과 분리되면 좋겠다
결국 우리는 다른 thead에서
Canvas Rendering을 하고싶다
WebWorker
<canvas></canvas>는 DOM의 일부이기 때문에 불가
DOM으로부터 분리할 수 있는 방법은 없을까?
OffscreenCanvas!
OffscreenCanvas란?
● Canvas Rendering을 DOM과는 별개로 Worker thread에서 수행할 수 있도록
해주는 새로운 API
● 기존의 Canvas Rendering Logic은 고치지 않고 thread만 옮겨가서 그대로
수행할 수 있도록 고안
● Chrome 69 Stable에 이미 Shipping
16.7 ms16.7 ms
Main thread
Javascript
Overhead
Skia
Overhead
DOM
Overhead
GPU Process
Raster
Raster Raster
Raster
Raster Raster
다시 참혹한 현실..
16.7 ms16.7 ms
Main thread Javascript
DOM
Rendering
Worker thread
Canvas
Javascript
Skia
Canvas
Javascript
Skia
Skia
OffscreenCanvas를 도입하면..
16.7 ms16.7 ms
Main thread Javascript
DOM
Rendering
Worker thread
Canvas
Javascript
Skia
Canvas
Javascript
Skia
Skia
GPU Process
Raster
Raster Raster
Raster
Raster Raster
OffscreenCanvas를 도입하면..
7.
HOW TO USE
OFFSCREEN CANVAS
Main-thread에서 해야 할 일..
Canvas 객체 얻어오기
const canvas = document.getElementById(‘canvas’);
OffscreenCanvas 객체 얻어오기
const canvas = document.getElementById(‘canvas’);
const offscreen = canvas.transferControlToOffscreen();
Worker thread 생성하기
const canvas = document.getElementById(‘canvas’);
const offscreen = canvas.transferControlToOffscreen();
const worker = new Worker(‘canvas-worker.js’);
Worker thread로 OffscreenCanvas 전달
const canvas = document.getElementById(‘canvas’);
const offscreen = canvas.transferControlToOffscreen();
const worker = new Worker(‘canvas-worker.js’);
worker.postMessage({ canvas: offscreen }, [offscreen]);
Worker thread에서 해야 할 일..
Message Handler 설정
self.onmessage = event => {
};
OffscreenCanvas 전달받기
self.onmessage = event => {
const offscreen = event.data.canvas;
};
CanvasRenderingContext 생성
self.onmessage = event => {
const offscreen = event.data.canvas;
const context = canvas.getContext(‘2d’);
};
일반적인 Canvas와 동일하게 그림을 그린다
self.onmessage = event => {
const offscreen = event.data.canvas;
const context = canvas.getContext(‘2d’);
function render(time) {
drawSomething(context);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
};
16.7 ms16.7 ms
Main thread Javascript
DOM
Rendering
Worker thread
Canvas
Javascript
Skia
Canvas
Javascript
Skia
Skia
GPU Process
Raster
Raster Raster
Raster
Raster Raster
OffscreenCanvas를 도입하면..
DEMO
8.
CASE STUDY
CASE1:
Three.js에서 OffscreenCanvas 사용하기
The aim of the project is to create an easy to use,
lightweight, 3D library. The library provides Canvas 2D, SVG,
CSS3D and WebGL renderers.
일반적인 Three.js의 Renderer 생성
const renderer = new THREE.WebGLRenderer();
renderer.render(scene, camera);
Three.js에서 OffscreenCanvas 사용
const offscreen = canvas.transferControlToOffscreen();
const renderer = new THREE.WebGLRenderer({
canvas: offscreen
});
renderer.render(scene, camera);
일반적인 Three.js의 Texture 생성
// TextureLoader has a DOM dependency (HTMLImageElement)
const t = new THREE.TextureLoader().load('textures/crate.gif');
OffscreenCanvas를 사용할 때 Texture 생성
const loader = new THREE.ImageBitmapLoader();
loader.load( '../../textures/crate.gif', imageBitmap => {
const texture = new THREE.CanvasTexture(imageBitmap);
}, ...);
여기까지 하고나면 대부분 잘 동작한다
한 가지 또 다른 문제점은..
Three.js의 내부 setSize()
this.setSize = function (width, height, updateStyle) {
...
if ( updateStyle !== false ) {
_canvas.style.width = width + 'px';
_canvas.style.height = height + 'px';
}
...
};
OffscreenCanvas는 DOM의 일부가 아니므로
style property가 존재하지 않는다
Uncaught TypeError: Cannot read property ‘width’ of undefined
style property에 대한 stub을 만들어 준다
const offscreen = canvas.transferControlToOffscreen();
offscreen.style = { width: 0, height: 0 };
const renderer = new THREE.WebGLRenderer({
canvas: offscreen
});
renderer.render(scene, camera);
여기까지 하고나면 대부분 잘 동작한다
CASE2:
Zero-copy Background Rendering
앞서 살펴 본 “drawImage()를 통한 개선”을
더 효율적인 방법으로 대체할 수 있음
drawImage()를 활용한 Rendering 개선
const presentationCanvas = document.getElementById('canvas');
const presentationContext = presentationCanvas.getContext('2d');
const backgroundCanvas = document.createElement('canvas');
const backgroundContext = backgroundCanvas.getContext('2d');
drawComplexObject(backgroundContext);
presentationContext.drawImage(backgroundCanvas, ...);
이 방법으로는 Worker에서 그릴 수 없고,
Image 복사가 발생한다
OffscreenCanvas를 활용하여 개선하자!
OffscreenCanvas의 Background Rendering
const presentationCanvas = document.getElementById('canvas');
const presentationContext = presentationCanvas.getContext('2d');
const backgroundCanvas = new OffscreenCanvas(width, height);
const backgroundContext = backgroundCanvas.getContext('2d');
drawComplexObject(backgroundContext);
const image = backgroundCanvas.transferToImageBitmap();
presentationContext.drawImage(image, ...);
TODO: Image zero-copy 그림
CASE3:
Multi-view rendering with WebGL
OffscreenCanvas의 Multi-view Rendering
const presentationCanvas = document.getElementById('canvas');
const presentationContext = presentationCanvas.getContext('2d');
const backgroundCanvas = new OffscreenCanvas(width, height);
const backgroundContext = backgroundCanvas.getContext('webgl');
drawComplexObject(backgroundContext);
let snapshot = backgroundCanvas.transferToImageBitmap();
presentationContext.drawImage(snapshot, ...);
rotateObject(backgroundContext);
snapshot = backgroundCanvas.transferToImageBitmap();
presentationContext.drawImage(snapshot, ...);
Multi-view Rendering 개선하기
const presentationCanvas = document.getElementById('canvas');
const presentationContext = presentationCanvas.getContext('2d');
const backgroundCanvas = new OffscreenCanvas(width, height);
const backgroundContext = backgroundCanvas.getContext('webgl');
drawComplexObject(backgroundContext);
let snapshot = backgroundCanvas.transferToImageBitmap();
presentationContext.drawImage(snapshot, ...);
Multi-view Rendering 개선하기
const presentationCanvas = document.getElementById('canvas');
const presentationContext =
presentationCanvas.getContext(‘bitmaprenderer’);
const backgroundCanvas = new OffscreenCanvas(width, height);
const backgroundContext = backgroundCanvas.getContext('webgl');
drawComplexObject(backgroundContext);
let snapshot = backgroundCanvas.transferToImageBitmap();
presentationContext.drawImage(snapshot, ...);
Multi-view Rendering 개선하기
const presentationCanvas = document.getElementById('canvas');
const presentationContext =
presentationCanvas.getContext(‘bitmaprenderer’);
const backgroundCanvas = new OffscreenCanvas(width, height);
const backgroundContext = backgroundCanvas.getContext('webgl');
drawComplexObject(backgroundContext);
let snapshot = backgroundCanvas.transferToImageBitmap();
presentationContext.transferFromImageBitmap(snapshot);
CASE4:
WebXR with OffscreenCanvas
CASE5:
Tensorflow.js with OffscreenCanvas
Q & A
Thank you

More Related Content

What's hot

AWS 기반 대규모 트래픽 견디기 - 장준엽 (구로디지털 모임) :: AWS Community Day 2017
AWS 기반 대규모 트래픽 견디기 - 장준엽 (구로디지털 모임) :: AWS Community Day 2017AWS 기반 대규모 트래픽 견디기 - 장준엽 (구로디지털 모임) :: AWS Community Day 2017
AWS 기반 대규모 트래픽 견디기 - 장준엽 (구로디지털 모임) :: AWS Community Day 2017
AWSKRUG - AWS한국사용자모임
 
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
현철 조
 
AWS로 게임 런칭 준비하기 ::: 장준성, 채민관, AWS Game Master 온라인 시리즈 #4
AWS로 게임 런칭 준비하기 ::: 장준성, 채민관, AWS Game Master 온라인 시리즈 #4AWS로 게임 런칭 준비하기 ::: 장준성, 채민관, AWS Game Master 온라인 시리즈 #4
AWS로 게임 런칭 준비하기 ::: 장준성, 채민관, AWS Game Master 온라인 시리즈 #4
Amazon Web Services Korea
 
UX, Front-end and Back-end: How front-end can help these guys?
UX, Front-end and Back-end: How front-end can help these guys?UX, Front-end and Back-end: How front-end can help these guys?
UX, Front-end and Back-end: How front-end can help these guys?
Diego Eis
 
Single Page Application
Single Page ApplicationSingle Page Application
Single Page Application
Isuru Madusanka
 
Java Entreprise Edition
Java Entreprise EditionJava Entreprise Edition
Java Entreprise Edition
Sabri Bouchlema
 
Unreal Open Day 2017 Optimize in Mobile UI
Unreal Open Day 2017 Optimize in Mobile UIUnreal Open Day 2017 Optimize in Mobile UI
Unreal Open Day 2017 Optimize in Mobile UI
Epic Games China
 
[0903 구경원] recast 네비메쉬
[0903 구경원] recast 네비메쉬[0903 구경원] recast 네비메쉬
[0903 구경원] recast 네비메쉬KyeongWon Koo
 
WebGL and three.js
WebGL and three.jsWebGL and three.js
WebGL and three.js
Anton Narusberg
 
[2D4]Python에서의 동시성_병렬성
[2D4]Python에서의 동시성_병렬성[2D4]Python에서의 동시성_병렬성
[2D4]Python에서의 동시성_병렬성
NAVER D2
 
프론트엔드 개발자를 위한 Layer Model
프론트엔드 개발자를 위한 Layer Model프론트엔드 개발자를 위한 Layer Model
프론트엔드 개발자를 위한 Layer Model
Han Lee
 
PyAutoGUI等Pythonライブラリによる自動化支援
PyAutoGUI等Pythonライブラリによる自動化支援PyAutoGUI等Pythonライブラリによる自動化支援
PyAutoGUI等Pythonライブラリによる自動化支援
H Iseri
 
(DEV307) Introduction to Version 3 of the AWS SDK for Python (Boto) | AWS re:...
(DEV307) Introduction to Version 3 of the AWS SDK for Python (Boto) | AWS re:...(DEV307) Introduction to Version 3 of the AWS SDK for Python (Boto) | AWS re:...
(DEV307) Introduction to Version 3 of the AWS SDK for Python (Boto) | AWS re:...
Amazon Web Services
 
오딘: 발할라 라이징 MMORPG의 성능 최적화 사례 공유 [카카오게임즈 - 레벨 300] - 발표자: 김문권, 팀장, 라이온하트 스튜디오...
오딘: 발할라 라이징 MMORPG의 성능 최적화 사례 공유 [카카오게임즈 - 레벨 300] - 발표자: 김문권, 팀장, 라이온하트 스튜디오...오딘: 발할라 라이징 MMORPG의 성능 최적화 사례 공유 [카카오게임즈 - 레벨 300] - 발표자: 김문권, 팀장, 라이온하트 스튜디오...
오딘: 발할라 라이징 MMORPG의 성능 최적화 사례 공유 [카카오게임즈 - 레벨 300] - 발표자: 김문권, 팀장, 라이온하트 스튜디오...
Amazon Web Services Korea
 
Amazon RDS Proxy 집중 탐구 - 윤석찬 :: AWS Unboxing 온라인 세미나
Amazon RDS Proxy 집중 탐구 - 윤석찬 :: AWS Unboxing 온라인 세미나Amazon RDS Proxy 집중 탐구 - 윤석찬 :: AWS Unboxing 온라인 세미나
Amazon RDS Proxy 집중 탐구 - 윤석찬 :: AWS Unboxing 온라인 세미나
Amazon Web Services Korea
 
Killzone Shadow Fall Demo Postmortem
Killzone Shadow Fall Demo PostmortemKillzone Shadow Fall Demo Postmortem
Killzone Shadow Fall Demo Postmortem
Guerrilla
 
1장 Java란 무엇인가.key
1장 Java란 무엇인가.key1장 Java란 무엇인가.key
1장 Java란 무엇인가.key
김 한도
 
Masked Occlusion Culling
Masked Occlusion CullingMasked Occlusion Culling
Masked Occlusion Culling
Intel® Software
 
[오픈소스컨설팅]이기종 WAS 클러스터링 솔루션- Athena Dolly
[오픈소스컨설팅]이기종 WAS 클러스터링 솔루션- Athena Dolly[오픈소스컨설팅]이기종 WAS 클러스터링 솔루션- Athena Dolly
[오픈소스컨설팅]이기종 WAS 클러스터링 솔루션- Athena Dolly
Ji-Woong Choi
 
Profiling - 실시간 대화식 프로파일러
Profiling - 실시간 대화식 프로파일러Profiling - 실시간 대화식 프로파일러
Profiling - 실시간 대화식 프로파일러
Heungsub Lee
 

What's hot (20)

AWS 기반 대규모 트래픽 견디기 - 장준엽 (구로디지털 모임) :: AWS Community Day 2017
AWS 기반 대규모 트래픽 견디기 - 장준엽 (구로디지털 모임) :: AWS Community Day 2017AWS 기반 대규모 트래픽 견디기 - 장준엽 (구로디지털 모임) :: AWS Community Day 2017
AWS 기반 대규모 트래픽 견디기 - 장준엽 (구로디지털 모임) :: AWS Community Day 2017
 
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
 
AWS로 게임 런칭 준비하기 ::: 장준성, 채민관, AWS Game Master 온라인 시리즈 #4
AWS로 게임 런칭 준비하기 ::: 장준성, 채민관, AWS Game Master 온라인 시리즈 #4AWS로 게임 런칭 준비하기 ::: 장준성, 채민관, AWS Game Master 온라인 시리즈 #4
AWS로 게임 런칭 준비하기 ::: 장준성, 채민관, AWS Game Master 온라인 시리즈 #4
 
UX, Front-end and Back-end: How front-end can help these guys?
UX, Front-end and Back-end: How front-end can help these guys?UX, Front-end and Back-end: How front-end can help these guys?
UX, Front-end and Back-end: How front-end can help these guys?
 
Single Page Application
Single Page ApplicationSingle Page Application
Single Page Application
 
Java Entreprise Edition
Java Entreprise EditionJava Entreprise Edition
Java Entreprise Edition
 
Unreal Open Day 2017 Optimize in Mobile UI
Unreal Open Day 2017 Optimize in Mobile UIUnreal Open Day 2017 Optimize in Mobile UI
Unreal Open Day 2017 Optimize in Mobile UI
 
[0903 구경원] recast 네비메쉬
[0903 구경원] recast 네비메쉬[0903 구경원] recast 네비메쉬
[0903 구경원] recast 네비메쉬
 
WebGL and three.js
WebGL and three.jsWebGL and three.js
WebGL and three.js
 
[2D4]Python에서의 동시성_병렬성
[2D4]Python에서의 동시성_병렬성[2D4]Python에서의 동시성_병렬성
[2D4]Python에서의 동시성_병렬성
 
프론트엔드 개발자를 위한 Layer Model
프론트엔드 개발자를 위한 Layer Model프론트엔드 개발자를 위한 Layer Model
프론트엔드 개발자를 위한 Layer Model
 
PyAutoGUI等Pythonライブラリによる自動化支援
PyAutoGUI等Pythonライブラリによる自動化支援PyAutoGUI等Pythonライブラリによる自動化支援
PyAutoGUI等Pythonライブラリによる自動化支援
 
(DEV307) Introduction to Version 3 of the AWS SDK for Python (Boto) | AWS re:...
(DEV307) Introduction to Version 3 of the AWS SDK for Python (Boto) | AWS re:...(DEV307) Introduction to Version 3 of the AWS SDK for Python (Boto) | AWS re:...
(DEV307) Introduction to Version 3 of the AWS SDK for Python (Boto) | AWS re:...
 
오딘: 발할라 라이징 MMORPG의 성능 최적화 사례 공유 [카카오게임즈 - 레벨 300] - 발표자: 김문권, 팀장, 라이온하트 스튜디오...
오딘: 발할라 라이징 MMORPG의 성능 최적화 사례 공유 [카카오게임즈 - 레벨 300] - 발표자: 김문권, 팀장, 라이온하트 스튜디오...오딘: 발할라 라이징 MMORPG의 성능 최적화 사례 공유 [카카오게임즈 - 레벨 300] - 발표자: 김문권, 팀장, 라이온하트 스튜디오...
오딘: 발할라 라이징 MMORPG의 성능 최적화 사례 공유 [카카오게임즈 - 레벨 300] - 발표자: 김문권, 팀장, 라이온하트 스튜디오...
 
Amazon RDS Proxy 집중 탐구 - 윤석찬 :: AWS Unboxing 온라인 세미나
Amazon RDS Proxy 집중 탐구 - 윤석찬 :: AWS Unboxing 온라인 세미나Amazon RDS Proxy 집중 탐구 - 윤석찬 :: AWS Unboxing 온라인 세미나
Amazon RDS Proxy 집중 탐구 - 윤석찬 :: AWS Unboxing 온라인 세미나
 
Killzone Shadow Fall Demo Postmortem
Killzone Shadow Fall Demo PostmortemKillzone Shadow Fall Demo Postmortem
Killzone Shadow Fall Demo Postmortem
 
1장 Java란 무엇인가.key
1장 Java란 무엇인가.key1장 Java란 무엇인가.key
1장 Java란 무엇인가.key
 
Masked Occlusion Culling
Masked Occlusion CullingMasked Occlusion Culling
Masked Occlusion Culling
 
[오픈소스컨설팅]이기종 WAS 클러스터링 솔루션- Athena Dolly
[오픈소스컨설팅]이기종 WAS 클러스터링 솔루션- Athena Dolly[오픈소스컨설팅]이기종 WAS 클러스터링 솔루션- Athena Dolly
[오픈소스컨설팅]이기종 WAS 클러스터링 솔루션- Athena Dolly
 
Profiling - 실시간 대화식 프로파일러
Profiling - 실시간 대화식 프로파일러Profiling - 실시간 대화식 프로파일러
Profiling - 실시간 대화식 프로파일러
 

Similar to [122]책에서는 맛볼 수 없는 HTML5 Canvas 이야기

Html5 소개 가이드
Html5 소개 가이드Html5 소개 가이드
Html5 소개 가이드Jong-hyun Park
 
[Naver d2]html5 canvas overview
[Naver d2]html5 canvas overview[Naver d2]html5 canvas overview
[Naver d2]html5 canvas overview
NAVER D2
 
웹 기반 하이퍼포먼스 그래픽 처리 - 문경두
웹 기반 하이퍼포먼스 그래픽 처리 - 문경두웹 기반 하이퍼포먼스 그래픽 처리 - 문경두
웹 기반 하이퍼포먼스 그래픽 처리 - 문경두
jscamp_kr
 
웹 소프트웨어 시대의 새로운 롤(role) 모델, 자바스크립트
웹 소프트웨어 시대의 새로운 롤(role) 모델, 자바스크립트웹 소프트웨어 시대의 새로운 롤(role) 모델, 자바스크립트
웹 소프트웨어 시대의 새로운 롤(role) 모델, 자바스크립트
Rhio Kim
 
Html5 canvas sprite animation
Html5 canvas sprite animationHtml5 canvas sprite animation
Html5 canvas sprite animation
SangHun Lee
 
[별천지 세미나] CSS3 Animation
[별천지 세미나] CSS3 Animation[별천지 세미나] CSS3 Animation
[별천지 세미나] CSS3 Animation양귀 김
 
[111217 아꿈사연말모임] 웹소켓과온라인게임
[111217 아꿈사연말모임] 웹소켓과온라인게임[111217 아꿈사연말모임] 웹소켓과온라인게임
[111217 아꿈사연말모임] 웹소켓과온라인게임
sung ki choi
 
Html5 canvas animation
Html5 canvas animationHtml5 canvas animation
Html5 canvas animation
SangHun Lee
 
[C3]collie deview2012
[C3]collie deview2012[C3]collie deview2012
[C3]collie deview2012NAVER D2
 
Web Animations 1.0 Overview
Web Animations 1.0 OverviewWeb Animations 1.0 Overview
Web Animations 1.0 Overview
Chang W. Doh
 
20131217 html5
20131217 html520131217 html5
20131217 html5
DK Lee
 
JS Game Engines
JS Game EnginesJS Game Engines
JS Game Engines
Wonjun Hwang
 
Html5 게임 기술의 개요
Html5 게임 기술의 개요Html5 게임 기술의 개요
Html5 게임 기술의 개요
Changhwan Yi
 
[211]대규모 시스템 시각화 현동석김광림
[211]대규모 시스템 시각화 현동석김광림[211]대규모 시스템 시각화 현동석김광림
[211]대규모 시스템 시각화 현동석김광림
NAVER D2
 
프론트엔드 개발자를 위한 크롬 렌더링 성능인자 이해하기
프론트엔드 개발자를 위한 크롬 렌더링 성능인자 이해하기프론트엔드 개발자를 위한 크롬 렌더링 성능인자 이해하기
프론트엔드 개발자를 위한 크롬 렌더링 성능인자 이해하기
Chang W. Doh
 
고성능 애니메이션 개발 기법 및 성능 최적화
고성능 애니메이션 개발 기법 및 성능 최적화고성능 애니메이션 개발 기법 및 성능 최적화
고성능 애니메이션 개발 기법 및 성능 최적화
Byung Ho Lee
 
Vagrant를 이용한 개발환경 구축과 NetBeans를 이용한 C/C++개발과 리모트 디버깅
Vagrant를 이용한 개발환경 구축과 NetBeans를 이용한 C/C++개발과 리모트 디버깅Vagrant를 이용한 개발환경 구축과 NetBeans를 이용한 C/C++개발과 리모트 디버깅
Vagrant를 이용한 개발환경 구축과 NetBeans를 이용한 C/C++개발과 리모트 디버깅
승엽 신
 
Html5 canvas introduction
Html5 canvas introductionHtml5 canvas introduction
Html5 canvas introduction
SangHun Lee
 
Web assembly 맛보기
Web assembly 맛보기Web assembly 맛보기
Web assembly 맛보기
GyeongSeok Seo
 

Similar to [122]책에서는 맛볼 수 없는 HTML5 Canvas 이야기 (20)

Html5 소개 가이드
Html5 소개 가이드Html5 소개 가이드
Html5 소개 가이드
 
[Naver d2]html5 canvas overview
[Naver d2]html5 canvas overview[Naver d2]html5 canvas overview
[Naver d2]html5 canvas overview
 
웹 기반 하이퍼포먼스 그래픽 처리 - 문경두
웹 기반 하이퍼포먼스 그래픽 처리 - 문경두웹 기반 하이퍼포먼스 그래픽 처리 - 문경두
웹 기반 하이퍼포먼스 그래픽 처리 - 문경두
 
Pp3 devweb
Pp3 devwebPp3 devweb
Pp3 devweb
 
웹 소프트웨어 시대의 새로운 롤(role) 모델, 자바스크립트
웹 소프트웨어 시대의 새로운 롤(role) 모델, 자바스크립트웹 소프트웨어 시대의 새로운 롤(role) 모델, 자바스크립트
웹 소프트웨어 시대의 새로운 롤(role) 모델, 자바스크립트
 
Html5 canvas sprite animation
Html5 canvas sprite animationHtml5 canvas sprite animation
Html5 canvas sprite animation
 
[별천지 세미나] CSS3 Animation
[별천지 세미나] CSS3 Animation[별천지 세미나] CSS3 Animation
[별천지 세미나] CSS3 Animation
 
[111217 아꿈사연말모임] 웹소켓과온라인게임
[111217 아꿈사연말모임] 웹소켓과온라인게임[111217 아꿈사연말모임] 웹소켓과온라인게임
[111217 아꿈사연말모임] 웹소켓과온라인게임
 
Html5 canvas animation
Html5 canvas animationHtml5 canvas animation
Html5 canvas animation
 
[C3]collie deview2012
[C3]collie deview2012[C3]collie deview2012
[C3]collie deview2012
 
Web Animations 1.0 Overview
Web Animations 1.0 OverviewWeb Animations 1.0 Overview
Web Animations 1.0 Overview
 
20131217 html5
20131217 html520131217 html5
20131217 html5
 
JS Game Engines
JS Game EnginesJS Game Engines
JS Game Engines
 
Html5 게임 기술의 개요
Html5 게임 기술의 개요Html5 게임 기술의 개요
Html5 게임 기술의 개요
 
[211]대규모 시스템 시각화 현동석김광림
[211]대규모 시스템 시각화 현동석김광림[211]대규모 시스템 시각화 현동석김광림
[211]대규모 시스템 시각화 현동석김광림
 
프론트엔드 개발자를 위한 크롬 렌더링 성능인자 이해하기
프론트엔드 개발자를 위한 크롬 렌더링 성능인자 이해하기프론트엔드 개발자를 위한 크롬 렌더링 성능인자 이해하기
프론트엔드 개발자를 위한 크롬 렌더링 성능인자 이해하기
 
고성능 애니메이션 개발 기법 및 성능 최적화
고성능 애니메이션 개발 기법 및 성능 최적화고성능 애니메이션 개발 기법 및 성능 최적화
고성능 애니메이션 개발 기법 및 성능 최적화
 
Vagrant를 이용한 개발환경 구축과 NetBeans를 이용한 C/C++개발과 리모트 디버깅
Vagrant를 이용한 개발환경 구축과 NetBeans를 이용한 C/C++개발과 리모트 디버깅Vagrant를 이용한 개발환경 구축과 NetBeans를 이용한 C/C++개발과 리모트 디버깅
Vagrant를 이용한 개발환경 구축과 NetBeans를 이용한 C/C++개발과 리모트 디버깅
 
Html5 canvas introduction
Html5 canvas introductionHtml5 canvas introduction
Html5 canvas introduction
 
Web assembly 맛보기
Web assembly 맛보기Web assembly 맛보기
Web assembly 맛보기
 

More from NAVER D2

[211] 인공지능이 인공지능 챗봇을 만든다
[211] 인공지능이 인공지능 챗봇을 만든다[211] 인공지능이 인공지능 챗봇을 만든다
[211] 인공지능이 인공지능 챗봇을 만든다
NAVER D2
 
[233] 대형 컨테이너 클러스터에서의 고가용성 Network Load Balancing: Maglev Hashing Scheduler i...
[233] 대형 컨테이너 클러스터에서의 고가용성 Network Load Balancing: Maglev Hashing Scheduler i...[233] 대형 컨테이너 클러스터에서의 고가용성 Network Load Balancing: Maglev Hashing Scheduler i...
[233] 대형 컨테이너 클러스터에서의 고가용성 Network Load Balancing: Maglev Hashing Scheduler i...
NAVER D2
 
[215] Druid로 쉽고 빠르게 데이터 분석하기
[215] Druid로 쉽고 빠르게 데이터 분석하기[215] Druid로 쉽고 빠르게 데이터 분석하기
[215] Druid로 쉽고 빠르게 데이터 분석하기
NAVER D2
 
[245]Papago Internals: 모델분석과 응용기술 개발
[245]Papago Internals: 모델분석과 응용기술 개발[245]Papago Internals: 모델분석과 응용기술 개발
[245]Papago Internals: 모델분석과 응용기술 개발
NAVER D2
 
[236] 스트림 저장소 최적화 이야기: 아파치 드루이드로부터 얻은 교훈
[236] 스트림 저장소 최적화 이야기: 아파치 드루이드로부터 얻은 교훈[236] 스트림 저장소 최적화 이야기: 아파치 드루이드로부터 얻은 교훈
[236] 스트림 저장소 최적화 이야기: 아파치 드루이드로부터 얻은 교훈
NAVER D2
 
[235]Wikipedia-scale Q&A
[235]Wikipedia-scale Q&A[235]Wikipedia-scale Q&A
[235]Wikipedia-scale Q&A
NAVER D2
 
[244]로봇이 현실 세계에 대해 학습하도록 만들기
[244]로봇이 현실 세계에 대해 학습하도록 만들기[244]로봇이 현실 세계에 대해 학습하도록 만들기
[244]로봇이 현실 세계에 대해 학습하도록 만들기
NAVER D2
 
[243] Deep Learning to help student’s Deep Learning
[243] Deep Learning to help student’s Deep Learning[243] Deep Learning to help student’s Deep Learning
[243] Deep Learning to help student’s Deep Learning
NAVER D2
 
[234]Fast & Accurate Data Annotation Pipeline for AI applications
[234]Fast & Accurate Data Annotation Pipeline for AI applications[234]Fast & Accurate Data Annotation Pipeline for AI applications
[234]Fast & Accurate Data Annotation Pipeline for AI applications
NAVER D2
 
Old version: [233]대형 컨테이너 클러스터에서의 고가용성 Network Load Balancing
Old version: [233]대형 컨테이너 클러스터에서의 고가용성 Network Load BalancingOld version: [233]대형 컨테이너 클러스터에서의 고가용성 Network Load Balancing
Old version: [233]대형 컨테이너 클러스터에서의 고가용성 Network Load Balancing
NAVER D2
 
[226]NAVER 광고 deep click prediction: 모델링부터 서빙까지
[226]NAVER 광고 deep click prediction: 모델링부터 서빙까지[226]NAVER 광고 deep click prediction: 모델링부터 서빙까지
[226]NAVER 광고 deep click prediction: 모델링부터 서빙까지
NAVER D2
 
[225]NSML: 머신러닝 플랫폼 서비스하기 & 모델 튜닝 자동화하기
[225]NSML: 머신러닝 플랫폼 서비스하기 & 모델 튜닝 자동화하기[225]NSML: 머신러닝 플랫폼 서비스하기 & 모델 튜닝 자동화하기
[225]NSML: 머신러닝 플랫폼 서비스하기 & 모델 튜닝 자동화하기
NAVER D2
 
[224]네이버 검색과 개인화
[224]네이버 검색과 개인화[224]네이버 검색과 개인화
[224]네이버 검색과 개인화
NAVER D2
 
[216]Search Reliability Engineering (부제: 지진에도 흔들리지 않는 네이버 검색시스템)
[216]Search Reliability Engineering (부제: 지진에도 흔들리지 않는 네이버 검색시스템)[216]Search Reliability Engineering (부제: 지진에도 흔들리지 않는 네이버 검색시스템)
[216]Search Reliability Engineering (부제: 지진에도 흔들리지 않는 네이버 검색시스템)
NAVER D2
 
[214] Ai Serving Platform: 하루 수 억 건의 인퍼런스를 처리하기 위한 고군분투기
[214] Ai Serving Platform: 하루 수 억 건의 인퍼런스를 처리하기 위한 고군분투기[214] Ai Serving Platform: 하루 수 억 건의 인퍼런스를 처리하기 위한 고군분투기
[214] Ai Serving Platform: 하루 수 억 건의 인퍼런스를 처리하기 위한 고군분투기
NAVER D2
 
[213] Fashion Visual Search
[213] Fashion Visual Search[213] Fashion Visual Search
[213] Fashion Visual Search
NAVER D2
 
[232] TensorRT를 활용한 딥러닝 Inference 최적화
[232] TensorRT를 활용한 딥러닝 Inference 최적화[232] TensorRT를 활용한 딥러닝 Inference 최적화
[232] TensorRT를 활용한 딥러닝 Inference 최적화
NAVER D2
 
[242]컴퓨터 비전을 이용한 실내 지도 자동 업데이트 방법: 딥러닝을 통한 POI 변화 탐지
[242]컴퓨터 비전을 이용한 실내 지도 자동 업데이트 방법: 딥러닝을 통한 POI 변화 탐지[242]컴퓨터 비전을 이용한 실내 지도 자동 업데이트 방법: 딥러닝을 통한 POI 변화 탐지
[242]컴퓨터 비전을 이용한 실내 지도 자동 업데이트 방법: 딥러닝을 통한 POI 변화 탐지
NAVER D2
 
[212]C3, 데이터 처리에서 서빙까지 가능한 하둡 클러스터
[212]C3, 데이터 처리에서 서빙까지 가능한 하둡 클러스터[212]C3, 데이터 처리에서 서빙까지 가능한 하둡 클러스터
[212]C3, 데이터 처리에서 서빙까지 가능한 하둡 클러스터
NAVER D2
 
[223]기계독해 QA: 검색인가, NLP인가?
[223]기계독해 QA: 검색인가, NLP인가?[223]기계독해 QA: 검색인가, NLP인가?
[223]기계독해 QA: 검색인가, NLP인가?
NAVER D2
 

More from NAVER D2 (20)

[211] 인공지능이 인공지능 챗봇을 만든다
[211] 인공지능이 인공지능 챗봇을 만든다[211] 인공지능이 인공지능 챗봇을 만든다
[211] 인공지능이 인공지능 챗봇을 만든다
 
[233] 대형 컨테이너 클러스터에서의 고가용성 Network Load Balancing: Maglev Hashing Scheduler i...
[233] 대형 컨테이너 클러스터에서의 고가용성 Network Load Balancing: Maglev Hashing Scheduler i...[233] 대형 컨테이너 클러스터에서의 고가용성 Network Load Balancing: Maglev Hashing Scheduler i...
[233] 대형 컨테이너 클러스터에서의 고가용성 Network Load Balancing: Maglev Hashing Scheduler i...
 
[215] Druid로 쉽고 빠르게 데이터 분석하기
[215] Druid로 쉽고 빠르게 데이터 분석하기[215] Druid로 쉽고 빠르게 데이터 분석하기
[215] Druid로 쉽고 빠르게 데이터 분석하기
 
[245]Papago Internals: 모델분석과 응용기술 개발
[245]Papago Internals: 모델분석과 응용기술 개발[245]Papago Internals: 모델분석과 응용기술 개발
[245]Papago Internals: 모델분석과 응용기술 개발
 
[236] 스트림 저장소 최적화 이야기: 아파치 드루이드로부터 얻은 교훈
[236] 스트림 저장소 최적화 이야기: 아파치 드루이드로부터 얻은 교훈[236] 스트림 저장소 최적화 이야기: 아파치 드루이드로부터 얻은 교훈
[236] 스트림 저장소 최적화 이야기: 아파치 드루이드로부터 얻은 교훈
 
[235]Wikipedia-scale Q&A
[235]Wikipedia-scale Q&A[235]Wikipedia-scale Q&A
[235]Wikipedia-scale Q&A
 
[244]로봇이 현실 세계에 대해 학습하도록 만들기
[244]로봇이 현실 세계에 대해 학습하도록 만들기[244]로봇이 현실 세계에 대해 학습하도록 만들기
[244]로봇이 현실 세계에 대해 학습하도록 만들기
 
[243] Deep Learning to help student’s Deep Learning
[243] Deep Learning to help student’s Deep Learning[243] Deep Learning to help student’s Deep Learning
[243] Deep Learning to help student’s Deep Learning
 
[234]Fast & Accurate Data Annotation Pipeline for AI applications
[234]Fast & Accurate Data Annotation Pipeline for AI applications[234]Fast & Accurate Data Annotation Pipeline for AI applications
[234]Fast & Accurate Data Annotation Pipeline for AI applications
 
Old version: [233]대형 컨테이너 클러스터에서의 고가용성 Network Load Balancing
Old version: [233]대형 컨테이너 클러스터에서의 고가용성 Network Load BalancingOld version: [233]대형 컨테이너 클러스터에서의 고가용성 Network Load Balancing
Old version: [233]대형 컨테이너 클러스터에서의 고가용성 Network Load Balancing
 
[226]NAVER 광고 deep click prediction: 모델링부터 서빙까지
[226]NAVER 광고 deep click prediction: 모델링부터 서빙까지[226]NAVER 광고 deep click prediction: 모델링부터 서빙까지
[226]NAVER 광고 deep click prediction: 모델링부터 서빙까지
 
[225]NSML: 머신러닝 플랫폼 서비스하기 & 모델 튜닝 자동화하기
[225]NSML: 머신러닝 플랫폼 서비스하기 & 모델 튜닝 자동화하기[225]NSML: 머신러닝 플랫폼 서비스하기 & 모델 튜닝 자동화하기
[225]NSML: 머신러닝 플랫폼 서비스하기 & 모델 튜닝 자동화하기
 
[224]네이버 검색과 개인화
[224]네이버 검색과 개인화[224]네이버 검색과 개인화
[224]네이버 검색과 개인화
 
[216]Search Reliability Engineering (부제: 지진에도 흔들리지 않는 네이버 검색시스템)
[216]Search Reliability Engineering (부제: 지진에도 흔들리지 않는 네이버 검색시스템)[216]Search Reliability Engineering (부제: 지진에도 흔들리지 않는 네이버 검색시스템)
[216]Search Reliability Engineering (부제: 지진에도 흔들리지 않는 네이버 검색시스템)
 
[214] Ai Serving Platform: 하루 수 억 건의 인퍼런스를 처리하기 위한 고군분투기
[214] Ai Serving Platform: 하루 수 억 건의 인퍼런스를 처리하기 위한 고군분투기[214] Ai Serving Platform: 하루 수 억 건의 인퍼런스를 처리하기 위한 고군분투기
[214] Ai Serving Platform: 하루 수 억 건의 인퍼런스를 처리하기 위한 고군분투기
 
[213] Fashion Visual Search
[213] Fashion Visual Search[213] Fashion Visual Search
[213] Fashion Visual Search
 
[232] TensorRT를 활용한 딥러닝 Inference 최적화
[232] TensorRT를 활용한 딥러닝 Inference 최적화[232] TensorRT를 활용한 딥러닝 Inference 최적화
[232] TensorRT를 활용한 딥러닝 Inference 최적화
 
[242]컴퓨터 비전을 이용한 실내 지도 자동 업데이트 방법: 딥러닝을 통한 POI 변화 탐지
[242]컴퓨터 비전을 이용한 실내 지도 자동 업데이트 방법: 딥러닝을 통한 POI 변화 탐지[242]컴퓨터 비전을 이용한 실내 지도 자동 업데이트 방법: 딥러닝을 통한 POI 변화 탐지
[242]컴퓨터 비전을 이용한 실내 지도 자동 업데이트 방법: 딥러닝을 통한 POI 변화 탐지
 
[212]C3, 데이터 처리에서 서빙까지 가능한 하둡 클러스터
[212]C3, 데이터 처리에서 서빙까지 가능한 하둡 클러스터[212]C3, 데이터 처리에서 서빙까지 가능한 하둡 클러스터
[212]C3, 데이터 처리에서 서빙까지 가능한 하둡 클러스터
 
[223]기계독해 QA: 검색인가, NLP인가?
[223]기계독해 QA: 검색인가, NLP인가?[223]기계독해 QA: 검색인가, NLP인가?
[223]기계독해 QA: 검색인가, NLP인가?
 

[122]책에서는 맛볼 수 없는 HTML5 Canvas 이야기