[cookbook] Meteor의 꼭 알아야할 뒷배경까기

Meteor의 뒷배경

Meteor.ui #1을 시작으로 연재를 시작했습니다. #2 편을 시작하기 전에 Meteor의 뒷배경의 호불호를 알려야 할거 같아서 이 글을 작성합니다.

hell

MongoDB 필수

meteor를 실행시키는 순간 mongodb 프로세스가 무조건 동작하게 됩니다. 이는 data를 저장하는 collection api와 관련이 있습니다. (session도 포함되나?) 포트는 일반적으로 아는바와 달리 3002 으로 실행됩니다.

$ ps ax | grep mongo
 3161 s002  S+     0:06.58 /usr/local/meteor/mongodb/bin/mongod --bind_ip 127.0.0.1 --smallfiles --port 3002 --dbpath /Users/nanhap/Projects/meteor/myapp/.meteor/local/db

그럼 어떻게 되어 있는지 접속해볼까요?

$ /usr/local/meteor/mongodb/bin/mongo --host localhost --port 3002                     
MongoDB shell version: 2.0.2                                                                  
connecting to: localhost:3002/test                                                            
> show dbs                                                                                    
local   (empty)                                                                               
meteor  0.0625GB                // meteor 라는 database가 보입니다.                                                               
> use meteor                                                                                  
switched to db meteor                                                                         
> show collections                                                                            
posts                           // 제가 테스트한 collection 입니다.         
system.indexes                                                                                
> db.posts.find()                                                                             
{ "name" : "nanhapark", "tags" : "frontpage", "_id" : "fb7ffe07-6e9f-418e-8df1-e1f92df7e14b" }
{ "name" : "nanhapark2", "tags" : "backpage", "_id" : "a8856316-56df-4432-9287-3b688d85df30" }

그럼 mongodb 데이타는 어디에 있나 궁금할 것입니다. meteor로 생성한 프로젝트 디렉토리내에 /your/project/path/.meteor/local/db 에 존재합니다.

그리고, npm 으로 meteor를 설치한 후 /usr/local/meteor 이곳에서 각종 라이브러리 파일과 mongodb 실행파일을 확인할 수 있습니다.

$ ll -R mongodb/
total 104
-rw-------  1 nanhap  admin  34520 10 15  2011 GNU-AGPL-3.0
-rw-------  1 nanhap  admin   1364 10 15  2011 README
-rw-------  1 nanhap  admin   9879 10 15  2011 THIRD-PARTY-NOTICES
drwxr-xr-x  4 nanhap  admin    136  7 10 09:24 bin

mongodb//bin:
total 30808
-rwxr-xr-x  1 nanhap  admin   3883392 12 15  2011 mongo
-rwxr-xr-x  1 nanhap  admin  11884944 12 15  2011 mongod

CONS #1

자 그럼 meteor가 추구하는 reactivity 라는 것이 어떤 영향을 background 에서 주고 있는지 알아보겠습니다.

우선 mongodb 입니다. mongodb 프로세스가 무조건 실행되는 이유는 아마도 reactivity 영향이라 생각됩니다. 지속적으로 xhr-polling을 시도하는데, 이때 mongodb 에 지속적으로 find() 명령을 요청합니다.

firebug-polling

이 상황을 지켜봤지만, 내부적으로 이런 작동을 하는지 몰랐습니다.

그럼 패킷을 보시죠.

