SlideShare une entreprise Scribd logo
1  sur  75
Télécharger pour lire hors ligne
CLEAN	
FRONTEND	
DEVELOPMENT
YOUN JISU,	CodeSquad
DEVIEW
2016
Last modified : 2016-10-26
Intro.
요즘 JavaScript 개발 이야기
Intro
오늘 이야기는 이쯤에 맞춥니다
IE6 Modern Browser
vanilla Full Framework
static
Web page
SPA
imgae: https://hackernoon.com/how-it-feels-to-learn-javascript-in-2016-d3a717dd577f#.mdtm38i8o
Intro
JavaScript Fatigue >.<
http://stateofjs.com/2016/opinions/
JavaScript 개발은 복잡하다
Intro
http://stateofjs.com/2016/opinions/
JavaScript 개발은 빠르게 변하고 있다
Intro
http://stateofjs.com/2016/opinions/
하지만 올바른 방향으로 가는 중
Intro
Frameworks 의 불편함
우량한 아이들 새로운 아이들
예측하기 어려운 미래 전략

병주고 약주고..

(SPA + Server-side rendering?)
브라우저 지원범위.

커뮤니티, 문서화, 생태계, 급격한 변화
다양한 Syntax와 Pattern 이 존재

새로운 Learning costs
Intro
공통적으로
On January 12, 2016 Microsoft announced end of support for IE10, IE9, and IE8.

> Progressive Enhancement 전략과 함께 CSS3, ES 최신 버전의 사용도 가능
주변은,
Intro
Mobile Web Browser 의 꾸준한성장

> static view 중심의 서비스

> data 처리보다는 seamless한 animation 처리가 더 중요
ES2015,ES2016,ES2017 (thanks to jQuery, underscor, lodash)

> 다양한 readable syntax 제공. 다양한 라이브러리와의 이별
Standard transpilers (not Typescript, coffeeScript, JSX) with Builders

> ES를 더 땡길 수 있는 기회!
우리 서비스는 지속가능해야 한다

성능을 깊게 개선할 수 있어야 한다

동료가 쉽게 이해할 수 있는 코드를 구현해야 한다

다양한 환경에서 동작가능해야 한다

항상 더 좋은 UX를 고민하자

