SlideShare a Scribd company logo
Facebook은
React를 왜 만들었을까?
NAVER Corp.
Blog & Post Development Lab
김훈민
[명사] 1. 사물ㆍ현상이 놓여 있는 모양이나 형편.
#1
상태(state)
UI가 놓여있는 모습이나 형편
UI의 상태
상태 관리 -> 데이터 관리
상태가 복잡하다 -> 관리할 데이터가 많다
우리가 보는 UI는
특정 시점의 데이터를 표현
http://info.cern.ch/hypertext/WWW/TheProject.html
http://info.cern.ch/hypertext/WWW/TheProject.html
정적(static)인 상태User’s
Action
Page
하이퍼 링크로 문서와 문서를 연결하는
아주 단순한 웹
http://www.infinitezest.com/articles/xmlhttprequest-and-ajax-on-google-suggest.aspx
JavaScript 비중 증가
심각한 브라우저 파편화
개발 난도(難度) 상승
동적(Dynamic)인 상태User’s
Action
Page
크로스 브라우징, XHR 처리, DOM 셀렉팅,
DOM 노드 탐색, 엘리먼트 상태/스타일 변경 등…
브라우저 호환성,
편리한 사용성,
간결한 인터페이스
update: function( el ) {

if( !el.offsetWidth ) { return; }



var $el = $( el ),

height = $el.outerHeight(),

initialOffset = $el.data( S.keys.offset ),

startTop = $el.data( S.keys.startTop ),

scroll = S.getScrollTop(),

isAlreadyOn = $el.is( '.' + S.classes.active ),

toggle = function( turnOn ) {

$el[ turnOn ? 'addClass' : 'removeClass' ]( S.classes.active )

[ !turnOn ? 'addClass' : 'removeClass' ]( S.classes.inactive );

},

viewportHeight = $( window ).height(),

position = $el.data( S.keys.position ),

skipSettingToFixed,

elTop,

elBottom,

$parent = $el.parent(),

parentOffset = $parent.offset().top,

parentHeight = $parent.outerHeight();



if( initialOffset === undefined ) {

initialOffset = $el.offset().top + startTop;

$el.data( S.keys.offset, initialOffset );

$el.after( $( '<div>' ).addClass( S.classes.clone ).height( height ) );

}



if( !position ) {

// Some browsers require fixed/absolute to report accurate top/left values.

skipSettingToFixed = $el.css( 'top' ) !== 'auto' || $el.css( 'bottom' ) !== 'auto';



if( !skipSettingToFixed ) {

$el.css( 'position', 'fixed' );

}



position = {

top: $el.css( 'top' ) !== 'auto',

bottom: $el.css( 'bottom' ) !== 'auto'

};



if( !skipSettingToFixed ) {

$el.css( 'position', '' );

}



$el.data( S.keys.position, position );

}



function isFixedToTop() {

var offsetTop = scroll + elTop;



관심사 분리나 OOP 지원 같은 설계 관점 부재
- Smart UI 양산
- 상태 관리 전략 모호
- 잦은 DOM 셀렉팅으로 인한 성능 저하
HTML + JavaScript + CSS가 강하게 결합
- 코드 유연성 저하
- 테스트 곤란
복잡도 증가
웹 프론트엔드에 불기 시작한 새로운 바람
이렇게 된 이상
MVC로 간다!
대표적인 SPA Framework
웹 프론트엔드 환경에 맞게 MVC를 재해석
도메인 모델 + REST API
Backbone.js
Server
Client
대표적인 SPA Framework
웹 프론트엔드 환경에 맞게 MVC를 재해석
도메인 모델 + REST API
Backbone.js
View Model Server
initialize : function(){

this.listenTo(this.model, "add", this._onAddFriend, this);

this.listenTo(this.model, "change:display", this._onChangeDisplay, this);

this.model.fetch();

},



addFriend : function(friend){

this.model.add(friend);

},



hideFriend : function(){

this.model.set("display", false);

},



_onAddFriend : function(friend){

var friendView = new FriendView({

model : friend,

oGroupModel : this.model

});



this.$el.append(friendView.render());

},



_onChangeDisplay : function(isDisplay){

if(isDisplay){

this.$elFriendList.show();

} else {

this.$elFriendList.hide();

}

}
표현 로직과 업무 로직 분리에 초점
데이터 동기화, UI 상태 관리는 여전히 개발자의 몫
동기화는 “님”들이 알아서
View Model
동기화는 누가?
동기화는 누가?
View의 상태는?
동기화를
프레임워크가 책임진다면
정말 좋겠네
View의 상태와 Model의 데이터를 바인딩하여
한 쪽의 상태 변경을 다른 쪽에 실시간으로
반영하는 프로세스
데이터 바인딩
(Data Binding)
Ember.js
KVO(Key-Value Observing)
프레임워크에 종속적인 코드 스타일을 강제
엔터프라이즈에 강점
Model과 View를 알려주면
내가 동기화해줄게!
App.GravatarImageComponent = Ember.Component.extend({

size: 200,

email: '',



gravatarUrl: Ember.computed('email', 'size', function() {

var email = this.get('email').toLowerCase(),

size = this.get('size');



return 'http://www.gravatar.com/avatar/' + md5(email) + '?s=' + size;

})

});
<img src={{gravatarUrl}}>

<div class="email-input">

{{input type="email" value=email placeholder="Enter your Gravatar e-mail"}}

</div>

user = Ember.Object.create({

fullName: 'Kara Gates'

});



UserComponent = Ember.Component.extend({

userName: Ember.computed.oneWay('user.fullName')

});



userComponent = UserComponent.create({

user: user

});



// Changing the name of the user object changes

// the value on the view.

user.set(‘fullName', 'Krang Gates');

// userComponent.userName will become "Krang Gates"



// ...but changes to the view don't make it back to

// the object.

userComponent.set('userName', 'Truckasaurus Gates');

user.get(‘fullName'); // "Krang Gates"
Angular.js
양방향(Two-Way) 데이터 바인딩
POJO(Plain Old JavaScript Object) + Dirty Checking
그냥, 다 확인하지 뭐
Template View Model
<div ng-controller="Controller">

Date format: <input ng-model="format"> <hr/>

Current time is: <span my-current-time="format"></span>

</div>
angular.module('docsTimeDirective', [])

.controller('Controller', ['$scope', function($scope) {

$scope.format = 'M/d/yy h:mm:ss a';

}])

.directive('myCurrentTime', ['$interval', 'dateFilter', function($interval, dateFilter) {



function link(scope, element, attrs) {

var format,

timeoutId;



function updateTime() {

element.text(dateFilter(new Date(), format));

}



scope.$watch(attrs.myCurrentTime, function(value) {

format = value;

updateTime();

});



element.on('$destroy', function() {

$interval.cancel(timeoutId);

});



// start the UI update process; save the timeoutId for canceling

timeoutId = $interval(function() {

updateTime(); // update DOM

}, 1000);

}



return {

link: link

};

}]);
#2
React Begins못 살겠다, 바꿔보자
디버깅의 어려움
높은 학습비용
고질적인 성능 이슈
아직도
배가 고프다
No magical data binding
No model dirty checking
No more explicit DOM operations
조금만 더
단순할 수는 없을까?User’s
Action
Page
상태 변경 -> 렌더링
DOM은 그저 특정 시점의 상태를 표현할 뿐
Make it Reactive!
var Timer = React.createClass({

displayName: "Timer",



getInitialState: function getInitialState() {

return { secondsElapsed: 0 };

},

tick: function tick() {

this.setState({ secondsElapsed: this.state.secondsElapsed + 1 });

},

componentDidMount: function componentDidMount() {

this.interval = setInterval(this.tick, 1000);

},

componentWillUnmount: function componentWillUnmount() {

clearInterval(this.interval);

},

render: function render() {

return React.createElement(

"div",

null,

"Seconds Elapsed: ",

this.state.secondsElapsed

);

}

});



ReactDOM.render(React.createElement(Timer, null), mountNode);
JavaScript로 DOM 엘리먼트 생성하는
코드 넘 구린 듯!
차라리 템플릿이 나은 듯!
JavaScript로 DOM 엘리먼트 생성하는
코드 넘 구린 듯!
차라리 템플릿이 나은 듯!
인정!
JSX 쓰면 어떰?
var Timer = React.createClass({

getInitialState: function() {

return {secondsElapsed: 0};

},

tick: function() {

this.setState({secondsElapsed: this.state.secondsElapsed + 1});

},

componentDidMount: function() {

this.interval = setInterval(this.tick, 1000);

},

componentWillUnmount: function() {

clearInterval(this.interval);

},

render: function() {

return (

<div>Seconds Elapsed: {this.state.secondsElapsed}</div>

);

}

});



ReactDOM.render(<Timer />, mountNode);
XML 스타일의 코드를 작성할 수 있게 JavaScript를 확장한 문법
ECMAScript 표준 스펙과는 별개
트랜스파일하여 ECMAScript로 변환
JSX
var dropdown =

<Dropdown>

A dropdown list

<Menu>

<MenuItem>Do Something</MenuItem>

<MenuItem>Do Something Fun!</MenuItem>

<MenuItem>Do Something Else</MenuItem>

</Menu>

</Dropdown>;



render(dropdown);
JavaScript로 DOM 엘리먼트 생성하는
코드 넘 구린 듯!
차라리 템플릿이 나은 듯!
인정!
JSX 쓰면 어떰?
으악! 저게 머임!
님 관심사 분리 모름?
누가 요즘 JavaScript 코드 안에 HTML 씀?
JavaScript로 DOM 엘리먼트 생성하는
코드 넘 구린 듯!
차라리 템플릿이 나은 듯!
인정!
JSX 쓰면 어떰?
으악! 저게 머임!
님 관심사 분리 모름?
누가 요즘 JavaScript 코드 안에 HTML 씀?
HTML이랑 JavaScript를 분리한다고
관심사 분리가 됨?
복잡성을 덜기 위해 관심사를 분리
HTML과 JavaScript의 분리는 관심사가 아닌 기술의 분리
관심사란
객체가 맡고 있는 책임
어떤 입력을 처리하고, 무엇을 보여줄 것인가?
재사용할 수 있는 대상은 주로 컴포넌트
진짜 관심사는,
UI 인터랙션
export default class NaverMain extends React.Component {



constructor(){

super();

}



render() {

return (

<div>

<SearchBar/>

<TabMenu />

<NewsHeadLineList />

<RealTimeSearchPanel />

<HotNewsSlide />

</div>

);

}



}
JavaScript는 HTML을 객체화 한 DOM을 조작
HTML과 JavaScript는 논리적으로 강하게 결합
기능(JavaScript)과
구조(HTML)를 분리하면
의존성을 줄일 수 있을까?
<!DOCTYPE html>

<html>

<head>

<script>

function myFunction() {

document.getElementById("demo").innerHTML = "Paragraph changed.";

}

</script>

</head>



<body>



<h1>My Web Page</h1>

<p id="demo">A Paragraph</p>

<button type="button" onclick="myFunction()">Try it</button>



</body>

</html>
function addElement () {

var newDiv = document.createElement("div");

var newContent = document.createTextNode("Hi there and greetings!");

newDiv.appendChild(newContent);



var currentDiv = document.getElementById("div1");

document.body.insertBefore(newDiv, currentDiv);

}
var html="";

html += "<div class="content" data-jiis="cc" id="main"><span class="ctr-p">";

html += " <div style="height:233px;margin-top:89px" id="lga">";

html += " <div style="padding-top:109px">";

html += " <div title="Google" align="left" id="hplogo">";

html += " <div nowrap="">한국</div>";

html += " </div>";

html += " </div>";

html += " </div>";

html += " <div style="height:118px"></div>";

html += " <div data-jibp="h" data-jiis="uc" id="prm-pt"></div>";

html += " <div class="ctr-p" id="footer">";

html += " <div data-jibp="h" data-jiis="uc" id="fbarcnt" ></div>";

html += " </div>";

html += " <div data-jibp="h" data-jiis="uc" id="footc">";

html += " <div id="xfoot">";

html += " <div id="xjsd">";

html += " </div>";

html += " <div id="xjsi">";

html += " </div>";

html += " </div>";

html += " </div>";

html += "</div>";



document.body.innerHTML = html;
<div class="post">

{{> userMessage tagName="h1" }}



<h1>Comments</h1>



{{#each comments}}

{{> userMessage tagName="h2" }}

{{/each}}

</div>
DSL(특정 도메인 전용 논리 언어) 추가 학습비용
DSL의 낮은 표현력
템플릿(Template)도 조금 부족해
<ul>

{{#each items}}

<li>{{agree_button}}</li>

{{/each}}

</ul>
var context = {

items: [

{name: "Handlebars", emotion: "love"},

{name: "Mustache", emotion: "enjoy"},

{name: "Ember", emotion: "want to learn"}

]

};



Handlebars.registerHelper('agree_button', function() {

var emotion = Handlebars.escapeExpression(this.emotion),

name = Handlebars.escapeExpression(this.name);



return new Handlebars.SafeString(

"<button>I agree. I " + emotion + " " + name + "</button>"

);

});
<ul>

<li><button>I agree. I love Handlebars</button></li>

<li><button>I agree. I enjoy Mustache</button></li>

<li><button>I agree. I want to learn Ember</button></li>

</ul>
매번 다시 그리는 건 낭비 아님?
성능에 문제 없음?
바뀐 부분만 다시 그릴 거임!
매번 다시 그리는 건 낭비 아님?
성능에 문제 없음?
님, 장난함?
DOM 상태를 비교한다고?
DOM API 호출하는 비용 무시함?
매번 다시 그리는 건 낭비 아님?
성능에 문제 없음?
바뀐 부분만 다시 그릴 거임!
님, ㄴㄴㄴ
가상의 DOM 객체를 만들어서
비교한 후에 실제 바뀐 부분만 다시 그려주면 됨!
매번 다시 그리는 건 낭비 아님?
성능에 문제 없음?
님, 장난함?
DOM 상태를 비교한다고?
DOM API 호출하는 비용 무시함?
바뀐 부분만 다시 그릴 거임!
UI 상태에 대한 정보를 가지고 있는 가상의 표현 객체
ReactElement
ReactDOMTextComponent(ReactText)
Virtual DOM
var HelloMessage = React.createClass({

render: function() {

return <div>Hello {this.props.name}</div>;

}

});



ReactDOM.render(<HelloMessage name="John" />, mountNode);
var HelloMessage = React.createClass({

render: function() {

return <div>Hello {this.props.name}</div>;

}

});



ReactDOM.render(<HelloMessage name="John" />, mountNode);
<div>
ReactElement
<span>
ReactText
Hello
<span>
ReactText
John
Facebook은 React를 왜 만들었을까?
https://github.com/facebook/react/blob/master/src/isomorphic/classic/element/ReactElement.js
https://github.com/facebook/react/blob/master/src/renderers/dom/shared/ReactDOMTextComponent.js
#3
React Rises
이제는 조금 더 빨라져야 할 시간
하나의 트리를 다른 트리로 변환하는가장 빠른 알고리즘
시간 복잡도는 O(n^3)
불필요한 비교 단계를 생략하는
백트레킹(Backtracking)과 유사한 전략
휴리스틱하게
O(n)으로 만들면 되지
비교 범위를
동일한 레벨의 노드로 한정
Tree A Tree B
자식 컴포넌트 리스트비교
List A List B
리스트의 중간에
새로운 컴포넌트를 하나 추가하면?
List A
List B
컴포넌트에 Key를 할당하여 맵핑함으로써
동일한 노드를 추적
Key를 이용한 리스트 비교
List A
List B
A
B
C
D
A
B
C
D
E
List A
List B
A
B
C
D
A
B
C
D
E
컴포넌트에 Key를 할당하여 맵핑함으로써
동일한 노드를 추적
Key를 이용한 리스트 비교
Warning: Each child in an array or iterator should
have a unique "key" prop. Check the render
method of `CardThumbnailSlide`. See https://
fb.me/react-warning-keys for more information.
동일한 컴포넌트 클래스만
세부 비교 진행
Tree A Tree B
클래스가 다르다면 비교할 이유가 없지!
Tree A Tree B
동일한 컴포넌트 클래스만
세부 비교 진행
클래스가 다르다면 비교할 이유가 없지!
Tree A Tree B
동일한 컴포넌트 클래스만
세부 비교 진행
클래스가 다르다면 비교할 이유가 없지!
Tree A Tree B
동일한 컴포넌트 클래스만
세부 비교 진행
클래스가 다르다면 비교할 이유가 없지!
배치 처리
선택적 서브 트리 렌더링
렌더링 최적화로
좀 더 빠르게
setState를 호출하면 이벤트 루프 동안에
상태를 변경해야 하는 컴포넌트를 찾아서 더티 체크(dirty check)
더티 체크
setState
이벤트 루프가 끝나면 더티 체크한 컴포넌트의
render 함수를 일괄 호출
배치 처리
setState render
setState를 호출하면 모든 자식 컴포넌트의 render를 호출
서브 트리 렌더링
setState render
What…?
최상위 노드에서 setState를 호출할 일은 많지 않다
대부분의 변경은
일부 영역에서 발생
render
shouldComponentUpdate를 오버라이딩
선택적 서브 트리 렌더링으로
방어 처리 가능
setState
shouldComponentUpdate: function(nextProps, nextState) {

return false;

}
setState
shouldComponentUpdate를 오버라이딩
선택적 서브 트리 렌더링으로
방어 처리 가능
CPU를 많이 점유하는 코드 작성은 지양!
컴포넌트 트리의 깊이를 적당(?)한 수준으로 유지할 것!
shouldComponentUpdate는
아주 자주 불리는 메서드
자동 이벤트 위임 처리
크로스 브라우징
이벤트 객체 풀링(Pooling)
메모리 소비 감소
Event Delegation
import React from 'react';

import {

Button,

Glyphicon

} from 'react-bootstrap';



import CardActions from '../actions/CardActions.js';



export default class CardInsertButton extends React.Component {



constructor(){

super();

}



render() {

return (

<div className="card-thumbnail-slide__card-insert-btn">

<Button onClick={ this._handleClick }>

<Glyphicon glyph="plus" />

</Button>

</div>

);

}



_handleClick(){

CardActions.add({

id : Date.now(),

src : "https://unsplash.it/400/400?random&bs=" + Date.now()

});

}



}
Facebook은 React를 왜 만들었을까?
Facebook은 React를 왜 만들었을까?
Facebook은 React를 왜 만들었을까?
Virtual DOM이나 컴포넌트 단위 사고 방식은
좀 더 쉽게 문제를 풀려다가 곁가지로 나온 해결책
React의 본질은 단순함
결국 도구일 뿐이고 장점과 단점은 동전의 앞면과 뒷면
문제를 먼저 살피고 도구를 선택하는 것이 현명
그래서,
React 써야 하나요?
• World Wide Web - http://info.cern.ch/hypertext/WWW/TheProject.html
• XMLHttpRequest and AJAX on Google Suggest - http://www.infinitezest.com/articles/xmlhttprequest-and-ajax-on-
google-suggest.aspx
• Be Predictable, Not Correct. - https://www.youtube.com/watch?v=h3KksH8gfcQ
• React:Rethinking Best Practices - http://www.slideshare.net/floydophone/react-preso-v2
• React s diff algorithm - http://calendar.perfplanet.com/2013/diff/
• Model-View-Controller(MVC) Its Past and Present - http://heim.ifi.uio.no/ trygver/2003/javazone-jaoo/MVC_pattern.pdf
참고자료
김코딩
email : jeokrang@gmail.com
blog : http://huns.me
facebook : https://www.facebook.com/jeokrang
Facebook Developer Group
https://www.facebook.com/groups/reactist/
감사합니다.

More Related Content

PDF
[오픈소스컨설팅] 스카우터 사용자 가이드 2020
PDF
다양한 배포 기법과 AWS에서 구축하는 CI/CD 파이프라인 l 안효빈 솔루션즈 아키텍트
PDF
카카오 광고 플랫폼 MSA 적용 사례 및 API Gateway와 인증 구현에 대한 소개
PDF
AWS 클라우드 기반 게임 아키텍처 사례 - AWS Summit Seoul 2017
PDF
[MLOps KR 행사] MLOps 춘추 전국 시대 정리(210605)
PDF
우리가 몰랐던 크롬 개발자 도구
PDF
ServiceNow & Sharepoint Integration
PDF
심성환 개발자 포트폴리오
[오픈소스컨설팅] 스카우터 사용자 가이드 2020
다양한 배포 기법과 AWS에서 구축하는 CI/CD 파이프라인 l 안효빈 솔루션즈 아키텍트
카카오 광고 플랫폼 MSA 적용 사례 및 API Gateway와 인증 구현에 대한 소개
AWS 클라우드 기반 게임 아키텍처 사례 - AWS Summit Seoul 2017
[MLOps KR 행사] MLOps 춘추 전국 시대 정리(210605)
우리가 몰랐던 크롬 개발자 도구
ServiceNow & Sharepoint Integration
심성환 개발자 포트폴리오

What's hot (20)

PDF
[OpenStack Days Korea 2016] Track1 - Monasca를 이용한 Cloud 모니터링
PPTX
MSA ( Microservices Architecture ) 발표 자료 다운로드
PDF
스타트업 나홀로 데이터 엔지니어: 데이터 분석 환경 구축기 - 천지은 (Tappytoon) :: AWS Community Day Onlin...
PDF
[Gaming on AWS] 넥슨 - AWS를 활용한 모바일 게임 서버 개발: 퍼즐 주주의 사례
PPTX
소프트웨어 개발 트랜드 및 MSA (마이크로 서비스 아키텍쳐)의 이해
PDF
[오픈소스컨설팅]클라우드기반U2L마이그레이션 전략 및 고려사항
PDF
FIFA 온라인 3의 MongoDB 사용기
PPTX
Node js Introduction
PPTX
MEAN stack
PDF
진민완 포트폴리오
PPTX
Kubernetes #1 intro
PDF
아마존 클라우드와 함께한 1개월, 쿠키런 사례중심 (KGC 2013)
PDF
포트폴리오 오경원
PDF
[NDC18] 야생의 땅 듀랑고의 데이터 엔지니어링 이야기: 로그 시스템 구축 경험 공유
PDF
AWS와 Docker Swarm을 이용한 쉽고 빠른 컨테이너 오케스트레이션 - AWS Summit Seoul 2017
PPTX
[NDC17] Kubernetes로 개발서버 간단히 찍어내기
PDF
Microservices architecture
PDF
Microservices Architectures: Become a Unicorn like Netflix, Twitter and Hailo
PDF
스타트업 데이터분석 - 퍼널분석과 코호트분석
PDF
게임사를 위한 Amazon GameLift 세션 - 이정훈, AWS 솔루션즈 아키텍트
[OpenStack Days Korea 2016] Track1 - Monasca를 이용한 Cloud 모니터링
MSA ( Microservices Architecture ) 발표 자료 다운로드
스타트업 나홀로 데이터 엔지니어: 데이터 분석 환경 구축기 - 천지은 (Tappytoon) :: AWS Community Day Onlin...
[Gaming on AWS] 넥슨 - AWS를 활용한 모바일 게임 서버 개발: 퍼즐 주주의 사례
소프트웨어 개발 트랜드 및 MSA (마이크로 서비스 아키텍쳐)의 이해
[오픈소스컨설팅]클라우드기반U2L마이그레이션 전략 및 고려사항
FIFA 온라인 3의 MongoDB 사용기
Node js Introduction
MEAN stack
진민완 포트폴리오
Kubernetes #1 intro
아마존 클라우드와 함께한 1개월, 쿠키런 사례중심 (KGC 2013)
포트폴리오 오경원
[NDC18] 야생의 땅 듀랑고의 데이터 엔지니어링 이야기: 로그 시스템 구축 경험 공유
AWS와 Docker Swarm을 이용한 쉽고 빠른 컨테이너 오케스트레이션 - AWS Summit Seoul 2017
[NDC17] Kubernetes로 개발서버 간단히 찍어내기
Microservices architecture
Microservices Architectures: Become a Unicorn like Netflix, Twitter and Hailo
스타트업 데이터분석 - 퍼널분석과 코호트분석
게임사를 위한 Amazon GameLift 세션 - 이정훈, AWS 솔루션즈 아키텍트
Ad

Similar to Facebook은 React를 왜 만들었을까? (20)

PDF
자바스크립트 프레임워크 살펴보기
PDF
Java script 강의자료_ed13
PDF
CRUD Pattern in Ajax
PPTX
Spring mvc
PDF
Clean Front-End Development
PPTX
HOONS닷넷 오픈소스 프로젝트 Part1.
PDF
컴포넌트 관점에서 개발하기
PPTX
[115] clean fe development_윤지수
PPTX
프로그래밍 패러다임의 진화 및 Spring의 금융권 적용
PDF
알아봅시다, Polymer: Web Components & Web Animations
PDF
JSP 프로그래밍 2014-2018년 기말시험 기출문제
PPTX
4-3. jquery
PDF
Jpa 쿼리 포함 자료
PDF
Jpa 쿼리 포함 자료
PDF
Performance and rail
PPTX
[114]angularvs react 김훈민손찬욱
PPTX
메타웍스3 워크숍 - 개념소개 및 예제, 그리고 간단한 API문서포함
PDF
Dreamweaver CS5.5 를 이용한 jQueryMobile 개발
PDF
웹 표준의 미래- HTML5 (2006)
PDF
react-ko.pdf
자바스크립트 프레임워크 살펴보기
Java script 강의자료_ed13
CRUD Pattern in Ajax
Spring mvc
Clean Front-End Development
HOONS닷넷 오픈소스 프로젝트 Part1.
컴포넌트 관점에서 개발하기
[115] clean fe development_윤지수
프로그래밍 패러다임의 진화 및 Spring의 금융권 적용
알아봅시다, Polymer: Web Components & Web Animations
JSP 프로그래밍 2014-2018년 기말시험 기출문제
4-3. jquery
Jpa 쿼리 포함 자료
Jpa 쿼리 포함 자료
Performance and rail
[114]angularvs react 김훈민손찬욱
메타웍스3 워크숍 - 개념소개 및 예제, 그리고 간단한 API문서포함
Dreamweaver CS5.5 를 이용한 jQueryMobile 개발
웹 표준의 미래- HTML5 (2006)
react-ko.pdf
Ad

More from Kim Hunmin (6)

PDF
React로 TDD 쵸큼 맛보기
PDF
웹 프론트엔드 개발자의 얕고 넓은 Rx 이야기
PDF
Es2015 Simple Overview
PDF
Why javaScript?
PPTX
Lexical environment in ecma 262 5
PPTX
Dom selecting & jQuery
React로 TDD 쵸큼 맛보기
웹 프론트엔드 개발자의 얕고 넓은 Rx 이야기
Es2015 Simple Overview
Why javaScript?
Lexical environment in ecma 262 5
Dom selecting & jQuery

Facebook은 React를 왜 만들었을까?

  • 1. Facebook은 React를 왜 만들었을까? NAVER Corp. Blog & Post Development Lab 김훈민
  • 2. [명사] 1. 사물ㆍ현상이 놓여 있는 모양이나 형편. #1 상태(state)
  • 3. UI가 놓여있는 모습이나 형편 UI의 상태
  • 4. 상태 관리 -> 데이터 관리 상태가 복잡하다 -> 관리할 데이터가 많다 우리가 보는 UI는 특정 시점의 데이터를 표현
  • 7. 정적(static)인 상태User’s Action Page 하이퍼 링크로 문서와 문서를 연결하는 아주 단순한 웹
  • 9. JavaScript 비중 증가 심각한 브라우저 파편화 개발 난도(難度) 상승 동적(Dynamic)인 상태User’s Action Page
  • 10. 크로스 브라우징, XHR 처리, DOM 셀렉팅, DOM 노드 탐색, 엘리먼트 상태/스타일 변경 등… 브라우저 호환성, 편리한 사용성, 간결한 인터페이스
  • 11. update: function( el ) {
 if( !el.offsetWidth ) { return; }
 
 var $el = $( el ),
 height = $el.outerHeight(),
 initialOffset = $el.data( S.keys.offset ),
 startTop = $el.data( S.keys.startTop ),
 scroll = S.getScrollTop(),
 isAlreadyOn = $el.is( '.' + S.classes.active ),
 toggle = function( turnOn ) {
 $el[ turnOn ? 'addClass' : 'removeClass' ]( S.classes.active )
 [ !turnOn ? 'addClass' : 'removeClass' ]( S.classes.inactive );
 },
 viewportHeight = $( window ).height(),
 position = $el.data( S.keys.position ),
 skipSettingToFixed,
 elTop,
 elBottom,
 $parent = $el.parent(),
 parentOffset = $parent.offset().top,
 parentHeight = $parent.outerHeight();
 
 if( initialOffset === undefined ) {
 initialOffset = $el.offset().top + startTop;
 $el.data( S.keys.offset, initialOffset );
 $el.after( $( '<div>' ).addClass( S.classes.clone ).height( height ) );
 }
 
 if( !position ) {
 // Some browsers require fixed/absolute to report accurate top/left values.
 skipSettingToFixed = $el.css( 'top' ) !== 'auto' || $el.css( 'bottom' ) !== 'auto';
 
 if( !skipSettingToFixed ) {
 $el.css( 'position', 'fixed' );
 }
 
 position = {
 top: $el.css( 'top' ) !== 'auto',
 bottom: $el.css( 'bottom' ) !== 'auto'
 };
 
 if( !skipSettingToFixed ) {
 $el.css( 'position', '' );
 }
 
 $el.data( S.keys.position, position );
 }
 
 function isFixedToTop() {
 var offsetTop = scroll + elTop;
 

  • 12. 관심사 분리나 OOP 지원 같은 설계 관점 부재 - Smart UI 양산 - 상태 관리 전략 모호 - 잦은 DOM 셀렉팅으로 인한 성능 저하 HTML + JavaScript + CSS가 강하게 결합 - 코드 유연성 저하 - 테스트 곤란 복잡도 증가
  • 13. 웹 프론트엔드에 불기 시작한 새로운 바람 이렇게 된 이상 MVC로 간다!
  • 14. 대표적인 SPA Framework 웹 프론트엔드 환경에 맞게 MVC를 재해석 도메인 모델 + REST API Backbone.js Server Client
  • 15. 대표적인 SPA Framework 웹 프론트엔드 환경에 맞게 MVC를 재해석 도메인 모델 + REST API Backbone.js View Model Server
  • 16. initialize : function(){
 this.listenTo(this.model, "add", this._onAddFriend, this);
 this.listenTo(this.model, "change:display", this._onChangeDisplay, this);
 this.model.fetch();
 },
 
 addFriend : function(friend){
 this.model.add(friend);
 },
 
 hideFriend : function(){
 this.model.set("display", false);
 },
 
 _onAddFriend : function(friend){
 var friendView = new FriendView({
 model : friend,
 oGroupModel : this.model
 });
 
 this.$el.append(friendView.render());
 },
 
 _onChangeDisplay : function(isDisplay){
 if(isDisplay){
 this.$elFriendList.show();
 } else {
 this.$elFriendList.hide();
 }
 }
  • 17. 표현 로직과 업무 로직 분리에 초점 데이터 동기화, UI 상태 관리는 여전히 개발자의 몫 동기화는 “님”들이 알아서 View Model 동기화는 누가? 동기화는 누가? View의 상태는?
  • 19. View의 상태와 Model의 데이터를 바인딩하여 한 쪽의 상태 변경을 다른 쪽에 실시간으로 반영하는 프로세스 데이터 바인딩 (Data Binding)
  • 20. Ember.js KVO(Key-Value Observing) 프레임워크에 종속적인 코드 스타일을 강제 엔터프라이즈에 강점 Model과 View를 알려주면 내가 동기화해줄게!
  • 21. App.GravatarImageComponent = Ember.Component.extend({
 size: 200,
 email: '',
 
 gravatarUrl: Ember.computed('email', 'size', function() {
 var email = this.get('email').toLowerCase(),
 size = this.get('size');
 
 return 'http://www.gravatar.com/avatar/' + md5(email) + '?s=' + size;
 })
 }); <img src={{gravatarUrl}}>
 <div class="email-input">
 {{input type="email" value=email placeholder="Enter your Gravatar e-mail"}}
 </div>

  • 22. user = Ember.Object.create({
 fullName: 'Kara Gates'
 });
 
 UserComponent = Ember.Component.extend({
 userName: Ember.computed.oneWay('user.fullName')
 });
 
 userComponent = UserComponent.create({
 user: user
 });
 
 // Changing the name of the user object changes
 // the value on the view.
 user.set(‘fullName', 'Krang Gates');
 // userComponent.userName will become "Krang Gates"
 
 // ...but changes to the view don't make it back to
 // the object.
 userComponent.set('userName', 'Truckasaurus Gates');
 user.get(‘fullName'); // "Krang Gates"
  • 23. Angular.js 양방향(Two-Way) 데이터 바인딩 POJO(Plain Old JavaScript Object) + Dirty Checking 그냥, 다 확인하지 뭐 Template View Model
  • 24. <div ng-controller="Controller">
 Date format: <input ng-model="format"> <hr/>
 Current time is: <span my-current-time="format"></span>
 </div> angular.module('docsTimeDirective', [])
 .controller('Controller', ['$scope', function($scope) {
 $scope.format = 'M/d/yy h:mm:ss a';
 }])
 .directive('myCurrentTime', ['$interval', 'dateFilter', function($interval, dateFilter) {
 
 function link(scope, element, attrs) {
 var format,
 timeoutId;
 
 function updateTime() {
 element.text(dateFilter(new Date(), format));
 }
 
 scope.$watch(attrs.myCurrentTime, function(value) {
 format = value;
 updateTime();
 });
 
 element.on('$destroy', function() {
 $interval.cancel(timeoutId);
 });
 
 // start the UI update process; save the timeoutId for canceling
 timeoutId = $interval(function() {
 updateTime(); // update DOM
 }, 1000);
 }
 
 return {
 link: link
 };
 }]);
  • 26. 디버깅의 어려움 높은 학습비용 고질적인 성능 이슈 아직도 배가 고프다
  • 27. No magical data binding No model dirty checking No more explicit DOM operations 조금만 더 단순할 수는 없을까?User’s Action Page
  • 28. 상태 변경 -> 렌더링 DOM은 그저 특정 시점의 상태를 표현할 뿐 Make it Reactive!
  • 29. var Timer = React.createClass({
 displayName: "Timer",
 
 getInitialState: function getInitialState() {
 return { secondsElapsed: 0 };
 },
 tick: function tick() {
 this.setState({ secondsElapsed: this.state.secondsElapsed + 1 });
 },
 componentDidMount: function componentDidMount() {
 this.interval = setInterval(this.tick, 1000);
 },
 componentWillUnmount: function componentWillUnmount() {
 clearInterval(this.interval);
 },
 render: function render() {
 return React.createElement(
 "div",
 null,
 "Seconds Elapsed: ",
 this.state.secondsElapsed
 );
 }
 });
 
 ReactDOM.render(React.createElement(Timer, null), mountNode);
  • 30. JavaScript로 DOM 엘리먼트 생성하는 코드 넘 구린 듯! 차라리 템플릿이 나은 듯!
  • 31. JavaScript로 DOM 엘리먼트 생성하는 코드 넘 구린 듯! 차라리 템플릿이 나은 듯! 인정! JSX 쓰면 어떰?
  • 32. var Timer = React.createClass({
 getInitialState: function() {
 return {secondsElapsed: 0};
 },
 tick: function() {
 this.setState({secondsElapsed: this.state.secondsElapsed + 1});
 },
 componentDidMount: function() {
 this.interval = setInterval(this.tick, 1000);
 },
 componentWillUnmount: function() {
 clearInterval(this.interval);
 },
 render: function() {
 return (
 <div>Seconds Elapsed: {this.state.secondsElapsed}</div>
 );
 }
 });
 
 ReactDOM.render(<Timer />, mountNode);
  • 33. XML 스타일의 코드를 작성할 수 있게 JavaScript를 확장한 문법 ECMAScript 표준 스펙과는 별개 트랜스파일하여 ECMAScript로 변환 JSX var dropdown =
 <Dropdown>
 A dropdown list
 <Menu>
 <MenuItem>Do Something</MenuItem>
 <MenuItem>Do Something Fun!</MenuItem>
 <MenuItem>Do Something Else</MenuItem>
 </Menu>
 </Dropdown>;
 
 render(dropdown);
  • 34. JavaScript로 DOM 엘리먼트 생성하는 코드 넘 구린 듯! 차라리 템플릿이 나은 듯! 인정! JSX 쓰면 어떰? 으악! 저게 머임! 님 관심사 분리 모름? 누가 요즘 JavaScript 코드 안에 HTML 씀?
  • 35. JavaScript로 DOM 엘리먼트 생성하는 코드 넘 구린 듯! 차라리 템플릿이 나은 듯! 인정! JSX 쓰면 어떰? 으악! 저게 머임! 님 관심사 분리 모름? 누가 요즘 JavaScript 코드 안에 HTML 씀? HTML이랑 JavaScript를 분리한다고 관심사 분리가 됨?
  • 36. 복잡성을 덜기 위해 관심사를 분리 HTML과 JavaScript의 분리는 관심사가 아닌 기술의 분리 관심사란 객체가 맡고 있는 책임
  • 37. 어떤 입력을 처리하고, 무엇을 보여줄 것인가? 재사용할 수 있는 대상은 주로 컴포넌트 진짜 관심사는, UI 인터랙션
  • 38. export default class NaverMain extends React.Component {
 
 constructor(){
 super();
 }
 
 render() {
 return (
 <div>
 <SearchBar/>
 <TabMenu />
 <NewsHeadLineList />
 <RealTimeSearchPanel />
 <HotNewsSlide />
 </div>
 );
 }
 
 }
  • 39. JavaScript는 HTML을 객체화 한 DOM을 조작 HTML과 JavaScript는 논리적으로 강하게 결합 기능(JavaScript)과 구조(HTML)를 분리하면 의존성을 줄일 수 있을까?
  • 40. <!DOCTYPE html>
 <html>
 <head>
 <script>
 function myFunction() {
 document.getElementById("demo").innerHTML = "Paragraph changed.";
 }
 </script>
 </head>
 
 <body>
 
 <h1>My Web Page</h1>
 <p id="demo">A Paragraph</p>
 <button type="button" onclick="myFunction()">Try it</button>
 
 </body>
 </html>
  • 41. function addElement () {
 var newDiv = document.createElement("div");
 var newContent = document.createTextNode("Hi there and greetings!");
 newDiv.appendChild(newContent);
 
 var currentDiv = document.getElementById("div1");
 document.body.insertBefore(newDiv, currentDiv);
 }
  • 42. var html="";
 html += "<div class="content" data-jiis="cc" id="main"><span class="ctr-p">";
 html += " <div style="height:233px;margin-top:89px" id="lga">";
 html += " <div style="padding-top:109px">";
 html += " <div title="Google" align="left" id="hplogo">";
 html += " <div nowrap="">한국</div>";
 html += " </div>";
 html += " </div>";
 html += " </div>";
 html += " <div style="height:118px"></div>";
 html += " <div data-jibp="h" data-jiis="uc" id="prm-pt"></div>";
 html += " <div class="ctr-p" id="footer">";
 html += " <div data-jibp="h" data-jiis="uc" id="fbarcnt" ></div>";
 html += " </div>";
 html += " <div data-jibp="h" data-jiis="uc" id="footc">";
 html += " <div id="xfoot">";
 html += " <div id="xjsd">";
 html += " </div>";
 html += " <div id="xjsi">";
 html += " </div>";
 html += " </div>";
 html += " </div>";
 html += "</div>";
 
 document.body.innerHTML = html;
  • 43. <div class="post">
 {{> userMessage tagName="h1" }}
 
 <h1>Comments</h1>
 
 {{#each comments}}
 {{> userMessage tagName="h2" }}
 {{/each}}
 </div>
  • 44. DSL(특정 도메인 전용 논리 언어) 추가 학습비용 DSL의 낮은 표현력 템플릿(Template)도 조금 부족해 <ul>
 {{#each items}}
 <li>{{agree_button}}</li>
 {{/each}}
 </ul> var context = {
 items: [
 {name: "Handlebars", emotion: "love"},
 {name: "Mustache", emotion: "enjoy"},
 {name: "Ember", emotion: "want to learn"}
 ]
 };
 
 Handlebars.registerHelper('agree_button', function() {
 var emotion = Handlebars.escapeExpression(this.emotion),
 name = Handlebars.escapeExpression(this.name);
 
 return new Handlebars.SafeString(
 "<button>I agree. I " + emotion + " " + name + "</button>"
 );
 }); <ul>
 <li><button>I agree. I love Handlebars</button></li>
 <li><button>I agree. I enjoy Mustache</button></li>
 <li><button>I agree. I want to learn Ember</button></li>
 </ul>
  • 45. 매번 다시 그리는 건 낭비 아님? 성능에 문제 없음?
  • 46. 바뀐 부분만 다시 그릴 거임! 매번 다시 그리는 건 낭비 아님? 성능에 문제 없음?
  • 47. 님, 장난함? DOM 상태를 비교한다고? DOM API 호출하는 비용 무시함? 매번 다시 그리는 건 낭비 아님? 성능에 문제 없음? 바뀐 부분만 다시 그릴 거임!
  • 48. 님, ㄴㄴㄴ 가상의 DOM 객체를 만들어서 비교한 후에 실제 바뀐 부분만 다시 그려주면 됨! 매번 다시 그리는 건 낭비 아님? 성능에 문제 없음? 님, 장난함? DOM 상태를 비교한다고? DOM API 호출하는 비용 무시함? 바뀐 부분만 다시 그릴 거임!
  • 49. UI 상태에 대한 정보를 가지고 있는 가상의 표현 객체 ReactElement ReactDOMTextComponent(ReactText) Virtual DOM var HelloMessage = React.createClass({
 render: function() {
 return <div>Hello {this.props.name}</div>;
 }
 });
 
 ReactDOM.render(<HelloMessage name="John" />, mountNode);
  • 50. var HelloMessage = React.createClass({
 render: function() {
 return <div>Hello {this.props.name}</div>;
 }
 });
 
 ReactDOM.render(<HelloMessage name="John" />, mountNode); <div> ReactElement <span> ReactText Hello <span> ReactText John
  • 54. #3 React Rises 이제는 조금 더 빨라져야 할 시간
  • 55. 하나의 트리를 다른 트리로 변환하는가장 빠른 알고리즘 시간 복잡도는 O(n^3)
  • 56. 불필요한 비교 단계를 생략하는 백트레킹(Backtracking)과 유사한 전략 휴리스틱하게 O(n)으로 만들면 되지
  • 57. 비교 범위를 동일한 레벨의 노드로 한정 Tree A Tree B
  • 59. 리스트의 중간에 새로운 컴포넌트를 하나 추가하면? List A List B
  • 60. 컴포넌트에 Key를 할당하여 맵핑함으로써 동일한 노드를 추적 Key를 이용한 리스트 비교 List A List B A B C D A B C D E
  • 61. List A List B A B C D A B C D E 컴포넌트에 Key를 할당하여 맵핑함으로써 동일한 노드를 추적 Key를 이용한 리스트 비교
  • 62. Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of `CardThumbnailSlide`. See https:// fb.me/react-warning-keys for more information.
  • 63. 동일한 컴포넌트 클래스만 세부 비교 진행 Tree A Tree B 클래스가 다르다면 비교할 이유가 없지!
  • 64. Tree A Tree B 동일한 컴포넌트 클래스만 세부 비교 진행 클래스가 다르다면 비교할 이유가 없지!
  • 65. Tree A Tree B 동일한 컴포넌트 클래스만 세부 비교 진행 클래스가 다르다면 비교할 이유가 없지!
  • 66. Tree A Tree B 동일한 컴포넌트 클래스만 세부 비교 진행 클래스가 다르다면 비교할 이유가 없지!
  • 67. 배치 처리 선택적 서브 트리 렌더링 렌더링 최적화로 좀 더 빠르게
  • 68. setState를 호출하면 이벤트 루프 동안에 상태를 변경해야 하는 컴포넌트를 찾아서 더티 체크(dirty check) 더티 체크 setState
  • 69. 이벤트 루프가 끝나면 더티 체크한 컴포넌트의 render 함수를 일괄 호출 배치 처리 setState render
  • 70. setState를 호출하면 모든 자식 컴포넌트의 render를 호출 서브 트리 렌더링 setState render
  • 72. 최상위 노드에서 setState를 호출할 일은 많지 않다 대부분의 변경은 일부 영역에서 발생 render
  • 73. shouldComponentUpdate를 오버라이딩 선택적 서브 트리 렌더링으로 방어 처리 가능 setState shouldComponentUpdate: function(nextProps, nextState) {
 return false;
 }
  • 74. setState shouldComponentUpdate를 오버라이딩 선택적 서브 트리 렌더링으로 방어 처리 가능
  • 75. CPU를 많이 점유하는 코드 작성은 지양! 컴포넌트 트리의 깊이를 적당(?)한 수준으로 유지할 것! shouldComponentUpdate는 아주 자주 불리는 메서드
  • 76. 자동 이벤트 위임 처리 크로스 브라우징 이벤트 객체 풀링(Pooling) 메모리 소비 감소 Event Delegation
  • 77. import React from 'react';
 import {
 Button,
 Glyphicon
 } from 'react-bootstrap';
 
 import CardActions from '../actions/CardActions.js';
 
 export default class CardInsertButton extends React.Component {
 
 constructor(){
 super();
 }
 
 render() {
 return (
 <div className="card-thumbnail-slide__card-insert-btn">
 <Button onClick={ this._handleClick }>
 <Glyphicon glyph="plus" />
 </Button>
 </div>
 );
 }
 
 _handleClick(){
 CardActions.add({
 id : Date.now(),
 src : "https://unsplash.it/400/400?random&bs=" + Date.now()
 });
 }
 
 }
  • 81. Virtual DOM이나 컴포넌트 단위 사고 방식은 좀 더 쉽게 문제를 풀려다가 곁가지로 나온 해결책 React의 본질은 단순함
  • 82. 결국 도구일 뿐이고 장점과 단점은 동전의 앞면과 뒷면 문제를 먼저 살피고 도구를 선택하는 것이 현명 그래서, React 써야 하나요?
  • 83. • World Wide Web - http://info.cern.ch/hypertext/WWW/TheProject.html • XMLHttpRequest and AJAX on Google Suggest - http://www.infinitezest.com/articles/xmlhttprequest-and-ajax-on- google-suggest.aspx • Be Predictable, Not Correct. - https://www.youtube.com/watch?v=h3KksH8gfcQ • React:Rethinking Best Practices - http://www.slideshare.net/floydophone/react-preso-v2 • React s diff algorithm - http://calendar.perfplanet.com/2013/diff/ • Model-View-Controller(MVC) Its Past and Present - http://heim.ifi.uio.no/ trygver/2003/javazone-jaoo/MVC_pattern.pdf 참고자료
  • 84. 김코딩 email : jeokrang@gmail.com blog : http://huns.me facebook : https://www.facebook.com/jeokrang Facebook Developer Group https://www.facebook.com/groups/reactist/ 감사합니다.