2015년 8월 26일 수요일

Om - 기본 튜토리얼 따라하기

오늘은 Om 튜토리얼 중 기본을 따라가봤다.  (사이드바 링크에 Intermediate/Advanced도 있음!)

Om은 React.js의 ClojureScript 바인딩 라이브러리다. ClojureScript 쪽에서 워낙에 유명한 David Nolen이 만든 라이브러리이고, React.js를 래핑한 라이브러리이면서 더 나은 성능을 보이는 특이한 라이브러리다. (물론 더 빠를 수야 없겠지만 Plain JS로 개발할 때에는 기본적으로 꺼둘수 밖에 없는 최적화 옵션을 ClojureScript에선 기본으로 켜 놓을 수 있기 때문이다.)

야, 이건 꼭 해봐야겠다~ 싶었던 Figwheel을 기본으로 진행! Good!

Basic이면서 꽤나 길게 설명되어 있어서 결국 마지막 단계는 눈으로만 보고 끝내버렸는데, 내일 시간내서 코드 보지 않고 쭈욱 따라가는 연습을 더 해봐야겠다.

오늘 보면서 느낀 점, 궁금한 점 등을 남긴다.

  • Figwheel의 REPL은 Browser Connected REPL과 어떤 관계일까?
  • reify 매크로는 anonymous type & its instance 를 만들기 위한 것. 프로토콜이나 인터페이스를 구현할 목적으로 사용할 수 있다. Om에서는 reify를 주로 사용하나? 직접 타입을 만드는 것은 Clojure Idiomatic 하지 않은 것인가?
  • 아래와 같은 코드가 잠깐 나오는데,  (.. e -target -value) 부분에서 잠깐 막혔다.  (..) 매크로 는 Java(Script) Interop 중 하나. 뒤에 멤버를 계속 연결하여 값을 얻을 수 있다. 멤버는 (.method arg)나 -field 중 하나. (->) 매크로와 사용 목적이 비슷하다. 매크로가 너무 많은 것 아닌가? 몇가지 표준적인 방법을 제공하고 일관된 코드를 추구하는 것이 나을 것 같은데, 개인들의 스타일에 따라 너무 달라질 것 같다. 

(defn handle-change [e owner {:keys [text]}]
  (om/set-state! owner :text (.. e -target -value)))

  • #js 라는 tagged literal 도 뭔가 헷갈렸다. reader가 이어지는 데이터를 어떻게 처리할지 지정하기 위한 것. built-in으로는 #inst와 #UUID가 있다. ClojureScript에선 #js가 built-in인 모양이다. 이어지는 리스트/맵을 JavaScript Object로 생성하기 위함.
  • 버튼 이벤트를 처리하는 부분을 core.async로 처리했는데, 적당한 방법인지? Intermediate/Advanced 튜토리얼에 답이 있기를.  왜냐면 이건 너무 귀찮은 방법이니까! 특히 아래와 같이 직접 put!으로 데이터를 던지고 go/loop/recur로 처리하는 건 좀 아닌것 같다. 좀더 reactive한 방법이 없다면 cycle.js로 ...
 (dom/button #js {:onClick (fn [e] (put! delete @contact))} "Delete")))))


        (go (loop []
          (let [contact (<! delete)]
            (om/transact! data :contacts
              (fn [xs] (vec (remove #(= contact %) xs))))
            (recur))))))

  • mapv 가 뭘까? 코드만 보면서 유추해보려다 포기했는데, 답은 strict 버전이라는 것. map이 lazy 버전인데, Om은 Lazy와 잘 맞지 않는다고! 그래서 map대신 mapv를 여기저기 많이 쓰게 된다. lazy가 장점이라고 했다가 결국은 non-lazy를 선택적으로 사용해야 하는 상황은 어쩐지 선택지가 늘어나서 정밀하게 컨트롤할수 있다는 장점같으면서도 개발자를 더 불편하게 만드는 요소가 아닐까 싶다. 하스켈과도 마찬가지!
  • 그건 그렇고 아래의 코드는 정말 이해하기 어려웠다. map 자료형이 그 자체로 함수처럼 동작하여 key -> value 가 되기도 하고, key가 함수처럼 동작하여 map -> value 가 되기도 하는데, 그 두가지 방법이 다 적용되어 있다. 게다가 if는 else-branch가 없어서 결과에는 nil이 포함되어 있을거다. Haskell/Scala등으로 타입에 많이 중독된 입장에서 보자면 매우 불안불안한 코드.

(defn people [data]
  (->> data
    :people
    (mapv (fn [x]
            (if (:classes x)
              (update-in x [:classes]
                (fn [cs] (mapv (:classes data) cs)))
               x)))))



결론적으로,
  • 여전히 Clojure(Script)에 대해 모르는게 많고,
  • 마음에 안드는 부분들이 있는데, 
  • 이건 아직 제대로 된 방법을 잘 몰라서 그런 것일 뿐이라고 보고 일단은 Go~

댓글 없음:

댓글 쓰기