jQuery 개발자보단 Front-end 개발자가 되면 좋겠다
한편, FE개발자의 본능적 미션 !
Intro
“
”
standard Code,
with all tools
이런 전략은 어떨까?
Intro
standard Code,
with all tools
“Polyfill, Transpiler" based Architecture
transpiling
ES6 based
service codes
ES5 Codes
Polyfills
Utilities codes Production
code
Intro
FUTURE !
Intro
transpiling
ES6 based
service codes
ES5 Codes
Polyfills
Utilities codes Production
code
jQuery Free
<!-- jQuery -->
<script src="vendor/jquery/jquery.min.js"></script>
<!-- Bootstrap Core JavaScript -->
<script src="vendor/bootstrap/js/bootstrap.min.js"></script>
<!-- Plugin JavaScript -->
<script src=“vender/jquery/jquery.easing.min.js”></script>
<!-- Theme JavaScript -->
<script src="js/agency.min.js"></script>
간단한 modal control, scroll effect 에 필요한
JavaScript 파일들
jQuery Free
Scroll 효과 정도는 Vanilla로 충분
let mainNav = document.querySelector(“#mainNav");
window.addEventListener("scroll", (evt) => {
let currentScrollY = window.pageYOffset;
if(currentScrollY > MY_STATIC.SCROLL_TOP_CHANGE) {
if(DOWNMODE) return;
mainNav.classList.add("affix");
DOWNMODE = true;
} else {
mainNav.classList.remove("affix");
DOWNMODE = false;;
}
});
jQuery Free
let mainNav = document.querySelector(“#mainNav");
window.addEventListener("scroll", (evt) => {
let currentScrollY = window.pageYOffset;
if(currentScrollY > MY_STATIC.SCROLL_TOP_CHANGE) {
if(DOWNMODE) return;
mainNav.classList.add("affix");
DOWNMODE = true;
} else {
mainNav.classList.remove("affix");
DOWNMODE = false;;
}
});
demo
Event Delegation
el.addEventListener("click", (evt) => {
evt.preventDefault();
let ellink = evt.target.closest(".portfolio-link");
if(!ellink) return;
let sHTML = this.myAsync.execAsyncAwait(ellink("href").substring(1));
document.querySelector("footer").insertAdjacentHTML('afterend', sHTML);
});
jQuery Free
Element.closest, matches 메서드만 잘써도 :-)
은근 다 있다
new XMLHttpRequest()
xhr.addEventListener
document.createElement
setAttribute
getElementsByTagName
requestAnimationFrame
getBoundingClientRect
Object.prototype.toString.call
JSON.parse
bind
JSON.stringify
unshift
splice
Object.keys
forEach
isArray
Date.now
evt.stopPropagation
Math.round
parseInt
cloneNode
insertBefore
appendChild
localStorage.setItem
evt.changedTouches[0].pageY
querySelector
jQuery Free
jQuery Free
if(bMouseEvent) {
pageX = evt.pageX;
pageY = evt.pageY;
} else {
pageX = evt.changedTouches[0].pageX;
pageY = evt.changedTouches[0].pageY;
}
this.nStartPosX = Math.floor(pageX);
this.nStartPosY = Math.floor(pageY);
this.nStartTranslateX = _cu.getTranslate3dX(this.elTarget);
this.nTouchStartTime = Date.now();
}
handlerTouchMove(evt) {
evt.stopPropagation();
if(this.bAnimationing) return;
if(!this.bSwipe) return;
let bMouseEvent = evt.type.substr(0,5) === "mouse";
let htCurrentEvt = (bMouseEvent) ? evt : evt.changedTouches[0];
this.nMovePosX = Math.floor(htCurrentEvt.pageX);
this.nMovePosY = Math.floor(htCurrentEvt.pageY);
….
Mobile Web & Vanilla 자연스럽다
DOM Append Performance
var $c = $("<div />").addClass("container");
for (var i=0; i<10000; i++) {
$c.append($("<div />").addClass("test-div"));
}
$("BODY").append($c);
432.524ms
var c = document.createDocumentFragment();
for (var i=0; i<10000; i++) {
var e = document.createElement("div");
e.className = "test-div";
c.appendChild(e);
}
document.body.appendChild(c);
16.237ms
https://howchoo.com/g/mmu0nguznjg/learn-the-slow-and-fast-way-to-append-elements-to-the-dom
jQuery
Pure JavaScript
jQuery Free
https://medium.com/the-vue-point/vue-2-0-is-here-ef1f26acf4b8#.7rbhdnuyp
rendering layer benchmark Oct,1,2016 by VueJS
DOM rendering layer performance
jQuery Free
jQuery Plugin
vanillaJS
Component
최근 5년간 jQuery Plugin Trend
jQuery Free
Clean jQuery Free

VanillaJS는 더 지속 가능한 코드다.

모바일웹에서 VanillaJS는 훌륭한 조합.

PC에서도 polyfill을 잘 활용하며 jQuery Free를!

pure DOM API가 대부분 상황에서는 가장 빠르다.
jQuery Free
Modules
Modules
import (ES2015)
import { member } from "module-name";
export default function (…) { … }
good-bye AMD API (Require.js)..
CLASS
import tc from '../lib/TabComponent.js';
class MyAsync{
constructor() {
this.name = "xhr";
}
simpleFetch(url) {
return new Promise(function(resolve, reject) {
var req = new XMLHttpRequest();
req.addEventListener("load", function() {
let sData = JSON.parse(req.responseText);
if(typeof sData !== "object") reject("wrong data");
else resolve(sData);
});
req.open("GET", url);
req.send();
});
}
Modules
Code
scroll effect코드를 import, export로 모듈화
Modules
Clean Modules
Use Class & Import & Export !!
Modules
Two-way Data Binding
Two way
binding
Two-way data binding
데이터가 변경될때, UI를 변경

UI가 변경될때, 데이터를 변경
Two way
binding
Dirty Checking (digest cycle)
작은 변화에 과한 렌더링. 지속적인 CPU 부하
Proxy (ES2015)
Interception API
Two way
binding
let msgData = {};
let elMessage = document.getElementById("message");
let msgProxy = new Proxy(msgData, {
get: function(target, name, receiver) {
return target[name];
},
set: function(obj, prop, value) {
obj[prop] = value;
elMessage.value = value;
document.getElementById("text-count").textContent = value.length;
return true;
}
});
elMessage.addEventListener("input", (evt)=>{
msgProxy.content = evt.target.value;
});
Proxy
Two way
binding
그런데 Proxy는 좀더 걸릴 듯 하다..
babel polyfill 로도 지원하지 않는 중
Two way
binding
Simple Accessor
ES5 getter/setter 통해 비교적 간단히 구현가능.
Object.defineProperty(obj, prop, descriptor)
Two way
binding
bindModel(obj, property, elView, fnCallback) {
Object.defineProperty(obj, property, {
get: function() {
return elView.value;
},
set: function(newValue) {
elView.value = newValue;
fnCallback(newValue);
},
configurable: true
});
}
Simple Accessor
Two way
binding
demo
Data binding using ‘bindModelInput’
Two way
binding
Clean Two-way data binding
Two-way data binding은 framework에서만 가능한 건 아님.

Proxy API를 지켜보자.

간단한 data binding은 defineProperty 로 간단히 처리!
Asynchronous
simpleAjax("../data/first.json", function(data) {
try {
var name = data.user.name;
var imgUrl = "../data/img/" + name + ".json";
simpleAjax(imgUrl, function(data2) {
try {
setTimeout(function(){
try {
var aImage = data2.images;
aImage.forEach((v) => logMsg(elLog,v));
} catch (err) {
console.log('error 3' , err );
}
},500);
} catch (err) {
console.log('error 2' , err );
}
});
} catch (err) {
console.log("error 1: ", err);
}
});
Asynchronous
가끔 브라우저에서도 Hell
Asynchronous
다행인지, 

Pure JavaScript에서는 그 해법이 쏟아져 나옴.

> Synchronous-looking style
Asynchronous
Promise A+
• 비동기 로직에서 콜백의 분리

• thenable

• async의 밑바탕 기술
function simpleFetch(url) {
return new Promise(function(resolve, reject){
var req = new XMLHttpRequest();
req.addEventListener("load", function() {
let htData = JSON.parse(req.responseText);
if(typeof htData !== "object") reject("wrong data");
else resolve(htData);
});
req.open("GET", url);
req.send();
});
}
simpleFetch("../data/first.json")
.then(function(data) {
var name = data.user.name;
var imgUrl = "../data/img/" + name + ".json";
return simpleFetch(imgUrl);
})
.then(function(data2) {
return simpleSetTimeoutPromise(500,data2);
})
.then(function(data3) {
let elLog = document.querySelector(".log");
let aImage = data3.images;
aImage.forEach((v) => logMsg(elLog,v));
})
.catch(function(err){
console.log("error : " + err);
})
Asynchronous
generator/yield
딱 비동기 문제를 위한 것만은 아니다.
Promise와 조합하는게 좋고, 

단, generator를 조정하는 

역할을 하는 코드를 구현 함(runner)
function *myGeneratorWithPromise() {
try {
var data = yield simpleFetch("../data/first.json");
var url2 = "../data/img/" + data.user.name + ".json";
var data2 = yield simpleFetch(url2);
var aImage = data2.images;
//do something..
}
//code : https://davidwalsh.name/async-generators.
function runGenerator(g) {
var it = g(), ret;
(function iterate(val){
ret = it.next( val );
if (!ret.done) {
if (typeof ret.value === "object" && ("then" in ret.value)) {
ret.value.then( iterate );
}
else {
setTimeout( function(){
iterate( ret.value );
}, 0 );
}
}
})();
}
fnlist.generatorAndPromise = function() {
runGenerator(myGeneratorWithPromise);
}
Asynchronous
wow! async/await !
뭐 이건…좋다.

async 함수는 promise를 반환한다는 점을 주의

ES2017 이라는 소문 +.+

하지만 Babel과 함께라면 당장! 

(generator 로 변환)
fnlist.asyncAwait = async function () {
try {
var data = await simpleFetch("../data/
first.json");
var url2 = "../data/img/" + data.user.name +
".json";
var data2 = await simpleFetch(url2);
var aImage = data2.images;
//parallel task using Promise.all function.
var data3 = await Promise.all([
simpleSetTimeoutPromise(100, aImage),
simpleSetTimeoutPromise(500, "dummy"),
simpleSetTimeoutPromise(1000, "dummy"),
]);
var elLog = document.querySelector(".log");
data3[0].forEach((v) => logMsg(elLog,v));
} catch (err) {
console.log("error during myGenerator : ",
err);
}
}
}
thanks to WebPack&Babel
Asynchronous
observable (rx.js)
아.. 음..

functional programming의 필요성
진심 느끼는 분들께.
var chainPromise =
Rx.Observable.just('../data/first.json')
.flatMap(simpleFetch)
.map( (x) => { return ("../data/img/" +
x.user.name +".json")})
.flatMap(simpleFetch)
.delay(500)
.subscribe((x) => {
let elLog =
document.querySelector(".log");
let aImage = x.images;
aImage.forEach((v) => logMsg(elLog,v));
});
thanks to WebPack&Babel
Asynchronous
Clean Asynchronous
그럭저럭 콜백 지옥 상황에선, 

> 콜백 몸체를 분리하는 정도만으로 충분

빈번한 콜백 지옥이라면, 

> async,await 와 같은 다양한 방법으로 코드를 clean하게 구현
Templating
Pure Templating Engine
var templateRunner = function(sHtml){
return function(oData){
for(var value in oData){
var re = "{%s?" + value + “s?%}";
sHtml = sHtml.replace(new RegExp(re, "ig"), oData[value]
}
return sHtml;
};
};
simple !
Templating
서비스 logic 은 clean하게 유지.

Template HTML은 쉽게 관리.

PreCompile 로 좀더 갈끔하게
template
html
template
html
template
html
PreCompile
[Build Step]
template

function
[Service Step]
복잡한 상황에서는 ?
Templating
PreCompile
loaders: [
{
test : /-tpl.hbs$/,
loader :
'handlebars'
},
…
Webpack handlebar-loader
Templating
Templating with ES2015 Modules
var listTpl = require('/template/portfolioModal-tpl.hbs');
listTpl( { name: ‘hello codeSquad' } );
import modalTpl from '/template/portfolioModal-tpl.hbs';
listTpl( { name: ‘hello codeSquad' } );
Templating
Clean Templating
간단한 templating 은 replace 로 간단히 구현

복잡한 작업에서는 로직과 html을 잘 분리

Templating
Virtual DOM
view 처리의 또다른 해법
VIEW조작의 복잡도를 해결하기 위해

virtual DOM 이 필요하고,

그래서 React를 써야 한다며?
Virtual DOM
> 일단, Virtual DOM 자체가 pure DOM보단 

항상 빠른 건 아니다.
https://vdom-benchmark.github.io/vdom-benchmark/
virtual DOM은 React가 짱인가?
simple한 virtual DOM 라이브러리가 2~3배 빠르다
Virtual DOM
<ul className=”list”>
<li>item 1</li>
<li>item 2</li>
</ul>
h(‘ul’, { className: ‘list’ },
h(‘li’, {}, ‘item 1’),
h(‘li’, {}, ‘item 2’),
);
참고, Virtual DOM 만들기 과정
JSX Transpiled code JavaScript Object
thanks to WebPack&Babel
Virtual DOM
{ type: ‘ul’, props: { className: ‘list’ }, children: [
{ type: ‘li’, props: {}, children: [‘item 1’] },
{ type: ‘li’, props: {}, children: [‘item 2’] }
] }
function renderMaquette() {
return h("ul.ul-wrap", [
aData.map(function(value, index) {
return h("li" , [
h("span", [""+ value])
]);
})
]);
}
projector.replace(domNode, renderMaquette);
template library 와 비스무리.
Virtual DOM
Simple VD example(maquette.js)
Simple VD example(maquette.js)
Virtual DOM
Clean Virtual DOM
VD는 성능이 분명 빠를 때 사용하기

사용해야하는 경우 코드의 복잡도는 더 올라갈 수 있음.

가벼운 VD 라이브러리가 좋은 선택지가 될 수 있음.
Virtual DOM
Loose Coupling
Dependency Injection
MODAL
Loose
Coupling
XHR
JSONP
Local Storage
의존성있는 동일한 행위의 Class들과의 관계

느슨하게 유지하기
XHR
JSONP
Local Storage
Loose Coupling
let dependencyContainer = {
modalDependency : {
storagePlugin : new XHR(),
otherPlugin : new MyAsync()
}
}
let oModal = new Main(dependencyContainer.modalDependency);
Loose
Coupling
조금 아쉬움이 있다

직접 class를 쓴 거랑 큰 차이는 안나고, Lazy instantiation 이 안되고.
Static Dependency Injection
Loose
Coupling
Register1
{XHR, Other2} new mainClass(...aDepClassInstance)
getInstance2
Injection3
DI Factory
XHR JSONP
Local
Storage
Other1 Other2 Other3
Dependencies Class
XHR Other2
Main Class
Dependency Injection
Loose
Coupling
class Service {
constructor(storagePlugin, otherPlugin) {
this.storagePlugin = storagePlugin;
this.otherPlugin = otherPlugin;
}
getStorageData() {
return this.storagePlugin.getData();
}
getOtherData() {
return this.otherPlugin.getData();
}
}
Main Class
Dependency Injection
의존성 있는 Class과의 관계는 느슨하다.
Loose
Coupling
//register depedencies
let myDI = new DIFactory();
myDI.register('xhr', XHR);
myDI.register('jsonp', JSONP);
myDI.register('other', Other);
//dependency injection
let cInstance = myDI.getInstance(Service, ["xhr","other"]);
console.log(cInstance.getStorageData());
Service code
Dependency Injection
Dependency 관계를 미리 정의하고, 인스턴스를 나중에 생성
Loose
Coupling
class DIFactory {
constructor() {
this.matching = {};
}
register(name, dClass) {
this.matching[name] = new dClass();
}
getInstance(mainClass, aDepClass) {
let aDepClassInstance = aDepClass.map((v) => {
return this.matching[v];
});
return new mainClass(...aDepClassInstance);
}
}
DI Factory
이렇게 처리하기 위해 필요한 

DI Factory 는 겨우 이정도
Code
Dependency Injection using simple factory
Register function
User
custom function
subscribe publish
‘FN_AFTER_FOCUS’
‘FN_AFTER_SUBMIT’
Remove methods of Dependencies.
Resuable
Codes
Plugin function
Emit Event
Plugin function
Loose
Coupling
Custom Function & Event Driven
Resuable
Codes
Common
Component
AA Component BB Component CC Component
A-1 plugin A-2 plugin B-1 plugin B-2 plugin C-1 plugin C-2 plugin
utility library
Component의 공통 기능

option 설정

plugin 등록
모든 파일에서 참고하는 유틸리티 메서드

animation 처리

css 속성 추가

null 체크 

..
Components

해당 component에 필요한 기능
Plugins

option으로 제공되는 추가기능.
LooseCoupling -> Resuable Component !
Loose
Coupling
Clean Loose Coupling
Dependency를 줄이는 패턴은 어렵고 복잡할 필요는 없다. 간단한 방법도 있다.

커다란 Framework에서만 구현 가능한 것도 아니다.

다양하게 구현된 Module, Component 상황에 최적의 방법이 무엇인지 고민하기
Loose
Coupling
사용된 코드는 여기,

https://github.com/nigayo/cleanfe
Async 코드는 여기,

https://github.com/nigayo/javascript-async
Build Tools
Without gulp or grunt
only NPM !
NPM
Builds
"scripts": {
"test": "echo "Error: no test specified" && exit 1",
"uglify": "mkdir -p dist/js && uglifyjs src/js/A.js src/js/B.js -m -o dist/js/all.min.js",
"watch:js" : "onchange 'src/js/*.js' -- npm run uglify"
},
NPM Scripts
간단하다면 npm build 만으로도 충분하다!
"scripts": {
"build": "webpack"
},
entry: {
'script': ['babel-polyfill', './docs/js/main.js'],
'style': './docs/less/agency.less'
},
watch: true,
debug: true,
devtool: 'source-map',
module: {
loaders: [
{
test: /.es6$/,
exclude: /node_modules/,
loader: "babel-loader",
query: {
presets: ['es2015', 'stage-3']
}
},
{
test: /.(ttf.*|eot.*|woff.*|ogg|mp3|html)$/,
loader: 'file-loader'
},
{
test: /.(png|jpe?g|gif|svg.*)$/,
loader: 'file-loader!img-loader'
},
webpack.configNPM Scripts
Without gulp or grunt
NPM + Webpack
NPM
Builds
Clean Build tools
NPM Scripts 나 Webpack 만으로도 clean build환경을.
Resuable
Codes
Standard code with all tools,

사용자에게 더 좋은 UX를 제공하고, 

개발에서 또 다른 즐거움을 느끼길 바랍니다 :-)
마무리
그리고, 앞으로 더 많은 분들과 함께,

이런 고민을 하게 되길 바라겠습니다
윤지수, codesquad
crong@codesquad.kr

Contenu connexe

Tendances

진짜기초 Node.js
진짜기초 Node.js진짜기초 Node.js
진짜기초 Node.jsWoo Jin Kim
 
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
 
ReactJS | 서버와 클라이어트에서 동시에 사용하는
ReactJS | 서버와 클라이어트에서 동시에 사용하는ReactJS | 서버와 클라이어트에서 동시에 사용하는
ReactJS | 서버와 클라이어트에서 동시에 사용하는Taegon Kim
 
React를 이용하여 멀티플랫폼에서 개발하기
React를 이용하여 멀티플랫폼에서 개발하기React를 이용하여 멀티플랫폼에서 개발하기
React를 이용하여 멀티플랫폼에서 개발하기WebFrameworks
 
XECon2015 :: [2-2] 박상현 - React로 개발하는 SPA 실무 이야기
XECon2015 :: [2-2] 박상현 - React로 개발하는 SPA 실무 이야기XECon2015 :: [2-2] 박상현 - React로 개발하는 SPA 실무 이야기
XECon2015 :: [2-2] 박상현 - React로 개발하는 SPA 실무 이야기XpressEngine
 
ReactJS로 시작하는 멀티플랫폼 개발하기
ReactJS로 시작하는 멀티플랫폼 개발하기ReactJS로 시작하는 멀티플랫폼 개발하기
ReactJS로 시작하는 멀티플랫폼 개발하기Taegon Kim
 
Facebook은 React를 왜 만들었을까?
Facebook은 React를 왜 만들었을까? Facebook은 React를 왜 만들었을까?
Facebook은 React를 왜 만들었을까? Kim Hunmin
 
Nodejs, PhantomJS, casperJs, YSlow, expressjs
Nodejs, PhantomJS, casperJs, YSlow, expressjsNodejs, PhantomJS, casperJs, YSlow, expressjs
Nodejs, PhantomJS, casperJs, YSlow, expressjs기동 이
 
Web Components 101 polymer & brick
Web Components 101 polymer & brickWeb Components 101 polymer & brick
Web Components 101 polymer & brickyongwoo Jeon
 
Spring boot-summary(part2-part3)
Spring boot-summary(part2-part3)Spring boot-summary(part2-part3)
Spring boot-summary(part2-part3)Jaesup Kwak
 
React 튜토리얼 1차시
React 튜토리얼 1차시React 튜토리얼 1차시
React 튜토리얼 1차시태현 김
 
Progressive Web Apps
Progressive Web AppsProgressive Web Apps
Progressive Web Appsjungkees
 
옛날 웹 개발자가 잠깐 맛본 Vue.js 소개
옛날 웹 개발자가 잠깐 맛본 Vue.js 소개옛날 웹 개발자가 잠깐 맛본 Vue.js 소개
옛날 웹 개발자가 잠깐 맛본 Vue.js 소개beom kyun choi
 
Django in Production
Django in ProductionDjango in Production
Django in ProductionHyun-woo Park
 
[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
 
혁신적인 웹컴포넌트 라이브러리 - Polymer
혁신적인 웹컴포넌트 라이브러리 - Polymer혁신적인 웹컴포넌트 라이브러리 - Polymer
혁신적인 웹컴포넌트 라이브러리 - PolymerJae Sung Park
 
자바스크립트 프레임워크 살펴보기
자바스크립트 프레임워크 살펴보기자바스크립트 프레임워크 살펴보기
자바스크립트 프레임워크 살펴보기Jeado Ko
 
발렌타인 웨비너 7회 - React를 이용한 웹 앱 개발 살펴보기
발렌타인 웨비너 7회 - React를 이용한 웹 앱 개발 살펴보기발렌타인 웨비너 7회 - React를 이용한 웹 앱 개발 살펴보기
발렌타인 웨비너 7회 - React를 이용한 웹 앱 개발 살펴보기DoHyun Jung
 
다시보는 Angular js
다시보는 Angular js다시보는 Angular js
다시보는 Angular jsJeado Ko
 

Tendances (20)

진짜기초 Node.js
진짜기초 Node.js진짜기초 Node.js
진짜기초 Node.js
 
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
 
ReactJS | 서버와 클라이어트에서 동시에 사용하는
ReactJS | 서버와 클라이어트에서 동시에 사용하는ReactJS | 서버와 클라이어트에서 동시에 사용하는
ReactJS | 서버와 클라이어트에서 동시에 사용하는
 
React를 이용하여 멀티플랫폼에서 개발하기
React를 이용하여 멀티플랫폼에서 개발하기React를 이용하여 멀티플랫폼에서 개발하기
React를 이용하여 멀티플랫폼에서 개발하기
 
XECon2015 :: [2-2] 박상현 - React로 개발하는 SPA 실무 이야기
XECon2015 :: [2-2] 박상현 - React로 개발하는 SPA 실무 이야기XECon2015 :: [2-2] 박상현 - React로 개발하는 SPA 실무 이야기
XECon2015 :: [2-2] 박상현 - React로 개발하는 SPA 실무 이야기
 
ReactJS로 시작하는 멀티플랫폼 개발하기
ReactJS로 시작하는 멀티플랫폼 개발하기ReactJS로 시작하는 멀티플랫폼 개발하기
ReactJS로 시작하는 멀티플랫폼 개발하기
 
Facebook은 React를 왜 만들었을까?
Facebook은 React를 왜 만들었을까? Facebook은 React를 왜 만들었을까?
Facebook은 React를 왜 만들었을까?
 
Nodejs, PhantomJS, casperJs, YSlow, expressjs
Nodejs, PhantomJS, casperJs, YSlow, expressjsNodejs, PhantomJS, casperJs, YSlow, expressjs
Nodejs, PhantomJS, casperJs, YSlow, expressjs
 
Web Components 101 polymer & brick
Web Components 101 polymer & brickWeb Components 101 polymer & brick
Web Components 101 polymer & brick
 
Spring boot-summary(part2-part3)
Spring boot-summary(part2-part3)Spring boot-summary(part2-part3)
Spring boot-summary(part2-part3)
 
React 튜토리얼 1차시
React 튜토리얼 1차시React 튜토리얼 1차시
React 튜토리얼 1차시
 
Progressive Web Apps
Progressive Web AppsProgressive Web Apps
Progressive Web Apps
 
옛날 웹 개발자가 잠깐 맛본 Vue.js 소개
옛날 웹 개발자가 잠깐 맛본 Vue.js 소개옛날 웹 개발자가 잠깐 맛본 Vue.js 소개
옛날 웹 개발자가 잠깐 맛본 Vue.js 소개
 
Django in Production
Django in ProductionDjango in Production
Django in Production
 
[DevOn 2013] Backbone.js로 능동적 M-V 디자인 구현하기
[DevOn 2013] Backbone.js로 능동적  M-V 디자인 구현하기[DevOn 2013] Backbone.js로 능동적  M-V 디자인 구현하기
[DevOn 2013] Backbone.js로 능동적 M-V 디자인 구현하기
 
혁신적인 웹컴포넌트 라이브러리 - Polymer
혁신적인 웹컴포넌트 라이브러리 - Polymer혁신적인 웹컴포넌트 라이브러리 - Polymer
혁신적인 웹컴포넌트 라이브러리 - Polymer
 
자바스크립트 프레임워크 살펴보기
자바스크립트 프레임워크 살펴보기자바스크립트 프레임워크 살펴보기
자바스크립트 프레임워크 살펴보기
 
4-3. jquery
4-3. jquery4-3. jquery
4-3. jquery
 
발렌타인 웨비너 7회 - React를 이용한 웹 앱 개발 살펴보기
발렌타인 웨비너 7회 - React를 이용한 웹 앱 개발 살펴보기발렌타인 웨비너 7회 - React를 이용한 웹 앱 개발 살펴보기
발렌타인 웨비너 7회 - React를 이용한 웹 앱 개발 살펴보기
 
다시보는 Angular js
다시보는 Angular js다시보는 Angular js
다시보는 Angular js
 

En vedette

Front-End 개발의 괜찮은 선택 ES6 & React
Front-End 개발의 괜찮은 선택  ES6 & ReactFront-End 개발의 괜찮은 선택  ES6 & React
Front-End 개발의 괜찮은 선택 ES6 & React지수 윤
 
코드스쿼드 마스터즈세미나 - UI개발자가돼보자
코드스쿼드 마스터즈세미나 - UI개발자가돼보자코드스쿼드 마스터즈세미나 - UI개발자가돼보자
코드스쿼드 마스터즈세미나 - UI개발자가돼보자지수 윤
 
재사용UI 컴포넌트설계
재사용UI 컴포넌트설계재사용UI 컴포넌트설계
재사용UI 컴포넌트설계지수 윤
 
하코사세미나_캔버스 파이그래프 만들기
하코사세미나_캔버스 파이그래프 만들기하코사세미나_캔버스 파이그래프 만들기
하코사세미나_캔버스 파이그래프 만들기정석 양
 
최전방 생존법 - 프론트엔드 개발자로 살아가기
최전방 생존법 - 프론트엔드 개발자로 살아가기최전방 생존법 - 프론트엔드 개발자로 살아가기
최전방 생존법 - 프론트엔드 개발자로 살아가기Hyeonjin Cho
 
퍼블리셔, 프론트엔드개발을 시작하다
퍼블리셔, 프론트엔드개발을 시작하다퍼블리셔, 프론트엔드개발을 시작하다
퍼블리셔, 프론트엔드개발을 시작하다정석 양
 
프론트엔드로 시작하는 웹 개발 방법과 지식들
프론트엔드로 시작하는 웹 개발 방법과 지식들프론트엔드로 시작하는 웹 개발 방법과 지식들
프론트엔드로 시작하는 웹 개발 방법과 지식들Eun Cho
 
웹 Front-End 실무 이야기
웹 Front-End 실무 이야기웹 Front-End 실무 이야기
웹 Front-End 실무 이야기JinKwon Lee
 
WEB Front-End 개발과정 살펴보기
WEB Front-End 개발과정 살펴보기WEB Front-End 개발과정 살펴보기
WEB Front-End 개발과정 살펴보기지수 윤
 
프론트엔드 개발자의 자바스크립트
프론트엔드 개발자의 자바스크립트 프론트엔드 개발자의 자바스크립트
프론트엔드 개발자의 자바스크립트 jeong seok yang
 
AngularJS 2, version 1 and ReactJS
AngularJS 2, version 1 and ReactJSAngularJS 2, version 1 and ReactJS
AngularJS 2, version 1 and ReactJSKenneth Ceyer
 
6주 javaScript 시작하며
6주  javaScript 시작하며6주  javaScript 시작하며
6주 javaScript 시작하며지수 윤
 
초보 개발자를 위한 웹 프론트엔드 개발 101
초보 개발자를 위한 웹 프론트엔드 개발 101초보 개발자를 위한 웹 프론트엔드 개발 101
초보 개발자를 위한 웹 프론트엔드 개발 101Chang W. Doh
 
[124] 하이브리드 앱 개발기 김한솔
[124] 하이브리드 앱 개발기 김한솔[124] 하이브리드 앱 개발기 김한솔
[124] 하이브리드 앱 개발기 김한솔NAVER D2
 
재사용가능한 서비스코드제작
재사용가능한 서비스코드제작재사용가능한 서비스코드제작
재사용가능한 서비스코드제작지수 윤
 
Meteor에서 flow-router / react 사용기
Meteor에서 flow-router / react 사용기Meteor에서 flow-router / react 사용기
Meteor에서 flow-router / react 사용기Haydn Kim
 
[TechDays Korea 2015] 녹슨 C++ 코드에 모던 C++로 기름칠하기
[TechDays Korea 2015] 녹슨 C++ 코드에 모던 C++로 기름칠하기[TechDays Korea 2015] 녹슨 C++ 코드에 모던 C++로 기름칠하기
[TechDays Korea 2015] 녹슨 C++ 코드에 모던 C++로 기름칠하기Chris Ohk
 
Ajax ellen seon_ss
Ajax ellen seon_ssAjax ellen seon_ss
Ajax ellen seon_ssEllen Seon
 
Chapter 14. json
Chapter 14. jsonChapter 14. json
Chapter 14. jsonkidoki
 
Change my perspective designer&developer
Change my perspective designer&developerChange my perspective designer&developer
Change my perspective designer&developerTae Young Lee
 

En vedette (20)

Front-End 개발의 괜찮은 선택 ES6 & React
Front-End 개발의 괜찮은 선택  ES6 & ReactFront-End 개발의 괜찮은 선택  ES6 & React
Front-End 개발의 괜찮은 선택 ES6 & React
 
코드스쿼드 마스터즈세미나 - UI개발자가돼보자
코드스쿼드 마스터즈세미나 - UI개발자가돼보자코드스쿼드 마스터즈세미나 - UI개발자가돼보자
코드스쿼드 마스터즈세미나 - UI개발자가돼보자
 
재사용UI 컴포넌트설계
재사용UI 컴포넌트설계재사용UI 컴포넌트설계
재사용UI 컴포넌트설계
 
하코사세미나_캔버스 파이그래프 만들기
하코사세미나_캔버스 파이그래프 만들기하코사세미나_캔버스 파이그래프 만들기
하코사세미나_캔버스 파이그래프 만들기
 
최전방 생존법 - 프론트엔드 개발자로 살아가기
최전방 생존법 - 프론트엔드 개발자로 살아가기최전방 생존법 - 프론트엔드 개발자로 살아가기
최전방 생존법 - 프론트엔드 개발자로 살아가기
 
퍼블리셔, 프론트엔드개발을 시작하다
퍼블리셔, 프론트엔드개발을 시작하다퍼블리셔, 프론트엔드개발을 시작하다
퍼블리셔, 프론트엔드개발을 시작하다
 
프론트엔드로 시작하는 웹 개발 방법과 지식들
프론트엔드로 시작하는 웹 개발 방법과 지식들프론트엔드로 시작하는 웹 개발 방법과 지식들
프론트엔드로 시작하는 웹 개발 방법과 지식들
 
웹 Front-End 실무 이야기
웹 Front-End 실무 이야기웹 Front-End 실무 이야기
웹 Front-End 실무 이야기
 
WEB Front-End 개발과정 살펴보기
WEB Front-End 개발과정 살펴보기WEB Front-End 개발과정 살펴보기
WEB Front-End 개발과정 살펴보기
 
프론트엔드 개발자의 자바스크립트
프론트엔드 개발자의 자바스크립트 프론트엔드 개발자의 자바스크립트
프론트엔드 개발자의 자바스크립트
 
AngularJS 2, version 1 and ReactJS
AngularJS 2, version 1 and ReactJSAngularJS 2, version 1 and ReactJS
AngularJS 2, version 1 and ReactJS
 
6주 javaScript 시작하며
6주  javaScript 시작하며6주  javaScript 시작하며
6주 javaScript 시작하며
 
초보 개발자를 위한 웹 프론트엔드 개발 101
초보 개발자를 위한 웹 프론트엔드 개발 101초보 개발자를 위한 웹 프론트엔드 개발 101
초보 개발자를 위한 웹 프론트엔드 개발 101
 
[124] 하이브리드 앱 개발기 김한솔
[124] 하이브리드 앱 개발기 김한솔[124] 하이브리드 앱 개발기 김한솔
[124] 하이브리드 앱 개발기 김한솔
 
재사용가능한 서비스코드제작
재사용가능한 서비스코드제작재사용가능한 서비스코드제작
재사용가능한 서비스코드제작
 
Meteor에서 flow-router / react 사용기
Meteor에서 flow-router / react 사용기Meteor에서 flow-router / react 사용기
Meteor에서 flow-router / react 사용기
 
[TechDays Korea 2015] 녹슨 C++ 코드에 모던 C++로 기름칠하기
[TechDays Korea 2015] 녹슨 C++ 코드에 모던 C++로 기름칠하기[TechDays Korea 2015] 녹슨 C++ 코드에 모던 C++로 기름칠하기
[TechDays Korea 2015] 녹슨 C++ 코드에 모던 C++로 기름칠하기
 
Ajax ellen seon_ss
Ajax ellen seon_ssAjax ellen seon_ss
Ajax ellen seon_ss
 
Chapter 14. json
Chapter 14. jsonChapter 14. json
Chapter 14. json
 
Change my perspective designer&developer
Change my perspective designer&developerChange my perspective designer&developer
Change my perspective designer&developer
 

Similaire à Clean Front-End Development

Deep dive into Modern frameworks - HTML5 Forum 2018
Deep dive into Modern frameworks - HTML5 Forum 2018Deep dive into Modern frameworks - HTML5 Forum 2018
Deep dive into Modern frameworks - HTML5 Forum 2018Kenneth Ceyer
 
GDG DevFest 2017 Seoul 프론트엔드 모던 프레임워크 낱낱히 파헤치기
 GDG DevFest 2017 Seoul 프론트엔드 모던 프레임워크 낱낱히 파헤치기 GDG DevFest 2017 Seoul 프론트엔드 모던 프레임워크 낱낱히 파헤치기
GDG DevFest 2017 Seoul 프론트엔드 모던 프레임워크 낱낱히 파헤치기Kenneth Ceyer
 
overview of spring4
overview of spring4overview of spring4
overview of spring4Arawn Park
 
5-4. html5 offline and storage
5-4. html5 offline and storage5-4. html5 offline and storage
5-4. html5 offline and storageJinKyoungHeo
 
Naver api for android
Naver api for androidNaver api for android
Naver api for androidSangon Lee
 
처음배우는 자바스크립트, 제이쿼리 #4
처음배우는 자바스크립트, 제이쿼리 #4처음배우는 자바스크립트, 제이쿼리 #4
처음배우는 자바스크립트, 제이쿼리 #4성일 한
 
Node.js and react
Node.js and reactNode.js and react
Node.js and reactHyungKuIm
 
Android 기초강좌 애플리캐이션 구조
Android 기초강좌 애플리캐이션 구조Android 기초강좌 애플리캐이션 구조
Android 기초강좌 애플리캐이션 구조Sangon Lee
 
[D2 오픈세미나]5.robolectric 안드로이드 테스팅
[D2 오픈세미나]5.robolectric 안드로이드 테스팅[D2 오픈세미나]5.robolectric 안드로이드 테스팅
[D2 오픈세미나]5.robolectric 안드로이드 테스팅NAVER D2
 
2.Connect Sunshine to the Cloud - 시온고 안드로이드 스터디
2.Connect Sunshine to the Cloud - 시온고 안드로이드 스터디2.Connect Sunshine to the Cloud - 시온고 안드로이드 스터디
2.Connect Sunshine to the Cloud - 시온고 안드로이드 스터디Youngbin Han
 
React 실무활용 이야기
React 실무활용 이야기React 실무활용 이야기
React 실무활용 이야기철민 배
 
Ajax 기술문서 - 김연수
Ajax 기술문서 - 김연수Ajax 기술문서 - 김연수
Ajax 기술문서 - 김연수Yeon Soo Kim
 
7가지 동시성 모델 람다아키텍처
7가지 동시성 모델  람다아키텍처7가지 동시성 모델  람다아키텍처
7가지 동시성 모델 람다아키텍처Sunggon Song
 
웹개발자가 알아야할 기술
웹개발자가 알아야할 기술웹개발자가 알아야할 기술
웹개발자가 알아야할 기술jaypi Ko
 
Meteor React Tutorial 따라하기
Meteor React Tutorial 따라하기Meteor React Tutorial 따라하기
Meteor React Tutorial 따라하기Jiam Seo
 

Similaire à Clean Front-End Development (20)

Deep dive into Modern frameworks - HTML5 Forum 2018
Deep dive into Modern frameworks - HTML5 Forum 2018Deep dive into Modern frameworks - HTML5 Forum 2018
Deep dive into Modern frameworks - HTML5 Forum 2018
 
Redux
ReduxRedux
Redux
 
GDG DevFest 2017 Seoul 프론트엔드 모던 프레임워크 낱낱히 파헤치기
 GDG DevFest 2017 Seoul 프론트엔드 모던 프레임워크 낱낱히 파헤치기 GDG DevFest 2017 Seoul 프론트엔드 모던 프레임워크 낱낱히 파헤치기
GDG DevFest 2017 Seoul 프론트엔드 모던 프레임워크 낱낱히 파헤치기
 
pjax
pjaxpjax
pjax
 
overview of spring4
overview of spring4overview of spring4
overview of spring4
 
5-4. html5 offline and storage
5-4. html5 offline and storage5-4. html5 offline and storage
5-4. html5 offline and storage
 
Naver api for android
Naver api for androidNaver api for android
Naver api for android
 
처음배우는 자바스크립트, 제이쿼리 #4
처음배우는 자바스크립트, 제이쿼리 #4처음배우는 자바스크립트, 제이쿼리 #4
처음배우는 자바스크립트, 제이쿼리 #4
 
Nodejs express
Nodejs expressNodejs express
Nodejs express
 
Node.js and react
Node.js and reactNode.js and react
Node.js and react
 
Android 기초강좌 애플리캐이션 구조
Android 기초강좌 애플리캐이션 구조Android 기초강좌 애플리캐이션 구조
Android 기초강좌 애플리캐이션 구조
 
[Codelab 2017] ReactJS 기초
[Codelab 2017] ReactJS 기초[Codelab 2017] ReactJS 기초
[Codelab 2017] ReactJS 기초
 
[D2 오픈세미나]5.robolectric 안드로이드 테스팅
[D2 오픈세미나]5.robolectric 안드로이드 테스팅[D2 오픈세미나]5.robolectric 안드로이드 테스팅
[D2 오픈세미나]5.robolectric 안드로이드 테스팅
 
2.Connect Sunshine to the Cloud - 시온고 안드로이드 스터디
2.Connect Sunshine to the Cloud - 시온고 안드로이드 스터디2.Connect Sunshine to the Cloud - 시온고 안드로이드 스터디
2.Connect Sunshine to the Cloud - 시온고 안드로이드 스터디
 
React 실무활용 이야기
React 실무활용 이야기React 실무활용 이야기
React 실무활용 이야기
 
Swt J Face 2/3
Swt J Face 2/3Swt J Face 2/3
Swt J Face 2/3
 
Ajax 기술문서 - 김연수
Ajax 기술문서 - 김연수Ajax 기술문서 - 김연수
Ajax 기술문서 - 김연수
 
7가지 동시성 모델 람다아키텍처
7가지 동시성 모델  람다아키텍처7가지 동시성 모델  람다아키텍처
7가지 동시성 모델 람다아키텍처
 
웹개발자가 알아야할 기술
웹개발자가 알아야할 기술웹개발자가 알아야할 기술
웹개발자가 알아야할 기술
 
Meteor React Tutorial 따라하기
Meteor React Tutorial 따라하기Meteor React Tutorial 따라하기
Meteor React Tutorial 따라하기
 

Plus de 지수 윤

개발자를 알아보자.
개발자를 알아보자.개발자를 알아보자.
개발자를 알아보자.지수 윤
 
크로스브라우징
크로스브라우징크로스브라우징
크로스브라우징지수 윤
 
WEBUI Advanced중간시험
WEBUI Advanced중간시험WEBUI Advanced중간시험
WEBUI Advanced중간시험지수 윤
 
비동기와 이벤트큐 수업자료
비동기와 이벤트큐 수업자료비동기와 이벤트큐 수업자료
비동기와 이벤트큐 수업자료지수 윤
 
JavaScript OOP Pattern
JavaScript OOP PatternJavaScript OOP Pattern
JavaScript OOP Pattern지수 윤
 
JS특징(scope,this,closure)
JS특징(scope,this,closure)JS특징(scope,this,closure)
JS특징(scope,this,closure)지수 윤
 
JavaScript Debugging (수업자료)
JavaScript Debugging (수업자료)JavaScript Debugging (수업자료)
JavaScript Debugging (수업자료)지수 윤
 
JavaScript Debugging (동영상강의자료)
JavaScript Debugging (동영상강의자료)JavaScript Debugging (동영상강의자료)
JavaScript Debugging (동영상강의자료)지수 윤
 
더 나은 SW프로젝트를 위해
 더 나은 SW프로젝트를 위해 더 나은 SW프로젝트를 위해
더 나은 SW프로젝트를 위해지수 윤
 
9주 DOM & Event Advanced
9주  DOM & Event Advanced9주  DOM & Event Advanced
9주 DOM & Event Advanced지수 윤
 
7주 JavaScript Part2
7주 JavaScript Part27주 JavaScript Part2
7주 JavaScript Part2지수 윤
 
7주 JavaScript Part1
7주 JavaScript Part17주 JavaScript Part1
7주 JavaScript Part1지수 윤
 
10주 ajax 실습
10주 ajax 실습10주 ajax 실습
10주 ajax 실습지수 윤
 
8주 dom & event basic
8주  dom & event basic8주  dom & event basic
8주 dom & event basic지수 윤
 
8주 dom & event basic 실습
8주  dom & event basic 실습8주  dom & event basic 실습
8주 dom & event basic 실습지수 윤
 
9주 dom & event advanced 실습
9주  dom & event advanced 실습9주  dom & event advanced 실습
9주 dom & event advanced 실습지수 윤
 
9주 dom & event advanced
9주  dom & event advanced9주  dom & event advanced
9주 dom & event advanced지수 윤
 

Plus de 지수 윤 (20)

HTML,CSS Next
HTML,CSS NextHTML,CSS Next
HTML,CSS Next
 
개발자를 알아보자.
개발자를 알아보자.개발자를 알아보자.
개발자를 알아보자.
 
크로스브라우징
크로스브라우징크로스브라우징
크로스브라우징
 
WEBUI Advanced중간시험
WEBUI Advanced중간시험WEBUI Advanced중간시험
WEBUI Advanced중간시험
 
비동기와 이벤트큐 수업자료
비동기와 이벤트큐 수업자료비동기와 이벤트큐 수업자료
비동기와 이벤트큐 수업자료
 
JavaScript OOP Pattern
JavaScript OOP PatternJavaScript OOP Pattern
JavaScript OOP Pattern
 
JS특징(scope,this,closure)
JS특징(scope,this,closure)JS특징(scope,this,closure)
JS특징(scope,this,closure)
 
JavaScript Debugging (수업자료)
JavaScript Debugging (수업자료)JavaScript Debugging (수업자료)
JavaScript Debugging (수업자료)
 
JavaScript Debugging (동영상강의자료)
JavaScript Debugging (동영상강의자료)JavaScript Debugging (동영상강의자료)
JavaScript Debugging (동영상강의자료)
 
CSS Layout
CSS LayoutCSS Layout
CSS Layout
 
더 나은 SW프로젝트를 위해
 더 나은 SW프로젝트를 위해 더 나은 SW프로젝트를 위해
더 나은 SW프로젝트를 위해
 
9주 DOM & Event Advanced
9주  DOM & Event Advanced9주  DOM & Event Advanced
9주 DOM & Event Advanced
 
7주 JavaScript Part2
7주 JavaScript Part27주 JavaScript Part2
7주 JavaScript Part2
 
7주 JavaScript Part1
7주 JavaScript Part17주 JavaScript Part1
7주 JavaScript Part1
 
10주 ajax
10주 ajax10주 ajax
10주 ajax
 
10주 ajax 실습
10주 ajax 실습10주 ajax 실습
10주 ajax 실습
 
8주 dom & event basic
8주  dom & event basic8주  dom & event basic
8주 dom & event basic
 
8주 dom & event basic 실습
8주  dom & event basic 실습8주  dom & event basic 실습
8주 dom & event basic 실습
 
9주 dom & event advanced 실습
9주  dom & event advanced 실습9주  dom & event advanced 실습
9주 dom & event advanced 실습
 
9주 dom & event advanced
9주  dom & event advanced9주  dom & event advanced
9주 dom & event advanced
 

Clean Front-End Development

  • 3. Intro 오늘 이야기는 이쯤에 맞춥니다 IE6 Modern Browser vanilla Full Framework static Web page SPA
  • 8. Frameworks 의 불편함 우량한 아이들 새로운 아이들 예측하기 어려운 미래 전략 병주고 약주고..
 (SPA + Server-side rendering?) 브라우저 지원범위. 커뮤니티, 문서화, 생태계, 급격한 변화 다양한 Syntax와 Pattern 이 존재 새로운 Learning costs Intro 공통적으로
  • 9. On January 12, 2016 Microsoft announced end of support for IE10, IE9, and IE8. > Progressive Enhancement 전략과 함께 CSS3, ES 최신 버전의 사용도 가능 주변은, Intro Mobile Web Browser 의 꾸준한성장 > static view 중심의 서비스 > data 처리보다는 seamless한 animation 처리가 더 중요 ES2015,ES2016,ES2017 (thanks to jQuery, underscor, lodash) > 다양한 readable syntax 제공. 다양한 라이브러리와의 이별 Standard transpilers (not Typescript, coffeeScript, JSX) with Builders > ES를 더 땡길 수 있는 기회!
  • 10. 우리 서비스는 지속가능해야 한다 성능을 깊게 개선할 수 있어야 한다 동료가 쉽게 이해할 수 있는 코드를 구현해야 한다 다양한 환경에서 동작가능해야 한다 항상 더 좋은 UX를 고민하자 jQuery 개발자보단 Front-end 개발자가 되면 좋겠다 한편, FE개발자의 본능적 미션 ! Intro “ ”
  • 11. standard Code, with all tools 이런 전략은 어떨까? Intro standard Code, with all tools
  • 12. “Polyfill, Transpiler" based Architecture transpiling ES6 based service codes ES5 Codes Polyfills Utilities codes Production code Intro
  • 13. FUTURE ! Intro transpiling ES6 based service codes ES5 Codes Polyfills Utilities codes Production code
  • 15. <!-- jQuery --> <script src="vendor/jquery/jquery.min.js"></script> <!-- Bootstrap Core JavaScript --> <script src="vendor/bootstrap/js/bootstrap.min.js"></script> <!-- Plugin JavaScript --> <script src=“vender/jquery/jquery.easing.min.js”></script> <!-- Theme JavaScript --> <script src="js/agency.min.js"></script> 간단한 modal control, scroll effect 에 필요한 JavaScript 파일들 jQuery Free
  • 16. Scroll 효과 정도는 Vanilla로 충분 let mainNav = document.querySelector(“#mainNav"); window.addEventListener("scroll", (evt) => { let currentScrollY = window.pageYOffset; if(currentScrollY > MY_STATIC.SCROLL_TOP_CHANGE) { if(DOWNMODE) return; mainNav.classList.add("affix"); DOWNMODE = true; } else { mainNav.classList.remove("affix"); DOWNMODE = false;; } }); jQuery Free let mainNav = document.querySelector(“#mainNav"); window.addEventListener("scroll", (evt) => { let currentScrollY = window.pageYOffset; if(currentScrollY > MY_STATIC.SCROLL_TOP_CHANGE) { if(DOWNMODE) return; mainNav.classList.add("affix"); DOWNMODE = true; } else { mainNav.classList.remove("affix"); DOWNMODE = false;; } }); demo
  • 17. Event Delegation el.addEventListener("click", (evt) => { evt.preventDefault(); let ellink = evt.target.closest(".portfolio-link"); if(!ellink) return; let sHTML = this.myAsync.execAsyncAwait(ellink("href").substring(1)); document.querySelector("footer").insertAdjacentHTML('afterend', sHTML); }); jQuery Free Element.closest, matches 메서드만 잘써도 :-)
  • 18. 은근 다 있다 new XMLHttpRequest() xhr.addEventListener document.createElement setAttribute getElementsByTagName requestAnimationFrame getBoundingClientRect Object.prototype.toString.call JSON.parse bind JSON.stringify unshift splice Object.keys forEach isArray Date.now evt.stopPropagation Math.round parseInt cloneNode insertBefore appendChild localStorage.setItem evt.changedTouches[0].pageY querySelector jQuery Free
  • 19. jQuery Free if(bMouseEvent) { pageX = evt.pageX; pageY = evt.pageY; } else { pageX = evt.changedTouches[0].pageX; pageY = evt.changedTouches[0].pageY; } this.nStartPosX = Math.floor(pageX); this.nStartPosY = Math.floor(pageY); this.nStartTranslateX = _cu.getTranslate3dX(this.elTarget); this.nTouchStartTime = Date.now(); } handlerTouchMove(evt) { evt.stopPropagation(); if(this.bAnimationing) return; if(!this.bSwipe) return; let bMouseEvent = evt.type.substr(0,5) === "mouse"; let htCurrentEvt = (bMouseEvent) ? evt : evt.changedTouches[0]; this.nMovePosX = Math.floor(htCurrentEvt.pageX); this.nMovePosY = Math.floor(htCurrentEvt.pageY); …. Mobile Web & Vanilla 자연스럽다
  • 20. DOM Append Performance var $c = $("<div />").addClass("container"); for (var i=0; i<10000; i++) { $c.append($("<div />").addClass("test-div")); } $("BODY").append($c); 432.524ms var c = document.createDocumentFragment(); for (var i=0; i<10000; i++) { var e = document.createElement("div"); e.className = "test-div"; c.appendChild(e); } document.body.appendChild(c); 16.237ms https://howchoo.com/g/mmu0nguznjg/learn-the-slow-and-fast-way-to-append-elements-to-the-dom jQuery Pure JavaScript jQuery Free
  • 21. https://medium.com/the-vue-point/vue-2-0-is-here-ef1f26acf4b8#.7rbhdnuyp rendering layer benchmark Oct,1,2016 by VueJS DOM rendering layer performance jQuery Free
  • 22. jQuery Plugin vanillaJS Component 최근 5년간 jQuery Plugin Trend jQuery Free
  • 23. Clean jQuery Free VanillaJS는 더 지속 가능한 코드다. 모바일웹에서 VanillaJS는 훌륭한 조합. PC에서도 polyfill을 잘 활용하며 jQuery Free를! pure DOM API가 대부분 상황에서는 가장 빠르다. jQuery Free
  • 25. Modules import (ES2015) import { member } from "module-name"; export default function (…) { … } good-bye AMD API (Require.js)..
  • 26. CLASS import tc from '../lib/TabComponent.js'; class MyAsync{ constructor() { this.name = "xhr"; } simpleFetch(url) { return new Promise(function(resolve, reject) { var req = new XMLHttpRequest(); req.addEventListener("load", function() { let sData = JSON.parse(req.responseText); if(typeof sData !== "object") reject("wrong data"); else resolve(sData); }); req.open("GET", url); req.send(); }); } Modules
  • 27. Code scroll effect코드를 import, export로 모듈화 Modules
  • 28. Clean Modules Use Class & Import & Export !! Modules
  • 30. Two way binding Two-way data binding 데이터가 변경될때, UI를 변경 UI가 변경될때, 데이터를 변경
  • 31. Two way binding Dirty Checking (digest cycle) 작은 변화에 과한 렌더링. 지속적인 CPU 부하 Proxy (ES2015) Interception API
  • 32. Two way binding let msgData = {}; let elMessage = document.getElementById("message"); let msgProxy = new Proxy(msgData, { get: function(target, name, receiver) { return target[name]; }, set: function(obj, prop, value) { obj[prop] = value; elMessage.value = value; document.getElementById("text-count").textContent = value.length; return true; } }); elMessage.addEventListener("input", (evt)=>{ msgProxy.content = evt.target.value; }); Proxy
  • 33. Two way binding 그런데 Proxy는 좀더 걸릴 듯 하다.. babel polyfill 로도 지원하지 않는 중
  • 34. Two way binding Simple Accessor ES5 getter/setter 통해 비교적 간단히 구현가능. Object.defineProperty(obj, prop, descriptor)
  • 35. Two way binding bindModel(obj, property, elView, fnCallback) { Object.defineProperty(obj, property, { get: function() { return elView.value; }, set: function(newValue) { elView.value = newValue; fnCallback(newValue); }, configurable: true }); } Simple Accessor
  • 36. Two way binding demo Data binding using ‘bindModelInput’
  • 37. Two way binding Clean Two-way data binding Two-way data binding은 framework에서만 가능한 건 아님. Proxy API를 지켜보자. 간단한 data binding은 defineProperty 로 간단히 처리!
  • 39. simpleAjax("../data/first.json", function(data) { try { var name = data.user.name; var imgUrl = "../data/img/" + name + ".json"; simpleAjax(imgUrl, function(data2) { try { setTimeout(function(){ try { var aImage = data2.images; aImage.forEach((v) => logMsg(elLog,v)); } catch (err) { console.log('error 3' , err ); } },500); } catch (err) { console.log('error 2' , err ); } }); } catch (err) { console.log("error 1: ", err); } }); Asynchronous 가끔 브라우저에서도 Hell
  • 40. Asynchronous 다행인지, Pure JavaScript에서는 그 해법이 쏟아져 나옴. > Synchronous-looking style
  • 41. Asynchronous Promise A+ • 비동기 로직에서 콜백의 분리 • thenable • async의 밑바탕 기술 function simpleFetch(url) { return new Promise(function(resolve, reject){ var req = new XMLHttpRequest(); req.addEventListener("load", function() { let htData = JSON.parse(req.responseText); if(typeof htData !== "object") reject("wrong data"); else resolve(htData); }); req.open("GET", url); req.send(); }); } simpleFetch("../data/first.json") .then(function(data) { var name = data.user.name; var imgUrl = "../data/img/" + name + ".json"; return simpleFetch(imgUrl); }) .then(function(data2) { return simpleSetTimeoutPromise(500,data2); }) .then(function(data3) { let elLog = document.querySelector(".log"); let aImage = data3.images; aImage.forEach((v) => logMsg(elLog,v)); }) .catch(function(err){ console.log("error : " + err); })
  • 42. Asynchronous generator/yield 딱 비동기 문제를 위한 것만은 아니다. Promise와 조합하는게 좋고, 단, generator를 조정하는 역할을 하는 코드를 구현 함(runner) function *myGeneratorWithPromise() { try { var data = yield simpleFetch("../data/first.json"); var url2 = "../data/img/" + data.user.name + ".json"; var data2 = yield simpleFetch(url2); var aImage = data2.images; //do something.. } //code : https://davidwalsh.name/async-generators. function runGenerator(g) { var it = g(), ret; (function iterate(val){ ret = it.next( val ); if (!ret.done) { if (typeof ret.value === "object" && ("then" in ret.value)) { ret.value.then( iterate ); } else { setTimeout( function(){ iterate( ret.value ); }, 0 ); } } })(); } fnlist.generatorAndPromise = function() { runGenerator(myGeneratorWithPromise); }
  • 43. Asynchronous wow! async/await ! 뭐 이건…좋다. async 함수는 promise를 반환한다는 점을 주의 ES2017 이라는 소문 +.+ 하지만 Babel과 함께라면 당장! (generator 로 변환) fnlist.asyncAwait = async function () { try { var data = await simpleFetch("../data/ first.json"); var url2 = "../data/img/" + data.user.name + ".json"; var data2 = await simpleFetch(url2); var aImage = data2.images; //parallel task using Promise.all function. var data3 = await Promise.all([ simpleSetTimeoutPromise(100, aImage), simpleSetTimeoutPromise(500, "dummy"), simpleSetTimeoutPromise(1000, "dummy"), ]); var elLog = document.querySelector(".log"); data3[0].forEach((v) => logMsg(elLog,v)); } catch (err) { console.log("error during myGenerator : ", err); } } } thanks to WebPack&Babel
  • 44. Asynchronous observable (rx.js) 아.. 음.. functional programming의 필요성 진심 느끼는 분들께. var chainPromise = Rx.Observable.just('../data/first.json') .flatMap(simpleFetch) .map( (x) => { return ("../data/img/" + x.user.name +".json")}) .flatMap(simpleFetch) .delay(500) .subscribe((x) => { let elLog = document.querySelector(".log"); let aImage = x.images; aImage.forEach((v) => logMsg(elLog,v)); }); thanks to WebPack&Babel
  • 45. Asynchronous Clean Asynchronous 그럭저럭 콜백 지옥 상황에선, > 콜백 몸체를 분리하는 정도만으로 충분 빈번한 콜백 지옥이라면, > async,await 와 같은 다양한 방법으로 코드를 clean하게 구현
  • 47. Pure Templating Engine var templateRunner = function(sHtml){ return function(oData){ for(var value in oData){ var re = "{%s?" + value + “s?%}"; sHtml = sHtml.replace(new RegExp(re, "ig"), oData[value] } return sHtml; }; }; simple ! Templating
  • 48. 서비스 logic 은 clean하게 유지. Template HTML은 쉽게 관리. PreCompile 로 좀더 갈끔하게 template html template html template html PreCompile [Build Step] template function [Service Step] 복잡한 상황에서는 ? Templating
  • 49. PreCompile loaders: [ { test : /-tpl.hbs$/, loader : 'handlebars' }, … Webpack handlebar-loader Templating
  • 50. Templating with ES2015 Modules var listTpl = require('/template/portfolioModal-tpl.hbs'); listTpl( { name: ‘hello codeSquad' } ); import modalTpl from '/template/portfolioModal-tpl.hbs'; listTpl( { name: ‘hello codeSquad' } ); Templating
  • 51. Clean Templating 간단한 templating 은 replace 로 간단히 구현 복잡한 작업에서는 로직과 html을 잘 분리 Templating
  • 52. Virtual DOM view 처리의 또다른 해법
  • 53. VIEW조작의 복잡도를 해결하기 위해 virtual DOM 이 필요하고, 그래서 React를 써야 한다며? Virtual DOM > 일단, Virtual DOM 자체가 pure DOM보단 항상 빠른 건 아니다.
  • 54. https://vdom-benchmark.github.io/vdom-benchmark/ virtual DOM은 React가 짱인가? simple한 virtual DOM 라이브러리가 2~3배 빠르다 Virtual DOM
  • 55. <ul className=”list”> <li>item 1</li> <li>item 2</li> </ul> h(‘ul’, { className: ‘list’ }, h(‘li’, {}, ‘item 1’), h(‘li’, {}, ‘item 2’), ); 참고, Virtual DOM 만들기 과정 JSX Transpiled code JavaScript Object thanks to WebPack&Babel Virtual DOM { type: ‘ul’, props: { className: ‘list’ }, children: [ { type: ‘li’, props: {}, children: [‘item 1’] }, { type: ‘li’, props: {}, children: [‘item 2’] } ] }
  • 56. function renderMaquette() { return h("ul.ul-wrap", [ aData.map(function(value, index) { return h("li" , [ h("span", [""+ value]) ]); }) ]); } projector.replace(domNode, renderMaquette); template library 와 비스무리. Virtual DOM Simple VD example(maquette.js)
  • 58. Clean Virtual DOM VD는 성능이 분명 빠를 때 사용하기 사용해야하는 경우 코드의 복잡도는 더 올라갈 수 있음. 가벼운 VD 라이브러리가 좋은 선택지가 될 수 있음. Virtual DOM
  • 60. MODAL Loose Coupling XHR JSONP Local Storage 의존성있는 동일한 행위의 Class들과의 관계 느슨하게 유지하기 XHR JSONP Local Storage Loose Coupling
  • 61. let dependencyContainer = { modalDependency : { storagePlugin : new XHR(), otherPlugin : new MyAsync() } } let oModal = new Main(dependencyContainer.modalDependency); Loose Coupling 조금 아쉬움이 있다 직접 class를 쓴 거랑 큰 차이는 안나고, Lazy instantiation 이 안되고. Static Dependency Injection
  • 62. Loose Coupling Register1 {XHR, Other2} new mainClass(...aDepClassInstance) getInstance2 Injection3 DI Factory XHR JSONP Local Storage Other1 Other2 Other3 Dependencies Class XHR Other2 Main Class Dependency Injection
  • 63. Loose Coupling class Service { constructor(storagePlugin, otherPlugin) { this.storagePlugin = storagePlugin; this.otherPlugin = otherPlugin; } getStorageData() { return this.storagePlugin.getData(); } getOtherData() { return this.otherPlugin.getData(); } } Main Class Dependency Injection 의존성 있는 Class과의 관계는 느슨하다.
  • 64. Loose Coupling //register depedencies let myDI = new DIFactory(); myDI.register('xhr', XHR); myDI.register('jsonp', JSONP); myDI.register('other', Other); //dependency injection let cInstance = myDI.getInstance(Service, ["xhr","other"]); console.log(cInstance.getStorageData()); Service code Dependency Injection Dependency 관계를 미리 정의하고, 인스턴스를 나중에 생성
  • 65. Loose Coupling class DIFactory { constructor() { this.matching = {}; } register(name, dClass) { this.matching[name] = new dClass(); } getInstance(mainClass, aDepClass) { let aDepClassInstance = aDepClass.map((v) => { return this.matching[v]; }); return new mainClass(...aDepClassInstance); } } DI Factory 이렇게 처리하기 위해 필요한 DI Factory 는 겨우 이정도
  • 67. Register function User custom function subscribe publish ‘FN_AFTER_FOCUS’ ‘FN_AFTER_SUBMIT’ Remove methods of Dependencies. Resuable Codes Plugin function Emit Event Plugin function Loose Coupling Custom Function & Event Driven
  • 68. Resuable Codes Common Component AA Component BB Component CC Component A-1 plugin A-2 plugin B-1 plugin B-2 plugin C-1 plugin C-2 plugin utility library Component의 공통 기능 option 설정 plugin 등록 모든 파일에서 참고하는 유틸리티 메서드 animation 처리 css 속성 추가 null 체크 .. Components 해당 component에 필요한 기능 Plugins option으로 제공되는 추가기능. LooseCoupling -> Resuable Component ! Loose Coupling
  • 69. Clean Loose Coupling Dependency를 줄이는 패턴은 어렵고 복잡할 필요는 없다. 간단한 방법도 있다. 커다란 Framework에서만 구현 가능한 것도 아니다. 다양하게 구현된 Module, Component 상황에 최적의 방법이 무엇인지 고민하기 Loose Coupling
  • 70. 사용된 코드는 여기, https://github.com/nigayo/cleanfe Async 코드는 여기, https://github.com/nigayo/javascript-async
  • 72. Without gulp or grunt only NPM ! NPM Builds "scripts": { "test": "echo "Error: no test specified" && exit 1", "uglify": "mkdir -p dist/js && uglifyjs src/js/A.js src/js/B.js -m -o dist/js/all.min.js", "watch:js" : "onchange 'src/js/*.js' -- npm run uglify" }, NPM Scripts 간단하다면 npm build 만으로도 충분하다!
  • 73. "scripts": { "build": "webpack" }, entry: { 'script': ['babel-polyfill', './docs/js/main.js'], 'style': './docs/less/agency.less' }, watch: true, debug: true, devtool: 'source-map', module: { loaders: [ { test: /.es6$/, exclude: /node_modules/, loader: "babel-loader", query: { presets: ['es2015', 'stage-3'] } }, { test: /.(ttf.*|eot.*|woff.*|ogg|mp3|html)$/, loader: 'file-loader' }, { test: /.(png|jpe?g|gif|svg.*)$/, loader: 'file-loader!img-loader' }, webpack.configNPM Scripts Without gulp or grunt NPM + Webpack NPM Builds
  • 74. Clean Build tools NPM Scripts 나 Webpack 만으로도 clean build환경을. Resuable Codes
  • 75. Standard code with all tools, 사용자에게 더 좋은 UX를 제공하고, 개발에서 또 다른 즐거움을 느끼길 바랍니다 :-) 마무리 그리고, 앞으로 더 많은 분들과 함께, 이런 고민을 하게 되길 바라겠습니다 윤지수, codesquad crong@codesquad.kr