기본 콘텐츠로 건너뛰기

한방에 뷰에서 데이터 베이스까지?! Model-View Autosubscribe.

요몇일 Meteor에 완전 정신없이 빠져있었는데
불만도 많고 엉성하기도 하지만 예전에 만들려고 했었던 프레임웤이랑 사상이 너무 비슷한 부분이 많아서 마치 뇌스캔 당한 기분이기도 했다.
몇가지 특징을 순서없이 꼽아보자면

  • 서버와 클라이언트가 마치 하나의 어플리케이션처럼 이어져있다. 마치 옛날의 RAD환경처럼.
  • 저장=디플로이. 사실 이거 되는 건 많은데 서버랑 클라이언트가 동시에 적용된다.
  • 뷰-모델 바인딩. Database 를 수정하면 뷰까지 함께 바뀐다.
  • backbone.js를 이용한 클라이언트쪽 Routing.
  • 클라이언트 콘솔에서 직접 데이터베이스 관련 커맨드를 날려볼 수 있다. 아직은 안막아 놓았는데 개발 편의를 위해선 좋지만 보안면에선 완전 꽝이라고 생각할 수 있지만 언제든지 meteor remove insecure하면 된다.
  • 간편한 디플로이. 과연 호스팅쪽 백엔드를 어떻게 할지는 모르겠지만 현재는 meteor deploy <appname>.meteor.com 명령만으로 디플로이 가능
  • 이하 인상적인 패키지들. 매우 참고가 되었음.
  • minimongo
  • fiber 를 이용한 coroutine

더 많지만 내겐 이정도가 인상적이었다.
그중 MVVM프레임워크인 knockout.js 등에서도 Meteor 에서도 흥미로왔던 모델=뷰 바인딩(이하 Autosubscribe라고 하겠음)기법에 대해서 한번 구현해 보고자 한다.
마치 마법같은 일인데 일단 모델만 써보자 (요즘 쓰고 있는 CoffeeeScript 스타일로 ,를 뺐다)
employees = {
  employee : [
    {
      "name" : "Scott"
      "department" : "TF Team"
    }
    {
      "name" : "Tiger"
      "department" : "SE Team"
    }
  ]
}
이런 모델을

<ul class="employees">
  <li class="employee">
    <ul>
      <li class="name">
        Scott
      </li>
      <li class="department">
        TF Team
      </li>
    </ul>
  </li>
  <li class="employee">
    <ul>
      <li class="name">
        Tiger
      </li>
      <li class="department">
        SE Team
      </li>
    </ul>
  </li>
</ul>
모델에서 데이터를 변경하면 위와 같이 바로 뷰에서도 반영이 되도록 하려면 어떻게 해야할까?
무한 루프를 돌면서 계속 모델을 감시하다가 변경이 있을때 뷰를 갱신하게 할 수도 있겠지만 너무 무식한 방법이다.

사실 아이디어는 단순한 부분부터 시작한다.
console.log(employees.employee[0].name);
employees.employee[0].name = "David";

이런 식으로 접근하는 걸 setter/getter 로 보면
console.log(employees.employee[0].getName());
employees.employee[0].setName("David");

사실 이것과 크게 다르지 않다.
employee 객체를 보면 이런 식이 되겠지.
var employee = function() {
  return {
    name:"",
    department:"",
    setName:function(val) {
      this.name = val;
    },
    getName:function() {
      return this.name;
    }
  };
};

var emp = new employee();
emp.setName("Scott");
console.log(emp.getName());

http://jsbin.com/amopak 에 일단 링크.

employee.setName 을 할때 특정 객체를 바인딩하면 좋겠다.
var employee = function() {
  return {
    name:"",
    department:"",
    setName:function(val) {
      this.name = val;
      $(".name").text(val);
    },
    getName:function() {
      return $(".name").text();
    }
  };
};

var emp = new employee();
emp.setName("Scott");
console.log(emp.getName());

바인딩이라고 이런식으로 구현이 가능하겠다. 물론 input 이면 text 대신 val을 디테일로 가면 더 복잡하겠다.
여러개가 있을 수 있으니 특정 DOM아래에 붙도록 해보자.

var employee = function(target) {
  return {
    name:"",
    department:"",
    setName:function(val) {
      this.name = val;
      $(target).find(".name").text(val);
    },
    getName:function() {
      return $(target).find(".name").text();
    }
  };
};
http://jsbin.com/amopak/3 중복을 만들고 중복을 계속 제거해나가는 식의 접근을 하고 있다.

http://jsbin.com/amopak/7

다른 속성도 넣고 중복도 제거해보자.
var employee = function(target) {
  return {
    set:function(key,val) {
      target.find('.'+key).text(val);
    },
    get:function(key) {
      return target.find('.'+key).text();
    }
  };
};
http://jsbin.com/amopak/5 employee의 set 과 get method 로 하위 셀렉터를 접근할 수 있다.

Meteor관련 링크 첨부.


이 블로그의 인기 게시물

meteor로 nw.js 개발하기.

실제로 nw.js 어플리케이션을 개발하다보면 UI구현하기 막막하고 수동으로 리프레쉬 하는 것도 귀찮아서 Meteor 연동을 하려고 했더니 생각보다 간단했다.

