블로그 이미지
윤영식
Full Stacker, Application Architecter, KnowHow Dispenser and Bike Rider

Publication

Category

Recent Post

2016. 10. 23. 22:59 Angular/Concept

Angular v2가 정식 릴리즈되었다. Angular v1 은 Two-way data-binding 이라는 독특한 특징으로 인해 많은 사용자 층을 확보했지만 장점 만큼이나 성능상의 단점도 존재했었다. 또한 처음엔 쉬운듯 하면서 좀 더 깊게 들어가볼려고 하면 학습곡선이 갑자기 껑충뛰기도 했다. 가장 많이 사용했던 Directive(지시자)가 대표적이다. 많은 개발자가 만들어 놓은 지시자를 쉽게 가져다 쓸 수는 있지만 직접 만들어 애플리케이션에 접목하려 할 때 첫 문턱을 만나게 된다. 그리고 jQuery사용에 익숙한 개발자에게 Angular v1 시점상의 차이로 Angular v1 방식의 개발패턴을 요구하기도 했다. 관성은 무섭다. 기존에 사용하던 방식을 버리고 Angular v1에 맞춰서 애플리케이션을 만들어 가기란 곤혹스럽다. Angular v2 또한 그런 인식의 전환을 요구할까? 그렇다 그리고 아니다. 






웹 애플리케이션 흐름

웹 애플리케이션 개발을 위해 우리가 사용하는 jQuery같은 라이브러리나 Angular, Backbone같은 프레임워크의 가장 1차적인 목적은 무엇일까? 나는 Data Projection이라 생각한다. 데이터를 화면에 출력하기 위해 DOM을 얼마나 쉽게 조작하고 상호 작용할 수 있느냐가 선택의 기준이라 생각한다. Data Projection을 일관되고 확장가능하고 배포가능하게 하는 방식으로 기술은 발전해 왔고, 현재는 화면에 대한 제어방식이 컴포넌트 기반 방식으로 발전해 오고 있다. 


Data Projection의 역사를 보면 초장기엔 Server Side Rendering 를 사용해 웹 애플리케이션을 개발했다. 예로 JSP, PHP, ASP 같이 서버 미들웨어서 데이터를 조회하고 HTML을 조작하여 결과 HTML을 브라우져에 전송하던 시대이다. 




1세대에는 AJAX가 나오고 다양한 라이브러리나 프레임워크가 나왔다. 이때는 데이터변경에 대한 DOM반영이 서버에서 클라이언트 개발자의 몫으로 넘어오게 되었다. 즉, 직접 DOM 을 얻어와서 특정 위치에 넣어 주어야 했고, DOM에서 발생하는 이벤트를 Listening해서 처리하고 DOM에 반영하는 모든 작업이 웹 개발자가 직접 코딩하던 단계였다. Java의 프레임워크 역사로 보면 Struts 로 비유할 수 있지 않을까 싶다. 




2세대로 넘어오게 되면 Model을 DOM 에 반영하는 방식은 자동화 된다. 여기에 대표적인 프레임워크가 Ember 와 Angular v1 이다. 이때 부터 Single Page Application (SPA) 개발이라는 용어가 나오게 된다. URI 변경에 대한 대응으로 Routing  개념이 나오고, Data Projection후 원하는 일부 DOM을 변경하는 역할이 프레임워크로 넘어갔고, 웹 개발자는 좀 더 애플리케이션 비즈니스 로직에 집중토록 만들었다. Java 프레임워크로 비유하자면 Struts와 Spring Framework 초기버전의 중간 지대 정도 쯤이라 생각한다.  이때부터 Frontend (프론트앤드)라는 직군이 웹 개발자와 분리되기 시작한 지점이라 생각한다. 이에 대한 자세한 설명은 태곤님이 작성한 "[번역] 프론트엔드 개발자는 왜 구하기 어렵나요?"를 참조하자. 2011년을 기점으로 2013년 웹 애플리케이션 프레임워크가 정착을 해가는 시기였고, 현재는 대부분의 스타트업이나 중견기업에서 2세대 웹 애플리케이션 프레임워크를 선택할 경우 프론트엔드 개발자와 백앤드 개발자를 구분하여 팀을 구성하고 있는 추세이다.





3세대는 2세대의 과도기를 거쳐 2세대의 장점을 흡수 하면서 성능상의 이슈를 해결하고, 점점 복잡해 지고있는 웹 애플리케이션을 보다 직관적이고 쉽게 개발할 수 있게 노력하고 있다. 대표적인 프레임워크로는 Facebook의 React와 Google의 Angular v2 (이하 Angular)이다. Angular는 Component기반 개발 방식으로 표준인 Web Components를 지원하며 Typescript를 기본 언어로 채택했다. Typescript는 Type 시스템을 제공하기 때문에 개발단계에서 버그의 가능성을 쉽게 찾을 수 있도록 도와준다. React와 Angular에 대한 장단점은 손창욱님의 "React보다 Angular v2에 더 주목해야 하는 이유"를 참조하자. Java의 Spring Framework이 성숙하면서 Annotation 같은 기능이 추가되듯, Angular v2 프레임워크는 Java의 Spring 프레임워크 최신버전과 비유할 수 있다. 



Angular v1에 대한 개발 및 컨설팅을 3년 가까이 하면서 올해 초 Angular v2를 공부하고 기존 v1 코드를 v2 코드로 전환하면서 코드 베이스는 50%가량 줄었고, 반응속도는 30%가량 개선되었다. 8명 프론트앤드 개발자와 컨버전을 진행하면서 이구동성으로 말하는 것은 "코드가 직관적으로 변했다. 코드량이 현저히 줄었다. Typescript의 타입체킹으로 인해 실수를 최소화 할 수 있었다" 이다. 



Angular v2 왜 배워야 하는가?

Angular를 왜 배워야 하는가? 답하자면 안배워도 된다. 단순 홈페이지나 업무 화면이라면 쉽고 더 빨리 만들 수 있는 워드프레스나 서비스를 이용하거나 DOM 핸들링 라이브러리나 플러그인을 사용해 개발하는 편이 낫다. 하지만 솔루션의 복잡한 요구사항을 지속적으로 반영해야 하고 DOM제어가 복잡해 질 가능성이 높다면 jQuery, React 같은 라이브러리 보다는 Angular 같은 프레임워크를 선택하는 것이 좋다. 그리고 최근에는 ES2015 표준이 확정되었고 최신 브라우져에 대부분 기능이 구현되고 있다. 2세대와 3세대 Data Projection의 가장 큰 개발 방식의 차이는 ES2015의 이해에서부터 시작한다.  즉, ES2015 문법을 잘 알고 사용하면 좀 더 쉽고 간단하게 코드 베이스를 유지하면서 오류를 최소화할 수 있다. 예로 -> 펑션은 this에 대한 오류를 방지하고, Set/Map등 Collection은 Java의 Collection과 유사한다. 



