'프로그래밍'에 해당되는 글 98건

  1. 2016.08.02 속성 탐색하기
  2. 2016.06.16 will-change:content
  3. 2016.03.05 Getting Started with Redux 2
  4. 2016.01.05 (append|prepend...)To 관련 함수의 활용 사례
  5. 2015.12.23 childNodes vs nextSibling (and vs children) 돔 탐색 성능 차이
  6. 2015.04.19 t3js 1
  7. 2015.04.14 angular
  8. 2015.04.07 자바스크립트 this
  9. 2015.03.25 EcmaScript 2015
  10. 2015.03.18 Prototyping

예전에 qunit에서 [code review] 받을 때 [Richard Gibson]이 알려준 내용인데 [jsmocktool] 관련해서 개발하다가 갑자기 생각하서 또 잊을까봐 정리한다.


당시 코드에서 regexp 객체에 flags가 있는지 확인하는 방법으로 속성에 접근해서 아래와 같이 사용했다.


1
return regexp.flags || regexp.toString().match(/[gimuy]*$/)[0];
cs


근데 Richard Gibson이 "나는 불필요한 동작을 하지 않기 위해 in연산자를 사용한다"며 in 연산자를 사용하길 바랬다. 첨에 "엇 뭐지?"라는 생각을 했지만, 잠깐 고민해보니 좋은 의견이였다. 그리고 오늘 글을 쓰기 위해 좀 더 조사를 해봤다.


먼저 속성이 있는지 확인하는 방법은 크게 3가지가 있다.


1. 동등 연산자( == ,=== )

1
2
if(o[k] === undefined){    
}
cs


2. hasOwnProperty 메서드

1
2
if(o.hasOwnProperty(v)){    
}
cs


3. in 연산자

1
2
if(v in o){    
}
cs



이 3가지중 어떤게 가장 빠를까? 한번 고민해보고 아래 글을 읽으면 재밌을거라 생각한다.


시점/브라우저 등 여러가지 상황에 따라 다를 수 있는데 V8(크롬)에서 보면 1번이 가장 빠르다. 왜 그런지는 V8 개발자인 [Vyacheslav Egorov]의 설명을 보면 알 수 있다. 요약하면, 1번의 경우는 흔히 얘기하는 hidden class로 특정 offset을 가지고 있고 반복 호출되면 [Inline Cache] 때문에 굉장히 빠르지만, hasOwnProperty와 in 연산자의 경우는 별도의 캐시를 하지 않고 매번 새로 찾기 때문에 느리다. [비교] (이 말은 키값(offset)이 고정되어 있지 않으면 차이가 없다는 말이다. 실제로 로직에서  키 값을 항상 변경해서 사용하면 성능에 크게 차이가 없다.)


하지만, 비교에서 보면 최근에 hasOwnProperty은 [개선]되어서 지금은 hasOwnProperty도 실제로 비슷한 성능을 내고 있으며 [in 연산자] 역시 언젠가 빠를 것 같다.


다시 돌아와서. 지금까지 보면 1번이 여러 상황에서 적절한 것 같은데 왜 Richard Gibson은 `in`연산자를 사용하라고 했을까?

단순 객체에 속성을 확인하는건 1번이 빠를진 몰라도, 일반적으로 FE을 개발할 때 DOM등 브라우저에 있는 native 객체들에 위의 비교문을 많이 사용한다. 그래서 속성을 읽을 때 단순히 값을 반환하는 경우도 있겠지만, 내부적으로 복잡한 연산이 들어가기 때문에 오히려 1번이 가장 느릴 경우가 많다.


예를 들어. 특정 객체에 offsetHeight라는 속성이 있는지 확인한다면, 1번의 경우는 [forced layout]이 발생하여 엄청나게 느리지만, 2번이나 3번의 경우는 속성이 있는지만 확인하기 때문에 불필요한 forced layout이 발생하지 않는다.


이렇게 단순히 자바스크립트 객체의 속성을 확인하는 방법으로 좋을지 모르지만, DOM이나 기타 native 객체들은 2, 3번(주로 3을 선호한다. 이유는 아래에)을 사용하는게 오히려 좀 더 나은 practice라고 생각하며 아마도 Richard Gibson이 이런 의미로 얘기한 것 같다.