T 127.0.0.1:55970 -> 127.0.0.1:3002 [AP]                                                             
....................meteor.posts..............                                                       
##                                                                                                   
T 127.0.0.1:3002 -> 127.0.0.1:55970 [AP]                                                             
....................................[....name.                                                       
...nanhapark..tags.                                                                                  
...frontpage.._id.%...fb7ffe07-6e9f-418e-8df1-e1f92df7e14b..[....name.....nanhapark2..tags.....backpa
ge.._id.%...a8856316-56df-4432-9287-3b688d85df30..                                                   
##                                                                                                   
T 127.0.0.1:55970 -> 127.0.0.1:3002 [AP]                                                             
P...................admin.$cmd.........)....replSetGetStatus......forShell......                     
##                                                                                                   
T 127.0.0.1:3002 -> 127.0.0.1:55970 [AP]                                                             
\...................................8....errmsg.....not running with --replSet..ok..........         
#                                                                                                    

이는 db.collection.find() 할 때 나오는 패킷과 동일합니다. 이것을 주기적으로 요청하여 변화량을 감지합니다. 물론 이 주기를 설정할 수 있도록 API가 준비되어 있습니다. 아래 전체적인 polling packet 보시죠.

interface: lo0 (127.0.0.0/255.0.0.0)
filter: (ip) and ( port 3002 )
#####
T 127.0.0.1:55358 -> 127.0.0.1:3002 [AP]
;...................meteor.$cmd..............ismaster......
##
T 127.0.0.1:3002 -> 127.0.0.1:55358 [AP]
W...{...............................3....ismaster...maxBsonObjectSize......ok........?.
##
T 127.0.0.1:55358 -> 127.0.0.1:3002 [AP]
*...................meteor.posts..........
##
T 127.0.0.1:55358 -> 127.0.0.1:3002 [AP]
R...................meteor.$cmd.........*....count.....posts..query......
fields..
##
T 127.0.0.1:3002 -> 127.0.0.1:55358 [AP]
@...|....................................n..........ok........?.
##
T 127.0.0.1:55358 -> 127.0.0.1:3002 [AP]
|...................meteor.posts.[....name.
...nanhapark..tags.
...frontpage.._id.%...fb7ffe07-6e9f-418e-8df1-e1f92df7e14b..
##
T 127.0.0.1:55358 -> 127.0.0.1:3002 [AP]
?...................meteor.$cmd..............getlasterror......
##
T 127.0.0.1:3002 -> 127.0.0.1:55358 [AP]
S...}.............................../....n......connectionId.....
err..ok........?.
##
T 127.0.0.1:55358 -> 127.0.0.1:3002 [AP]
|...................meteor.posts.[....name.....nanhapark2..tags.....backpage.._id.%...a8856316-56df-4432-9287-3b688d85df30..
##
T 127.0.0.1:55358 -> 127.0.0.1:3002 [AP]
?...................meteor.$cmd..............getlasterror......
##
T 127.0.0.1:3002 -> 127.0.0.1:55358 [AP]
S...~.............................../....n......connectionId.....
err..ok........?.
##
T 127.0.0.1:3002 -> 127.0.0.1:55358 [AP]
........)...........................[....name.
...nanhapark..tags.
...frontpage.._id.%...fb7ffe07-6e9f-418e-8df1-e1f92df7e14b..[....name.....nanhapark2..tags.....backpage.._id.%...a8856316-56df-4432-9287-3b688d85df30..
##
T 127.0.0.1:55358 -> 127.0.0.1:3002 [AP]
....*...............meteor.posts..............
##
T 127.0.0.1:3002 -> 127.0.0.1:55358 [AP]
........*...........................[....name.
...nanhapark..tags.
...frontpage.._id.%...fb7ffe07-6e9f-418e-8df1-e1f92df7e14b..[....name.....nanhapark2..tags.....backpage.._id.%...a8856316-56df-4432-9287-3b688d85df30..
##
T 127.0.0.1:55358 -> 127.0.0.1:3002 [AP]
....+...............meteor.posts..............
##
T 127.0.0.1:3002 -> 127.0.0.1:55358 [AP]
........+...........................[....name.
...nanhapark..tags.
...frontpage.._id.%...fb7ffe07-6e9f-418e-8df1-e1f92df7e14b..[....name.....nanhapark2..tags.....backpage.._id.%...a8856316-56df-4432-9287-3b688d85df30..
##
T 127.0.0.1:55358 -> 127.0.0.1:3002 [AP]
....,...............meteor.posts..............
##
T 127.0.0.1:3002 -> 127.0.0.1:55358 [AP]
........,...........................[....name.
...nanhapark..tags.
...frontpage.._id.%...fb7ffe07-6e9f-418e-8df1-e1f92df7e14b..[....name.....nanhapark2..tags.....backpage.._id.%...a8856316-56df-4432-9287-3b688d85df30..
##
T 127.0.0.1:55358 -> 127.0.0.1:3002 [AP]
....-...............meteor.posts..............
##
T 127.0.0.1:3002 -> 127.0.0.1:55358 [AP]
........-...........................[....name.
...nanhapark..tags.
...frontpage.._id.%...fb7ffe07-6e9f-418e-8df1-e1f92df7e14b..[....name.....nanhapark2..tags.....backpage.._id.%...a8856316-56df-4432-9287-3b688d85df30..
…
…
…
…
…
…
계속 반복되는 mongodb polling 합니다.

MongoDB polling? 이거 쫌 너무한데…. 데이타가 많으면 어쩌실려고 이런 polling 을… ;; 앞으로 개선되길 바랍니다.

CONS #2

배경

웹페이지는 구조적인 문서이고, 이를 javascript, css와 결합하여 더욱 멋진 효과를 낼 수 있습니다. 즉 다시 말하면, html, javascript, css 는 각자 독립적으로 역할을 해야 한다는 것입니다. 어느하나 dependency 하면 안됩니다. 하지만, 근래 웹페이지는 javascript 없이 HTML은 동작하지 않은것이 현실입니다. javascript를 웹페이지 삽입하여 효과를 내고자 한다면, 최소한 HTML 로딩에 영향을 주지 않기 위한 여러가지 방법이 나와 있는데, 가장 적절한것이 </body> 위에 넣는 것입니다. 즉, 웹페이지 로딩에는 javascript따위가 간섭하여 웹페이지 로딩을 지연시키는것을 방지하자는 목적입니다. 한발짝 더 나아간다면 domready line 뒷 시점으로 로딩하는 labjs, headjs … 를 사용하는 것도 좋습니다. 페이스북의 waterfall diagram 한번 보시죠.

facebook

파란선이 domready 라인이고, 빨간선이 onload 시점라인입니다. javascript가 이렇게 많이 로딩되면서 domready 시점에 영향을 절대로 주지 않고 있습니다.

아래는 최초 meteor가 안내해주는 localhost:3000 접속한 패킷입니다.

######                                                                                                                                                                                         [1294/1920]
T 127.0.0.1:51457 -> 127.0.0.1:3000 [AP]
GET / HTTP/1.1.
Host: localhost:3000.
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:13.0) Gecko/20100101 Firefox/13.0.1.
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8.
Accept-Language: ko-kr,ko;q=0.8,en-us;q=0.5,en;q=0.3.
Accept-Encoding: gzip, deflate.
Connection: keep-alive.
Cache-Control: max-age=0.
.

##
T 127.0.0.1:3000 -> 127.0.0.1:51457 [AP]
HTTP/1.1 200 OK.
content-type: text/html.
connection: keep-alive.
transfer-encoding: chunked.
.
12f4.

12f4 chunk size 알려주고요. 그 만큼 읽어드립니다.

##
T 127.0.0.1:3000 -> 127.0.0.1:51457 [AP]
<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" href="/myapp.css?9297ad4aa173c4e0c19aebd27c62a5c43242bb93">


<script type="text/javascript">
__meteor_runtime_config__ = {};

</script>

  <script type="text/javascript" src="/packages/underscore/underscore.js?772b2587aa2fa345fb760eff9ebe5acd97937243"></script>
  <script type="text/javascript" src="/packages/meteor/client_environment.js?b157cf590c380de2b08e97439017132517a1ea4b"></script>
  <script type="text/javascript" src="/packages/meteor/helpers.js?71d94de5b2e532dba62dcbf68be35f05d6ba7834"></script>
  <script type="text/javascript" src="/packages/meteor/timers.js?751790703a2d75d770e3a46b896d1e2b6ebf2dab"></script>
  <script type="text/javascript" src="/packages/meteor/dynamics_browser.js?0dba61d7ab17d06bcbbb8cc24d3ec2b8eab136c9"></script>
  <script type="text/javascript" src="/packages/deps/deps.js?f8cf99fe4b1eaaf75f0f0df346ea65f11d49119b"></script>
  <script type="text/javascript" src="/packages/logging/logging.js?b9c522c3b350fdcf851971f3373c042776bd3ec4"></script>
  <script type="text/javascript" src="/packages/json/json2.js?b6fa2247d96bb52f6fd1be0e21414e71c8e6c8d0"></script>
  <script type="text/javascript" src="/packages/reload/reload.js?5c82c8d9acc1bab7488b333142dac992be096de1"></script>
  <script type="text/javascript" src="/packages/session/session.js?1b357412ec4fbc237503bac28cba6596739607cc"></script>
  <script type="text/javascript" src="/packages/uuid/uuid.js?c7e0f800b5fa9d7f9b93fd2b8861e299b7705917"></script>
  <script type="text/javascript" src="/packages/stream/sockjs-0.3.1.js?8ce34d6c5d32220265d00fa69f276944cfc3aa35"></script>
  <script type="text/javascript" src="/packages/stream/stream_client.js?78f233e1e7dcc64fee38c0709f18c1f18e16ecdc"></script>
  <script type="text/javascript" src="/packages/minimongo/minimongo.js?18e700c18433ca8bd4d8e2a61d6bf4e0ca38e9c4"></script>
  <script type="text/javascript" src="/packages/minimongo/selector.js?578d2e13347d3d352292820f3864795c2d4ff7e3"></script>
  <script type="text/javascript" src="/packages/minimongo/sort.js?136c6aef9d5ee6e98cd3458e123f07b2dc97b0c4"></script>
  <script type="text/javascript" src="/packages/minimongo/uuid.js?c7951b84520d018dc4c5c3345d3c6eda3aefafd5"></script>
  <script type="text/javascript" src="/packages/minimongo/modify.js?bf153b2f3f4b1e7e7cb92b9ec45f33bf29470a19"></script>
  <script type="text/javascript" src="/packages/minimongo/diff.js?b6eea41bc2810a57e5c9f2d3c1d31ccaaded0e2f"></script>
  <script type="text/javascript" src="/packages/livedata/livedata_common.js?773a10abb9382b8c09f3fec5d093ae5c2312e405"></script>
  <script type="text/javascript" src="/packages/livedata/livedata_connection.js?ea1a42f17f205bb759d07ec7f699138e4f98c3a1"></script>
  <script type="text/javascript" src="/packages/livedata/client_convenience.js?2dc0295b95003f0d71c4bd502a8550c704ceb969"></script>
  <script type="text/javascript" src="/packages/mongo-livedata/local_collection_driver.js?da7264171ea833248c328c5260b0c1cdd88505e4"></script>
  <script type="text/javascript" src="/packages/mongo-livedata/collection.js?9abd0002ec6cc4fa756d1a1eca1f63eb7e344d6b"></script>
  <script type="text/javascript" src="/packages/jquery/jquery.js?0d7896e2bb23f88e26e52b22a075350b354df447"></script>
  <script type="text/javascript" src="/packages/liveui/liveevents_w3c.js?06b5518cfb6016d193301424d16c062a5b1252a2"></script>
  <script type="text/javascript" src="/packages/liveui/liveevents_now3c.js?5e11cd968e999ac40beab39dea52c590074de8bf"></script>
  <script type="text/javascript" src="/packages/liveui/liveevents.js?5fb40c8650dc69fcb73125bc6d01a055221f6e5d"></script>
  <script type="text/javascript" src="/packages/liveui/liverange.js?404a971eacc9de214a6e5215ac3356dd76f0acd0"></script>
  <script type="text/javascript" src="/packages/liveui/liveui.js?8db4ad83e4a673fed96e7b4b519e64ca33a5f86f"></script>
  <script type="text/javascript" src="/packages/liveui/innerhtml.js?851934560da34a3cd81ef497095b290acdd85c43"></script>
  <script type="text/javascript" src="/packages/liveui/smartpatch.js?34a3dabf43b5eb9719b11a93d7e5fafc43ecfa69"></script>
  <script type="text/javascript" src="/packages/templating/deftemplate.js?faaaa542ffa1357a99ffacebd8e9326fc20dd6b7"></script>
  <script type="text/javascript" src="/packages/startup/startup_client.js?11f135cd7902c8bb2b6c2116f4c6b5b75e27162e"></script>
  <script type="text/javascript" src="/packages/handlebars/evaluate.js?f1f25693b48efd2f92f56801fe1295f61c8f77dd"></script>
  <script type="text/javascript" src="/packages/past/past.js?113a23ab979bc394bb29f16cdec1b2d7e420de54"></script>
  <script type="text/javascript" src="/template.myapp.js?a85fb75078cdd75ce3749eebfa1712fa4ed07dd8"></script>
  <script type="text/javascript" src="/myapp.js?ec02178975d2d123dfaaf44df71b87e3d097b748"></script>
<title>myapp</title>
</head>
<body>

</body>
</html>

헉. 이게 뭘까요? apple에서 만든 SproutCore를 보는거 같군요. 아니 DomReady 시대에 HEAD에다가 이렇게 많은 자바스크립트를 때려밖는 다는게 어이가 없네요.

사이즈는 179.5 KB 입니다. http://code.jquery.com/jquery-1.8.0.min.js 이 82 KB 이니 굉장히 큰것입니다.

Conclusion

앞으로 meteor연재를 계속 하겠으나, 이런 뒷배경은 알려드려야 할거 같아서 작성합니다. 그럼 수고하세요. 감사합니다.

추천 관련글