Angular v2 시작하면 초기에 배워야 하는 것들이 갑자기 늘어난다. 이것은 2세대와 3세대의 개발 패턴이 바뀌었음을 시사한다. ES2015 문법은 그대로 TypeScript에 녹아 있고, Type System과 Annotation 기능이 녹아 들어 더욱 편리한 개발을 가능토록 한다. 따라서 ES2015의 Syntax와 개념을 이해해야 한다. 그리고 Typescript를 다시 공부해야 한다. 또한 요즘 인기를 누리고 있는 Reactive Programming을 표방한 대표적인 라이브러리인 RxJS를 Angular가 근간으로 사용하고 있다. 따라서 RxJS 에 대한 개념과 사용법을 익혀야 한다. 그런후 Web Components 란 무엇인지 알아야 하고, Angular 프레임워크의 아키텍쳐를 구성하는 개념인 Change Detection 동작원리, Dependency Management, Modulization 을 알아야 하고, 다음으로 주변의 Tooling System으로 SystemJS (Webpack), Gulp 등을 알아야 한다. 


이렇게 열거해 보니 참으로 배울 것이 많다. 다시 말하지만 안 배워도 된다. 하지만 자신의 근육을 한단계 업그레이드 시키기 위해 고통스러운 인내의 시간은 필요하다. 배워야 하는 기준은 두가지 정도로 이야기 해본다. 


첫째, 서비스 버전업을 위해 요구사항이 계속 증가하고 있는가?

둘째, 더 적고 직관적인 코드 베이스를 유지하면서 성능을 높이고 싶은가?


 

프론트엔드 개발자 직군이 새롭게 자리잡게된  5년기간 동안 많은 부분이 기존의 백앤드 개발 패턴과 유사해 지고 있다. 모듈 의존성 관리, 빌드 시스템, 프레임워크의 발전은 Java개발자들이 초장기 프레임워크 없이 개발하다 Struts를 만났을 때 기쁨에서 Spring을 만나 자유를 얻었지만 여전히 배워야 할 것들은 더욱 증가했음을 알것이다. 그러나 어쩌겠는가 우리는 더 게을러 지고싶다는 욕구가 있고 프레임워크가 그것을 만족시켜줄것이라는 희망을 품고 있는 한 배움과 진보는 계속될 뿐이다. 



참조


posted by 윤영식
2016. 4. 8. 18:54 Angular/Concept

Angular2 또는 최신 라이브러리를 읽기 위해서는 ES2015 (ES6)에 대한 기본적인 이해가 필요하다. 모질라의 Depth in ES6 번역글과 S65 페북모임에서 얻은 지식을 한 페이지로 정리해 본다. 






let 과 const


기본 var는 함수에 대한 scope(스코프)만을 갖는다. for, {} 블록에 대한 스코프가 없다. var의 대체제가 let 이다. 

  - let은 블럭을 기준으로 스코프를 결정한다. block-scoped

  - 글로벌 let은 없다. 즉 window.xxx 접근이 안된다. 어디간의 블럭안의 스코프에 속한다. 

  - for (let x...) 루프구문에서 x 변수를 새로 바인딩 한다. 

  - let 변수를 선언 전에 참조하는 것은 에러이다. 

  - let, var 충돌시에는 ES2015 모듈패턴을 사용해서 let으로 전환한다. 


const는 최초 값을 할당한 후 재 할당 할 수 없다. 단, 객체의 속성은 가능하다. 변수 중에 불변의 값을 갖는 것은 모두 const로 할당한다. 재 할당이 안된다는 것 외에는 let과 완전히 동일하므로 애플리케이션 상태 관리의 복잡도를 단순화 시켜줄 수 있다. 




class


이제는 OOP(Object Oriented Programming)를 위한 접근이 훨씬 쉬워졌다. Java의 OOP에 익숙한 개발자라면 import, class, super, extends, implements(TypeScript 지원)등을 통해 이전 Prototypal Inheritance의 이해 없이도 쉽게 JavaScript를 이용한 OOP가 가능해 진것이다

class Parent {

   contructor(params) { ... }

   static XXX() { ... }

   YYY() { ... }

   get ZZZ() { ... }

   set ZZZ(value) { ... }

}




Arrow Function


event 또는 XHR 콜백 펑션을 등록할 때 간혹 내부에 this를 사용하면 Global scope를 참조하게 된다. 이때 var that = this; 한 후 that을 넘겨 사용하기도 하는데 이제는 더 이상 그럴 필요가 없다. 자신 Execution Context를 만들지 않고 (function 보다 가볍다) 화살표 함수를 감싸는 외부 스코프의 this 값을 바로 쓸 수 있는 방법이 => 화살표 함수이다. 

$('.button').click(function (event) {

  ...

});


변경

$('.button').click(event => {

  ...

});


한 줄일 경우는 {}을 사용하지 않고 자동 return 구문이 된다. 만일 여러 줄일 경우는 {} 으로 감싼다. 단, 한 줄로 비어있는 객체를 return하고 싶다면 어떻게 해야할까?

arrs.map( item => ({}) ); // 성공

arrs.map( item => {} ); // bug




iterable 과 for~of 구문


배열을 순회(loop)하기 위한 방법으로 ES5의 myArray.forEach(function (value) { ....});를 사용한다. 기존 for ~ in 루프는 확장 속성들도 순회하기 때문에 성능상 이점이 없다. 배열에 만일 myArray.name = 'dowon'을 넣으면 name도 순회하고 prototype chain도 순회한다. 또는 가끔 무작위 순서로 순회하기도 한다. 쇗!! 이에 대한 해결로 for ~ of가 나왔다. 

for (var value of myArray) {

  console.log(value);  // 값이다. for ~ in 처럼 속성의 key가 아니다

}


Array, Map, Set은 순회를 위한 iterator 메소드를 제공한다. 사용자가 원하는 객체에 iterator 객체를 제공할 수 있다. 

  - 어떤 객체든 myObject[Symbol.iterator]() 메소드를 추가하면 자바스크립트에서 해당 객체를 순회할 수 있다. 

  - Duck Typing의 예로 iterator가 있으므로 해당 객체도 순회가 가능하다는 방식이다. 

  - myObject['iterator'] = function () {...} 라고 했고 만일 iterator() 가 이미 있다면 문제가 될 것이다. 이를 위해 제 7원소 Symbol을 사용해 어떤 코드의 key와도 충돌하지 않게 만든다. 

  - [Symbol.iterator]() 메소드를 제공하는 겍체를 이터러블 객체 (iterable object)라고 한다. 

Iterable is a simple representation of a series of elements that can be iterated over. current state만 있고, Iterator제공하는 메소드 하나를 가진다. 

Iterator is the object with iteration state. hasNext(), next()를 통해 다음 엘러먼트로 이동한다. 


iterator는 next를 제공해야 하므로 Symbol을 이용할 경우 다음과 같이 한다. value를 계속 0 만 주무로 무한루프이다. 

var myIterator = {

  [Symbol.iterator]: function() {

    return this;

  },

  next: function() {

    return { done: false, value: 0 } 

  }

}



형식

for ( VAR of ITERALBE ) {

  STATEMENT

}

동등한 코드 

var $iterator = ITERABLE[Symbol.iterator]();

var $result = $iterator.next();

while (!$result.done) {

  VAR = $result.value;

  STATEMENT

  $result = $iterator.next();

}




Collection 


자바스크립트의 Object는 key-value 쌍의 컬렉션이다. 즉 속성을 추가하고 값을 할당할 수 있고 이런 속성의 집합을 객체라 한다. 일반 객체로 해결할 수 없는 자료구조에서 Map, Set을 도입한다. 

  - 속성 key를 객체로 사용하고 싶을 경우 (객체는 key는 문자열만 가능, 단 ES2015에는 Symbol이라는 새로운 타입이 존재한다)

  - 일반 객체는 iterable 하지 않기에 for~of 구문이나, ... 구문을 사용할 수 없다. 