당연하지만, getter의 경우도 1번에서는 동작하지만, 2, 3의 경우는 동작하지 않는다. 참고로 hasOwnProperty는 1, 3번 약간은 다르다. hasOwnProperty은 prototype chaining하지 않고 속성을 찾기 때문에 기대했던 생각과 다른 결과를 만날 수 있다. [참고


요약하면,


단순 오브젝트를 확인하는건 속성에 접근하여 확인하는게 빠르지만, 브라우저의 객체나 DOM은 in/hasOwnProperty가 괜찮은 방법인 것 같다.


ps. Code HighLight을 하기 위해 보통 markup.su/highlighter/ 을 사용했는데 관리를 안하는지 다른 것을 찾아보다가 http://colorscripter.com/ 을 찾았는데 완전 좋네. 



참고 URL.

http://stackoverflow.com/questions/21763617/why-is-getting-a-member-faster-than-calling-hasownproperty

https://bugs.chromium.org/p/v8/issues/detail?id=2472#c8

https://bugs.chromium.org/p/v8/issues/detail?id=2743

Posted by 전용우
,

모바일 웹에서 성능을 높이는 방법으로 GPU가속을 사용하기 위해 translateZ(0)와 같은 hack코드를 넣곤 했다. 이후에 will-change가 나와서 hack을 대신해서 사용했다. 둘 다 GPU가속을 위해 사용했는데 굳이 will-change을 사용하는 이유는  "브라우저가 효과적으로 GPU가속을 사용할 수 있기" 때문이였다.


문서에는 브라우저마다 will-change을 다르게 사용한다고 하지만, 실제로 크롬에서는 will-change가 어떤 영향을 주는지 코드로 확인하고 싶었다. 아쉽게도 당시 코드를 봤을 때 딱히 크롬이 스마트하게 판단하는지는 찾지 못했다. 그렇게 내가 아직 잘 모르는구나 하는 생각을 하고 지나갔다.


그리고 몇 일전에 will-change: scroll-position, content이 성능에 어떤 영향을 받는지 문의한 글이 있었는데 이 글을 보고 예전 생각이 나서 정리한다. 


일단 scroll-position는 스크롤의 위치가 변경될 수 있음을 알려주는 힌트이고 content는 엘리먼트가 변경될 수 있음을 알려주는 힌트다. [링크]


답변 내용은 현재까진 will-change: scroll-position은 어떤 영향을 미치지 않는다. will-change: content의 경우는  content을 가진 엘리먼트의 자식 엘리먼트가 will-change: <hint>을 가지면 변경할 가능성이 있다고 판단하여 자식 엘리먼트는 composited layer을 만들지 않는다. 


예제를 보면 이해하기 쉬운데 아래 두개만 composited layer을 만든다.

<div style="will-change: scroll-position"></div>

<div style="will-change: contents"></div>

<div style="will-change: transform"></div> // <--------- composited layer

<div style="will-change: contents">
    <div style="will-change: transform"></div>
</div>

<div style="will-change: scroll-position">
    <div style="will-change: transform"></div> // <--------- composited layer
</div>


blink코드를 보면 더 정확히 할 수 있다.

if (style.hasWillChangeCompositingHint() && !style.subtreeWillChangeContents())
        reasons |= CompositingReasonWillChangeCompositingHint;


그리고 will-change에 들어갈 수 있는 style은 [opacity, transform, webkit-transform, top, left, bottom, right]이다.


switch (rareNonInheritedData->m_willChange->m_properties[i]) {
        case CSSPropertyOpacity:
        case CSSPropertyTransform:
        case CSSPropertyAliasWebkitTransform:
        case CSSPropertyTop:
        case CSSPropertyLeft:
        case CSSPropertyBottom:
        case CSSPropertyRight:
            return true;
        default:
            break;
}


이걸 보면서, 예전에 궁금했던 점이 조금 이해됐다. 현재는 content속성에 대해서만 되어 있지만, 나중에는 scroll-position에 대해서도 최적화가 들어갈 것 같고 이후에는 W3C에 나와 있는 것 처럼 최적화가 되지 않을까 생각된다.




Posted by 전용우
,

먼저, 잡담부터 시작.

예전에 태훈님한데 egghead을 지나가듯 들었는데 정수형이 다시 알려줘서 redux 강의를 들었다. redux강의 하나를 들었는데 다른 강의를 보지 않아도 돈을 내고 들을만 하다고 생각한다.

내가 본 건 [getting-started-with-redux] 인데  영상의 컨셉이 redux가 왜 필요한지 부터 시작해서 redux을 간단하게 만들면서 적용하는 과정이다. 영어긴 한데 누가 [정리한 글]도 있고 주로 코딩을 하기 때문에 보는데 무리가 없었다.


다시 돌아와서, 내가 이 강의를 들으면서 고민했던 부분을 정리하려고 한다. 이미 전반적인 내용을 정리한 글은 많아서 난 좀 이슈 위주로 정리. 


- stateless functional components의 존재

 : 난 이게 왜 필요한지 한참을 고민했다. 말그대로 상태가 없는 함수형 컴포넌트다. 여기서는 기본적으로 상태을 최소한으로 유지하고 각 컴포넌트가 가지고 있기 보다 container에서 관리하기 때문에 가능하면 상태를 관리하지 않도록 한다. 근데 이게 생각보다 잘 안되는지 기능적으로 개발할 때 상태를 가지지 못하게 한게 이 컴포넌트인 것 같다. 이건 이해했는데, 이게 성능이 빠르다고 하는게 이해가 안됬다. 왜냐하면, 이 컴포넌트는 그냥 함수라 기본적인 life cycle이 없다. 그래서  "shouldComponentUpdate"를 활용해서 내가 virtual dom의 비교을 smart하게 할 수 없었다. 그리고 코드를 봐도 왜 빠른지 알 수가 없었는데 [링크]을 통해 이해했다. 정리하면 아직 옵티마이제이션되는건 없고 미래에 될 거다 이다. 그리고 pureRender나 shouldComponentUpdate가 오/남용이 많은가 보다.


- Provider와 connect의 존재

: 동영상을 따라면서 동영상처럼 한 JS에 작성했던게 아니고 클래스별로 잘라서 사용했는데, 이게 문제가 redux의 store을 각 컴포넌트에서 접근해서 사용하기가 너무 귀찬고 매번 prop으로 넘기는데 이게 뭔가 싶었다. 한참 짜증이 났는데 일단 끝까지 보자라는 생각으로 봤더니 끝나기 몇 회 전에 이 문제를 해결하는 방법을 알려줬다. 공통적으로 가지고 다니는 store나 route같은 객체가 있다면 Provider나 connect가 써야 한다. 잊지는 않겠지만, 난 이거 나중에 알아서 좀 짜증났음. 그리고 Provider을 사용할 때 context가 들어오는 시점이 construct가 아니라 "componentWillMount"부터 들어와서 좀 삽질했다.


- arrow function

: 이게 뭔지는 알았는데 실제로 사용하다보니 react에는 이게 2가지 패턴이 있다. 바로 반환하는 경우는 {}을 사용하지 않고 그냥 ()을 사용한다. 좀 더 정확히 말하면 => 는 바로 반환할 때는 별도의 brace을 넣지 않고 할 수 있는데 jsx때문에 ()을 넣는다. 근데 난 이게 정말 눈에 안뜀. 이것도 몇 번 삽질.    

const Footer = ({ currentFilter, onFilterClick }) => ( <p> <FilterLink filter='SHOW_ALL'>All</FilterLink> </p> ); const Footer = ({ currentFilter, onFilterClick }) => ( // 이렇게 쓰고 몇 번 헤멤 doSomething(); return ( <p> <FilterLink filter='SHOW_COMPLETED'>Completed</FilterLink> </p> ); );



- destructuring

: ES6의 문법중에 , 초반에 눈에 잘 안들어왔던 문법이 destructuring이다. 익숙해지면 완전 편한데 처음에 좀 걸리적거렸음.

{
  filter,
  currentFilter,
  children,
  store
}

{...todo}

[...state, todo(undefined, action)]

{ ...state, completed: !state.completed}



- es6/7은 꿀

: destructuring, import, arrrow...을 es5로 개발한다고 생각하면 좀 답답했을것 같다. 그리고 babel에 "stage-0" preset을 사용하면 es7나 제안중인 [static property]도 사용할 수 있다는건 흥미로웠다. 다만, 실무에 써보라고 한다면 스킬이 아직 좀 부족한것 같다. 그리고 아직 트랜스파일링 된 코드를 보는게 눈에 잘 들어온다. -_-;


- export이슈

: export하는 부분을 빼먹은 적이 많아서 아래 메세지를 여러번 만났다. 이것 때문에 나도 삽질 좀 많이 함.

Warning: React.createElement: type should not be null, undefined, boolean, or number. It should be a string (for DOM elements) or a ReactClass (for composite components). Check the render method of `TodoApp`.

Uncaught Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object. Check the render method of `TodoApp`.


- 폴더 구조

: 어떻게 폴더 구조를 가져가야 할 지 고민이 된다. 찾아보니 몇 가지 제안([링크], [링크]...)들이 있던데, 아직 내가 실제로 만들어보지 않아서 그런지 뭔가 공감이 안된다. -__-;



전반적으로 이 강의를 듣고 나서 react+redux을 어떻게 활용해야 할 지에 대한 감은 잡혔다. 다만, 많이 만들어보지 않아서 그런지 의문점들은 몇 개 있다. 

예를 들면, 스케일이 커지면 redux처럼 하나의 store로 가는게 좋은 방법인지 잘 모르겠다. 그 밖에 Presentational Component의 단위를 가능하면 작게 쪼개길 기대하는데 이게 뭔가 난 부자연스럽다. 왠지 virtual dom때문에 하는 작업처럼 느낌..., 객체가 커지면 새로 만드는 비용은 크게 문제가 없는지 등등 디테일은 좀 경험이 필요할 것 같다.

여튼 egghead,io강의는 훌륭함,



Posted by 전용우
,

기술 지원할 때 많은 코드를 보는데 가끔 (append|prepend...)To 관련 메서드을 활용하지 못해 좀 읽기 어렵게 개발하는 경우를 봐서 생각난 김에 정리한다.

(append|prepend...)To 관련 기능은 대부분의 라이브러리에 있지만, 여기선 [jQuery]을 예를 들어 설명한다. 

보통 append, prepend... VS appendTo, prependTo...의 차이를 모르는 사람은 거의 없다.

간단히 설명하면 append는 부모 엘리먼트에 자식 엘리먼트를 마지막 자식 노드로 추가하는 메서드이다. 그래서 $(parent).append(child)는 parent가 앞이고 child가 뒤이고, appendTo는 $(child).appendTo(parent) 처럼 반대다.

그럼.. 예를 들어, 아래와 같은 기능을 구현한다고 생각해보자.

.layer라는 클래스를 가진 엘리먼트를 #parent에 마지막 자식 노드로 추가하는데 fadeIn되어야 한다.
(IE 하위 버전을 지원하기 위해 CSS transform은 사용하지 않는다고 가정하자.)

이런 기능을 구현한다고 하면 내가 본 코드의 패턴 중 하나는 아래와 같다.

var layer = $("<div class='layer'>");
$("#parent").append(layer);
layer.fadeIn();

때론 jQuery을 chaining하기 위해 아래와 같이 사용하곤 한다.

$("#parent").append("<div class='layer'>").find(".layer").fadeIn();

여기서 .layer가 여러 개이면 아래와 같이 개발하는 경우도 있다.

$($("#parent").append("<div class='layer'>").find(".layer")[0]).fadeIn()

마지막을 제외하곤(마지막은 코드 읽기가 어렵다) 위의 방법이 모두 나쁘니깐 개선하면 좋겠다라는 의미로  얘기하기보다  xxxxTo관련 메서드로 아래와 같이 할 수도 있다 정도로 이해해주면 좋겠다.

보통 나는 아래처럼 작성한다.

$("<div class='layer'>").appendTo("#parent").fadeIn();

위의 예로 개발한 경우 xxxxTo을 모르는 경우가 거의 없었지만, 이런식으로 할 수 있다고 제안하면 새롭게 느끼는걸 알 수 있었다. 

정리하면 xxxxTo는 단순히 부모와 자식의 위치를 바꿔서 엘리먼트를 추가할 때  사용한다기 보다 등록하는 엘리먼트을 기준으로 추가 작업을 하기 위해 사용하는 메서드로 알고 있으면 좀 더 다양하게 활용할 수 있다.


마지막으로 실제 사례를 찾고 싶어서 [github]에서 찾아봤는데 비슷한 사례가 있어 소개한다.
아.. github은 advance search가 안되서 정말 아쉽다. 그립다 code.google.com이여.

// 실제 코드
$('body').append('<div class="fyr"></div>').find('div.fyr').findYourRep({apis: 'represent'});

// 개선 코드
$('<div class="fyr"></div>').appendTo('body').findYourRep({apis: 'represent'});


Posted by 전용우
,

며칠 전에 angular 코드를 보다가 design note을 찾으러 위키를 갔는데 우연히 [performance]을 봤다.(design note는 [다른 곳]에서 찾음.)

다른 내용들은 일반적인 내용인데 내가 의아하게 느낀 부분이 자식노드를 탐색할 때 `DOM.childNodes`이 `node.nextSibling`보다 느리다는 얘기다. 그 예로 [jsperf링크]가 있어서 확인해보니 실제로 nextSibling이 빨랐고 몇 개 브라우저에서 좀 더 확인해봤는데 모두 nextSibling이 항상 빨랐다.


"왜 그럴까?" 잠깐 고민해봤는데 딱히 아이디어가 안떠올라 blink의 구현로직을 찾아보기로 했다.


먼저 clideNodes부분을 보니 Container노드(parentNode)일 때 그 안에 childeNode을 찾아 nodelist로 만든 다음 반환하는데 뭔가 특별해보이진 않는다.

PassRefPtrWillBeRawPtr<NodeList> Node::childNodes()
{
    if (isContainerNode())
        return ensureRareData().ensureNodeLists().ensureChildNodeList(toContainerNode(*this));
    return ensureRareData().ensureNodeLists().ensureEmptyChildNodeList(*this);
}

그럼 nextSibling은 뭘까 찾아봤다.

Node* previousSibling() const { return m_previous; }
Node* nextSibling() const { return m_next; }

엇. 이거 뭐지 그냥 반환만 하네... 그래서 찾아보니 nextSibling, previousSibling을 호출할 때는 뭔가 찾는게 아니라 아래와 같이 Node가 변경되면 값을 업데이트하고 호출할 때는 위와 같이 그냥 반환한다.

void ContainerNode::insertBeforeCommon(Node& nextChild, Node& newChild)
{
    Node* prev = nextChild.previousSibling();
    nextChild.setPreviousSibling(&newChild);
    if (prev) {
        prev->setNextSibling(&newChild);
    } else {
        m_firstChild = &newChild;
    }
    newChild.setParentOrShadowHostNode(this);
    newChild.setPreviousSibling(prev);
    newChild.setNextSibling(&nextChild);
}

void ContainerNode::appendChildCommon(Node& child)
{
    child.setParentOrShadowHostNode(this);

    if (m_lastChild) {
        child.setPreviousSibling(m_lastChild);
        m_lastChild->setNextSibling(&child);
    } else {
        setFirstChild(&child);
    }

    setLastChild(&child);
}

즉, childNodes을 찾을 때는 하위 노드를 찾아서 nodelist로 만든 다음 반환하기 때문에 비용이 좀 드는 것 같고, nextSibling은 그냥 바로 노드를 반환하기 때문에 비용이 적게 드는 것 같다. 

갑자기 비슷한 children이 생각나서 이건 어떻게 구현되어 있을까 하고 찾아봤는데 아래와 같이 구현되어 있다. 

PassRefPtrWillBeRawPtr<HTMLCollection> ContainerNode::children()
{
    return ensureCachedCollection<HTMLCollection>(NodeChildren);
}

이건 우리가 알고 있는 [live nodelist]인 것 같아 아마도 성능이 좋지 않을까 하고 비교해봤는데 결과는 nextSibling보다는 느리지만, childNodes보다는 빨랐다. [링크]


처음 가지고 있던 의구심을 해결하고 nextSibling, previousSibling, lastChild, firstChild는 이미 계산되어 가지고 있다는 사실을 알게됐다.


ps. github에서 유명한 프로젝트에 childNodes을 사용하는 부분을 찾아서 pr줍기를 시도했지만... 테스트 코드를 제외하곤 거의 없어 아쉬었다. 하지만, 우연히 버그같은 코드를 발견해서 [pr 줍기 성공]. :)





Posted by 전용우
,

t3js

프로그래밍 2015. 4. 19. 23:07

토요일인가? 트위터에서 t3js[링크]라는 프레임워크를 만들었다는 트윗을 보고 이건 뭔가하고 주말에 와이프가 드라마를 보는 틈을 타 잠깐 살펴봤다.

t3js을 만든 사람이 니콜라스 자카스[링크]라고 다수의 JS책을 쓰고 JS관련 컨설팅을 하다가 최근에 프로필을 보니 BOX에서 수석 아키텍트를 하고 있다. 이 사람 낸 책 중 번역서는 대부분 봤는데[링크] 다 괜찮았던 책이고 아티클도 꾸준히 쓰는 편이라 신뢰감이 있었다.

먼저, 간단하게 설명을 한면 t3js는 아래 4가지를 알 필요가 있다.

Application - Module과 service을 관리하고 메시지를 전달한다. 모듈간의 커뮤니케이션과 라이프사이클등등 .(하나만 존재)

Module - 흔히 얘기하는 Component같은 역할이다. 돔에 이벤트를 바인딩하는등 application의 비지니스 로직을 담당한다.

Behavior - Module의 중복되는 부분을 뽑아 behavior을 만든 후 moudule에서 사용한다.(사실 module의 공통 부분이라고 생각하면된다)

Service - 유틸리티 같은 코드를 집합이다.(비지니스 로직을 제외한 외부 라이브러리 등등)


이 4가지의 역할을 다이어그램으로 표시하면 아래와 같다.


http://t3js.org/


특징은 보는 것과 같이 module간 커뮤니케이션을 할 수 없고 Application을 통해서만 모뮬간 커뮤니션을 한다. 그리고 jQuery의 의존성을 가지며, 제거할 예정이고 [이슈]에 다양한 라이브러리를 사용할 수 있도록 제안하는 내용이 있어 어떻게 변할지는 모르겠다.

개인적으로 생각하는 이런 류의 프레임워크들에게 기대하는 포인트는 어떻게 메세지를  관리하는가 이다.

규모가 커지면 커질수록 메시지 관리 이슈가 너무 많다.

그래서 이런 문제를 사용자가 덜 겪도록 혹은 해결할 수 있도록 프레임워크에서 적절하게 제어해줘야하는데 t3js는 이런 문제를 실제로 고민했는지 모르지만, 내가 느끼기에 그런 고민을 한 것 같다.

그렇게 생각한 이유가 프레임워크를 만들면 기능을 넣고 싶은 유혹이 많은데... 대표적으로 메세지가 아니라 이벤트처럼 beforeA, afterA와 같은 걸 만들고 싶다. 근데 이걸 만들게 되는 순간 헬..  그리고 다수개의 모듈을 관리하는 객체를 만들어서 관리하고 싶어지는데.. 이것도 만드는 순간 처음에는 좋아보이지만 헬 열림.

여튼 전체적으로 최대한 간단하게 메세지를 처리하려고 한 디자인이 나뻐보이지 않는다. 그렇다고 세련됐다고 보기 힘들어 아쉽다.

그리고 다른 괜찮았던 점은 처음 코드를 볼 때 왜 module context라는 객체가 필요할까 라는 고민이 있었다.아래와 같이 module context객체는 사실상 application의 메서드를 호출하는 수준이다. 

broadcast: function(name, data) {
    this.application.broadcast(name, data);
},
getService: function(serviceName) {
    return this.application.getService(serviceName);
},

그래서 이건 뭘까라는 고민하다가 테스트 작성하는 [문서]를 보고 테스트 때문임을 알았다. 괜찮은 아이디어.


아쉬운 점은 module의 사용법이 굉장히 어색하다.

먼저, 사용 가능한 이벤트가 한정적이고, 아래와 같이 이벤트를 처리하는 방식이 [data-type]속성으로 처리하는데 너무 어색하다.

<footer id="footer" data-module="footer">
    <button id="clear-completed" data-type="clear-btn">Clear completed</button>
</footer>

Application.addModule('footer', function(context) {
    return {
        onclick: function(event, element, elementType) {
            if (elementType === 'clear-btn') {
                // Do something
            }

        }
    };
});

나라면 elementType을 굳이 로직으로 처리해야 하나라는 생각이 들었다. 이런건 사실 delegate을 써서 안에서 처리해야 하는 내용일 것 같은데 아쉬웠다.

코드가 간단해서 간만에 재미있게 봤네.

ps. 근데 왜 t3인거지?


Posted by 전용우
,

angular

프로그래밍 2015. 4. 14. 23:43

angular는 아주 옛날에 우연히 알게됐다. 그 당시에 자바스크립트 테스트에 엄청 관심이 많았던 때인데 google test blog에서 [공개]된 [jstestdriver]라는 도구를 보고 신선해 하며 좋아했다.[당시 사용기]

그래서 당시 개발자인 [misko]의 블로그를 보며 많은 도움을 받았다. 블로그 내용이 대부분은 테스트에 대한 내용이고 일부분은 흔하지 않은 FE Test에 대한 내용들이라 많은 인사이트를 얻곤 했다.

그러던 중 misko는 angular라는 자바스크립트 라이브러리를 만들었다며 [공개]를 했다. 지금은 해당 동영상이 없지만, 기억을 더듬어서 생각해보면 한 10분(?)만에 자바스크립트 없어 마크업과 속성으로만 자동완성(or TODO List)을 완성하는 동영상이였다. 지금 생각해보면 현재의 [directive]였던 것 같다.

그때 솔직한 느낌은 "이걸 누가 쓰지?"라는 생각을 했다. 

그 이유는 당시의 상황은 IE6을 지원했던 시절이고, mail, calender..와 같이 나름 복잡한 UI들이 들어 있는 서비스를 개발하는 상황에서 단순히 프로그래밍 없이 속성으로 개발을 한다는 건 뭔가 현실을 알지 못하는 개발자가 만든 느낌이였다.

(참고로 예전 만큼은 아니지만, 아직도 angular을 좋아하는 편은 아니다)

한참이 지난 지금 시점에서 보면 angular는 전세계에서 손꼽히는 프레임워크가 됐다. 그래서 한편으론 어느 정도는 "misko가 정말 시대를 앞선 사람이였구나?.."라는 생각을 한다. 

그리고 많은 사람들이 angular을 높게 평가하는 기능이 2 way binding인데 개인적으론 이 기능보다 misko의 백그라운드에서 나온 특징이라고 생각하는데.. DI을 통해 mocking하여 testability을 높여 주는 설계를 할 수 있게 해준걸 높게 평가한다.


이렇게 주저리 주저리 쓰게 된 계기가 지난 주말에 잠깐 angular 2을 보면서 "한번 더 뭔가 변하는구나.."는 생각이 들어 옛날 생각이 나서... 정리하게 됐다. ㅎㅎ


ps. backbone에 대한 추억이 있는데 언제 한번 정리해야겠다.





Posted by 전용우
,

this에 대한 글들이 너무 많아서 굳이 설명하지 않아도 되는데 오늘 글을 읽다가 이상한 내용이 있어서 정리도 할 겸해서 글을 쓴다.

전에 함수형 자바스크립트[링크] 봤는데 최근에 보고 싶은 부분이 있어서 다시 보다가 잘못된 부분을 발견했다. 나의 책을 습관 중에 하나가 안다고 생각하는 부분을 건너 읽는데 이번에 자세히 보다가 발견. -_-;

어쨌든, 59 page에 보면 아래와 같은 글이 있다.

var bFunc = function(){return this};
var b = {name : "b", fun : bFunc};

b.fun(); //=> Window 같은 어떤 객체

"의도치 않은 일이 발생했다. 객체 인스턴스 외부에서 함수를 만들었다면 this는 전역 객체를 가리킨다. 따라서 나중에 bFunc를 b.fun필드로 바인딩해도 this객체는 b자신을 가르키지 않는다."


이건 완전 잘못된 설명이다. 처음에 번역이 잘못됐나하고 원서를 봤는데 역시 잘못되어있다. 그래서 재미있게 읽고 있는데 약간의 실망감이 들었다.


일단 많은 사람들이 this가 저자처럼 만들어 질 때 결정된다고 생각하는데 절대 아니다. this는 호출할 때 결정된다. 그래서 같은 함수는 어떻게 호출하냐에 따라 this가 결정되고 this는 실행환경에서는 변경되지 않는다.

위의 예를 들면, bFunc()을 호출하면 저자가 말한 것 처럼 global이다. node.js는 global, 브라우저는 window다.  근데 b.fun();을 호출하면 b객체를 가르킨다. 그럼 b.fun과 bFunc가 다른가? 똑같다. 즉, 호출하는 방법에 따라 this가 결정된다.


그럼 어떻게 결정될까?


복잡하게 설명하면 복잡한데 기본적으로 호출하는 메서드의 "."앞이 this고 없으면 global이다.

즉, b.fun()은 .앞에 b이기 때문에 this가 b이고, bFunc()는 없기 때문에 global(window)가 된다. 이것만 알아도 this을 이해하는데 대부분은 이해된다.


요약하면,

호출할 때 method의 "."앞부분이 this이고 없으면 global이다. this는 실행될 때 결정되고 실행 환경속에서는 변경할 수 없다.

Posted by 전용우
,

EcmaScript 2015

프로그래밍 2015. 3. 25. 13:42

언제부터 정리해야지 정리해야지 하다가. W3CKIG에서 발표를 하게 되어서 꾸역 꾸역 정리했다. -_-;

사실 이미 많은 사람들이 정리해서 내용은 크게 차이는 없는데 내가 좀 흥미롭게 본 부분은 EcmaScript 2015의 goals 중 하나가 타언어가 변환하는데 EcmaScript로 잘 쓸 수 있도록 지원하는 부분이다.

이걸 보면서 EcmaScript가 플랫폼에 가까운 모습으로 가지 않나라는 생각이 든다.

어쨌든 아래는 정리한 내용.

----

이런 공개한 줄 알았는데 안했네. 

Posted by 전용우
,

Prototyping

프로그래밍 2015. 3. 18. 01:08

가끔 특정 분야의 경험이 다른 분야에서 재인(recongnition)이 되는 순간들이 종종있다. 그럴 때마다 나름 통찰을 얻게 되는데 이러한 경험을 최근에 한 적이 있어 정리를 하면 좋을 것 같아 정리를 한다.

요즘 사용자 경험 스케치[링크]라는 책을 보고 있는데 여기서는 빠르게 스케치를 하여 괜찮은 스케치들을 프로토타이핑 해보고 사용자 경험을 구체화하는 것이 괜찮은 방법이라고 조언한다.

스케치/프로토타이핑의 장점은 여러가지가 있겠지만, 내가 생각하는 장점은 쉽고 빠르게 만들고, 편히 버릴 수 있는 것이다. 또한 다른 시각에서 보는게 가능하다. 이는 한참 만들고 삽집하는 비용을 줄일 수 있다.

내 경험한 바로는 처음에 스케치나 프로토타이핑의 퀄리티를 보고 웃기기도 하고 효용성에 대해 의심했는데 생각보다 얻는게 있다. 작년에 우연히 Design Thinking 수업을 청강할 일이 있었는데 이 강의에는 프로토타이핑을 role play로 했다. 프로토타이핑이라고 해서 뭔가 만들 줄 알았는데 그게 아니라 내가 만들 도구가 있다고 생각하고 사용하는 상황을 만들어 연기를 하는 것이다. 물론 어색하지만, 시각의 변화를 통해 아무것도 없이 연기만 해도 그 동안 활동을 통해 얻지 못한 아이디어들이 발견되어 신선했다. (나는 대본을 만들고 했는데 대본없이 하는 방법도 좋다고 김창준님이 조언을 줬다. 비록 해보진 않았지만 더 번뜩이는 아이디어가 많을 것 같다.)

이와 같은 느낌을 개발하면서 느꼈다. 공통 기능을 만들어 제공하는 일이 많은데 초반에는 어떻게 만들지 interface 디자인한 후 바로 개발했다. 그러다 보면 만드는 중간이나 만들고 나서 개선하거나 문제가 생기는 상황이 많았다. 그래서 추가한 방법이 interface 디자인을 하고 코드를 사용하는 상황을 만들어 내가 사용자가 되어 코드를 작성하는 것 이다. 이렇게 하면 생각하지 못했던 상황들이 종종 발견되고 리뷰, 조언을 들을 때도 상황이 있기 때문에 좀 더 의미있는 대화가 많아진다. 이때 가끔 동작하는 코드를 만들기도 하지만 동작하지 않아도 도움이 많이 된다. 또한, 이런 코드는 테스트 코드가 되어 도움을 준다.


개인적으로 뭔가를 구체적으로 만들기 전에 위와 같이 가볍게 프로토타입핑을 해보는 것을 다양하게 활용해봐야겠다.





Posted by 전용우
,