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
“
”
23. Clean jQuery Free
VanillaJS는 더 지속 가능한 코드다.
모바일웹에서 VanillaJS는 훌륭한 조합.
PC에서도 polyfill을 잘 활용하며 jQuery Free를!
pure DOM API가 대부분 상황에서는 가장 빠르다.
jQuery Free
37. Two way
binding
Clean Two-way data binding
Two-way data binding은 framework에서만 가능한 건 아님.
Proxy API를 지켜보자.
간단한 data binding은 defineProperty 로 간단히 처리!
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
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
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
75. Standard code with all tools,
사용자에게 더 좋은 UX를 제공하고,
개발에서 또 다른 즐거움을 느끼길 바랍니다 :-)
마무리
그리고, 앞으로 더 많은 분들과 함께,
이런 고민을 하게 되길 바라겠습니다
윤지수, codesquad
crong@codesquad.kr