Set은 중복을 제거할 때 사용한다. Value 를 추가하고 삭제하며 동일 Value는 포함 될 수 없기 때문이다. 

  - new Set, new Set(Iterable) : 새로운 set 만들기

  - size, has, add, delete, forEach, clear

  - 다양한 이터레이터를 리턴: keys, values, entries (Map과의 호환성을 제공)

  - set[Symbol.iterator]() 구문은 set안의 값들을 순회할 수 있는 새로운 이터레이터를 리턴한다. 

var uniqueWords = new Set(words);

for (var word of uniqueWords) {

  console.log(word);

}


Map은 key-value 쌍으로 이뤄진다. 순회시 분해(destructuring)을 사용할 수 있다. 

for (var [key, value] of addressMap) {

  console.log(key, ': ', value);


Set, Map의 대용이 없어지지않고 남아있으면 Garbage Collector가 메모리를 회수 할 수 없다. 이애 해결을 위해 WeakSet, WeakMap을 사용한다. 




Symbol


심볼은 ES2015의 7번째 타입이다. 프로그램에서 이름 충돌을 피하고자 객체 속성 키(symbol-keyed property)를 사용하고 싶을 경우 사용한다. 

  - Object.property 처럼 dot(.)로 접근할 수 없고 Object[] 형식으로 접근할 수 있다. 

  - if( MY_SYMBOL in element) 처럼 속성을 참조하거나, delete element[MY_SYMBOL] 처럼 속성을 제거할 수 있다. 

  - MY_SYMBOL은 실행 스코프안에서만 모든 행위가 가능해서 충돌을 걱정할 필요없이 캡슐화를 할 수 있다. 

var MY_SYMBOL = Symbol();

var myObj = {};

myObj[MY_SYMBOL] = "dowon";


사용방법

  - Symbol() 호출: 일반적인 사용 형태, Symbol('name') 과 같이 파라미터를 주는 것은 디버깅을 위한 용도이다. 

  - Symbol.for(string): 심볼을 공유하고 싶을 경우 사용

  - Symbol.iterator: 특정 객체에 대해 Duck Typing으로 iterator를 만들고 싶을 경우 사용 

  - core.js 폴리필을 첨부해야 사용이 가능하다


기본 6가지 타입

  - Undefined

  - Null

  - Boolean

  - Number

  - String

  - Object 




Generator, 2


자바스크립트의 co-routine 이다. 함수가 끝나기전에 자신의 스코프 밖으로 나올 수 없다. 그러나 제너레이터 함수(generator-function)를 만들면 가능해 진다.

  - 제너레이터 함수는 function* 키워드로 시작한다. 

  - 제너레이터 함수안에는 yield 구문이 존재한다. 함수의 return은 한번 실행되지만 yield는 여러번 수행 가능하다. yield는 제너레이터의 실행을 멈췄다가 다음에 다시 시작할 수 있게 만든다. 

function* mygen(name) {

  yield 'hi ' + name;

  yield 'Have a great day';

}


> var iter = myget('dowon');

 [object Generator]

> iter.next();

  'hi dowon'

> iter.next();

  'Have a great day'


제너레이터 함수를 호출하면 제너레이터 객체(generator object)를 전달 받는다. yield첫번째에  실행이 멈춘 상태의 객체이다. .next()를 호출하면 다음 yield까지만 수행한다. yield 구문이 실핼될 때, 제너레이터의 스택 프레임(stack frame: 로컬 변수, 인자, 임시 값, 제너레이터 코드의 실행 위치)은 스택에서 제거된다. 


제너레이터를 통해 이터레이터를 만들 수 있다. 

> Symbol을 통해 만들기: 실행

class RangeIterator {

  constructor(start, stop) {

    this.value = start;

    this.stop = stop;

  }


  [Symbol.iterator]() { return this; }


  next() {

    var value = this.value;

    if (value < this.stop) {

      this.value++;

      return {done: false, value: value};

    } else {

      return {done: true, value: undefined};

    }

  }

}


// 'start'에서 'stop'까지 더해나가는 새로운 이터레이터를 리턴합니다.

function range(start, stop) {

  return new RangeIterator(start, stop);

}


// 수행 

for ( let value of range(0, 5)) {

 console.log(value);

}


> Generator를 통해 만들기: 실행

 - Symbol과 동일한 역할을 하는 이유는 Generator는 .next() 코드와 [Symbol.iterator]() 코드를 내장하고 있기 때문이다. 그냥 루프 처리만 작성하면 된다. 

function* range(start, stop) {

  for (let i=start; i < stop; i++) {

    yield i;

  }

}


// 수행 

for ( let value of range(0, 5)) {

 console.log(value);

}


제너레이터는 객체를 이터러블하게 만들때, 엄청나게 큰 결과를 처리, 복잡한 루프 구문을 리팩토링, 이터러블을 다루는 도구등으로 사용한다. (이부분은 경험이 없어서 이해가 힘들다. 다음기회로..) 제너레이터의 동작은 동기적으로 싱글-쓰레드 환경에서 실행된다. yield에서 멈추고 .next()에서 수행되는 된다. 만일 for ~ of 구문의 경우 iterator 스팩에 따라 수행이 된다.  




Proxy


자바스크립트 스팩 레벨에서 특정 객체에 대한 hooking을 가능케 한다. 

  - 첫번째 인자는 후킹할 객체이다. 

  - 두번째 인자는 후킹을 위한 설정이다. 보통 스팩에서 정의한 14가지 내부 메소드(internal method)를 재정의한다. 

var obj = new Proxy(<후킹할 객체>, <핸들러>);


내부 메소드는 [[ ]] 로 감싼다. 내부 메소드는 가려져 있기때문에 개발자가 호출할 수 없다. 

  - 속성 값 가져오기: obj.[[Get]](key, receiver) 는 obj.prop 또는 obj[key] 사용시 호출된다. 여기서 receiver는 속성 조회를 처음 시작했던 대상 객체이다. 

  - 속성 값 할당: obj.[[Set]](key, value, receiver) 는 obj.prop = value 또는 obj[key] = value 사용시 호출된다.  

    예) obj.prop += 2 같은 할당문의 경우 [[Get]] 호출 후 [[Set]]을 호출한다. (++, -- 도 동일)

  - obj.[[HasProperty]](key): 속성이 존재하는지 테스트 

  - obj.[[GetPrototypeOf]](): obj의 프로토타입을 반환. obj.__proto__ 또는 Object.getPrototypeOf(obj) 사용시 호출된다. 

  - functionObj.[[Call]](thisValue, arguments): functionObj() 또는 x.method() 사용시 호출된다. 

  - constructorObj.[[Construct]](arguments, newTarget): 생성자를 실행. new Date(2017,1,1) 사용시 호출된다.  


핸들러 만들기

  - set시에 무조건 Error 발생시킴

  - get시에 Reflect를 통해 기본 동작을 수행하고 추가 작업을 수행할 수 있음

var target = {};

var handler = {

  set: function (target, key, value, receiver) {

    throw new Error('not settting value');

  }

  get: function (target, key, receiver) {

    // default action 

    var result = Reflect.get(target, key, receiver);

    // custom action 

  }

}

