미티어에서 가장 중요한 개념인 발행(publish)과 구독(subscribe)는 기본적으로 서버의 MongoDB에서 클라이언트의 Mini-Mongo에 데이터를 컬렉션형태로 전달하는 개념이다.
발행과 구독에 대한 자세한 설명은 아래 링크에 나와있다.
http://kr.discovermeteor.com/chapters/publications-and-subscriptions/
Google Books API를 이용하여 외부 API에서 데이터를 발행하는 프로젝트를 만들어보자.
Project 구조
Client Templates - main.html
<!doctype html>
<head> <title>pubsub2</title> </head>
<body>
<form id="add">
<input type="text" name="thumb" value="">
<input type="text" name="link" value="">
<input type="text" name="title" value="">
<input type="text" name="snippet" value="">
<input type="submit" value="Add">
</form>
<form id="search">
<input type="text" name="query" value="한국">
<input type="submit" value="Search"> </form>
{{#if searching}} <p>Searching...</p> {{else}} {{#if books.count}} <hr>
<table> {{#each books}} {{> book}} {{/each}} </table> {{/if}}{{/if}}
</body>
<template name="book">
<tr>
<td class="image"><img src="{{thumb}}"></td>
<td> <a href="{{link}}" target="_blank">{{title}}</a> <p>{{{snippet}}}</p> </td>
</tr>
</template>
Client - main.js
import {Random} from 'meteor/random';
Books = new Mongo.Collection('books');
Session.setDefault('searching', false);
Tracker.autorun(function() {
if (Session.get('query')) {
var searchHandle = Meteor.subscribe('booksSearch', Session.get('query'));
Session.set('searching', !searchHandle.ready());
}
});
Template.body.events({
'submit form#search': function(event, template) {
event.preventDefault();
var query = template.$('input[name=query]').val();
if (query)
Session.set('query', query);
}
});
Template.body.helpers({
books: function() {
// query = Session.get('query');
// console.log("query: "+query)
// return Books.find({title: {$regex: ".*" + query + ".*"}});
return Books.find();
},
searching: function() {
return Session.get('searching');
}
});
Books 컬렉션을 helper를 통해서 view에 뿌려준다.
Tracker.autorun() 안에 있는 내용은 Meteor의 시스템에서 Session과 같은 Reactive data가 변경되었을 때를 감지하여 변경이 될 경우에 다시 실행된다.
쿼리값이 변경되면 Meteor.subscribe 를 실행하여 구독해준다.
Server - main.js
import {Random} from 'meteor/random'
Books = new Mongo.Collection('books');
Meteor.publish('booksSearch', function(query) {
var self = this;
try {
var response = HTTP.get('https://www.googleapis.com/books/v1/volumes', {
params: {
q: query
}
});
_.each(response.data.items, function(item) {
var doc = {
thumb: item.volumeInfo.imageLinks.smallThumbnail,
title: item.volumeInfo.title,
link: item.volumeInfo.infoLink,
snippet: item.searchInfo && item.searchInfo.textSnippet
};
self.added('books', Random.id(), doc);
});
var initializing = true;
var handle = Books.find().observeChanges({
added: function(id, fields) {
if (!initializing) {
console.log("server - add: " + fields.title);
self.added('books', id, fields);
}
},
removed: function(id) {
console.log("server - remove: " + id);
}
});
initializing = false;
self.ready();
this.onStop(() => handle.stop());
} catch (error) {
console.log(error);
}
});
클라이언트에서 Meteor.subscribe 을 하면 서버에서는 Meteor.publish 부분이 실행된다.
이 때 보통 MongoDB에서 데이터를 가지고 올 경우에는 Books.find() 하면 해당 데이터가 구독되지만 실제로 코드 내부에서는 커서를 이용하여 .added() .ready()를 사용하는 작업을 한다.
self.added('books', Random.id(), doc);
publish 함수안에서만 호출되며 클라이언트에게 전달할 데이터를 추가한다.
self.ready();
publish 함수안에서만 호출되며 모든 데이터가 서버 쪽으로 가져오고 다른 작업이 필요하지 않음을 의미합니다.
그외에 .changed(), .removed() 등등 함수가 존재한다.
참고: https://docs.meteor.com/api/pubsub.html#Meteor-publish
observeChanges는 컬렉션의 추가, 제거, 변경 등이 일어났을 경우 콜백으로 작동한다.
실행화면:
여기서 데이터를 insert하는 부분을 만들어보면
Client - main.js
Template.body.events({
'submit form#search': function(event, template) {
event.preventDefault();
var query = template.$('input[name=query]').val();
if (query)
Session.set('query', query);
}
,
//이 부분을 추가
'submit form#add': function(event, template) {
event.preventDefault();
var thumbVal = template.$('input[name=thumb]').val();
var linkVal = template.$('input[name=link]').val();
var titleVal = template.$('input[name=title]').val();
var snippetVal = template.$('input[name=snippet]').val();
console.log(thumbVal + ' ' + linkVal + ' ' + titleVal + ' ' + snippetVal)
var books = {
thumb: thumbVal,
link: linkVal,
title: titleVal,
snippet: snippetVal
};
Books.insert(books);
}
});
input 박스로 부터 데이터를 값을 받아 collection의 insert함수로 넘겨주면 서버와 클라이언트 DB에 모두 저장된다.
*서버DB에 넘겨주지 않고 클라이언트 Mini mongo에만 저장하는 방법
*Books._collections.insert(books);
_collections를 이용하여 저장할 수 있다.
참고자료:
http://kr.discovermeteor.com/chapters/publications-and-subscriptions/
http://webframeworks.kr/tutorials/core_meteor/4_pub_sub_in_ac
https://docs.meteor.com/api/pubsub.html
http://meteorcapture.com/publishing-data-from-an-external-api/
'웹 프로그래밍 > 미티어' 카테고리의 다른 글
Meteor의 특징, Meteor 설치 가이드 (0) | 2017.05.25 |
---|