디렉토리 구조는 먼저 이렇게 잡았다.
`- app
  `-client
  `-public
`- dist
  `- 배포용 html,css,js
  `- package.json
`- package.json 아이디어는 이렇다. nw.js의 시작페이지를 http://localhost:3000으로 두고 배포시엔 meteor client 배포툴인 meteor-build-client를 사용하여 html,css,js 로 분리하는 계획이다.

가장 중요한 nw.js 용 package.json 파일은 아래와 같이 구성한다.
{
  "main": "http://localhost:3000",
  "node-remote": "http://localhost:3000",
  "name": "<앱이름>"
} 이게 전부. 어떻게 보면 Web과 nw.js를 동시에 개발할 수도 있는 환경이기도 한 것이다.
meteor create app 을 해서 meteor용 앱을 만들고 meteor 를 시작한다.
그리고, 위의 package.json이 있는 경로로 돌아가서 nw . 으로 nwjs를 실행한다.

한번 번쩍하더니 잘 된다.
cordova 등에서 index.html 대신 http://localhost:3000을 하는 것도 비슷한 느낌이다.

즐겁게 개발을 일단 마구 하고 실제로 배포하기 위해서는 개발환경이 아니라 html,css,js로 구성된 배포본을 만들어야한다.
npm install -g 해도 되지만 어짜피 Meteor에서만 쓸거
meteor npm install -g meteor-build-client 해버릴거다.

개발은 문제 없어 보이고 배포판을 한번 만들어보자. meteor app 이 있는 경로(meteor run으로 …

RxJS - ReactiveX 인터뷰

A: 왜 RxJS입니까
B: javascript는 참 쉽고 친숙한 언어죠.
A: 별로 그렇게 생각 안합니다만.
B: 그래서 좀 어렵고 있어보이는게 뭘까 싶어서...
A: 네?
B: 함수형이라는게 유행하기도 하고
f(x) 좋쟎습니까? 미스테리~ 미스테리~ 정수정짱짱 으아아

이런 수학선생님이라면 수포자 따윈 A: ...
B: 그리고 반응형이라는 말 뭔가
A: 뭔가?
B: 대충대충해도 막 알아서 할거 같고...
A: 그럴리가요?
B: 안그렇겠죠?
A: 네
B: 네

(잠시만 기다려주세요)

A: 그래도 뭔가 매력이 있으니 이렇게 시간을 내셔서 이것저것 Rx에 대해 글도 쓰고 이야기도 하고 그러시는거 아닌가요?
B: 매력이라.
으음.
제가 팔꿈치 터널 증후근이 좀 있어요.
오른손 세끼손가락, 약지손가락이 저립니다.
A: 무슨 상관이?
B: 그래서 각종 괄호를 쓰는게 너무 힘듭니다.
소중대괄호 만든 사람 죽었으면.
Hello world (ASCII): https://esolangs.org/wiki/Parenthesis_Hell
A: 이미 옛날에 돌아가셨겠죠.
B: 그렇겠네요.
아무튼 그래서 소중대괄호 의존이 적은 커피스크립트를 쓰는데요.
A: 빨리 본론을 말씀해주시죠.
B: 커피스크립트에서 가로로 80자 이상쓰면 Line exceeds maximum allowed length 라고 경고해요.
A: 그래서요?
B: 근데 Rx를 쓰면 코드를 가늘게 쓸 수가 있더라구요.
A: 호오?
B: 그리고 = 쓰는 것도 너무 힘듭니다.
A: 네?
B: 오른손을 쓰쟎아요.
A: ...
그러니까 정리하면
1. 괄호가 힘들다
2. 커피를 쓴다
3. 커피는 길게 쓰면 경고
4. Rx를 쓰면 코드가 가늘다
5. 대입문을 줄이고 싶다.
B: 네
하지만 5번은 생각보다 별로...
A:
B:

B: 아!
A: ?
B: 코드가 가늘어서 좋은 점이.
A: 네.
B: 핸드폰에서 코드를 보기 좋습니다.
A: ... 왜 팔꿈치 터널 증후근이 안 낫는지 알겠습니다.
B: 도와주세요.
쇠고기 사묵으면 나을 것 같습니…

Troubleshooting - Meteor package가 적용이 되지 않을 때

버전 1.5 기준 package.js에서 Package.onUse 에 새 패키지를 추가했는데 인식하지 못하는 경우가 있다.
Package.onUse((api) => {
  api.use([
    'vulcan:core',
    'vulcan:forms',
    'vulcan:accounts' /* <-- 추가함! */
  ]);
...
} 내부패키지건 원격패키지건 안되는 안된다. 이럴 때 meteor add 후 meteor remove 해도 되지만 더 간단한 방법이 있다. meteor update vulcan:accounts 이렇게 update 해주는 방법이 있다. .meteor/package 파일을 건들지 않아서 좋다. 그래도 역시 좋지 않다. Meteor 스럽지 않다. https://github.com/meteor/meteor/issues/7721 현재 1.5.2에서도 해결이 안되었군요. 해결되어 적용되면 다시 글 올리겠습니다.