var proxy = new Proxy(target, handler); 


> proxy.name = 'hi';

  Error: not settting value


프락시를 이용하면 어떤 객체에 대한 접근을 관찰하거나 로그를 남길 때 유용하다. 




디스트럭쳐링(Destructuring)


배열 또는 객체의 속성값을 일괄처리로 변수에 할당 받을 수 있는 방법이다. 객체나 배열을 XHR을 통해 JSON형태의 포멧으로 받을 경우 해체를 통해 값을 간편하게 변수로 받아 사용할 수 있다. 이는 코드의 가독성과 간결성을 유지해 줄 수 있다. 해체시 Default Value를 할당 할 수 있다. 배열의 경우는 인덱스 순서에 따라 하나씩 변수에 값을 할당 받지 않고 한번에 변수에 값을 할당 받는다. 

var first = myArray[0];

var second = myArray[1];


이것은 하기와 동일하다


let [first, second] = myArray;


또는 다차원 배열의 해체도 가능하다 


let [foo, [[bar], baz]] = [1, [[2], 3]]; 


또는 선택해서 받을 수 있다. 


let [ , , third] = [1, 2, 3];


또는 Rest 패턴을 통해 배열의 요소를 다른 배열로 받을 수도 있다.


let [first, ...second] = [1, 2, 3, 4, 5];


또는 함수에서 배열 리턴값을 해체한다 


function myArrayFunc() {

  return [1, 2, 3, 4];

}

let [a, b, c, d] = myArrayFunc();


객체를 해체할 수 있다. 객체 해체시에는 반드시 let, const 또는 var를 써야한다. 객체의 경우 이름이 같으면 변수 alias를 사용하지 않아도 된다. 

let myObj = { name: 'dowon' };


// myObj.name을 받아 myName 이라는 변수에 할당한다.

let { name: myName } = myObj;


좀 더 복잡한 객체의 해체도 가능하다, second = 'kangnam'이라는 default value를 할당했다. 


let complicateObj = {

  arrProps: [

    'dowon',

    { address: 'seoul'}

  ]

}

let { arrProps: [first, { second = 'kangnam' }] } = complicateObj;


이터레이션 프로토콜과 함께 사용할 수 있다


for (let [key, value] of map) {

   console.log(key, value);

}


또는 함수에서 객체 리턴값을 해체한다


function myObjFunc() {

  return {

    name: 'dowon',

    address: 'seoul'

  }

}

let { name, address } = myObjFunc();


또는 continuation passing style 사용도 가능하다. k 라는 callback에 값 1, 2를 주면 foo = 1, bar = 2 각 해체되어 할당된다. 


function returnMultipleValue(k) {

  k(1, 2);

}

returnMultipleValue(( foo, bar ) => ..... ); 


또는 ES2015의 import 구문에서 사용한다


import { Component } from 'angular2/core'; 


함수의 파라미터가 객체일때 파라미터를 해체하는 구문을 사용할 수 있다. 기존에는 파라미터 객체를 받아서 함수 내부에서 다시 변수에 할당하는 방식이 있을 경우 파로 파라미터 객체 해체를 통해 코드 간결성을 유지할 수 있다.

