Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Deep dive into Modern frameworks - HTML5 Forum 2018

289 views

Published on

React / Angular / VueJS 내부 동작부터 서비스 적용 사례까지 한눈에

Published in: Technology
  • Login to see the comments

  • Be the first to like this

Deep dive into Modern frameworks - HTML5 Forum 2018

  1. 1. 한성민 SungMin Han Deep dive into Modern frameworks
  2. 2. 프론트엔드의 러닝커브 모던 프레임워크 톺아보기 Today, We’ll discuss about Front-end Learning Curve Looking around Front-end Modern Frameworks
  3. 3. 프론트엔드의 러닝커브
  4. 4. 프론트엔드 기술의 변화 jQuery Vanila Javascript AngularJS React VueJS Angular 2006 2013 2009 2014 2016
  5. 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
  6. 6. 오늘날의 프론트엔드 스택
  7. 7. Welcome to Hell
  8. 8. 동적 렌더링 모듈링 / 번들링 타이핑 현재 프론트엔드 진형의 중요 키워드 테스트 자동화
  9. 9. 동적 렌더링 모듈링 / 번들링 타이핑 현재 프론트엔드 진형의 중요 키워드 테스트 자동화 Two-way binding, SPA, Virtual DOM, Change Detection … CommonJS, AMD, UMD, Uglify, Grunt, Webpack … Typescript, Proptypes, Flow, Props … UnitTest, e2e Test, HeadLess Browser …
  10. 10. 그리고 그것들을 제공하는 많은 도구들
  11. 11. Angular 완전하고 빠른 프레임워크 React 활발하고 오픈 되어 있으며 합리적인 프레임워크 VueJS 가볍고 친숙하며 장점만을 합쳐놓은 프레임워크 그러던 중 나타난 프레임워크들 그리고 프레임워크는 그 모든 것을 쉽게 만들어주었나니..
  12. 12. Angular 완전하고 빠른 프레임워크 React 활발하고 오픈 되어 있으며 합리적인 프레임워크 VueJS 가볍고 친숙하며 장점만을 합쳐놓은 프레임워크 그러던 중 나타난 프레임워크들 그리고 프레임워크는 그 모든 것을 쉽게 만들어주었나니..
  13. 13. Angular 완전하고 빠른 프레임워크 인기가 없음, 오버엔지니어링 React 활발하고 오픈 되어 있으며 합리적인 프레임워크 너무 힙함 VueJS 가볍고 친숙하며 장점만을 합쳐놓은 프레임워크 DOM 테스트하기 힘듦 그러던 중 나타난 프레임워크들 그리고 프레임워크는 그 모든 것을 쉽게 만들어주었나니..
  14. 14. Angular 모든 기능이 내장되어 있으며 성능이 훌륭하지만, 진입장벽이 가장 높음 React 에코시스템이 활발하게 움직이고 또 그것을 장려하지만 의존과 버전에 민감하고 라이브러리 자체의 기능만으로는 부족함 VueJS 프레임워크 자체가 가볍고 진입장벽이 낮으며 각 프레임워크의 장점을 흡수 다만 크기가 커질 수록 재활용성은 떨어지며, 테스트하기 어렵고 느림 이를 풀어 설명하자면
  15. 15. 모던 프레임워크 톺아보기
  16. 16. 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
  17. 17. 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
  18. 18. 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
  19. 19. 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
  20. 20. 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>
  21. 21. 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)
  22. 22. 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;
  23. 23. 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
  24. 24. 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
  25. 25. 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
  26. 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 (view -> viewmodel) React code
  27. 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; state changed React code
  28. 28. 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>
  29. 29. 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)
  30. 30. 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)
  31. 31. 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)
  32. 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 view query (it is not bind)
  33. 33. 트랜드 - Trend Fight 1
  34. 34. 42,938 star 116,226 star 120,113 star GitHub Stars 변화하는 프레임워크 관심도 Google Trend 2018. 11
  35. 35. 42,938 star 116,226 star 120,113 star 2018 Stars 변화하는 프레임워크 관심도 29,994 star 81,002 star 73,628 star 2017 Stars
  36. 36. React 트랜드 및 에코시스템이 가장 활발 VueJS가 무서운 속도로 트랜드를 따라잡고 있음 Angular가 AngularJS 까지 포함한다면 가장 큼
  37. 37. 진입장벽 – Entry barriers Fight 2
  38. 38. Blogged from Marius Duta 일반적인 케이스에서 Angular의 학습곡선이 압도적으로 높고 Vue의 학습곡선이 가장 낮음 학습곡선
  39. 39. 각 프레임워크를 배우기 위해서 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
  40. 40. 각 프레임워크 컴포넌트 라이프사이클
  41. 41. Angular 진입전에 다른 프레임워크 경험 권장 React의 라이프 사이클과 상태관리는 상대적 어려움 AngularJS를 사용하고 있다면 VueJS 권장
  42. 42. 성능 – Performance Fight 3
  43. 43. Benchmark Vue >= Angular > React AOT Compilation 이후 성능 비교에서는 Angular가 더욱 빠를 것으로 예상
  44. 44. TreeShaking TreeShaking (나무털기) 마치 나무에 달린 열매를 털듯이 사용하지 않는 모듈은 빌드 단계에서 제외시키는 최적화 기법 지원 지원 (Webpack2) 지원 (Webpack2)
  45. 45. 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 옵션을 통해 추가적으로 최적화가 가능하니 참고해주세요
  46. 46. 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
  47. 47. AOT 성능 변화 크기 (minified) 지연시간 (initial load) 메모리 (snapshot) 442KB 585ms 38.5MB 198KB 305ms 15.3MB -55% -48% -60% JIT AOT JIT AOT
  48. 48. 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
  49. 49. VirtualDOM 기존의 비싼 비용의 Native DOM 처리를 javascript 상의 diff 알고리즘을 통해 저렴한 비용으로 효율적인 처리가 가능해짐 MDN에 공개된 브라우저 Layout 처리
  50. 50. Angular의 최적화가 적용되지 않은 케이스에서는 VueJS가 성능이 빠를 것으로 예상됩니다. (VueJS에서 제공하는 자료와 벤치마크 데이터 참조)
  51. 51. 구성요소 – Component Fight 4
  52. 52. 모듈 구성 @NgModule Main @Component @Injectable @NgModule Vue Vue.component Vue.directive Vue.filter Vue.mixin ReactDOM.render Component or Class Component or Class
  53. 53. 마이크로 프로젝트에는 VueJS 권장 서버사이드 랜더링이 필요한 프로젝트에는 React 대규모의 프로젝트에는 Angular
  54. 54. 템플릿 {{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
  55. 55. 템플릿 표현식은 Angular가 체계적이지만 VueJS가 접근장벽이 낮음 AngularJS (Angular 1)는 VueJS 템플릿과 유사
  56. 56. 변화감지 ChangeDetection NgZone RxJS Props / State Reconciliation React Fiber Redux Redux Saga Redux Thunk Watcher VirtualDOM (based Snabdom) vuex vue-rx
  57. 57. Angular Change Detection & NgZone NgZone의 몽키패칭된 이벤트로부터 변화를 감지하여 Change Detection Strategy에 맞게 변화를 전파 setTimeout, addEventListener, requestAnimationFrame NgZone Monkey Patched Tick
  58. 58. 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 변경
  59. 59. VueJS watcher & VirtualDOM data 프로퍼티에서 Object.defineProperty()를 통해 Watcher가 변화를 감지 변화를 수신 시 render 함수에 의해 VirtualDOM에 따른 DOM 변경
  60. 60. 생태계 – Eco System Fight 5
  61. 61. Progressive Web App(PWA)
  62. 62. Native Mobile
  63. 63. Native Mobile 모두 NativeScript 지원
  64. 64. Native Desktop 모두 Electron 지원
  65. 65. Server Side Rendering Angular Universal ReactDOMServer vue-server-renderer
  66. 66. 각 프레임워크 별 오픈소스는 계속적으로 발전 중 따라서 어느것이 더 안정적인가 더 알려져있는가가 선택사항이 될 수 있음
  67. 67. Question?
  68. 68. Show more in GitHub! https://github.com/KennethanCeyer/html5-forum-2018 WIP
  69. 69. Thank you! https://github.com/KennethanCeyer - GitHub kenneth@pigno.se - Email

×