SlideShare uma empresa Scribd logo
1 de 73
Baixar para ler offline
한성민 SungMin Han
Deep dive into
Modern frameworks
프론트엔드의 러닝커브
모던 프레임워크 톺아보기
Today, We’ll discuss about
Front-end Learning Curve
Looking around Front-end Modern Frameworks
프론트엔드의 러닝커브
프론트엔드 기술의 변화
jQuery
Vanila
Javascript
AngularJS
React
VueJS
Angular
2006 2013
2009 2014
2016
조금 더 넓게..
jQuery
Vanila
Javascript
AngularJS
React
VueJS
Angular
2006 2013
2009 2014
2016
XMLHTTPRequest(XHR)
2002
ES2015
2015
Node.js
2013
Redux
2015
RxJS
2012
Typescript
2012
Ember.js
2011
CoffeScript
2009
AMD
2010
CommonJS
(CJS)
2009
ES2016
2016
WebAssembly
2015
오늘날의 프론트엔드 스택
Deep dive into Modern frameworks - HTML5 Forum 2018
Deep dive into Modern frameworks - HTML5 Forum 2018
Deep dive into Modern frameworks - HTML5 Forum 2018
Welcome to Hell
동적 렌더링
모듈링 / 번들링
타이핑
현재 프론트엔드 진형의 중요 키워드
테스트 자동화
동적 렌더링
모듈링 / 번들링
타이핑
현재 프론트엔드 진형의 중요 키워드
테스트 자동화
Two-way binding, SPA, Virtual DOM, Change Detection …
CommonJS, AMD, UMD, Uglify, Grunt, Webpack …
Typescript, Proptypes, Flow, Props …
UnitTest, e2e Test, HeadLess Browser …
그리고 그것들을 제공하는 많은 도구들
Angular
완전하고 빠른 프레임워크
React
활발하고 오픈 되어 있으며 합리적인 프레임워크
VueJS
가볍고 친숙하며 장점만을 합쳐놓은 프레임워크
그러던 중 나타난 프레임워크들
그리고 프레임워크는 그 모든 것을 쉽게 만들어주었나니..
Angular
완전하고 빠른 프레임워크
React
활발하고 오픈 되어 있으며 합리적인 프레임워크
VueJS
가볍고 친숙하며 장점만을 합쳐놓은 프레임워크
그러던 중 나타난 프레임워크들
그리고 프레임워크는 그 모든 것을 쉽게 만들어주었나니..
Angular
완전하고 빠른 프레임워크 인기가 없음, 오버엔지니어링
React
활발하고 오픈 되어 있으며 합리적인 프레임워크 너무 힙함
VueJS
가볍고 친숙하며 장점만을 합쳐놓은 프레임워크 DOM 테스트하기 힘듦
그러던 중 나타난 프레임워크들
그리고 프레임워크는 그 모든 것을 쉽게 만들어주었나니..
Angular
모든 기능이 내장되어 있으며 성능이 훌륭하지만, 진입장벽이 가장 높음
React
에코시스템이 활발하게 움직이고 또 그것을 장려하지만
의존과 버전에 민감하고 라이브러리 자체의 기능만으로는 부족함
VueJS
프레임워크 자체가 가볍고 진입장벽이 낮으며 각 프레임워크의 장점을 흡수
다만 크기가 커질 수록 재활용성은 떨어지며, 테스트하기 어렵고 느림
이를 풀어 설명하자면
모던 프레임워크 톺아보기
Angular
릴리즈
개발자/개발사
버전
언어
모델
컴파일
2016년 6월 공식출시
Google Inc
2017년 11월 기준 v5.0.1 stable
Typescript, Dart, Javascript
MVVM / Change Detection / NgZone
JIT (built-in core) / AOT (ng, ngc) / TreeShaking with ng cli
React
릴리즈
개발자/개발사
버전
언어
모델
컴파일
2013년 3월 공식출시
Facebook, Instagram
2017년 11월 기준 V16.1.1 stable
Javascript, JSX
View Engine / Virtual DOM / PropTypes
JIT (built-in core) / TreeShaking with Webpack2
VueJS
릴리즈
개발자/개발사
버전
언어
모델
컴파일
2014년 2월 공식출시
Evan you
2017년 11월 기준 V2.5.3 stable
Javascript, JSX(호환)
MVVM / VirtualDOM / core와 companion 분리 / Vuex
JIT (built-in core) / TreeShaking with Webpack2
Angular code
import { Component, ViewChild, ElementRef } from '@angular/core';
const DEFAULT_INITIALIZE_FOOD_LIST: string[] = [ '치킨', '탕수육',
'닭도리탕' ];
@Component({
selector: 'mukkit-list',
templateUrl: './mukkit_list.html',
styleUrls: [ './mukkit_list.css' ]
})
export class MukkitListComponent {
public foodList: string[] = [...DEFAULT_INITIALIZE_FOOD_LIST];
public newFood: string;
@ViewChild('input') inputEl: ElementRef;
ngAfterViewInit() {
this.focusFood();
}
focusFood(): void {
this.inputEl.nativeElement.focus();
}
enterFood($event: KeyboardEvent): void {
if ($event.keyCode === 13) {
this.addFood();
}
}
addFood(): void {
if (this.foodList.indexOf(this.newFood) === -1) {
this.foodList.push(this.newFood);
this.newFood = '';
} else {
alert('해당 음식은 이미 있습니다.');
}
}
}
mukkitList.component.ts
Angular code
mukkitList.html
<div class="mukkit-list-container">
<img width="180" src="data:image…">
<h2>먹킷리스트</h2>
</div>
<ul class="mukkit-list">
<li *ngFor="let food of foodList">
<span>{{food}}</span>
</li>
<li>
<input type="text"
#input
[(ngModel)]="newFood"
(keypress)="enterFood($event);">
<button (click)="addFood();">먹킷리스트 추가</button>
</li>
</ul>
Angular code
mukkitList.html
<div class="mukkit-list-container">
<img width="180" src="data:image…">
<h2>먹킷리스트</h2>
</div>
<ul class="mukkit-list">
<li *ngFor="let food of foodList">
<span>{{food}}</span>
</li>
<li>
<input type="text"
#input
[(ngModel)]="newFood"
(keypress)="enterFood($event);">
<button (click)="addFood();">먹킷리스트 추가</button>
</li>
</ul>
export class MukkitListComponent {
public foodList: string[] = [...DEFAULT_INITIALIZE_FOOD_LIST];
public newFood: string;
@ViewChild('input') inputEl: ElementRef;
…
enterFood($event: KeyboardEvent): void {
…
}
addFood(): void {
…
}
}
mukkit_list.component.ts
1way binding (viewmodel -> view)
2way binding (videmodel <-> view)
view query (it is not bind)
1way binding (view <- viewmodel)
mukkitList.js
React code
import React, { Component } from 'react';
import logo from './logo.svg';
import './MukkitList.css';
const DEFAULT_INITIALIZE_FOOD_LIST = [ '치킨', '탕수육', '닭도리탕' ];
class MukkitList extends Component {
constructor(props) {
super(props);
this.state = {
foodList: [...DEFAULT_INITIALIZE_FOOD_LIST],
newFood: ''
};
}
changeFood(event) {
this.setState({'newFood': event.target.value});
}
enterFood(event) {
if (event.key === 'Enter') this.addFood();
}
addFood(event) {
if (this.state.foodList.indexOf(this.state.newFood) === -1) {
this.setState({
foodList: [...this.state.foodList, this.state.newFood],
newFood: ''
});
} else {
alert('해당 음식은 이미 있습니다.');
}
}
render() {
return (
<div className="container">
<header className="mukkit-list-header">
<img src={logo} className="mukkit-list-logo" alt="logo" />
<h2 className="mukkit-list-title">먹킷리스트</h2>
</header>
<ul className="mukkit-list">
{this.state.foodList.map((food, index) => <li key={index}><span>{food}</span></li>)}
<li>
<input type="text“ value={this.state.newFood}
onChange={this.changeFood.bind(this)}
onKeyPress={this.enterFood.bind(this)} />
<button onClick={this.addFood.bind(this)}>먹킷리스트 추가</button>
</li>
</ul >
</div >
);
}
}
export default MukkitList;
mukkitList.js
import React, { Component } from 'react';
import logo from './logo.svg';
import './MukkitList.css';
const DEFAULT_INITIALIZE_FOOD_LIST = [ '치킨', '탕수육', '닭도리탕' ];
class MukkitList extends Component {
constructor(props) {
super(props);
this.state = {
foodList: [...DEFAULT_INITIALIZE_FOOD_LIST],
newFood: ''
};
}
changeFood(event) {
this.setState({'newFood': event.target.value});
}
enterFood(event) {
if (event.key === 'Enter') this.addFood();
}
addFood(event) {
if (this.state.foodList.indexOf(this.state.newFood) === -1) {
this.setState({
foodList: [...this.state.foodList, this.state.newFood],
newFood: ''
});
} else {
alert('해당 음식은 이미 있습니다.');
}
}
render() {
return (
<div className="container">
<header className="mukkit-list-header">
<img src={logo} className="mukkit-list-logo" alt="logo" />
<h2 className="mukkit-list-title">먹킷리스트</h2>
</header>
<ul className="mukkit-list">
{this.state.foodList.map((food, index) => <li key={index}><span>{food}</span></li>)}
<li>
<input type="text“ value={this.state.newFood}
onChange={this.changeFood.bind(this)}
onKeyPress={this.enterFood.bind(this)} />
<button onClick={this.addFood.bind(this)}>먹킷리스트 추가</button>
</li>
</ul >
</div >
);
}
}
export default MukkitList;
1way binding (videmodel -> view)
React code
mukkitList.js
import React, { Component } from 'react';
import logo from './logo.svg';
import './MukkitList.css';
const DEFAULT_INITIALIZE_FOOD_LIST = [ '치킨', '탕수육', '닭도리탕' ];
class MukkitList extends Component {
constructor(props) {
super(props);
this.state = {
foodList: [...DEFAULT_INITIALIZE_FOOD_LIST],
newFood: ''
};
}
changeFood(event) {
this.setState({'newFood': event.target.value});
}
enterFood(event) {
if (event.key === 'Enter') this.addFood();
}
addFood(event) {
if (this.state.foodList.indexOf(this.state.newFood) === -1) {
this.setState({
foodList: [...this.state.foodList, this.state.newFood],
newFood: ''
});
} else {
alert('해당 음식은 이미 있습니다.');
}
}
render() {
return (
<div className="container">
<header className="mukkit-list-header">
<img src={logo} className="mukkit-list-logo" alt="logo" />
<h2 className="mukkit-list-title">먹킷리스트</h2>
</header>
<ul className="mukkit-list">
{this.state.foodList.map((food, index) => <li key={index}><span>{food}</span></li>)}
<li>
<input type="text“ value={this.state.newFood}
onChange={this.changeFood.bind(this)}
onKeyPress={this.enterFood.bind(this)} />
<button onClick={this.addFood.bind(this)}>먹킷리스트 추가</button>
</li>
</ul >
</div >
);
}
}
export default MukkitList;
render DOM
React code
mukkitList.js
import React, { Component } from 'react';
import logo from './logo.svg';
import './MukkitList.css';
const DEFAULT_INITIALIZE_FOOD_LIST = [ '치킨', '탕수육', '닭도리탕' ];
class MukkitList extends Component {
constructor(props) {
super(props);
this.state = {
foodList: [...DEFAULT_INITIALIZE_FOOD_LIST],
newFood: ''
};
}
changeFood(event) {
this.setState({'newFood': event.target.value});
}
enterFood(event) {
if (event.key === 'Enter') this.addFood();
}
addFood(event) {
if (this.state.foodList.indexOf(this.state.newFood) === -1) {
this.setState({
foodList: [...this.state.foodList, this.state.newFood],
newFood: ''
});
} else {
alert('해당 음식은 이미 있습니다.');
}
}
render() {
return (
<div className="container">
<header className="mukkit-list-header">
<img src={logo} className="mukkit-list-logo" alt="logo" />
<h2 className="mukkit-list-title">먹킷리스트</h2>
</header>
<ul className="mukkit-list">
{this.state.foodList.map((food, index) => <li key={index}><span>{food}</span></li>)}
<li>
<input type="text“ value={this.state.newFood}
onChange={this.changeFood.bind(this)}
onKeyPress={this.enterFood.bind(this)} />
<button onClick={this.addFood.bind(this)}>먹킷리스트 추가</button>
</li>
</ul >
</div >
);
}
}
export default MukkitList;
1way binding (viewmodel -> view)
React code
mukkitList.js
import React, { Component } from 'react';
import logo from './logo.svg';
import './MukkitList.css';
const DEFAULT_INITIALIZE_FOOD_LIST = [ '치킨', '탕수육', '닭도리탕' ];
class MukkitList extends Component {
constructor(props) {
super(props);
this.state = {
foodList: [...DEFAULT_INITIALIZE_FOOD_LIST],
newFood: ''
};
}
changeFood(event) {
this.setState({'newFood': event.target.value});
}
enterFood(event) {
if (event.key === 'Enter') this.addFood();
}
addFood(event) {
if (this.state.foodList.indexOf(this.state.newFood) === -1) {
this.setState({
foodList: [...this.state.foodList, this.state.newFood],
newFood: ''
});
} else {
alert('해당 음식은 이미 있습니다.');
}
}
render() {
return (
<div className="container">
<header className="mukkit-list-header">
<img src={logo} className="mukkit-list-logo" alt="logo" />
<h2 className="mukkit-list-title">먹킷리스트</h2>
</header>
<ul className="mukkit-list">
{this.state.foodList.map((food, index) => <li key={index}><span>{food}</span></li>)}
<li>
<input type="text“ value={this.state.newFood}
onChange={this.changeFood.bind(this)}
onKeyPress={this.enterFood.bind(this)} />
<button onClick={this.addFood.bind(this)}>먹킷리스트 추가</button>
</li>
</ul >
</div >
);
}
}
export default MukkitList;
1way binding (view -> viewmodel)
React code
mukkitList.js
import React, { Component } from 'react';
import logo from './logo.svg';
import './MukkitList.css';
const DEFAULT_INITIALIZE_FOOD_LIST = [ '치킨', '탕수육', '닭도리탕' ];
class MukkitList extends Component {
constructor(props) {
super(props);
this.state = {
foodList: [...DEFAULT_INITIALIZE_FOOD_LIST],
newFood: ''
};
}
changeFood(event) {
this.setState({'newFood': event.target.value});
}
enterFood(event) {
if (event.key === 'Enter') this.addFood();
}
addFood(event) {
if (this.state.foodList.indexOf(this.state.newFood) === -1) {
this.setState({
foodList: [...this.state.foodList, this.state.newFood],
newFood: ''
});
} else {
alert('해당 음식은 이미 있습니다.');
}
}
render() {
return (
<div className="container">
<header className="mukkit-list-header">
<img src={logo} className="mukkit-list-logo" alt="logo" />
<h2 className="mukkit-list-title">먹킷리스트</h2>
</header>
<ul className="mukkit-list">
{this.state.foodList.map((food, index) => <li key={index}><span>{food}</span></li>)}
<li>
<input type="text“ value={this.state.newFood}
onChange={this.changeFood.bind(this)}
onKeyPress={this.enterFood.bind(this)} />
<button onClick={this.addFood.bind(this)}>먹킷리스트 추가</button>
</li>
</ul >
</div >
);
}
}
export default MukkitList;
state changed
React code
mukkitList.vue
VueJS code
<template>
<ul class="mukkit-list">
<li v-for="food in foodList">
<span>{{food}}</span>
</li>
<li>
<input type="text"
ref="input"
v-model="newFood"
v-on:keypress.enter="addFood">
<button v-on:click="addFood">먹킷리스트 추가</button>
</li>
</ul>
</template>
<script>
const DEFAULT_INITIALIZE_FOOD_LIST = [ '치킨', '탕수육', '닭도리탕' ]
export default {
name: 'MukkitList',
data () {
return {
foodList: [...DEFAULT_INITIALIZE_FOOD_LIST],
newFood: ''
}
},
mounted () {
this.focusFood()
},
methods: {
focusFood () {
this.$refs.input.focus()
},
addFood () {
if (this.foodList.indexOf(this.newFood) === -1) {
this.foodList.push(this.newFood)
this.newFood = ''
this.focusFood()
} else {
alert('해당 음식은 이미 있습니다.')
}
}
}
}
</script>
mukkitList.vue
<template>
<ul class="mukkit-list">
<li v-for="food in foodList">
<span>{{food}}</span>
</li>
<li>
<input type="text"
ref="input"
v-model="newFood"
v-on:keypress.enter="addFood">
<button v-on:click="addFood">먹킷리스트 추가</button>
</li>
</ul>
</template>
<script>
const DEFAULT_INITIALIZE_FOOD_LIST = [ '치킨', '탕수육', '닭도리탕' ]
export default {
name: 'MukkitList',
data () {
return {
foodList: [...DEFAULT_INITIALIZE_FOOD_LIST],
newFood: ''
}
},
mounted () {
this.focusFood()
},
methods: {
focusFood () {
this.$refs.input.focus()
},
addFood () {
if (this.foodList.indexOf(this.newFood) === -1) {
this.foodList.push(this.newFood)
this.newFood = ''
this.focusFood()
} else {
alert('해당 음식은 이미 있습니다.')
}
}
}
}
</script>
VueJS code
2way binding (videmodel <-> view)
mukkitList.vue
<template>
<ul class="mukkit-list">
<li v-for="food in foodList">
<span>{{food}}</span>
</li>
<li>
<input type="text"
ref="input"
v-model="newFood"
v-on:keypress.enter="addFood">
<button v-on:click="addFood">먹킷리스트 추가</button>
</li>
</ul>
</template>
<script>
const DEFAULT_INITIALIZE_FOOD_LIST = [ '치킨', '탕수육', '닭도리탕' ]
export default {
name: 'MukkitList',
data () {
return {
foodList: [...DEFAULT_INITIALIZE_FOOD_LIST],
newFood: ''
}
},
mounted () {
this.focusFood()
},
methods: {
focusFood () {
this.$refs.input.focus()
},
addFood () {
if (this.foodList.indexOf(this.newFood) === -1) {
this.foodList.push(this.newFood)
this.newFood = ''
this.focusFood()
} else {
alert('해당 음식은 이미 있습니다.')
}
}
}
}
</script>
VueJS code
1way binding (viewmodel -> view)
mukkitList.vue
<template>
<ul class="mukkit-list">
<li v-for="food in foodList">
<span>{{food}}</span>
</li>
<li>
<input type="text"
ref="input"
v-model="newFood"
v-on:keypress.enter="addFood">
<button v-on:click="addFood">먹킷리스트 추가</button>
</li>
</ul>
</template>
<script>
const DEFAULT_INITIALIZE_FOOD_LIST = [ '치킨', '탕수육', '닭도리탕' ]
export default {
name: 'MukkitList',
data () {
return {
foodList: [...DEFAULT_INITIALIZE_FOOD_LIST],
newFood: ''
}
},
mounted () {
this.focusFood()
},
methods: {
focusFood () {
this.$refs.input.focus()
},
addFood () {
if (this.foodList.indexOf(this.newFood) === -1) {
this.foodList.push(this.newFood)
this.newFood = ''
this.focusFood()
} else {
alert('해당 음식은 이미 있습니다.')
}
}
}
}
</script>
VueJS code
1way binding (view -> viewmodel)
mukkitList.vue
<template>
<ul class="mukkit-list">
<li v-for="food in foodList">
<span>{{food}}</span>
</li>
<li>
<input type="text"
ref="input"
v-model="newFood"
v-on:keypress.enter="addFood">
<button v-on:click="addFood">먹킷리스트 추가</button>
</li>
</ul>
</template>
<script>
const DEFAULT_INITIALIZE_FOOD_LIST = [ '치킨', '탕수육', '닭도리탕' ]
export default {
name: 'MukkitList',
data () {
return {
foodList: [...DEFAULT_INITIALIZE_FOOD_LIST],
newFood: ''
}
},
mounted () {
this.focusFood()
},
methods: {
focusFood () {
this.$refs.input.focus()
},
addFood () {
if (this.foodList.indexOf(this.newFood) === -1) {
this.foodList.push(this.newFood)
this.newFood = ''
this.focusFood()
} else {
alert('해당 음식은 이미 있습니다.')
}
}
}
}
</script>
VueJS code
view query (it is not bind)
트랜드 - Trend
Fight 1
42,938 star
116,226 star
120,113 star
GitHub Stars
변화하는 프레임워크 관심도
Google Trend 2018. 11
42,938 star
116,226 star
120,113 star
2018 Stars
변화하는 프레임워크 관심도
29,994 star
81,002 star
73,628 star
2017 Stars
Deep dive into Modern frameworks - HTML5 Forum 2018
React 트랜드 및 에코시스템이 가장 활발
VueJS가 무서운 속도로 트랜드를 따라잡고 있음
Angular가 AngularJS 까지 포함한다면 가장 큼
진입장벽 – Entry barriers
Fight 2
Blogged from Marius Duta
일반적인 케이스에서
Angular의 학습곡선이 압도적으로 높고 Vue의 학습곡선이 가장 낮음
학습곡선
각 프레임워크를 배우기 위해서
Language Module / Components DeploymentData Flow
Others/
Advanced
일반적으로
Typescript
일반적으로
Javascript (ES6)
일반적으로
Javascript (ES6)
Controller / Directive
Pipe / Service
ContentChild / ViewChild
QueryList
Smart Component
Dumb Component
Global Component
Local Component
Directive / Filter / Plugin
RxJS / ng-redux
Redux / MobX
vuex / vue-rx
Bundling
Compilation (ngc)
Bundling
Bundling
DI pattern
ngZone
CD Strategy
Immutable
Link State Optimization
Server-side Rendering
Flow
Computed Property
Observed Property
flow-typed
각 프레임워크 컴포넌트 라이프사이클
Angular 진입전에 다른 프레임워크 경험 권장
React의 라이프 사이클과 상태관리는 상대적 어려움
AngularJS를 사용하고 있다면 VueJS 권장
성능 – Performance
Fight 3
Benchmark
Vue >= Angular > React
AOT Compilation 이후 성능 비교에서는 Angular가 더욱 빠를 것으로 예상
TreeShaking
TreeShaking (나무털기)
마치 나무에 달린 열매를 털듯이 사용하지 않는 모듈은
빌드 단계에서 제외시키는 최적화 기법
지원
지원 (Webpack2)
지원 (Webpack2)
AOT(Ahead Of Time)
Ahead Of Time (조기 컴파일)
JIT (Just In Time) 컴파일 방식과는 다르게
사전에 컴파일러가 중간코드로 컴파일하여 사용자 브라우저에서 컴파일 시간을 최소화 하는 최적화 기법
지원
미지원
미지원
JIT
@NgModule
Bootstraping
Javascript
CSS
HTML
@angular/platform-browser-dynamic
Parse
AST
memory
load
CD
host
viewDef
Renderer
pipeDef
ngContentDef
nodeValue
compilation-side
browser-side
AOT
@NgModuleFactory
Bootstraping
Javascript
CSS
HTML
host
viewDef
Renderer
pipeDef
ngContentDef
nodeValue
…
compilation-side
@angular/platform-browser
Parse
AST
load
CD
browser-side
Angular5 부터는 build-optimizer 옵션을 통해 추가적으로 최적화가 가능하니 참고해주세요
function View_MukkitListComponent_0(_l) {
return __WEBPACK_IMPORTED_MODULE_1__angular_core__["_25" /* ɵvid */]
(0, [__WEBPACK_IMPORTED_MODULE_1__angular_core__["_22" /* ɵqud */]
(402653184, 1, { inputEl: 0 }),
(_l()(), __WEBPACK_IMPORTED_MODULE_1__angular_core__["_8" /* ɵeld */](1, 0, null, null, 6, "div", [["class", "mukkit-list-
container"]], null, null, null, null, null)),
(_l()(), __WEBPACK_IMPORTED_MODULE_1__angular_core__["_24" /* ɵted */](-1, null, ["n "])),
(_l()(), __WEBPACK_IMPORTED_MODULE_1__angular_core__["_8" /* ɵeld */](3, 0, null, null, 0, "img", [["src",
"data:image/svg+xml;base64,…"], ["width", "180"]], null, null, null, null, null)),
(_l()(), __WEBPACK_IMPORTED_MODULE_1__angular_core__["_24" /* ɵted */](-1, null, ["n "])),
(_l()(), __WEBPACK_IMPORTED_MODULE_1__angular_core__["_8" /* ɵeld */](5, 0, null, null, 1, "h2", [], null, null, null, null,
null)),
(_l()(), __WEBPACK_IMPORTED_MODULE_1__angular_core__["_24" /* ɵted */](-1, null, ["uBA39uD0B7uB9ACuC2A4uD2B8"])),
(_l()(), __WEBPACK_IMPORTED_MODULE_1__angular_core__["_24" /* ɵted */](-1, null, ["n"])),
(_l()(), __WEBPACK_IMPORTED_MODULE_1__angular_core__["_24" /* ɵted */](-1, null, ["nn"])),
(_l()(), __WEBPACK_IMPORTED_MODULE_1__angular_core__["_8" /* ɵeld */](9, 0, null, null, 17, "ul", [["class", "mukkit-list"]],
null, null, null, null, null)),
(_l()(), __WEBPACK_IMPORTED_MODULE_1__angular_core__["_24" /* ɵted */](-1, null, ["n "])),
(_l()(), __WEBPACK_IMPORTED_MODULE_1__angular_core__["_3" /* ɵand */](16777216, null, null, 1, null, View_MukkitListComponent_1)),
__WEBPACK_IMPORTED_MODULE_1__angular_core__["_7" /* ɵdid */](
12, 802816, null, 0, __WEBPACK_IMPORTED_MODULE_2__angular_common__["c" /* NgForOf */],
[__WEBPACK_IMPORTED_MODULE_1__angular_core__["R" /* ViewContainerRef */],
__WEBPACK_IMPORTED_MODULE_1__angular_core__["N" /* TemplateRef */],
__WEBPACK_IMPORTED_MODULE_1__angular_core__["u" /* IterableDiffers */]],
{ ngForOf: [0, "ngForOf"] }, null),
(_l()(), __WEBPACK_IMPORTED_MODULE_1__angular_core__["_24" /* ɵted */](-1, null, ["n "])),
…
AOT Compiled Code
AOT 성능 변화
크기 (minified)
지연시간 (initial load)
메모리 (snapshot)
442KB
585ms
38.5MB
198KB
305ms
15.3MB
-55%
-48%
-60%
JIT AOT
JIT AOT
VirtualDOM
VirtualDOM (가상 DOM)
뷰 모델에서 발생하는 변경사항을 메모리에서 관리하는 논리적 DOM에서 먼저 감지 한 후
실제 DOM의 업데이트를 최소화하여 성능을 향상시키고 UX 측면에서 발생하는 문제를 줄임
미지원
지원
지원
VirtualDOMViewModel
Element A
Element B1
Element B2
Element B
Element A
Element B1
Element B2
Element B
header
.list-item
.list-item
.container
NativeDOM
(Real DOM)
diff patch
VirtualDOM
기존의 비싼 비용의 Native DOM 처리를 javascript 상의 diff 알고리즘을 통해
저렴한 비용으로 효율적인 처리가 가능해짐
MDN에 공개된 브라우저 Layout 처리
Angular의 최적화가 적용되지 않은 케이스에서는
VueJS가 성능이 빠를 것으로 예상됩니다.
(VueJS에서 제공하는 자료와 벤치마크 데이터 참조)
구성요소 – Component
Fight 4
모듈 구성
@NgModule Main
@Component
@Injectable
@NgModule
Vue
Vue.component
Vue.directive
Vue.filter
Vue.mixin
ReactDOM.render
Component or Class
Component or Class
마이크로 프로젝트에는 VueJS 권장
서버사이드 랜더링이 필요한 프로젝트에는 React
대규모의 프로젝트에는 Angular
템플릿
{{interpolation}}
[1way data binding]
[(2way data binding)]
(1way data binding (event))
{{interpolation with pipe | pipeName}}
*ngFor *ngIf
[ngSwitch] [hidden] [innerHTML] [ngClass]
(click) (keypress) (blur) (input) (change)
…
React에서 공식적으로
제공하는 템플릿은 없습니다.
모든 것을
JSX 혹은 Javascript를 이용하여
표현합니다.
react-templates
라이브러리를 이용하면
다른 프레임워크와 유사하게
템플릿을 사용하실 수 있습니다.
v-directive-name:parameter
{{interpolation | filter}}
v-bind:id v-if v-html
v-for v-else v-else-if
v-show v-bind:class v-bind:style
v-on:event-name
v-bind:bind-target-name
{{interpolation}}
:store-name
v-model
템플릿 표현식은 Angular가 체계적이지만
VueJS가 접근장벽이 낮음
AngularJS (Angular 1)는 VueJS 템플릿과 유사
변화감지
ChangeDetection
NgZone
RxJS
Props / State
Reconciliation
React Fiber
Redux
Redux Saga
Redux Thunk
Watcher
VirtualDOM (based Snabdom)
vuex
vue-rx
Angular Change Detection & NgZone
NgZone의 몽키패칭된 이벤트로부터 변화를 감지하여 Change Detection Strategy에 맞게 변화를 전파
setTimeout, addEventListener,
requestAnimationFrame
NgZone
Monkey Patched
Tick
1
React Reconciliation & React Fiber
React Reconciliation
React FibershouldComponentUpdate()
Dealing control by element types
(aka. Pair-wise diff)
2 3
Dealing control by key
(aka. List-wise diff)
Update DOM
render() 호출 시 VirtualDOM 생성 및 Dirty model을 감지하여 React Reconciliation 과정을 진행 후 React Fiber 혹은 DOM 변경
VueJS watcher & VirtualDOM
data 프로퍼티에서 Object.defineProperty()를 통해 Watcher가 변화를 감지 변화를 수신 시
render 함수에 의해 VirtualDOM에 따른 DOM 변경
생태계 – Eco System
Fight 5
Progressive Web App(PWA)
Native Mobile
Native Mobile
모두 NativeScript 지원
Native Desktop
모두 Electron 지원
Server Side Rendering
Angular Universal ReactDOMServer vue-server-renderer
각 프레임워크 별 오픈소스는 계속적으로 발전 중
따라서 어느것이 더 안정적인가 더 알려져있는가가
선택사항이 될 수 있음
Question?
Show more in GitHub!
https://github.com/KennethanCeyer/html5-forum-2018
WIP
Thank you!
https://github.com/KennethanCeyer - GitHub
kenneth@pigno.se - Email

Mais conteúdo relacionado

Mais procurados

[DevOn 2013] Backbone.js로 능동적 M-V 디자인 구현하기
[DevOn 2013] Backbone.js로 능동적  M-V 디자인 구현하기[DevOn 2013] Backbone.js로 능동적  M-V 디자인 구현하기
[DevOn 2013] Backbone.js로 능동적 M-V 디자인 구현하기Gyutae Jo
 
Node.js and react
Node.js and reactNode.js and react
Node.js and reactHyungKuIm
 
Angular2를 위한 타입스크립트
Angular2를 위한 타입스크립트Angular2를 위한 타입스크립트
Angular2를 위한 타입스크립트Jin wook
 
Web Components 101 polymer & brick
Web Components 101 polymer & brickWeb Components 101 polymer & brick
Web Components 101 polymer & brickyongwoo Jeon
 
[TECHCON 2019: MOBILE - Android]2.예제에서는 알려주지 않는 Model 이야기
[TECHCON 2019: MOBILE - Android]2.예제에서는 알려주지 않는 Model 이야기[TECHCON 2019: MOBILE - Android]2.예제에서는 알려주지 않는 Model 이야기
[TECHCON 2019: MOBILE - Android]2.예제에서는 알려주지 않는 Model 이야기NAVER Engineering
 
Secrets of the JavaScript Ninja - Chapter 12. DOM modification
Secrets of the JavaScript Ninja - Chapter 12. DOM modificationSecrets of the JavaScript Ninja - Chapter 12. DOM modification
Secrets of the JavaScript Ninja - Chapter 12. DOM modificationHyuncheol Jeon
 
Vuejs 시작하기
Vuejs 시작하기Vuejs 시작하기
Vuejs 시작하기성일 한
 
Angular2 router&http
Angular2 router&httpAngular2 router&http
Angular2 router&httpDong Jun Kwon
 
React Native를 사용한
 초간단 커뮤니티 앱 제작
React Native를 사용한
 초간단 커뮤니티 앱 제작React Native를 사용한
 초간단 커뮤니티 앱 제작
React Native를 사용한
 초간단 커뮤니티 앱 제작Taegon Kim
 
Clean Front-End Development
Clean Front-End DevelopmentClean Front-End Development
Clean Front-End Development지수 윤
 
[115] clean fe development_윤지수
[115] clean fe development_윤지수[115] clean fe development_윤지수
[115] clean fe development_윤지수NAVER D2
 
Bs webgl소모임001 uniform버전
Bs webgl소모임001 uniform버전Bs webgl소모임001 uniform버전
Bs webgl소모임001 uniform버전Seonki Paik
 
Angular2를 활용한 컴포넌트 중심의 개발
Angular2를 활용한 컴포넌트 중심의 개발Angular2를 활용한 컴포넌트 중심의 개발
Angular2를 활용한 컴포넌트 중심의 개발Jin wook
 
Angular2 가기전 Type script소개
 Angular2 가기전 Type script소개 Angular2 가기전 Type script소개
Angular2 가기전 Type script소개Dong Jun Kwon
 
Bs webgl소모임002
Bs webgl소모임002Bs webgl소모임002
Bs webgl소모임002Seonki Paik
 
React Hooks 마법. 그리고 깔끔한 사용기
React Hooks 마법. 그리고 깔끔한 사용기React Hooks 마법. 그리고 깔끔한 사용기
React Hooks 마법. 그리고 깔끔한 사용기NAVER SHOPPING
 
Nodejs, PhantomJS, casperJs, YSlow, expressjs
Nodejs, PhantomJS, casperJs, YSlow, expressjsNodejs, PhantomJS, casperJs, YSlow, expressjs
Nodejs, PhantomJS, casperJs, YSlow, expressjs기동 이
 

Mais procurados (20)

[DevOn 2013] Backbone.js로 능동적 M-V 디자인 구현하기
[DevOn 2013] Backbone.js로 능동적  M-V 디자인 구현하기[DevOn 2013] Backbone.js로 능동적  M-V 디자인 구현하기
[DevOn 2013] Backbone.js로 능동적 M-V 디자인 구현하기
 
Node.js and react
Node.js and reactNode.js and react
Node.js and react
 
Angular2를 위한 타입스크립트
Angular2를 위한 타입스크립트Angular2를 위한 타입스크립트
Angular2를 위한 타입스크립트
 
Web Components 101 polymer & brick
Web Components 101 polymer & brickWeb Components 101 polymer & brick
Web Components 101 polymer & brick
 
[TECHCON 2019: MOBILE - Android]2.예제에서는 알려주지 않는 Model 이야기
[TECHCON 2019: MOBILE - Android]2.예제에서는 알려주지 않는 Model 이야기[TECHCON 2019: MOBILE - Android]2.예제에서는 알려주지 않는 Model 이야기
[TECHCON 2019: MOBILE - Android]2.예제에서는 알려주지 않는 Model 이야기
 
Redux and redux saga
Redux and redux sagaRedux and redux saga
Redux and redux saga
 
Secrets of the JavaScript Ninja - Chapter 12. DOM modification
Secrets of the JavaScript Ninja - Chapter 12. DOM modificationSecrets of the JavaScript Ninja - Chapter 12. DOM modification
Secrets of the JavaScript Ninja - Chapter 12. DOM modification
 
Vuejs 시작하기
Vuejs 시작하기Vuejs 시작하기
Vuejs 시작하기
 
Angular2 router&http
Angular2 router&httpAngular2 router&http
Angular2 router&http
 
Flux 예제 분석 2
Flux 예제 분석 2Flux 예제 분석 2
Flux 예제 분석 2
 
React Native를 사용한
 초간단 커뮤니티 앱 제작
React Native를 사용한
 초간단 커뮤니티 앱 제작React Native를 사용한
 초간단 커뮤니티 앱 제작
React Native를 사용한
 초간단 커뮤니티 앱 제작
 
Clean Front-End Development
Clean Front-End DevelopmentClean Front-End Development
Clean Front-End Development
 
[115] clean fe development_윤지수
[115] clean fe development_윤지수[115] clean fe development_윤지수
[115] clean fe development_윤지수
 
Bs webgl소모임001 uniform버전
Bs webgl소모임001 uniform버전Bs webgl소모임001 uniform버전
Bs webgl소모임001 uniform버전
 
Angular2를 활용한 컴포넌트 중심의 개발
Angular2를 활용한 컴포넌트 중심의 개발Angular2를 활용한 컴포넌트 중심의 개발
Angular2를 활용한 컴포넌트 중심의 개발
 
Angular2 가기전 Type script소개
 Angular2 가기전 Type script소개 Angular2 가기전 Type script소개
Angular2 가기전 Type script소개
 
Bs webgl소모임002
Bs webgl소모임002Bs webgl소모임002
Bs webgl소모임002
 
Deview2013 track1 session7
Deview2013 track1 session7Deview2013 track1 session7
Deview2013 track1 session7
 
React Hooks 마법. 그리고 깔끔한 사용기
React Hooks 마법. 그리고 깔끔한 사용기React Hooks 마법. 그리고 깔끔한 사용기
React Hooks 마법. 그리고 깔끔한 사용기
 
Nodejs, PhantomJS, casperJs, YSlow, expressjs
Nodejs, PhantomJS, casperJs, YSlow, expressjsNodejs, PhantomJS, casperJs, YSlow, expressjs
Nodejs, PhantomJS, casperJs, YSlow, expressjs
 

Semelhante a Deep dive into Modern frameworks - HTML5 Forum 2018

GDG DevFest 2017 Seoul 프론트엔드 모던 프레임워크 낱낱히 파헤치기
 GDG DevFest 2017 Seoul 프론트엔드 모던 프레임워크 낱낱히 파헤치기 GDG DevFest 2017 Seoul 프론트엔드 모던 프레임워크 낱낱히 파헤치기
GDG DevFest 2017 Seoul 프론트엔드 모던 프레임워크 낱낱히 파헤치기Kenneth Ceyer
 
Meteor React Tutorial 따라하기
Meteor React Tutorial 따라하기Meteor React Tutorial 따라하기
Meteor React Tutorial 따라하기Jiam Seo
 
Facebook은 React를 왜 만들었을까?
Facebook은 React를 왜 만들었을까? Facebook은 React를 왜 만들었을까?
Facebook은 React를 왜 만들었을까? Kim Hunmin
 
Angular js quick start
Angular js quick startAngular js quick start
Angular js quick start정기 김
 
[114]angularvs react 김훈민손찬욱
[114]angularvs react 김훈민손찬욱[114]angularvs react 김훈민손찬욱
[114]angularvs react 김훈민손찬욱NAVER D2
 
04.실행환경 실습교재(화면처리)
04.실행환경 실습교재(화면처리)04.실행환경 실습교재(화면처리)
04.실행환경 실습교재(화면처리)Hankyo
 
Vue.js 기초 실습.pptx
Vue.js 기초 실습.pptxVue.js 기초 실습.pptx
Vue.js 기초 실습.pptxwonyong hwang
 
컴포넌트 관점에서 개발하기
컴포넌트 관점에서 개발하기컴포넌트 관점에서 개발하기
컴포넌트 관점에서 개발하기우영 주
 
Web Components - Part.I, @KIG 30th
Web Components - Part.I, @KIG 30thWeb Components - Part.I, @KIG 30th
Web Components - Part.I, @KIG 30thChang W. Doh
 
Dreamweaver CS5.5 를 이용한 jQueryMobile 개발
Dreamweaver CS5.5 를 이용한 jQueryMobile 개발Dreamweaver CS5.5 를 이용한 jQueryMobile 개발
Dreamweaver CS5.5 를 이용한 jQueryMobile 개발JongKwang Kim
 
[D2 오픈세미나]5.robolectric 안드로이드 테스팅
[D2 오픈세미나]5.robolectric 안드로이드 테스팅[D2 오픈세미나]5.robolectric 안드로이드 테스팅
[D2 오픈세미나]5.robolectric 안드로이드 테스팅NAVER D2
 
스프링프레임워크 & 마이바티스 무.료 강의자료 제공 (Spring IoC & DI)_ 구로자바학원/구로오라클학원/구로IT학원
스프링프레임워크 & 마이바티스 무.료 강의자료 제공 (Spring IoC & DI)_ 구로자바학원/구로오라클학원/구로IT학원스프링프레임워크 & 마이바티스 무.료 강의자료 제공 (Spring IoC & DI)_ 구로자바학원/구로오라클학원/구로IT학원
스프링프레임워크 & 마이바티스 무.료 강의자료 제공 (Spring IoC & DI)_ 구로자바학원/구로오라클학원/구로IT학원탑크리에듀(구로디지털단지역3번출구 2분거리)
 
React 실무활용 이야기
React 실무활용 이야기React 실무활용 이야기
React 실무활용 이야기철민 배
 
Angular 2 rc5 조사
Angular 2 rc5 조사Angular 2 rc5 조사
Angular 2 rc5 조사Rjs Ryu
 
Naver api for android
Naver api for androidNaver api for android
Naver api for androidSangon Lee
 

Semelhante a Deep dive into Modern frameworks - HTML5 Forum 2018 (20)

GDG DevFest 2017 Seoul 프론트엔드 모던 프레임워크 낱낱히 파헤치기
 GDG DevFest 2017 Seoul 프론트엔드 모던 프레임워크 낱낱히 파헤치기 GDG DevFest 2017 Seoul 프론트엔드 모던 프레임워크 낱낱히 파헤치기
GDG DevFest 2017 Seoul 프론트엔드 모던 프레임워크 낱낱히 파헤치기
 
Meteor React Tutorial 따라하기
Meteor React Tutorial 따라하기Meteor React Tutorial 따라하기
Meteor React Tutorial 따라하기
 
Facebook은 React를 왜 만들었을까?
Facebook은 React를 왜 만들었을까? Facebook은 React를 왜 만들었을까?
Facebook은 React를 왜 만들었을까?
 
Angular js quick start
Angular js quick startAngular js quick start
Angular js quick start
 
[Codelab 2017] ReactJS 기초
[Codelab 2017] ReactJS 기초[Codelab 2017] ReactJS 기초
[Codelab 2017] ReactJS 기초
 
[114]angularvs react 김훈민손찬욱
[114]angularvs react 김훈민손찬욱[114]angularvs react 김훈민손찬욱
[114]angularvs react 김훈민손찬욱
 
04.실행환경 실습교재(화면처리)
04.실행환경 실습교재(화면처리)04.실행환경 실습교재(화면처리)
04.실행환경 실습교재(화면처리)
 
Vue.js 기초 실습.pptx
Vue.js 기초 실습.pptxVue.js 기초 실습.pptx
Vue.js 기초 실습.pptx
 
컴포넌트 관점에서 개발하기
컴포넌트 관점에서 개발하기컴포넌트 관점에서 개발하기
컴포넌트 관점에서 개발하기
 
Hacosa jquery 1th
Hacosa jquery 1thHacosa jquery 1th
Hacosa jquery 1th
 
react-ko.pdf
react-ko.pdfreact-ko.pdf
react-ko.pdf
 
Web Components - Part.I, @KIG 30th
Web Components - Part.I, @KIG 30thWeb Components - Part.I, @KIG 30th
Web Components - Part.I, @KIG 30th
 
Dreamweaver CS5.5 를 이용한 jQueryMobile 개발
Dreamweaver CS5.5 를 이용한 jQueryMobile 개발Dreamweaver CS5.5 를 이용한 jQueryMobile 개발
Dreamweaver CS5.5 를 이용한 jQueryMobile 개발
 
[D2 오픈세미나]5.robolectric 안드로이드 테스팅
[D2 오픈세미나]5.robolectric 안드로이드 테스팅[D2 오픈세미나]5.robolectric 안드로이드 테스팅
[D2 오픈세미나]5.robolectric 안드로이드 테스팅
 
스프링프레임워크 & 마이바티스 무.료 강의자료 제공 (Spring IoC & DI)_ 구로자바학원/구로오라클학원/구로IT학원
스프링프레임워크 & 마이바티스 무.료 강의자료 제공 (Spring IoC & DI)_ 구로자바학원/구로오라클학원/구로IT학원스프링프레임워크 & 마이바티스 무.료 강의자료 제공 (Spring IoC & DI)_ 구로자바학원/구로오라클학원/구로IT학원
스프링프레임워크 & 마이바티스 무.료 강의자료 제공 (Spring IoC & DI)_ 구로자바학원/구로오라클학원/구로IT학원
 
Nest js 101
Nest js 101Nest js 101
Nest js 101
 
React 실무활용 이야기
React 실무활용 이야기React 실무활용 이야기
React 실무활용 이야기
 
Angular 2 rc5 조사
Angular 2 rc5 조사Angular 2 rc5 조사
Angular 2 rc5 조사
 
Coded ui가이드
Coded ui가이드Coded ui가이드
Coded ui가이드
 
Naver api for android
Naver api for androidNaver api for android
Naver api for android
 

Mais de Kenneth Ceyer

이미지 프로세싱 in Python Open Source - PYCON KOREA 2020
이미지 프로세싱 in Python Open Source - PYCON KOREA 2020이미지 프로세싱 in Python Open Source - PYCON KOREA 2020
이미지 프로세싱 in Python Open Source - PYCON KOREA 2020Kenneth Ceyer
 
LP(linear programming) Algorithm
LP(linear programming) AlgorithmLP(linear programming) Algorithm
LP(linear programming) AlgorithmKenneth Ceyer
 
AI 연구자를 위한 클린코드 - GDG DevFest Seoul 2019
AI 연구자를 위한 클린코드 - GDG DevFest Seoul 2019AI 연구자를 위한 클린코드 - GDG DevFest Seoul 2019
AI 연구자를 위한 클린코드 - GDG DevFest Seoul 2019Kenneth Ceyer
 
하둡 에코시스템 위에서 환상적인 테이크오프 - DSTS 2019
하둡 에코시스템 위에서 환상적인 테이크오프 - DSTS 2019 하둡 에코시스템 위에서 환상적인 테이크오프 - DSTS 2019
하둡 에코시스템 위에서 환상적인 테이크오프 - DSTS 2019 Kenneth Ceyer
 
AllReduce for distributed learning I/O Extended Seoul
AllReduce for distributed learning I/O Extended SeoulAllReduce for distributed learning I/O Extended Seoul
AllReduce for distributed learning I/O Extended SeoulKenneth Ceyer
 
gRPC와 goroutine 톺아보기 - GDG Golang Korea 2019
gRPC와 goroutine 톺아보기 - GDG Golang Korea 2019gRPC와 goroutine 톺아보기 - GDG Golang Korea 2019
gRPC와 goroutine 톺아보기 - GDG Golang Korea 2019Kenneth Ceyer
 
Test and refactoring
Test and refactoringTest and refactoring
Test and refactoringKenneth Ceyer
 
우아하게 준비하는 테스트와 리팩토링 - PyCon Korea 2018
우아하게 준비하는 테스트와 리팩토링 - PyCon Korea 2018우아하게 준비하는 테스트와 리팩토링 - PyCon Korea 2018
우아하게 준비하는 테스트와 리팩토링 - PyCon Korea 2018Kenneth Ceyer
 
엔지니어 관점에서 바라본 데이터시각화
엔지니어 관점에서 바라본 데이터시각화엔지니어 관점에서 바라본 데이터시각화
엔지니어 관점에서 바라본 데이터시각화Kenneth Ceyer
 
Dealing with Python Reactively - PyCon Korea 2017
Dealing with Python Reactively - PyCon Korea 2017Dealing with Python Reactively - PyCon Korea 2017
Dealing with Python Reactively - PyCon Korea 2017Kenneth Ceyer
 
파이썬 리액티브하게 짜기 - PyCon Korea 2017
파이썬 리액티브하게 짜기 - PyCon Korea 2017파이썬 리액티브하게 짜기 - PyCon Korea 2017
파이썬 리액티브하게 짜기 - PyCon Korea 2017Kenneth Ceyer
 
AngularJS 2, version 1 and ReactJS
AngularJS 2, version 1 and ReactJSAngularJS 2, version 1 and ReactJS
AngularJS 2, version 1 and ReactJSKenneth Ceyer
 

Mais de Kenneth Ceyer (13)

이미지 프로세싱 in Python Open Source - PYCON KOREA 2020
이미지 프로세싱 in Python Open Source - PYCON KOREA 2020이미지 프로세싱 in Python Open Source - PYCON KOREA 2020
이미지 프로세싱 in Python Open Source - PYCON KOREA 2020
 
LP(linear programming) Algorithm
LP(linear programming) AlgorithmLP(linear programming) Algorithm
LP(linear programming) Algorithm
 
AI 연구자를 위한 클린코드 - GDG DevFest Seoul 2019
AI 연구자를 위한 클린코드 - GDG DevFest Seoul 2019AI 연구자를 위한 클린코드 - GDG DevFest Seoul 2019
AI 연구자를 위한 클린코드 - GDG DevFest Seoul 2019
 
하둡 에코시스템 위에서 환상적인 테이크오프 - DSTS 2019
하둡 에코시스템 위에서 환상적인 테이크오프 - DSTS 2019 하둡 에코시스템 위에서 환상적인 테이크오프 - DSTS 2019
하둡 에코시스템 위에서 환상적인 테이크오프 - DSTS 2019
 
AllReduce for distributed learning I/O Extended Seoul
AllReduce for distributed learning I/O Extended SeoulAllReduce for distributed learning I/O Extended Seoul
AllReduce for distributed learning I/O Extended Seoul
 
gRPC와 goroutine 톺아보기 - GDG Golang Korea 2019
gRPC와 goroutine 톺아보기 - GDG Golang Korea 2019gRPC와 goroutine 톺아보기 - GDG Golang Korea 2019
gRPC와 goroutine 톺아보기 - GDG Golang Korea 2019
 
How to use vim
How to use vimHow to use vim
How to use vim
 
Test and refactoring
Test and refactoringTest and refactoring
Test and refactoring
 
우아하게 준비하는 테스트와 리팩토링 - PyCon Korea 2018
우아하게 준비하는 테스트와 리팩토링 - PyCon Korea 2018우아하게 준비하는 테스트와 리팩토링 - PyCon Korea 2018
우아하게 준비하는 테스트와 리팩토링 - PyCon Korea 2018
 
엔지니어 관점에서 바라본 데이터시각화
엔지니어 관점에서 바라본 데이터시각화엔지니어 관점에서 바라본 데이터시각화
엔지니어 관점에서 바라본 데이터시각화
 
Dealing with Python Reactively - PyCon Korea 2017
Dealing with Python Reactively - PyCon Korea 2017Dealing with Python Reactively - PyCon Korea 2017
Dealing with Python Reactively - PyCon Korea 2017
 
파이썬 리액티브하게 짜기 - PyCon Korea 2017
파이썬 리액티브하게 짜기 - PyCon Korea 2017파이썬 리액티브하게 짜기 - PyCon Korea 2017
파이썬 리액티브하게 짜기 - PyCon Korea 2017
 
AngularJS 2, version 1 and ReactJS
AngularJS 2, version 1 and ReactJSAngularJS 2, version 1 and ReactJS
AngularJS 2, version 1 and ReactJS
 

Deep dive into Modern frameworks - HTML5 Forum 2018

  • 1. 한성민 SungMin Han Deep dive into Modern frameworks
  • 2. 프론트엔드의 러닝커브 모던 프레임워크 톺아보기 Today, We’ll discuss about Front-end Learning Curve Looking around Front-end Modern Frameworks
  • 5. 조금 더 넓게.. jQuery Vanila Javascript AngularJS React VueJS Angular 2006 2013 2009 2014 2016 XMLHTTPRequest(XHR) 2002 ES2015 2015 Node.js 2013 Redux 2015 RxJS 2012 Typescript 2012 Ember.js 2011 CoffeScript 2009 AMD 2010 CommonJS (CJS) 2009 ES2016 2016 WebAssembly 2015
  • 11. 동적 렌더링 모듈링 / 번들링 타이핑 현재 프론트엔드 진형의 중요 키워드 테스트 자동화
  • 12. 동적 렌더링 모듈링 / 번들링 타이핑 현재 프론트엔드 진형의 중요 키워드 테스트 자동화 Two-way binding, SPA, Virtual DOM, Change Detection … CommonJS, AMD, UMD, Uglify, Grunt, Webpack … Typescript, Proptypes, Flow, Props … UnitTest, e2e Test, HeadLess Browser …
  • 14. Angular 완전하고 빠른 프레임워크 React 활발하고 오픈 되어 있으며 합리적인 프레임워크 VueJS 가볍고 친숙하며 장점만을 합쳐놓은 프레임워크 그러던 중 나타난 프레임워크들 그리고 프레임워크는 그 모든 것을 쉽게 만들어주었나니..
  • 15. Angular 완전하고 빠른 프레임워크 React 활발하고 오픈 되어 있으며 합리적인 프레임워크 VueJS 가볍고 친숙하며 장점만을 합쳐놓은 프레임워크 그러던 중 나타난 프레임워크들 그리고 프레임워크는 그 모든 것을 쉽게 만들어주었나니..
  • 16. Angular 완전하고 빠른 프레임워크 인기가 없음, 오버엔지니어링 React 활발하고 오픈 되어 있으며 합리적인 프레임워크 너무 힙함 VueJS 가볍고 친숙하며 장점만을 합쳐놓은 프레임워크 DOM 테스트하기 힘듦 그러던 중 나타난 프레임워크들 그리고 프레임워크는 그 모든 것을 쉽게 만들어주었나니..
  • 17. Angular 모든 기능이 내장되어 있으며 성능이 훌륭하지만, 진입장벽이 가장 높음 React 에코시스템이 활발하게 움직이고 또 그것을 장려하지만 의존과 버전에 민감하고 라이브러리 자체의 기능만으로는 부족함 VueJS 프레임워크 자체가 가볍고 진입장벽이 낮으며 각 프레임워크의 장점을 흡수 다만 크기가 커질 수록 재활용성은 떨어지며, 테스트하기 어렵고 느림 이를 풀어 설명하자면
  • 19. Angular 릴리즈 개발자/개발사 버전 언어 모델 컴파일 2016년 6월 공식출시 Google Inc 2017년 11월 기준 v5.0.1 stable Typescript, Dart, Javascript MVVM / Change Detection / NgZone JIT (built-in core) / AOT (ng, ngc) / TreeShaking with ng cli
  • 20. React 릴리즈 개발자/개발사 버전 언어 모델 컴파일 2013년 3월 공식출시 Facebook, Instagram 2017년 11월 기준 V16.1.1 stable Javascript, JSX View Engine / Virtual DOM / PropTypes JIT (built-in core) / TreeShaking with Webpack2
  • 21. VueJS 릴리즈 개발자/개발사 버전 언어 모델 컴파일 2014년 2월 공식출시 Evan you 2017년 11월 기준 V2.5.3 stable Javascript, JSX(호환) MVVM / VirtualDOM / core와 companion 분리 / Vuex JIT (built-in core) / TreeShaking with Webpack2
  • 22. Angular code import { Component, ViewChild, ElementRef } from '@angular/core'; const DEFAULT_INITIALIZE_FOOD_LIST: string[] = [ '치킨', '탕수육', '닭도리탕' ]; @Component({ selector: 'mukkit-list', templateUrl: './mukkit_list.html', styleUrls: [ './mukkit_list.css' ] }) export class MukkitListComponent { public foodList: string[] = [...DEFAULT_INITIALIZE_FOOD_LIST]; public newFood: string; @ViewChild('input') inputEl: ElementRef; ngAfterViewInit() { this.focusFood(); } focusFood(): void { this.inputEl.nativeElement.focus(); } enterFood($event: KeyboardEvent): void { if ($event.keyCode === 13) { this.addFood(); } } addFood(): void { if (this.foodList.indexOf(this.newFood) === -1) { this.foodList.push(this.newFood); this.newFood = ''; } else { alert('해당 음식은 이미 있습니다.'); } } } mukkitList.component.ts
  • 23. Angular code mukkitList.html <div class="mukkit-list-container"> <img width="180" src="data:image…"> <h2>먹킷리스트</h2> </div> <ul class="mukkit-list"> <li *ngFor="let food of foodList"> <span>{{food}}</span> </li> <li> <input type="text" #input [(ngModel)]="newFood" (keypress)="enterFood($event);"> <button (click)="addFood();">먹킷리스트 추가</button> </li> </ul>
  • 24. Angular code mukkitList.html <div class="mukkit-list-container"> <img width="180" src="data:image…"> <h2>먹킷리스트</h2> </div> <ul class="mukkit-list"> <li *ngFor="let food of foodList"> <span>{{food}}</span> </li> <li> <input type="text" #input [(ngModel)]="newFood" (keypress)="enterFood($event);"> <button (click)="addFood();">먹킷리스트 추가</button> </li> </ul> export class MukkitListComponent { public foodList: string[] = [...DEFAULT_INITIALIZE_FOOD_LIST]; public newFood: string; @ViewChild('input') inputEl: ElementRef; … enterFood($event: KeyboardEvent): void { … } addFood(): void { … } } mukkit_list.component.ts 1way binding (viewmodel -> view) 2way binding (videmodel <-> view) view query (it is not bind) 1way binding (view <- viewmodel)
  • 25. mukkitList.js React code import React, { Component } from 'react'; import logo from './logo.svg'; import './MukkitList.css'; const DEFAULT_INITIALIZE_FOOD_LIST = [ '치킨', '탕수육', '닭도리탕' ]; class MukkitList extends Component { constructor(props) { super(props); this.state = { foodList: [...DEFAULT_INITIALIZE_FOOD_LIST], newFood: '' }; } changeFood(event) { this.setState({'newFood': event.target.value}); } enterFood(event) { if (event.key === 'Enter') this.addFood(); } addFood(event) { if (this.state.foodList.indexOf(this.state.newFood) === -1) { this.setState({ foodList: [...this.state.foodList, this.state.newFood], newFood: '' }); } else { alert('해당 음식은 이미 있습니다.'); } } render() { return ( <div className="container"> <header className="mukkit-list-header"> <img src={logo} className="mukkit-list-logo" alt="logo" /> <h2 className="mukkit-list-title">먹킷리스트</h2> </header> <ul className="mukkit-list"> {this.state.foodList.map((food, index) => <li key={index}><span>{food}</span></li>)} <li> <input type="text“ value={this.state.newFood} onChange={this.changeFood.bind(this)} onKeyPress={this.enterFood.bind(this)} /> <button onClick={this.addFood.bind(this)}>먹킷리스트 추가</button> </li> </ul > </div > ); } } export default MukkitList;
  • 26. mukkitList.js import React, { Component } from 'react'; import logo from './logo.svg'; import './MukkitList.css'; const DEFAULT_INITIALIZE_FOOD_LIST = [ '치킨', '탕수육', '닭도리탕' ]; class MukkitList extends Component { constructor(props) { super(props); this.state = { foodList: [...DEFAULT_INITIALIZE_FOOD_LIST], newFood: '' }; } changeFood(event) { this.setState({'newFood': event.target.value}); } enterFood(event) { if (event.key === 'Enter') this.addFood(); } addFood(event) { if (this.state.foodList.indexOf(this.state.newFood) === -1) { this.setState({ foodList: [...this.state.foodList, this.state.newFood], newFood: '' }); } else { alert('해당 음식은 이미 있습니다.'); } } render() { return ( <div className="container"> <header className="mukkit-list-header"> <img src={logo} className="mukkit-list-logo" alt="logo" /> <h2 className="mukkit-list-title">먹킷리스트</h2> </header> <ul className="mukkit-list"> {this.state.foodList.map((food, index) => <li key={index}><span>{food}</span></li>)} <li> <input type="text“ value={this.state.newFood} onChange={this.changeFood.bind(this)} onKeyPress={this.enterFood.bind(this)} /> <button onClick={this.addFood.bind(this)}>먹킷리스트 추가</button> </li> </ul > </div > ); } } export default MukkitList; 1way binding (videmodel -> view) React code
  • 27. mukkitList.js import React, { Component } from 'react'; import logo from './logo.svg'; import './MukkitList.css'; const DEFAULT_INITIALIZE_FOOD_LIST = [ '치킨', '탕수육', '닭도리탕' ]; class MukkitList extends Component { constructor(props) { super(props); this.state = { foodList: [...DEFAULT_INITIALIZE_FOOD_LIST], newFood: '' }; } changeFood(event) { this.setState({'newFood': event.target.value}); } enterFood(event) { if (event.key === 'Enter') this.addFood(); } addFood(event) { if (this.state.foodList.indexOf(this.state.newFood) === -1) { this.setState({ foodList: [...this.state.foodList, this.state.newFood], newFood: '' }); } else { alert('해당 음식은 이미 있습니다.'); } } render() { return ( <div className="container"> <header className="mukkit-list-header"> <img src={logo} className="mukkit-list-logo" alt="logo" /> <h2 className="mukkit-list-title">먹킷리스트</h2> </header> <ul className="mukkit-list"> {this.state.foodList.map((food, index) => <li key={index}><span>{food}</span></li>)} <li> <input type="text“ value={this.state.newFood} onChange={this.changeFood.bind(this)} onKeyPress={this.enterFood.bind(this)} /> <button onClick={this.addFood.bind(this)}>먹킷리스트 추가</button> </li> </ul > </div > ); } } export default MukkitList; render DOM React code
  • 28. mukkitList.js import React, { Component } from 'react'; import logo from './logo.svg'; import './MukkitList.css'; const DEFAULT_INITIALIZE_FOOD_LIST = [ '치킨', '탕수육', '닭도리탕' ]; class MukkitList extends Component { constructor(props) { super(props); this.state = { foodList: [...DEFAULT_INITIALIZE_FOOD_LIST], newFood: '' }; } changeFood(event) { this.setState({'newFood': event.target.value}); } enterFood(event) { if (event.key === 'Enter') this.addFood(); } addFood(event) { if (this.state.foodList.indexOf(this.state.newFood) === -1) { this.setState({ foodList: [...this.state.foodList, this.state.newFood], newFood: '' }); } else { alert('해당 음식은 이미 있습니다.'); } } render() { return ( <div className="container"> <header className="mukkit-list-header"> <img src={logo} className="mukkit-list-logo" alt="logo" /> <h2 className="mukkit-list-title">먹킷리스트</h2> </header> <ul className="mukkit-list"> {this.state.foodList.map((food, index) => <li key={index}><span>{food}</span></li>)} <li> <input type="text“ value={this.state.newFood} onChange={this.changeFood.bind(this)} onKeyPress={this.enterFood.bind(this)} /> <button onClick={this.addFood.bind(this)}>먹킷리스트 추가</button> </li> </ul > </div > ); } } export default MukkitList; 1way binding (viewmodel -> view) React code
  • 29. mukkitList.js import React, { Component } from 'react'; import logo from './logo.svg'; import './MukkitList.css'; const DEFAULT_INITIALIZE_FOOD_LIST = [ '치킨', '탕수육', '닭도리탕' ]; class MukkitList extends Component { constructor(props) { super(props); this.state = { foodList: [...DEFAULT_INITIALIZE_FOOD_LIST], newFood: '' }; } changeFood(event) { this.setState({'newFood': event.target.value}); } enterFood(event) { if (event.key === 'Enter') this.addFood(); } addFood(event) { if (this.state.foodList.indexOf(this.state.newFood) === -1) { this.setState({ foodList: [...this.state.foodList, this.state.newFood], newFood: '' }); } else { alert('해당 음식은 이미 있습니다.'); } } render() { return ( <div className="container"> <header className="mukkit-list-header"> <img src={logo} className="mukkit-list-logo" alt="logo" /> <h2 className="mukkit-list-title">먹킷리스트</h2> </header> <ul className="mukkit-list"> {this.state.foodList.map((food, index) => <li key={index}><span>{food}</span></li>)} <li> <input type="text“ value={this.state.newFood} onChange={this.changeFood.bind(this)} onKeyPress={this.enterFood.bind(this)} /> <button onClick={this.addFood.bind(this)}>먹킷리스트 추가</button> </li> </ul > </div > ); } } export default MukkitList; 1way binding (view -> viewmodel) React code
  • 30. mukkitList.js import React, { Component } from 'react'; import logo from './logo.svg'; import './MukkitList.css'; const DEFAULT_INITIALIZE_FOOD_LIST = [ '치킨', '탕수육', '닭도리탕' ]; class MukkitList extends Component { constructor(props) { super(props); this.state = { foodList: [...DEFAULT_INITIALIZE_FOOD_LIST], newFood: '' }; } changeFood(event) { this.setState({'newFood': event.target.value}); } enterFood(event) { if (event.key === 'Enter') this.addFood(); } addFood(event) { if (this.state.foodList.indexOf(this.state.newFood) === -1) { this.setState({ foodList: [...this.state.foodList, this.state.newFood], newFood: '' }); } else { alert('해당 음식은 이미 있습니다.'); } } render() { return ( <div className="container"> <header className="mukkit-list-header"> <img src={logo} className="mukkit-list-logo" alt="logo" /> <h2 className="mukkit-list-title">먹킷리스트</h2> </header> <ul className="mukkit-list"> {this.state.foodList.map((food, index) => <li key={index}><span>{food}</span></li>)} <li> <input type="text“ value={this.state.newFood} onChange={this.changeFood.bind(this)} onKeyPress={this.enterFood.bind(this)} /> <button onClick={this.addFood.bind(this)}>먹킷리스트 추가</button> </li> </ul > </div > ); } } export default MukkitList; state changed React code
  • 31. mukkitList.vue VueJS code <template> <ul class="mukkit-list"> <li v-for="food in foodList"> <span>{{food}}</span> </li> <li> <input type="text" ref="input" v-model="newFood" v-on:keypress.enter="addFood"> <button v-on:click="addFood">먹킷리스트 추가</button> </li> </ul> </template> <script> const DEFAULT_INITIALIZE_FOOD_LIST = [ '치킨', '탕수육', '닭도리탕' ] export default { name: 'MukkitList', data () { return { foodList: [...DEFAULT_INITIALIZE_FOOD_LIST], newFood: '' } }, mounted () { this.focusFood() }, methods: { focusFood () { this.$refs.input.focus() }, addFood () { if (this.foodList.indexOf(this.newFood) === -1) { this.foodList.push(this.newFood) this.newFood = '' this.focusFood() } else { alert('해당 음식은 이미 있습니다.') } } } } </script>
  • 32. mukkitList.vue <template> <ul class="mukkit-list"> <li v-for="food in foodList"> <span>{{food}}</span> </li> <li> <input type="text" ref="input" v-model="newFood" v-on:keypress.enter="addFood"> <button v-on:click="addFood">먹킷리스트 추가</button> </li> </ul> </template> <script> const DEFAULT_INITIALIZE_FOOD_LIST = [ '치킨', '탕수육', '닭도리탕' ] export default { name: 'MukkitList', data () { return { foodList: [...DEFAULT_INITIALIZE_FOOD_LIST], newFood: '' } }, mounted () { this.focusFood() }, methods: { focusFood () { this.$refs.input.focus() }, addFood () { if (this.foodList.indexOf(this.newFood) === -1) { this.foodList.push(this.newFood) this.newFood = '' this.focusFood() } else { alert('해당 음식은 이미 있습니다.') } } } } </script> VueJS code 2way binding (videmodel <-> view)
  • 33. mukkitList.vue <template> <ul class="mukkit-list"> <li v-for="food in foodList"> <span>{{food}}</span> </li> <li> <input type="text" ref="input" v-model="newFood" v-on:keypress.enter="addFood"> <button v-on:click="addFood">먹킷리스트 추가</button> </li> </ul> </template> <script> const DEFAULT_INITIALIZE_FOOD_LIST = [ '치킨', '탕수육', '닭도리탕' ] export default { name: 'MukkitList', data () { return { foodList: [...DEFAULT_INITIALIZE_FOOD_LIST], newFood: '' } }, mounted () { this.focusFood() }, methods: { focusFood () { this.$refs.input.focus() }, addFood () { if (this.foodList.indexOf(this.newFood) === -1) { this.foodList.push(this.newFood) this.newFood = '' this.focusFood() } else { alert('해당 음식은 이미 있습니다.') } } } } </script> VueJS code 1way binding (viewmodel -> view)
  • 34. mukkitList.vue <template> <ul class="mukkit-list"> <li v-for="food in foodList"> <span>{{food}}</span> </li> <li> <input type="text" ref="input" v-model="newFood" v-on:keypress.enter="addFood"> <button v-on:click="addFood">먹킷리스트 추가</button> </li> </ul> </template> <script> const DEFAULT_INITIALIZE_FOOD_LIST = [ '치킨', '탕수육', '닭도리탕' ] export default { name: 'MukkitList', data () { return { foodList: [...DEFAULT_INITIALIZE_FOOD_LIST], newFood: '' } }, mounted () { this.focusFood() }, methods: { focusFood () { this.$refs.input.focus() }, addFood () { if (this.foodList.indexOf(this.newFood) === -1) { this.foodList.push(this.newFood) this.newFood = '' this.focusFood() } else { alert('해당 음식은 이미 있습니다.') } } } } </script> VueJS code 1way binding (view -> viewmodel)
  • 35. mukkitList.vue <template> <ul class="mukkit-list"> <li v-for="food in foodList"> <span>{{food}}</span> </li> <li> <input type="text" ref="input" v-model="newFood" v-on:keypress.enter="addFood"> <button v-on:click="addFood">먹킷리스트 추가</button> </li> </ul> </template> <script> const DEFAULT_INITIALIZE_FOOD_LIST = [ '치킨', '탕수육', '닭도리탕' ] export default { name: 'MukkitList', data () { return { foodList: [...DEFAULT_INITIALIZE_FOOD_LIST], newFood: '' } }, mounted () { this.focusFood() }, methods: { focusFood () { this.$refs.input.focus() }, addFood () { if (this.foodList.indexOf(this.newFood) === -1) { this.foodList.push(this.newFood) this.newFood = '' this.focusFood() } else { alert('해당 음식은 이미 있습니다.') } } } } </script> VueJS code view query (it is not bind)
  • 37. 42,938 star 116,226 star 120,113 star GitHub Stars 변화하는 프레임워크 관심도 Google Trend 2018. 11
  • 38. 42,938 star 116,226 star 120,113 star 2018 Stars 변화하는 프레임워크 관심도 29,994 star 81,002 star 73,628 star 2017 Stars
  • 40. React 트랜드 및 에코시스템이 가장 활발 VueJS가 무서운 속도로 트랜드를 따라잡고 있음 Angular가 AngularJS 까지 포함한다면 가장 큼
  • 41. 진입장벽 – Entry barriers Fight 2
  • 42. Blogged from Marius Duta 일반적인 케이스에서 Angular의 학습곡선이 압도적으로 높고 Vue의 학습곡선이 가장 낮음 학습곡선
  • 43. 각 프레임워크를 배우기 위해서 Language Module / Components DeploymentData Flow Others/ Advanced 일반적으로 Typescript 일반적으로 Javascript (ES6) 일반적으로 Javascript (ES6) Controller / Directive Pipe / Service ContentChild / ViewChild QueryList Smart Component Dumb Component Global Component Local Component Directive / Filter / Plugin RxJS / ng-redux Redux / MobX vuex / vue-rx Bundling Compilation (ngc) Bundling Bundling DI pattern ngZone CD Strategy Immutable Link State Optimization Server-side Rendering Flow Computed Property Observed Property flow-typed
  • 44. 각 프레임워크 컴포넌트 라이프사이클
  • 45. Angular 진입전에 다른 프레임워크 경험 권장 React의 라이프 사이클과 상태관리는 상대적 어려움 AngularJS를 사용하고 있다면 VueJS 권장
  • 47. Benchmark Vue >= Angular > React AOT Compilation 이후 성능 비교에서는 Angular가 더욱 빠를 것으로 예상
  • 48. TreeShaking TreeShaking (나무털기) 마치 나무에 달린 열매를 털듯이 사용하지 않는 모듈은 빌드 단계에서 제외시키는 최적화 기법 지원 지원 (Webpack2) 지원 (Webpack2)
  • 49. AOT(Ahead Of Time) Ahead Of Time (조기 컴파일) JIT (Just In Time) 컴파일 방식과는 다르게 사전에 컴파일러가 중간코드로 컴파일하여 사용자 브라우저에서 컴파일 시간을 최소화 하는 최적화 기법 지원 미지원 미지원 JIT @NgModule Bootstraping Javascript CSS HTML @angular/platform-browser-dynamic Parse AST memory load CD host viewDef Renderer pipeDef ngContentDef nodeValue compilation-side browser-side AOT @NgModuleFactory Bootstraping Javascript CSS HTML host viewDef Renderer pipeDef ngContentDef nodeValue … compilation-side @angular/platform-browser Parse AST load CD browser-side Angular5 부터는 build-optimizer 옵션을 통해 추가적으로 최적화가 가능하니 참고해주세요
  • 50. function View_MukkitListComponent_0(_l) { return __WEBPACK_IMPORTED_MODULE_1__angular_core__["_25" /* ɵvid */] (0, [__WEBPACK_IMPORTED_MODULE_1__angular_core__["_22" /* ɵqud */] (402653184, 1, { inputEl: 0 }), (_l()(), __WEBPACK_IMPORTED_MODULE_1__angular_core__["_8" /* ɵeld */](1, 0, null, null, 6, "div", [["class", "mukkit-list- container"]], null, null, null, null, null)), (_l()(), __WEBPACK_IMPORTED_MODULE_1__angular_core__["_24" /* ɵted */](-1, null, ["n "])), (_l()(), __WEBPACK_IMPORTED_MODULE_1__angular_core__["_8" /* ɵeld */](3, 0, null, null, 0, "img", [["src", "data:image/svg+xml;base64,…"], ["width", "180"]], null, null, null, null, null)), (_l()(), __WEBPACK_IMPORTED_MODULE_1__angular_core__["_24" /* ɵted */](-1, null, ["n "])), (_l()(), __WEBPACK_IMPORTED_MODULE_1__angular_core__["_8" /* ɵeld */](5, 0, null, null, 1, "h2", [], null, null, null, null, null)), (_l()(), __WEBPACK_IMPORTED_MODULE_1__angular_core__["_24" /* ɵted */](-1, null, ["uBA39uD0B7uB9ACuC2A4uD2B8"])), (_l()(), __WEBPACK_IMPORTED_MODULE_1__angular_core__["_24" /* ɵted */](-1, null, ["n"])), (_l()(), __WEBPACK_IMPORTED_MODULE_1__angular_core__["_24" /* ɵted */](-1, null, ["nn"])), (_l()(), __WEBPACK_IMPORTED_MODULE_1__angular_core__["_8" /* ɵeld */](9, 0, null, null, 17, "ul", [["class", "mukkit-list"]], null, null, null, null, null)), (_l()(), __WEBPACK_IMPORTED_MODULE_1__angular_core__["_24" /* ɵted */](-1, null, ["n "])), (_l()(), __WEBPACK_IMPORTED_MODULE_1__angular_core__["_3" /* ɵand */](16777216, null, null, 1, null, View_MukkitListComponent_1)), __WEBPACK_IMPORTED_MODULE_1__angular_core__["_7" /* ɵdid */]( 12, 802816, null, 0, __WEBPACK_IMPORTED_MODULE_2__angular_common__["c" /* NgForOf */], [__WEBPACK_IMPORTED_MODULE_1__angular_core__["R" /* ViewContainerRef */], __WEBPACK_IMPORTED_MODULE_1__angular_core__["N" /* TemplateRef */], __WEBPACK_IMPORTED_MODULE_1__angular_core__["u" /* IterableDiffers */]], { ngForOf: [0, "ngForOf"] }, null), (_l()(), __WEBPACK_IMPORTED_MODULE_1__angular_core__["_24" /* ɵted */](-1, null, ["n "])), … AOT Compiled Code
  • 51. AOT 성능 변화 크기 (minified) 지연시간 (initial load) 메모리 (snapshot) 442KB 585ms 38.5MB 198KB 305ms 15.3MB -55% -48% -60% JIT AOT JIT AOT
  • 52. VirtualDOM VirtualDOM (가상 DOM) 뷰 모델에서 발생하는 변경사항을 메모리에서 관리하는 논리적 DOM에서 먼저 감지 한 후 실제 DOM의 업데이트를 최소화하여 성능을 향상시키고 UX 측면에서 발생하는 문제를 줄임 미지원 지원 지원 VirtualDOMViewModel Element A Element B1 Element B2 Element B Element A Element B1 Element B2 Element B header .list-item .list-item .container NativeDOM (Real DOM) diff patch
  • 53. VirtualDOM 기존의 비싼 비용의 Native DOM 처리를 javascript 상의 diff 알고리즘을 통해 저렴한 비용으로 효율적인 처리가 가능해짐 MDN에 공개된 브라우저 Layout 처리
  • 54. Angular의 최적화가 적용되지 않은 케이스에서는 VueJS가 성능이 빠를 것으로 예상됩니다. (VueJS에서 제공하는 자료와 벤치마크 데이터 참조)
  • 57. 마이크로 프로젝트에는 VueJS 권장 서버사이드 랜더링이 필요한 프로젝트에는 React 대규모의 프로젝트에는 Angular
  • 58. 템플릿 {{interpolation}} [1way data binding] [(2way data binding)] (1way data binding (event)) {{interpolation with pipe | pipeName}} *ngFor *ngIf [ngSwitch] [hidden] [innerHTML] [ngClass] (click) (keypress) (blur) (input) (change) … React에서 공식적으로 제공하는 템플릿은 없습니다. 모든 것을 JSX 혹은 Javascript를 이용하여 표현합니다. react-templates 라이브러리를 이용하면 다른 프레임워크와 유사하게 템플릿을 사용하실 수 있습니다. v-directive-name:parameter {{interpolation | filter}} v-bind:id v-if v-html v-for v-else v-else-if v-show v-bind:class v-bind:style v-on:event-name v-bind:bind-target-name {{interpolation}} :store-name v-model
  • 59. 템플릿 표현식은 Angular가 체계적이지만 VueJS가 접근장벽이 낮음 AngularJS (Angular 1)는 VueJS 템플릿과 유사
  • 60. 변화감지 ChangeDetection NgZone RxJS Props / State Reconciliation React Fiber Redux Redux Saga Redux Thunk Watcher VirtualDOM (based Snabdom) vuex vue-rx
  • 61. Angular Change Detection & NgZone NgZone의 몽키패칭된 이벤트로부터 변화를 감지하여 Change Detection Strategy에 맞게 변화를 전파 setTimeout, addEventListener, requestAnimationFrame NgZone Monkey Patched Tick
  • 62. 1 React Reconciliation & React Fiber React Reconciliation React FibershouldComponentUpdate() Dealing control by element types (aka. Pair-wise diff) 2 3 Dealing control by key (aka. List-wise diff) Update DOM render() 호출 시 VirtualDOM 생성 및 Dirty model을 감지하여 React Reconciliation 과정을 진행 후 React Fiber 혹은 DOM 변경
  • 63. VueJS watcher & VirtualDOM data 프로퍼티에서 Object.defineProperty()를 통해 Watcher가 변화를 감지 변화를 수신 시 render 함수에 의해 VirtualDOM에 따른 DOM 변경
  • 64. 생태계 – Eco System Fight 5
  • 69. Server Side Rendering Angular Universal ReactDOMServer vue-server-renderer
  • 70. 각 프레임워크 별 오픈소스는 계속적으로 발전 중 따라서 어느것이 더 안정적인가 더 알려져있는가가 선택사항이 될 수 있음
  • 72. Show more in GitHub! https://github.com/KennethanCeyer/html5-forum-2018 WIP
  • 73. Thank you! https://github.com/KennethanCeyer - GitHub kenneth@pigno.se - Email