function myFn({ a, b, c, d }




Rest Parameter 와 Default Parameter


함수 파라미터의 해체(Destructuring)외에 함수 문법의 표현을 간결하게 해주는 두가지가 Rest/Default Parameter 이다. 함수의 파라미터를 가져올 때 기존엔 parameters를 통해 접근을 했다면 ES2015에서는 Rest Parameter로 접근한다. Rest Parameter는 함수의 마지막에 정의한다. 

function myFunc(first, ...myParams) {

  for (let param of myParams) {

    console.log(param);

  }

}


myFunc('hi', 'dowon', 'great', 'day');


... 점(Dot) 3개이후 파라미터 명칭을 설정하면 나머지 파라미터가 배열 객체로 넘어온다. 


함수의 파라미터 값이 undefined인지 검증하는 코드를 함수안에 넣는데 undefined일 경우 기본 값을 할당할 수 있다. 

function myFunc( first = 'dowon', second = 'hi') {

  console.log(first, second);

}


myFunc('Yun');


arguments 객체를 코드를 읽기 어렵게 만들고 JavaScript VM의 성능 최적화하는 것도 어렵게 만든다고 하니 앞으로는 Rest Parameter를 사용하자.




템플릿 문자열 (Template String)


백틱(Backtick) ` ` 을 이용해 문자열을 만드는 방법이 새롭게 생겼다. Angular2에서 template 정의시 많이 사용한다. 이에 더불어 문자 맵핑 채워넣기 (string interpolation) 을 백틱안에서 ${ } 를 사용해 넣을 수 있다. 

  - cross-iste scripting에 대한 공격을 피하려면 기존 처럼 신뢰할 수 없는 데이터에 대한 처리를 직접해주어야 한다. 

  - 다국어 처리도 직접한다

  - 루프문이 없다. 

let name = 'dowon';

let myStr = `Hi ${name}. Have a great day!`;


태그된 템플릿 (Tagged Template)은 백틱앞에 붙이는 사용자 정의 함수라 할 수 있다. 즉, 이 함수를 통해 템플릿 문자열을 커스터 마이징 할 수 있다. 태그 함수의 인자에는 어떤 것이 와도 되고, 리턴 값도 마찬가지이다. 

function SaferHTML(templateData) {

  var s = templateData[0];

  for (var i = 1; i < arguments.length; i++) {

    var arg = String(arguments[i]);


    // 대입문의 특수 문자들을 이스케이프시켜 표현합니다.

    s += arg.replace(/&/g, "&amp;")

            .replace(/</g, "&lt;")

            .replace(/>/g, "&gt;");


    // 템플릿의 특수 문자들은 이스케이프시키지 않습니다.

    s += templateData[i];

  }

  return s;

}


SaferHTML`<p>${name} hi</p>` 처럼 말이다. 




참조


  - Depth in ES6 번역문서

  - iterator, iterable 차이



posted by 윤영식
2016. 2. 19. 12:10 Angular/Concept

모듈단위의 파일을 만들어 모듈간에 모듈을 로딩해서 사용하는 방법을 제시하는 것이 Module Loader의 역할이고, 만들어진 모듈을 어떻게 묶어 사용할지 제시하는 것이 Module Bundler의 역할이다. 이번 글에서는 Module Bundler에 대해 알아보자. 



            





파일 번들링의 일반적인 방식 


index.html 에 <script> 태그를 이용해 첫번째는 개발자가 직접 넣는 방법, 두번째는 Grunt 또는 Gulp의 프론트앤드 툴의 도움을 받아 자동으로 넣는 방법이 있다. 하지만 응답성능에 민감한 애플리케이션에는 초기 다량의 모듈 파일 전송이라는 네트워크 성능이슈를 야기한다. 따라서 운영시에는 좀 더 컴팩하게 파일을 묶을 필요가 있다. 

  - 파일을 합치고(Concatenate)

  - 압축(Minify)하는 과정을 거친다. 


통합하고 압축하는 역할에 대한 플러그인이 Grunt/Gulp에 모두 존재한다. 하지만 CommonJS 또는 AMD나 ES2015 네이티브 로더를 사용할 때는 브라우져에 진화적인 코드로 변환해야 한다. 이때 사용하는 것이 Browserify, Webpack, JSPM 와 같은 모듈 번들러이다. 




Browserify


NodeJS에는 다양한 패키지가 존재하고 NPM(Node Package Manager)를 통해 설치한다. 모든 패키지가 CommonJS에 맞춰 모듈 패턴으로 구현을 하고 있다. 만약 이를 브라우져에서 사용하고 싶을 경우에는 Browserify 의 도움을 받으면 된다.

  - CommonJS를 번들링할 때 사용한다. 

  - AST (Abstract syntaxt tree) 에 따라 require한 모듈에서 require하고 해당 모듈이 require하고 있는 모든 하위의 모듈의 의존 파일을 자동으로 묶어준다. 

  - browserify 명령에서 entry 파일만 지정하면 된다. 의존

// app.js

var math  = require('math');

...


// console

browserify app.js -o bundle.js 




Webpack


AMD 패턴의 모듈을 번들링 할 때는 RequreJS에서 제공하는 r.js를 사용할 수 있다. 하지만 애플리케이션에서 NodeJS의 모듈도 사용하고 AMD 패턴 모듈도 사용한다면 어떻게 될까?  

  - CommonJS, AMD, ES2015 방식에 대한 번들링이 가능하다 

  - Bunlde Chunk라는 단위 묶으로 나누어서 번들링이 가능하다 


* Naver D2 Webpack 상세설명 참조




RollupJS


웹팩과 유사한 차세대 모듈 번들러로는 RollupJS가 있다. 특히 모듈안에 있는 내용중 사용하지 않는 것은 제거하는 Tree-Shaking 기술이 존재한다. 

  - maths.js에 square와 cube 펑션을 export 한다

  - cube만 사용한다. 

// maths.js 

export function square(x) {

 return x*x;


export function cube(x) {

  return x*x*x;

}


// test.js 

import { cube } from './maths.js';

console.log( cube(5) ); 


Tree Saking을 한후 square를 제거한다. 나무를 흔들면 필요없는 것은 떨어지고 필요한 것만 남는 것과 같다. (예제)

(function () {

'use strict';


// This function gets included

function cube ( x ) {

// rewrite this as `square( x ) * x`

// and see what happens!

return x * x * x;

}


console.log( cube( 5 ) ); // 125

}());




 

JSPM 


SystemJS는 모듈을 로딩하는 일관된 API를(System.config, System.import) 제공하고 패키지를 받아오고 로딩하는 역할로 JSPM을 사용할 수 있다.

  - SystemJS를 위한 패키지 메니져이다. 

  - ES6 Module Loader로 불린다

  - npm, bower, GitHub으로 부터 로딩한다. 

  - 브라우져에서 NodeJS 패키지가 browserify와 똑같이 작동한다

  - 개발시에는 개별 파일로 관리하다가 프러덕션에서는 번들링을 한다. 

  - 사용자 가이드


Browserify ==> Webpack ===> JSPM 순서로 정리 해보자. 




Angular2에서의 JSPM/SystemJS
  - JSPM을 패키지 메니져로 사용
  - SystemJS를 모듈 로더로 사용
  - TypeScript를 ES2015 자바스크립트 슈퍼셋으로 사용
  - Angular 2 를 통해 웹, 모바일, 네이티브 개발 플랫폼으로 사용


Module Loader는 CommonJS, AMD, UMD, ES2015 스팩 방식이 있고, Module Bundler는 Browserify, Webapck에서 JSPM(+SystemJS) 방식으로 수렴되고 있다. Angular2를 하게되면 Module Loader로서의 SystemJS와 Module Bundler이면서 패키지 메니져 역할을 수행하는 JSPM을 알아둘 필요가 있다.  

  - Angular 2에서 Bundler에 따른 사용 모듈 목록



<참조>

  - 모듈 번들러 설명 

  - 모듈 번들러 비교 slideshare

  - Choose ES6 Modules

  - Grunt에서 파일들을 통합/압축하는 방법

  - Browserify 와 Webpack 비교 

  - ES2015 스팩  

  - ES2015의 import/export 이야기

  


posted by 윤영식
2016. 2. 18. 18:02 Angular/Concept

프론트앤드 자바스크립트 개발이 점점 복잡해 짐에 따라 모듈 패턴으로 코드를 작성하고 단일 책임 원칙(Single Responsibility Principle)을 지키는 것이 좋다. 모듈 코드를 작성한 후 모듈을 로딩하고 배포(번들링)하는 다양한 방법들이 존재한다. 먼저 Module Loader에 대해 살펴보고 다음 글에서 Module Bundler에 대해 정리해 본다. 







모듈 패턴


모듈패턴을 사용하는 이유

  - 유지보수성(Maintainability): 단일 책임 원칙에 따라 필요한 기능을 담고 있으면서 별도 폴더와 파일로 유지하면 변경이나 확장 발생시 찾고 수정하기 쉽다. 전제 조건은 외부에 노출하는 API를 일관되게 유지하는 것이 중요하다. 

  - 이름공간(Namespacing): 자바스크립트에서 전역변수를 통한 개발을 하지 않는다. 이를 위해 즉시실행함수표현(IIFE)를 사용하여 전역변수의 오염을 방지하는데, 모듈 패턴 또한 전역변수 오명을 방지한다. 

  - 재사용성(Resuability): 모듈의 성격을 잘 나누어 놓으면 다음 프로젝트에서 그대로 사용해 쓸 수 있다. 보통 SDK나 Base Framework을 만들어 놓으면 초기 구축 비용을 최소로 할 수 있다. 


JohnPapa Angular 스타일 가이드를 보면 특별히 모듈을 지원하는 라이브러리의 도움없이 자바스크립트 모듈 패턴 방식으로 앵귤러 v1 코드를 작성토록 가이드하고 있고, 앵귤러 팀에서도 공식적으로 추천하고 있다. 

(function () {

    'use strict';


    angular

        .module('a3.common.action')

        .factory('currentAction', currentAction);


    /* @ngInject */

    function currentAction(ActionType, stateManager) {

        return {

            setDashboard: setDashboard,

            setWorkspace: setWorkspace

        };


        function setDashboard(dashboardId) {

            var action = {

                ...

            };

            stateManager.dispatch(action);

        }


        function setWorkspace(workspaceId, taskerId) {

            var action = {

                ...

            };

            stateManager.dispatch(action);

        }

    }

})();


순수 자바스크립트로 모듈 단위로 만든 후 상호 운영은 어떻게 해야할까? 일단 index.html에 설정을 하고 사용하는 순서에 index.html에 script 태그를 통해 로딩을 하는 간단한 방식을 생각해 볼 수 있다. 하지만 필요한 시점에 자바스크립트에서 로딩을 해서 사용하는 방식을 명시적으로 하려면 별도 로더의 도움이 필요하다. 




CommonJS & AMD & UMD


CommonJS는 지정한 코드를 동기적으로 로딩하는 방식으로 서버 사이드의 Node.js에서 사용한다. 

  - Object 만을 대상으로 한다.

  - module.exports 구문으로 Object를 export 한다

  - require 구문으로 Object를 import 한다. 

// 파일명: module.js 

function module() {

  this.hi = function () { return 'hi'; }

}

module.exports = module;



// 사용하는 파일: test.js

var module = require('module');

var m = new module();

m.hi();


위에서 require를 차례로 호출하면 동기적으로 하나씩 로딩을 한다. 즉, 비동기적이지 않기 때문에 로딩이 전부 되어야 수행이 된다. 브라우져에서 동기적으로 모듈 파일을 로딩하게 되면 모든 파일이 로딩된 후 화면이 실행되므로 성능 이슈를 야기할 수 있다. 따라서 CommonJS는 Node.js에서 주로 사용하고 브라우져에서는 사용하지 않는다. 


AMD(Asynchronous Module Definition)은 비동적으로 모듈을 로딩한다. 

  - Object, function, constructor, string, JSON 등 다른 타입들도 로딩이 가능한다. 

  - define 구문을 사용한다.

 define(['jquery', 'angular'], function($, angular) { 

   ...

 });


jquery, angular 파일에 대해 비동기적으로 로딩한다. AMD대표적 구현체로는 RequireJS가 있다. 


UMD(Universal Module Definition)은 AMD와 CommonJS의 기능을 둘다 지원하는 것이다. 

  - AMD, CommonJS를 고려한다 

  - 구현체로 SystemJS를 들 수 있다. SystemJS는 Universal dynamic module loader로 AMD, CommonJS뿐만 아니라 브라우져의 global scripts와 NodeJS 패키지 로딩을 하고 Traceur 또는 Babel 과 같이 작동할 수도 있다. 특히, Angular 2에서 사용한다.

  - 아래와 같이 CommonJS와 AMD를 체크하여 사용할 수도 있다. 구현 방식에 대한 다양한 예를 참조한다. 

(function (d3, jQuery) {

    'use strict';

   var Sankey2 = { ... };

   ....


    // Support AMD

    if (typeof define === 'function' && define.amd) {

        define('Sankey2', ['d3'], Sankey2);

    } 

   // Support CommonJS

   else if ('undefined' !== typeof exports && 'undefined' !== typeof module) {

        module.exports = Sankey2;

    } 

   // Support window

   else {

        window.Sankey2 = Sankey2;

    }


})(window.d3, window.$);


브라우져에서 ES6 module loader가 아닌 SystemJS (Universal module loader)를 사용할 경우 System.import 호출로 AMD, CommonJS, ES6 모듈 형식을 로딩할 수 있게 API를 제공하고  패키지 메니져로 JSPM을 사용할 수도 있다. JSPM은 무저항 브라우져용 모듈 패키지 메니져 (frictionless browser package management)로써 ES6 module loader가 작동하지 않는 곳에서 사용하는 Polyfill 이면서 AMD, CommonJS, Globals 자바스크립트 모듈 형식을 로딩할 수 있다. 



Native JS


자바스크립트 ES2015 (ES6)에서 모듈 로더를 공식지원한다. ES2015는 모듈의 importing과 exporting을 제공한다. (참조) 간결관 syntax와 비동기 로딩과 cyclic dependencies에 대해 보다 잘 지원을 한다. 

  - import, export 를 사용한다. 

// app.js 

export let count = 1;


export function hi() {

  return 'hi-' + count++;

}


// test.js

import * as app from './app';


console.log(app.hi());

console.log(app.count);



모듈로더에 대해 정리를 해보자. 자바스크립트 개발시 모듈 패턴에 입각하여 개발할 때 다양한 방식을 사용할 수 있으나

  - NodeJS 기반 서버 사이드 개발은 CommonJS 이고

  - Browser 기반 클라이언트 사이드 개발은 AMD구현체 중 하나인 RequireJS 를 사용한다. 


ppt에서 r.js는 RequireJS에서 제공하는 모듈 번들러이다. 모듈 로더에 맞는 모듈을 개발한 후에 모듈 파일을 운영 배포하기 위해 번들링 즉, 묶는 과정을 거친다. 번들링 방법은 대해 다음 글에서 살펴보자. 




<참조> 

  - 모듈 로딩 다이어그램

  - 모듈 로딩: CommonJS & AMD & UMD

  - 모듈 번들링: Browserify & Webpack 

  - CommonJS와 AMD - D2 

  - UMD 구현 예 

  - SystemJS: Universal dynamic module loader

  - Rollup.js: 차세대 Javascript module bundler

  - ES6 Module Loader Polyfill: Top Level SystemJS

  - ES6 vs CommonJS 비교

  - JavaScript Module Pattern

posted by 윤영식
2015. 11. 14. 17:54 Angular/Concept

Angular2 구현 언어는 TypeScript이다. TypeScript를 배우기 위한 준비과정을 알아본다. 








Transpiler


  ES2015(EcmaScript 6) 스펙은 모던 브라우저에서 완벽히 구현되어 있지 않기 때문에 최소한 ES5기준에 맞춰서 사용을 해야 한다. TypeScript는 ES2015를 포함해 정적 타입 시스템과 ES7에서 나오는 데코레이터 @을 지원하는 슈퍼셋이다. 따라서 Babel로 ES2015를 ES5로 트랜스파일(Transpile) 하지 않고 TypeScript만의 트랜스파일러를 사용해야 한다.  


$ sudo npm install -g typescript 


TypeScript 파일의 확장자는 .ts파일로 한다. 그리고 자바스크립 파일로 트랜스파일하기 위해 tsc 명령을  사용한다. 결과물로 동일 명칭의 .js 파일이 생성된다.


$ tsc  <fileName>.ts 






Editor 


  Microsoft에서 mac에서도 사용할 수 있는 전용 Code Editor(Visual Studio Code)를 내놓았다. 설치 후 어느 위치에서든 code . 하면 현재 폴더의 파일 구조를 가지고 에디터가 열린다. 그리고 .ts 파일에 대한 스마트 위저드 헬퍼가 자동으로 뜨기 때문에 MS Visual Studio에서 코딩하는 착각을 불러 일으킨다. 필자는 최근 Sublime 3에서 Atom으로 코딩 툴을 옮겼는데 참 흥미롭게 사용중이다. 큰 파일의 경우 약간의 성능저하를 견딜 수 있다면 사용해 보길 권한다. 




Atom을 사용한다면 atom-typescript 패키지 설치를 통해 Visual Studio Code에서의 .ts 에 대한 스마트한 기능(Auto Complete, Type Info on hover...)을 그대로 사용할 수 있다. 설치후 F6를 클릭하면 tsc <fileName>.ts 명령을 수행하고 결과를 Notify UI 창으로 성공 실패여부를 알려준다. 


 





tsconfig.json


  tsconfig.json 파일은 TypeScript를 위한 프로젝트 단위 환경 파일이다. Exclude 하고 싶은 폴더나 파일, Compile 옵션, File 옵션등을 설정 할 수 있다. TypeScript의 컴파일러인 tsc 명령 수행시 참조한다. tsconfig.json의 전체 스키마를 참조한다.  또는 TypeScript Deep Dive 깃북의 설명을 참조한다.


{

    "exclude": [

        "node_modules",

        "bower_components"

    ],


    "compilerOptions": {

        "target": "es5",

        "sourceMap": true,

        "module": "commonjs",

        "declaration": false,

        "noImplicitAny": false,

        "removeComments": true,

        "noLib": false

    }

}






TypeScript 배우기 


TypeScript를 배우기 위해 ES2015의 문법을 먼저 익히는게 좋다. 

  - ES2015-features 사이트에서 새로운 기능들이 ES5 스펙과 어떤 차이가 있는지 눈여겨 보자. 

  - 동영상 강좌를 본다. 필자는 egghead.io의 동영상을 먼저 참조한다. (Pro는 유료이다)


공식홈페이지는 http://www.typescriptlang.org/ 이고, TypeScript 구현체 자체도 오픈소스로 깃헙에 공개되어 있다. 

  - 공식홈페이지에서 제공하는 TypeScript 스펙 배우기

  - TypeScript Deep Dive 깃북






TSD


TypeScript Definition Manager의 약어이다. 이미 나와있는 프레임워크(angular), 라이브러리(jquery) 같은 것을 사용하면서 애플리케이션을 TypeScript로 작성할 때 이들 구현체의 정의 내역을 미리 알고 코드에서 가이드를 주기위한 파일이다. 확장자는 angular.d.ts 또는 jquery.d.ts처럼 <name>.d.ts 가 붙는다. 예로 $('.awesome').show(); 라고 하면 타입스크립트는 $를 알지 못 한다. 먼저 declare var $:any; 라고 해주어야 사용할 수 있다.  


$ npm install -g tsd


tsd를 설치하고 tsd install <name> 으로 설치하면 수행위치에 typings 폴더 밑으로 파일을 다운로드한다. 


$ tsd init

// tsd.json 파일 

{

  "version": "v4",

  "repo": "borisyankov/DefinitelyTyped",

  "ref": "master",

  "path": "typings",

  "bundle": "typings/tsd.d.ts",

  "installed": {

    "jquery/jquery.d.ts": {

      "commit": "efd40e67ff323f7147651bdbef03c03ead7b1675"

    },

    "angularjs/angular.d.ts": {

      "commit": "efd40e67ff323f7147651bdbef03c03ead7b1675"

    }

  }

}


$ tsd install jquery

$ tsd install angular



이미 만들어져 있는 d.ts 파일을 이곳에서 http://definitelytyped.org/tsd/ 찾아 볼 수 있다. DefinitelyTyped 공식 홈페이지를 참조하자.






WorkFlow 


 Atom 에디터와 기본 툴을 설치했으니, 프로젝트를 위한 워크플로우를 만들어 보자.   


  - 프로젝트 폴더 만들기 

  - NodeJSGit 설치 

  - "npm install gulp -g" 설치 

  - npm 초기화 및 develop dependencies 설정 

$ npm init 


// package.json 첨부

"devDependencies": {

        "gulp": "^3.8.11",

        "gulp-debug": "^2.0.1",

        "gulp-inject": "^1.2.0",

        "gulp-sourcemaps": "^1.5.1",

        "gulp-tslint": "^1.4.4",

        "gulp-typescript": "^2.5.0",

        "gulp-rimraf": "^0.1.1",

        "del": *,

        "superstatic": *,

        "browser-sync": *

    }


// 의존 라이브러리 설치

$ npm install 


  - tsd 설치하고, init 초기화 명령으로 tsd.json 파일과 typings 폴더에 tsd.d.ts 파일을 자동 생성한다.

$ npm install -g tsd 


$ tsd init 



  - angular 의 TypeScript Definition 파일을 설치해 보자. 더 많은 라이브러리는 이곳에서 http://definitelytyped.org/tsd/ 에서 찾을 수 있다.

$ tsd install angular --save

 - angularjs / angular

   -> jquery > jquery


>> running install..

>> written 2 files:

    - angularjs/angular.d.ts

    - jquery/jquery.d.ts



$ tsd install jquery --save

 - jquery / jquery


>> running install..

>> written 1 file:

    - jquery/jquery.d.ts



  - gulpfile.config.js와 gulpfile.js를 https://github.com/DanWahlin/AngularIn20TypeScript 에서 복사해서 만든다. Gulp Task 설명


  - ts 파일 lint를 위해 tslint.json파일 만든다.

{

    "rules": {

        "class-name": true,

        "curly": true,

        "eofline": false,

        "forin": true,

        "indent": [true, 4],

        "label-position": true,

        "label-undefined": true,

        "max-line-length": [true, 140],

        "no-arg": true,

        "no-bitwise": true,

        "no-console": [true,

            "debug",

            "info",

            "time",

            "timeEnd",

            "trace"

        ],

        "no-construct": true,

        "no-debugger": true,

        "no-duplicate-key": true,

        "no-duplicate-variable": true,

        "no-empty": true,

        "no-eval": true,

        "no-imports": true,

        "no-string-literal": false,

        "no-trailing-comma": true,

        "no-trailing-whitespace": true,

        "no-unused-variable": false,

        "no-unreachable": true,

        "no-use-before-declare": true,

        "one-line": [true,

            "check-open-brace",

            "check-catch",

            "check-else",

            "check-whitespace"

        ],

        "quotemark": [true, "single"],

        "radix": true,

        "semicolon": true,

        "triple-equals": [true, "allow-null-check"],

        "variable-name": false,

        "whitespace": [true,

            "check-branch",

            "check-decl",

            "check-operator",

            "check-separator"

        ]

    }

}


  - Atom에서 atom-typescript를 설치해서 사용한다면 tsconfig.json도 만든다. 아래와 같이 설정값을 입력한다. 설정 값이 있어야 atom-typescript 기능을 사용할 수 있다. 보다 자세한 tsconfig.json 작성 문법을 참조한다.

{

    "compilerOptions": {

        "target": "es5",

        "module": "commonjs",

        "declaration": false,

        "noImplicitAny": false,

        "removeComments": true,

        "noLib": false

    },

    "filesGlob": [

        "./**/*.ts",

        "!./node_modules/**/*.ts"

    ],

    "files": [

        "./globals.ts",

        "./linter.ts",

        "./main/atom/atomUtils.ts",

        "./main/atom/autoCompleteProvider.ts",

        "./worker/messages.ts",

        "./worker/parent.ts"

    ]

}


  - gulp 명령을 수행하면 .js 파일과 .js.map 파일이 생성된다. 


  - TypeScript 소개 영상과 소스를 확인해 보자.






Start Kit 


  yeoman의 generator 처럼 TypeScript프로젝트 관련한 스타트 깃을 사용해 보자. 물론 angular2 기반으로 프로젝트를 가정한다. 

  - AngularClass에서 제공하는 angular2-webpack-starter 

  

   


  - AngularClass에서 제공하는 Angular2의 Server Rendering을 접목한 Universal Starter





참조 


  - TypeScript Workflow with Gulp

  - TypeScript in Awesome Angular2

 - Atom TypeScript 패키지 : atom-typescript



posted by 윤영식
2015. 7. 14. 22:54 Angular/Concept

Meteor는 Modern Application Platform이기도 하면서 Reactive Manifesto에서 이야기하는 User Responsive를 위한 Resilient와 Scalable을 갖추고 있다. 그래서 Meteor를 Realtime Modern Application을 위한 Reactive Platform이라 이야기를 해도 좋을 것 같다. 하지만 정작 Reactive라고 이야기를 해놓고 Reactive의 개념이 와닿지 않는 것은 거시적, 미시적 이해가 없기 때문이다. 최근에 각광 받고 있는 AngularJS는 Reactive Templating을 지원한다. Reactive라 붙일 수 있는 이유는 Reactive Programming에 대해 위키에서 찾아보면 액셀 예를 통해 어떤것을 의미하는지 이해를 할 수 있다. 다수의 b가 a를 의존할 때 a의 변화에 b가 종속이 되고, 옵저버 패턴(Observer Pattern)으로 보면 다수의 의존하는 Observer(소비자)가 데이터를 제공하는 Observerable(생산자)에 의존하는 것으로 a에 상태변경(이벤트 발생)에 대해 b에도 상태값을 알려주는 구조이다. Reactive Programming(RP)의 관건은 Asynchronous Data Flow관점에서 프로래밍을 하고 Functional Reactive Programming으로 오면 filter, map, reduce와 같은 블럭을 통해 Reactive Programming을 한다. 



리액티브 프로그래밍(RP)은 비동기와 이벤트 기반의 데이터 스트리밍(Asynchronous and Event-based Data Streaming)을 Observable Sequences로 변환해 개발하는 프로그래밍 방식이다.







Reactive 거시적, 미시적 이해


  Reactive Manifesto 의 내용을 이해할 필요가 있다. 왜 Reactive 해야 하는지 이유는 본 글에 잘 설명되어 있다. 현재는 인터넷 보급과 모바일 기기의 보급으로 365일 24시간 무정지의 끊김없는 빠른 서비스를 제공해야 한다. 이를 위해서는 장애(Failure)에 빨리 복구(Resilient)되고, 서비스의 수평적 확장이(Scalable) 용이해야 하며, Resilient와 Scalable 바탕에는 느슨한 결합(loose coupling)의 메세지 기반(Message Driven) 아키텍처가 기반이 되어야 한다. 


  - Responsive를 위한 Resilient와 Scalable 및 Message Driven에 대한 이야기

  - NDC에서 김종욱님이 발표한 RX와 Functional Reactive Programming 이야기 (원문)

    + 엔시소프트 리니지 서버의 Rx 적용 경험 공유

    + 2009년 MS 에서 Reactive eXtension 소개

    + 2011년 RxJS, 2012년 RxJava등이 나오고 현재는 RxSwift도 존재함 

    

   

  - 2013년 Infoq에 발표한 Reactive programming의 동향

    + 코세라에서 Scala 기반 오픈 강의 개설(Scala 창시자와 Rx 개발자가 직접 강의함) : Principles of Reactive Programming

    + Netflix에서는 RxJava 기반으로 광범위하게 개발을 하고 있다. 

    + Facebook은 ReactJS를 오픈소스화하고 페이스북 웹과 인스타그램 웹에 사용하고 있다.

    + Javascript 기반의 Bacon.js, Kefir.jsRxJS, Reactive.js 라이브러리를 타 프레임워크와 접목해서 사용할 수도 있다. 

  - Microsoft에서 이야기하는 Reactive eXtension 정의

  - 다양한 언어의 구현체는 ReactiveX(http://reactivex.io)에서 볼 수 있다.

  - 확장가능하고 병행처리 가능한 웹 아키텍쳐 구축하기


  - Observable에 대한 이해

    + 2분만에 이해하는 Observable : Rx is the underscore.js for events

    + FRP 연산자들에 대한 Sync와 Async에 대해 시뮬레이션 예제를 통해 보여준다. (슬라이드DevNation)

    + ReactiveX.io의 설명

       Observer는 Observable에 subscribe하고 onNext, onError, onCompleted를 Observer에 구현하면 이를 Observable이 호출

       onNext에는 emit 한다고 말하고, onError, onCompleted는 notification한다고 말함.

    + MS의 Reactive eXtension의 워크샵 (동영상)


  - Observable에 대한 기본 개념 

    

  

  - ReaciveX를 위한 Operators 종류

    + 언어별로 동일 연산자를 가진다. 

    + Create Observable, Transform Observable, Filtering Observable, Combining Observable, Error Handling, Utility, Conditional & Boolean ...

    + Operator사용을 위해서 Decision Tree의 내용을 숙지해 보자. 





Reactive Programming for JavaScript


  먼저 RxJS를 이용한 Reactive Programming에 대한 이해를 선행한 후에 FRP(Functional Reactive Programming)에 대한 이해를 위해 learnrx의 FRP 개념 이해를 위한 실습을 전부 따라해 본다. 


  - Javascript의 Sync처리와 Asynch 처리에 대한 이해를 뭔저 해본다. 동영사의 21분에서 forEach가 Sync, Async 처리 되는 과정을 이해.

   + Event-Loop 와 Call Stack, Task Queue 관계 시뮬레이션 (21분경에 나옴)

    


  - 예제들이 ES6 기준으로 되어 있는 경우가 많아 ES6 문법을 공부하자

    + Depth in ES6 이해 요약정리

  - Functional Reactive Programming (FRP) 에 대한 개념을 이해하자. 

    + Functional Programming 과 Reactive Programming의 결합 === Functional + Async Data Stream (Data Flow) 

    



  - Frontend Developer 입장에서 본 RxJS에 대한 기본 개념 이해 

    + Array에서 제공하는 map, filter, reduce는 할 때마다 다시 배열을 할당한다.(learnrx를 따라해보고 이해하자) 따라서 GC에 대한 이슈존재

    + RxJS의 Observable을 사용할 경우 배열 재할당이 없으므로 GC에 대한 이슈도 없다. 

    


  - RxJS의 깃헙 Readme를 읽자

  - RxJS 학습하기 

    + egghead.io의 RxJS 강좌와 Asynchronous 강좌를 본다.

    + RxMarbles : Rx를 다이어그램으로 보여주어서 시각적 이해를 돕는다

    + RxJSKoans 학습

    + RxJS GitBook 책을 읽자 (그외 RxJS 레퍼런스)


  - RxJS를 이용한 FRP API 소개 : 맨뒤의 참조 목록을 방문하자 

    


  - ng-conf 2015에서 Nexflix UI 개발자가 발표하는 Obserable을 보자 (슬라이드

    + RxJS 개념은 Angular 2.0 core 에서 사용한다!!!

    

  - Bacon.js  : Functional Reactive Programming(FRP) Library for Javascript
    + 강좌-1 : Hacking with jQuery
    + 강좌-2 : Bacon.js started
    + 강좌-3 : AJAX and stuffs



Reactive Programming for Another Stuffs

Reactive 프로그래밍은 다양한 언어를 지원하고 http://reactivex.io 에서 언어별로 확인이 가능하다. 
  - Java를 위한 Reactive 프로그래밍으로 RxJava를 제공하고, 안드로이드 v2.3 이상부터도 사용을 할 수 있다. 
  - 김대성님의 FRP에 대한 이야기 : RxJava를 소개하고 있다. 유튜브 동영상을 시청하면 보자.   
    

  - 안드로이드 개발을 위한 Rx기반의 아키텍쳐링 방법도 제공을 하고, RxAndroid 라이브러리도 제공을 한다
    

    + cycle.js를 React 스타일로 재구성한 cycle-react
    + Flux Pattern을 Rx-Flux 구현

  - Angular에 RX 적용하기 
    + BangJS : Reactive AngularJS 로서 Bacon.js를 사용한다.

  - D3.js와 붙여보자 




<참조>

  - React & Bacon 예

  - Neflix API를 사용해 Reactive Programming하기

  - Reactive Programming using RxJS

  - Observable 과 Promise의 차이점

  - Reactive Extension in MS

  - Rx 관련한 대부분의 자료 모음

  - RP and MVC 예제

posted by 윤영식
prev 1 next