SlideShare a Scribd company logo
+
MEAN 스택을 사용한 IoT 개발
박재호(jrogue@gmail.com)
+
MEAN이란?
+
+
TESSEL 모듈 유형
+
TESSEL 스펙
+
Beagle Bone Black
+
bonescript
n  Beagle Bone에서 아두이노 스타일의 프로그램이 가능하게 만들어
주는 자바스크립트 라이브러리
+
AWS Lambda(1)
+
AWS Lambda(2)
+
AWS Lambda(3)
+
heimcontrol.js(1)
Raspberry PI and Arduino using Node.js
+
heimcontrol.js(2)
Socket.io(for Websockets)
Requirejs
HTML5/CSS3
Jade(for
templating)
+
Node.js인 이유는?(1)
+
Node.js인 이유는?(2)
n  개발 시간과 성능의 조화
n  아무리 성능이 좋더라도 개발 시간이 오래 걸릴 경우 생산성이 떨어진다
n  주의: 1행을 작성하는 시간은 어셈블리나 SQL이나 비슷하다
n  스크립트 언어의 경우 빨리 개발은 가능하지만 성능이 떨어진다
n  자바스크립트를 사용한 Node.js는 개발과 성능 양쪽 모두 뛰어나다
n  스타트업 vs 기업
n  스타트업은 빨리 변화하는 생태계에서 살아남기 위해 필연적으로 오픈
소스에 매진한다
n  대기업은 유지보수와 안정성, 그리고 성능에 관심이 많다
n  Node.js는 양쪽 모두를 만족시킨다(오픈 소스 기반, 자바와 같은 강력한
생태계)
+
Node.js인 이유는?(3)
n  뛰어난 성능
n  월마트는 블랙 프라이데이에 Node.js로 전제 모바일 사이트 오픈
n  초당 두 배 요청을 받아들이고 응답시간을 35%(200ms) 줄임
n  서버 CPU 사용량이 2%, 200만 명 온라인 접속 방어
n  이벤트 아키텍처
n  스레드가 아닌 단일 프로세스
n  대신 동기식 차단이 아닌 비동기식 I/O
n  웹 브라우저 특성상 이미 자바스크립트는 콜백을 사용하는 이벤트 구
동 방식을 지원(비동기식 코드에 대한 표현력이 강함)
+
동기식 입출력 vs 비동기식 입출력
+
멀티 스레드 vs 단일 스레드
+
LAMP vs MEAN
+
자기 조직화
+
MEAN stack 아키텍처
+
선행조건
n  MEAN 기본 스택 준비
n  Node.js 설치: http://nodejs.org/
n  MongoDB 설치: http://www.mongodb.org/
n  자바스크립트 편집기는 brackets 추천: http://brackets.io/
n  예제 소스 코드 저장소 위치
n  Node.js용 node-collector: https://bitbucket.org/jrogue/node-
collector
n  AngularJS용 angular-lamp-app: https://bitbucket.org/jrogue/
angular-lamp-app
+
무엇을 만들어볼까?
lamp 관리 시스템
+
기본 아키텍처
+
첫 Node.js 프로그램: /
server_plain_vanilla.js
/*jslint node: true */
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello Worldn');
}).listen(3000, '127.0.0.1');
console.log('Server running at http://127.0.0.1:3000/');
+
Node.js 프로그램을 위한 패키지 설
정: /package.json
{
"name": "node-collector",
"private": true,
"version": "0.1.0",
"description": "A starter project for Node.js",
"license": "MIT",
"devDependencies": {
"express": "4.x",
"body-parser": "1.4.x“,
"mongoose": "^3.8.20"
}
}
+
의존성 설치와 목록
+
Node.js를 사용한 첫 RESTful 프로그
램: /server.js
var express = require('express');
var app = express();
app.get('/lamps', function(req, res) {
res.send([{name: 'lamp1'}, {name: ‘lamp2'}]);
});
app.get('/lamps/:id', function(req, res) {
res.send({id:req.params.id, name: "lamp" + req.params.id, status: "lamp
ready"});
});
app.listen(3000);
console.log('Listening on port 3000...');
+
실행과 테스트 방법
+
Node.js 모듈 사용: /routes/lamps.js
exports.findAll = function (req, res) {
res.send([{name: 'lamp1'}, {name: 'lamp2'}, {name: ‘lamp3'}]);
};
exports.findById = function (req, res) {
res.send({id: req.params.id, name: "lamp" + req.params.id, status: "lamp
ready"});
};
var express = require('express'),
bodyParser = require('body-parser'),
lamps = require('./routes/lamps.js');
var app = express();
app.get('/lamps', lamps.findAll);
app.get('/lamps/:id', lamps.findById);
app.listen(3000);
console.log('Listening on port 3000...');
+
몽고DB 연동을 위한 준비: /db.js
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/lamps', function () {
console.log('mongodb connected')
});
module.exports = mongoose;
+
몽고DB 모델 생성: /models/lamp.js
var db = require('../db');
var Lamp = db.model('Lamp', {
lampname: { type: String, required: true },
status: { type: String, required: true },
date: { type: Date, required: true, default: Date.now }
});
module.exports = Lamp;
+
Node.js 모듈 내용 변경(1): /routes/
lamps.js
var Lamp = require('../models/lamp');
exports.addLamp = function (req, res, next) {
var lamp = new Lamp({
lampname: req.body.lampname,
status: req.body.status
});
lamp.save(function (err, lamp) {
if (err) { return next(err); }
res.status(201).json(lamp);
});
};
+
Node.js 모듈 내용 변경(2): /routes/
lamps.js
exports.updateLamp = function (req, res, next) {
Lamp.findOne({ _id: req.params.id }, function (err, lamp) {
if (err) { return next(err); }
lamp.status = req.body.status;
lamp.save(function (err, lamp) {
if (err) { return next(err); }
res.status(201).json(lamp);
});
});
};
exports.deleteLamp = function (req, res, next) {
Lamp.remove({ _id: req.params.id }, function (err, lamp) {
if (err) { return next(err); }
res.status(201).json(lamp);
});
};
+
Node.js 모듈 내용 변경(3): /routes/
lamps.js
exports.findAll = function (req, res, next) {
Lamp.find(function (err, lamps) {
if (err) { return next(err); }
res.status(201).json(lamps);
});
};
exports.findById = function (req, res, next) {
Lamp.findOne({ _id: req.params.id }, function (err, lamp)
{
if (err) { return next(err); }
res.status(201).json(lamp);
});
};
+
CRUD 전체 정의를 위한 변경: /
server.js
var express = require('express'),
bodyParser = require('body-parser'),
lamps = require('./routes/lamps.js');
var app = express();
app.use(bodyParser.json());
app.post('/lamps', lamps.addLamp);
app.get('/lamps', lamps.findAll);
app.get('/lamps/:id', lamps.findById);
app.put('/lamps/:id', lamps.updateLamp);
app.delete('/lamps/:id', lamps.deleteLamp);
app.listen(3000);
console.log('Listening on port 3000...');
+
서버 시작
n  서버 시작
n  $ node server
n  주의: 서버 시작에 앞서 지역 호스트(localhost)에 몽고DB를 설치
하고 시작했는지 반드시 확인하자!
+
단말 쪽 프로그래밍
n  REST 방식으로 API를 호출하면 된다
n  단말 조건: TCP/IP 스택이 설치되어 있으며, REST 클라이언트 라이브러
리를 사용할 수 있어야 한다.
n  만일 리눅스 기반으로 동작하는 단말인 경우 뒤에 테스트 예제에서
설명하는 curl을 system으로 호출하면 아주 쉽게 구현 가능하다.
n  C 언어로 개발할 경우 libcurl을 사용할 수도 있다.
n  스크립트 언어로 개발할 경우 스크립트 언어의 REST 클라이언트 패
키지를 사용하면 몇 줄로 서버 쪽에 자신의 상태를 전달할 수 있다.
n  이어지는 테스트 예제를 보며 CRUD 전달 방식을 확인하자.
+
CRUD 테스트: POSTMAN vs curl
크롬 확장: REST 클라이언트
http://curl.haxx.se/ (홈페이지)
http://www.confusedbycode.com/curl/ (윈도우 32비트/64비트)
참고: 여기서는 설명의 편의를 위해 cURL을 사용한다!
+
서버 구동 후 생성 테스트(curl 사용)
+
몽고DB 셸을 사용한 확인
+
(전체) 읽기 테스트
+
변경 테스트
+
(변경 내역 반영 검증을 위한) 읽기 테
스트
+
삭제 테스트
+
최종 확인
+
Single Page Application
+
MVC vs MVVM
+
AngularJS 샘플 앱의 디렉터리 구조
+
/index.html
<!DOCTYPE html>
<html ng-app="LampApp">
<head>
<link href="styles/main.css" rel="stylesheet">
<link rel="stylesheet" ref="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
</head>
<body>
<ul class="menu">
<li><a href="#/notice">notice</a></li>
<li><a href="#/list">list</a></li>
</ul>
<div class="container" ng-view=""></div>
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.5/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.5/angular-resource.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.5/angular-route.min.js"></script>
<script src="scripts/app.js"></script>
<script src="scripts/services/services.js"></script>
<script src="scripts/controllers/controllers.js"></script>
</body>
</html>
+
views/list.html
<div class="span6">
<table class="table table-striped table-condensed">
<thead>
<tr>
<th style="min-width: 300px;">Lamp ID</th>
<th style="min-width: 120px;">Name</th>
<th style="min-width: 120px;">Status</th>
<th style="min-width: 120px;">Action</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="lamp in lamps">
<td>{{ lamp._id }}</td>
<td>{{ lamp.lampname }}</td>
<td>{{ lamp.status }}</td>
<td><input type="radio" value="on"> on <input type="radio" value="off"> off</td>
</tr>
</tbody>
</table>
</div>
+
views/notice.html
<div>
<p>환영합니다.</p>
<p>{{ message }}</p>
</div>
+
scripts/services/services.js
'use strict';
var services = angular.module('lampApp.services', ['ngResource']);
var baseUrl = 'http://localhost:3000';
services.factory('NoticeFactory', function ($resource) {
return $resource(baseUrl + '/notice', {}, {
query: { method: 'GET', params: {} }
});
});
services.factory('LampsFactory', function ($resource) {
return $resource(baseUrl + '/lamps', {}, {
query: { method: 'GET', isArray: true }
});
});
services.factory('LampFactory', function ($resource) {
return $resource(baseUrl + '/lamps/:id', {}, {
show: { method: 'GET' }
});
});
+
scripts/controller/controller.js
'use strict';
var app = angular.module('lampApp.controllers', []);
// Clear browser cache (in development mode)
//
// http://stackoverflow.com/questions/14718826/angularjs-disable-partial-caching-on-
dev-machine
app.run(function ($rootScope, $templateCache) {
$rootScope.$on('$viewContentLoaded', function () {
$templateCache.removeAll();
});
});
app.controller('NoticeCtrl', ['$scope', 'NoticeFactory', function ($scope, NoticeFactory) {
$scope.message = '간단한 AngularJS 테스트 프로그램입니다. Lamp 상태를 보여줍니다. 아
직 Lamp 조작 기능은 구현되어 있지 않습니다.';
}]);
app.controller('ListCtrl', ['$scope', 'LampsFactory', function ($scope, LampsFactory) {
$scope.lamps = LampsFactory.query();
}]);
+
scripts/app.js
"use strict";
// Declare app level module which depends on views, and components
angular.module('LampApp', [
'ngResource',
'ngRoute',
'lampApp.services',
'lampApp.controllers'
]).
config(['$routeProvider', function ($routeProvider, $httpProvider) {
$routeProvider.when('/notice', { templateUrl: 'views/notice.html', controller: 'NoticeCtrl'});
$routeProvider.when('/list', { templateUrl: 'views/list.html', controller: 'ListCtrl'});
$routeProvider.otherwise({redirectTo: '/notice'});
}]);
+
HTTP 서버 사용하기
n  Node용 간이 http 서버 설치
n  npm install http-server –g
n  AngularJS를 서비스 하기 위한 HTTP 서버 시작
n  cd angular-app
n  http-server
실시간 미
리 보기
또는 Brackets에서
+
앱 결과 화면(index.html)
+
앱 결과 화면(index.html에서 list)
+
도전 과제
n  socket.io를 사용해 polling하지 않고서 추가/변경/삭제되는 Lamp
목록을 보여준다.
n  hard coded된 notice 문구 대신, 특정 Lamp에 문제가 생겼을 경
우 서버에서 경고를 받아 출력한다.
n  Action을 추가해, Lamp를 켜고/끄게 만든다.
n  bower를 사용해 AngularJS 개발 과정에서 복잡한 프론트엔드 의
존성을 자동으로 관리하게 만든다.
+
실제 사례
+
참고 자료
n  http://docs.aws.amazon.com/lambda/latest/dg/
walkthrough-custom-events.html
n  http://ni-c.github.io/heimcontrol.js/
n  http://coenraets.org/blog/2012/10/creating-a-rest-api-
using-node-js-express-and-mongodb/
n  https://blog.codecentric.de/en/2013/03/home-automation-
with-angularjs-and-node-js-on-a-raspberry-pi/
n  http://mean.io/
n  http://bcho.tistory.com/881
+
참고 서적(팩트 서적은 번역 진행 중)
+

More Related Content

PDF
MEAN Stack 기반 모바일 서비스 개발 overview
민태 김
 
PDF
웹 Front-End 실무 이야기
JinKwon Lee
 
PPTX
XECon2015 :: [2-2] 박상현 - React로 개발하는 SPA 실무 이야기
XpressEngine
 
PDF
Front end dev 2016 & beyond
Jae Sung Park
 
PDF
Node.js 기본
Han Jung Hyun
 
PDF
React를 이용하여 멀티플랫폼에서 개발하기
WebFrameworks
 
PDF
Resource Handling in Spring MVC
Arawn Park
 
PDF
Vue SSR vs Prerender
Changwan Jun
 
MEAN Stack 기반 모바일 서비스 개발 overview
민태 김
 
웹 Front-End 실무 이야기
JinKwon Lee
 
XECon2015 :: [2-2] 박상현 - React로 개발하는 SPA 실무 이야기
XpressEngine
 
Front end dev 2016 & beyond
Jae Sung Park
 
Node.js 기본
Han Jung Hyun
 
React를 이용하여 멀티플랫폼에서 개발하기
WebFrameworks
 
Resource Handling in Spring MVC
Arawn Park
 
Vue SSR vs Prerender
Changwan Jun
 

What's hot (20)

PDF
Universal Rendering
Taegon Kim
 
PPTX
Deview2013 track1 session7
joshua wordsworth
 
PPTX
[114]angularvs react 김훈민손찬욱
NAVER D2
 
PDF
서버리스 기반의 프론트엔드 서버 구축(Serverless frontend web server)
ChanMin Park
 
KEY
Meteor 0.3.6 Preview
Juntai Park
 
PPTX
Node.js
ymtech
 
PPTX
[123] electron 김성훈
NAVER D2
 
PDF
Isomorphicspring Isomorphic - spring web seminar 2015
sung yong jung
 
PDF
Javascript everywhere - Node.js | Devon 2012
Daum DNA
 
PPTX
Nodejs 발표자료
shanka2
 
PDF
Facebook은 React를 왜 만들었을까?
Kim Hunmin
 
PDF
프론트엔드 개발자를 위한 크롬 렌더링 성능인자 이해하기
Chang W. Doh
 
PDF
[213]monitoringwithscouter 이건희
NAVER D2
 
PDF
20131217 html5
DK Lee
 
PPTX
AngularJS의 개발방식에 대하여
Jin wook
 
PDF
역시 Redux
Leonardo YongUk Kim
 
PDF
AngularJS 2, version 1 and ReactJS
Kenneth Ceyer
 
PDF
Front-end Development Process - 어디까지 개선할 수 있나
JeongHun Byeon
 
PDF
React Native를 사용한
 초간단 커뮤니티 앱 제작
Taegon Kim
 
PDF
막하는 스터디 네 번째 만남 AngularJs (20151108)
연웅 조
 
Universal Rendering
Taegon Kim
 
Deview2013 track1 session7
joshua wordsworth
 
[114]angularvs react 김훈민손찬욱
NAVER D2
 
서버리스 기반의 프론트엔드 서버 구축(Serverless frontend web server)
ChanMin Park
 
Meteor 0.3.6 Preview
Juntai Park
 
Node.js
ymtech
 
[123] electron 김성훈
NAVER D2
 
Isomorphicspring Isomorphic - spring web seminar 2015
sung yong jung
 
Javascript everywhere - Node.js | Devon 2012
Daum DNA
 
Nodejs 발표자료
shanka2
 
Facebook은 React를 왜 만들었을까?
Kim Hunmin
 
프론트엔드 개발자를 위한 크롬 렌더링 성능인자 이해하기
Chang W. Doh
 
[213]monitoringwithscouter 이건희
NAVER D2
 
20131217 html5
DK Lee
 
AngularJS의 개발방식에 대하여
Jin wook
 
역시 Redux
Leonardo YongUk Kim
 
AngularJS 2, version 1 and ReactJS
Kenneth Ceyer
 
Front-end Development Process - 어디까지 개선할 수 있나
JeongHun Byeon
 
React Native를 사용한
 초간단 커뮤니티 앱 제작
Taegon Kim
 
막하는 스터디 네 번째 만남 AngularJs (20151108)
연웅 조
 
Ad

Similar to Mean 스택을 사용한 IoT 개발 (20)

PPTX
Nodejs express
Hyosung Jeon
 
PPTX
Nodejs, PhantomJS, casperJs, YSlow, expressjs
기동 이
 
PPTX
Node.js and react
HyungKuIm
 
PPTX
One-day-codelab
WebFrameworks
 
PPTX
Startup JavaScript 8 - NPM, Express.JS
Circulus
 
PDF
overview of spring4
Arawn Park
 
PDF
Create-React-App으로 SSR을 구현하며 배운 점 (feat. TypeScript)
LanarkSeung
 
PDF
Node.js 심화과정
Seokyou (Kevin) Hong
 
PPTX
Node.js의 도입과 활용
Jin wook
 
PDF
Express framework tutorial
우림 류
 
PDF
7가지 동시성 모델 람다아키텍처
Sunggon Song
 
PDF
[IoT] MAKE with Open H/W + Node.JS - 3rd
Park Jonggun
 
PDF
막하는스터디 두번째만남 Express(20151025)
연웅 조
 
PPTX
Golang Project Guide from A to Z: From Feature Development to Enterprise Appl...
Kyuhyun Byun
 
PPTX
Ksug 세미나 (윤성준) (20121208)
Sungjoon Yoon
 
PDF
#17.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/...
탑크리에듀(구로디지털단지역3번출구 2분거리)
 
PDF
Ryu with OpenFlow 1.3, REST API
jieun kim
 
PDF
(IT실무교육/국비지원교육/자바/스프링교육추천)#15.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)
탑크리에듀(구로디지털단지역3번출구 2분거리)
 
PPTX
Mongo db 최범균
beom kyun choi
 
PDF
Terraform을 이용한 Infrastructure as Code 실전 구성하기
JeongHun Byeon
 
Nodejs express
Hyosung Jeon
 
Nodejs, PhantomJS, casperJs, YSlow, expressjs
기동 이
 
Node.js and react
HyungKuIm
 
One-day-codelab
WebFrameworks
 
Startup JavaScript 8 - NPM, Express.JS
Circulus
 
overview of spring4
Arawn Park
 
Create-React-App으로 SSR을 구현하며 배운 점 (feat. TypeScript)
LanarkSeung
 
Node.js 심화과정
Seokyou (Kevin) Hong
 
Node.js의 도입과 활용
Jin wook
 
Express framework tutorial
우림 류
 
7가지 동시성 모델 람다아키텍처
Sunggon Song
 
[IoT] MAKE with Open H/W + Node.JS - 3rd
Park Jonggun
 
막하는스터디 두번째만남 Express(20151025)
연웅 조
 
Golang Project Guide from A to Z: From Feature Development to Enterprise Appl...
Kyuhyun Byun
 
Ksug 세미나 (윤성준) (20121208)
Sungjoon Yoon
 
#17.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/...
탑크리에듀(구로디지털단지역3번출구 2분거리)
 
Ryu with OpenFlow 1.3, REST API
jieun kim
 
(IT실무교육/국비지원교육/자바/스프링교육추천)#15.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)
탑크리에듀(구로디지털단지역3번출구 2분거리)
 
Mongo db 최범균
beom kyun choi
 
Terraform을 이용한 Infrastructure as Code 실전 구성하기
JeongHun Byeon
 
Ad

More from Jay Park (20)

PDF
[독서광] 코드 넘어 회사보다 오래 남을 개발자
Jay Park
 
PDF
(독서광) 윌 라슨의 엔지니어링 리더십 - 테크 리더를 위한 성공 전략
Jay Park
 
PDF
[독서광] 모던 소프트웨어 엔지니어링 - 소프트웨어 개발의 복잡함과 난해함 속에서 길을 찾으려는 엔지니어를 위한...
Jay Park
 
PDF
(독서광) Azure OpenAI로 ChatGPT와 LLM 시스템 쉽고 빠르게 구축하기
Jay Park
 
PDF
(독서광) 이펙티브 소프트웨어 설계 - 실수와 트레이드오프로부터 배우는 현명한 소프트웨어 설계 가이드
Jay Park
 
PDF
(독서광) 지능의 기원 - 우리의 뇌 그리고 AI를 만든 다섯 번의 혁신
Jay Park
 
PDF
(독서광) 린 프로덕트 플레이북: 시장에서 살아남는 프로덕트를 개발하는 6단계 프로세스
Jay Park
 
PDF
(OkdevTV) 2025년 1월 8일 개발 이야기
Jay Park
 
PDF
(독서광) 2024년 12월 모두를 위한 소프트웨어 보안 설계와 구현
Jay Park
 
PDF
(OkdevTV) 2024년 12월 18일 개발 이야기
Jay Park
 
PDF
(OKdevTV) 2024년 12월 5일 개발 이야기
Jay Park
 
PDF
(독서광) 2024년 11월 선택 설계자들 - 어떻게 함정을 피하고 탁월한 결정을 내릴 것인가
Jay Park
 
PDF
(OkdevTV) 2024년 10월 30일 개발 이야기
Jay Park
 
PDF
(OkdevTV) 2024년 10월 16일 개발 이야기
Jay Park
 
PDF
(독서광) 갈대 속의 영원 - 저항하고 꿈꾸고 연결하는 발명품, 책의 모험
Jay Park
 
PDF
(OkdevTV) 2024년 10월 2일 개발 이야기
Jay Park
 
PDF
(OkdevTV) 2024년 9월 2일 개발 이야기 - 좋은 리팩토링 vs 나쁜 리팩토링
Jay Park
 
PDF
[OkdevTV] 2024년 9월 2일 개발 이야기
Jay Park
 
PDF
[독서광] 프리세일즈 (Technical Presales) - 고객과 기업을 잇는 기술 대표
Jay Park
 
PDF
[OKdevTV] 2024년 8월 21일 개발 이야기
Jay Park
 
[독서광] 코드 넘어 회사보다 오래 남을 개발자
Jay Park
 
(독서광) 윌 라슨의 엔지니어링 리더십 - 테크 리더를 위한 성공 전략
Jay Park
 
[독서광] 모던 소프트웨어 엔지니어링 - 소프트웨어 개발의 복잡함과 난해함 속에서 길을 찾으려는 엔지니어를 위한...
Jay Park
 
(독서광) Azure OpenAI로 ChatGPT와 LLM 시스템 쉽고 빠르게 구축하기
Jay Park
 
(독서광) 이펙티브 소프트웨어 설계 - 실수와 트레이드오프로부터 배우는 현명한 소프트웨어 설계 가이드
Jay Park
 
(독서광) 지능의 기원 - 우리의 뇌 그리고 AI를 만든 다섯 번의 혁신
Jay Park
 
(독서광) 린 프로덕트 플레이북: 시장에서 살아남는 프로덕트를 개발하는 6단계 프로세스
Jay Park
 
(OkdevTV) 2025년 1월 8일 개발 이야기
Jay Park
 
(독서광) 2024년 12월 모두를 위한 소프트웨어 보안 설계와 구현
Jay Park
 
(OkdevTV) 2024년 12월 18일 개발 이야기
Jay Park
 
(OKdevTV) 2024년 12월 5일 개발 이야기
Jay Park
 
(독서광) 2024년 11월 선택 설계자들 - 어떻게 함정을 피하고 탁월한 결정을 내릴 것인가
Jay Park
 
(OkdevTV) 2024년 10월 30일 개발 이야기
Jay Park
 
(OkdevTV) 2024년 10월 16일 개발 이야기
Jay Park
 
(독서광) 갈대 속의 영원 - 저항하고 꿈꾸고 연결하는 발명품, 책의 모험
Jay Park
 
(OkdevTV) 2024년 10월 2일 개발 이야기
Jay Park
 
(OkdevTV) 2024년 9월 2일 개발 이야기 - 좋은 리팩토링 vs 나쁜 리팩토링
Jay Park
 
[OkdevTV] 2024년 9월 2일 개발 이야기
Jay Park
 
[독서광] 프리세일즈 (Technical Presales) - 고객과 기업을 잇는 기술 대표
Jay Park
 
[OKdevTV] 2024년 8월 21일 개발 이야기
Jay Park
 

Mean 스택을 사용한 IoT 개발

  • 3. +
  • 7. + bonescript n  Beagle Bone에서 아두이노 스타일의 프로그램이 가능하게 만들어 주는 자바스크립트 라이브러리
  • 11. + heimcontrol.js(1) Raspberry PI and Arduino using Node.js
  • 14. + Node.js인 이유는?(2) n  개발 시간과 성능의 조화 n  아무리 성능이 좋더라도 개발 시간이 오래 걸릴 경우 생산성이 떨어진다 n  주의: 1행을 작성하는 시간은 어셈블리나 SQL이나 비슷하다 n  스크립트 언어의 경우 빨리 개발은 가능하지만 성능이 떨어진다 n  자바스크립트를 사용한 Node.js는 개발과 성능 양쪽 모두 뛰어나다 n  스타트업 vs 기업 n  스타트업은 빨리 변화하는 생태계에서 살아남기 위해 필연적으로 오픈 소스에 매진한다 n  대기업은 유지보수와 안정성, 그리고 성능에 관심이 많다 n  Node.js는 양쪽 모두를 만족시킨다(오픈 소스 기반, 자바와 같은 강력한 생태계)
  • 15. + Node.js인 이유는?(3) n  뛰어난 성능 n  월마트는 블랙 프라이데이에 Node.js로 전제 모바일 사이트 오픈 n  초당 두 배 요청을 받아들이고 응답시간을 35%(200ms) 줄임 n  서버 CPU 사용량이 2%, 200만 명 온라인 접속 방어 n  이벤트 아키텍처 n  스레드가 아닌 단일 프로세스 n  대신 동기식 차단이 아닌 비동기식 I/O n  웹 브라우저 특성상 이미 자바스크립트는 콜백을 사용하는 이벤트 구 동 방식을 지원(비동기식 코드에 대한 표현력이 강함)
  • 16. + 동기식 입출력 vs 비동기식 입출력
  • 17. + 멀티 스레드 vs 단일 스레드
  • 21. + 선행조건 n  MEAN 기본 스택 준비 n  Node.js 설치: http://nodejs.org/ n  MongoDB 설치: http://www.mongodb.org/ n  자바스크립트 편집기는 brackets 추천: http://brackets.io/ n  예제 소스 코드 저장소 위치 n  Node.js용 node-collector: https://bitbucket.org/jrogue/node- collector n  AngularJS용 angular-lamp-app: https://bitbucket.org/jrogue/ angular-lamp-app
  • 24. + 첫 Node.js 프로그램: / server_plain_vanilla.js /*jslint node: true */ var http = require('http'); http.createServer(function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello Worldn'); }).listen(3000, '127.0.0.1'); console.log('Server running at http://127.0.0.1:3000/');
  • 25. + Node.js 프로그램을 위한 패키지 설 정: /package.json { "name": "node-collector", "private": true, "version": "0.1.0", "description": "A starter project for Node.js", "license": "MIT", "devDependencies": { "express": "4.x", "body-parser": "1.4.x“, "mongoose": "^3.8.20" } }
  • 27. + Node.js를 사용한 첫 RESTful 프로그 램: /server.js var express = require('express'); var app = express(); app.get('/lamps', function(req, res) { res.send([{name: 'lamp1'}, {name: ‘lamp2'}]); }); app.get('/lamps/:id', function(req, res) { res.send({id:req.params.id, name: "lamp" + req.params.id, status: "lamp ready"}); }); app.listen(3000); console.log('Listening on port 3000...');
  • 29. + Node.js 모듈 사용: /routes/lamps.js exports.findAll = function (req, res) { res.send([{name: 'lamp1'}, {name: 'lamp2'}, {name: ‘lamp3'}]); }; exports.findById = function (req, res) { res.send({id: req.params.id, name: "lamp" + req.params.id, status: "lamp ready"}); }; var express = require('express'), bodyParser = require('body-parser'), lamps = require('./routes/lamps.js'); var app = express(); app.get('/lamps', lamps.findAll); app.get('/lamps/:id', lamps.findById); app.listen(3000); console.log('Listening on port 3000...');
  • 30. + 몽고DB 연동을 위한 준비: /db.js var mongoose = require('mongoose'); mongoose.connect('mongodb://localhost/lamps', function () { console.log('mongodb connected') }); module.exports = mongoose;
  • 31. + 몽고DB 모델 생성: /models/lamp.js var db = require('../db'); var Lamp = db.model('Lamp', { lampname: { type: String, required: true }, status: { type: String, required: true }, date: { type: Date, required: true, default: Date.now } }); module.exports = Lamp;
  • 32. + Node.js 모듈 내용 변경(1): /routes/ lamps.js var Lamp = require('../models/lamp'); exports.addLamp = function (req, res, next) { var lamp = new Lamp({ lampname: req.body.lampname, status: req.body.status }); lamp.save(function (err, lamp) { if (err) { return next(err); } res.status(201).json(lamp); }); };
  • 33. + Node.js 모듈 내용 변경(2): /routes/ lamps.js exports.updateLamp = function (req, res, next) { Lamp.findOne({ _id: req.params.id }, function (err, lamp) { if (err) { return next(err); } lamp.status = req.body.status; lamp.save(function (err, lamp) { if (err) { return next(err); } res.status(201).json(lamp); }); }); }; exports.deleteLamp = function (req, res, next) { Lamp.remove({ _id: req.params.id }, function (err, lamp) { if (err) { return next(err); } res.status(201).json(lamp); }); };
  • 34. + Node.js 모듈 내용 변경(3): /routes/ lamps.js exports.findAll = function (req, res, next) { Lamp.find(function (err, lamps) { if (err) { return next(err); } res.status(201).json(lamps); }); }; exports.findById = function (req, res, next) { Lamp.findOne({ _id: req.params.id }, function (err, lamp) { if (err) { return next(err); } res.status(201).json(lamp); }); };
  • 35. + CRUD 전체 정의를 위한 변경: / server.js var express = require('express'), bodyParser = require('body-parser'), lamps = require('./routes/lamps.js'); var app = express(); app.use(bodyParser.json()); app.post('/lamps', lamps.addLamp); app.get('/lamps', lamps.findAll); app.get('/lamps/:id', lamps.findById); app.put('/lamps/:id', lamps.updateLamp); app.delete('/lamps/:id', lamps.deleteLamp); app.listen(3000); console.log('Listening on port 3000...');
  • 36. + 서버 시작 n  서버 시작 n  $ node server n  주의: 서버 시작에 앞서 지역 호스트(localhost)에 몽고DB를 설치 하고 시작했는지 반드시 확인하자!
  • 37. + 단말 쪽 프로그래밍 n  REST 방식으로 API를 호출하면 된다 n  단말 조건: TCP/IP 스택이 설치되어 있으며, REST 클라이언트 라이브러 리를 사용할 수 있어야 한다. n  만일 리눅스 기반으로 동작하는 단말인 경우 뒤에 테스트 예제에서 설명하는 curl을 system으로 호출하면 아주 쉽게 구현 가능하다. n  C 언어로 개발할 경우 libcurl을 사용할 수도 있다. n  스크립트 언어로 개발할 경우 스크립트 언어의 REST 클라이언트 패 키지를 사용하면 몇 줄로 서버 쪽에 자신의 상태를 전달할 수 있다. n  이어지는 테스트 예제를 보며 CRUD 전달 방식을 확인하자.
  • 38. + CRUD 테스트: POSTMAN vs curl 크롬 확장: REST 클라이언트 http://curl.haxx.se/ (홈페이지) http://www.confusedbycode.com/curl/ (윈도우 32비트/64비트) 참고: 여기서는 설명의 편의를 위해 cURL을 사용한다!
  • 39. + 서버 구동 후 생성 테스트(curl 사용)
  • 43. + (변경 내역 반영 검증을 위한) 읽기 테 스트
  • 48. + AngularJS 샘플 앱의 디렉터리 구조
  • 49. + /index.html <!DOCTYPE html> <html ng-app="LampApp"> <head> <link href="styles/main.css" rel="stylesheet"> <link rel="stylesheet" ref="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css"> </head> <body> <ul class="menu"> <li><a href="#/notice">notice</a></li> <li><a href="#/list">list</a></li> </ul> <div class="container" ng-view=""></div> <script src="https://code.jquery.com/jquery-2.1.1.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.5/angular.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.5/angular-resource.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.5/angular-route.min.js"></script> <script src="scripts/app.js"></script> <script src="scripts/services/services.js"></script> <script src="scripts/controllers/controllers.js"></script> </body> </html>
  • 50. + views/list.html <div class="span6"> <table class="table table-striped table-condensed"> <thead> <tr> <th style="min-width: 300px;">Lamp ID</th> <th style="min-width: 120px;">Name</th> <th style="min-width: 120px;">Status</th> <th style="min-width: 120px;">Action</th> </tr> </thead> <tbody> <tr ng-repeat="lamp in lamps"> <td>{{ lamp._id }}</td> <td>{{ lamp.lampname }}</td> <td>{{ lamp.status }}</td> <td><input type="radio" value="on"> on <input type="radio" value="off"> off</td> </tr> </tbody> </table> </div>
  • 52. + scripts/services/services.js 'use strict'; var services = angular.module('lampApp.services', ['ngResource']); var baseUrl = 'http://localhost:3000'; services.factory('NoticeFactory', function ($resource) { return $resource(baseUrl + '/notice', {}, { query: { method: 'GET', params: {} } }); }); services.factory('LampsFactory', function ($resource) { return $resource(baseUrl + '/lamps', {}, { query: { method: 'GET', isArray: true } }); }); services.factory('LampFactory', function ($resource) { return $resource(baseUrl + '/lamps/:id', {}, { show: { method: 'GET' } }); });
  • 53. + scripts/controller/controller.js 'use strict'; var app = angular.module('lampApp.controllers', []); // Clear browser cache (in development mode) // // http://stackoverflow.com/questions/14718826/angularjs-disable-partial-caching-on- dev-machine app.run(function ($rootScope, $templateCache) { $rootScope.$on('$viewContentLoaded', function () { $templateCache.removeAll(); }); }); app.controller('NoticeCtrl', ['$scope', 'NoticeFactory', function ($scope, NoticeFactory) { $scope.message = '간단한 AngularJS 테스트 프로그램입니다. Lamp 상태를 보여줍니다. 아 직 Lamp 조작 기능은 구현되어 있지 않습니다.'; }]); app.controller('ListCtrl', ['$scope', 'LampsFactory', function ($scope, LampsFactory) { $scope.lamps = LampsFactory.query(); }]);
  • 54. + scripts/app.js "use strict"; // Declare app level module which depends on views, and components angular.module('LampApp', [ 'ngResource', 'ngRoute', 'lampApp.services', 'lampApp.controllers' ]). config(['$routeProvider', function ($routeProvider, $httpProvider) { $routeProvider.when('/notice', { templateUrl: 'views/notice.html', controller: 'NoticeCtrl'}); $routeProvider.when('/list', { templateUrl: 'views/list.html', controller: 'ListCtrl'}); $routeProvider.otherwise({redirectTo: '/notice'}); }]);
  • 55. + HTTP 서버 사용하기 n  Node용 간이 http 서버 설치 n  npm install http-server –g n  AngularJS를 서비스 하기 위한 HTTP 서버 시작 n  cd angular-app n  http-server 실시간 미 리 보기 또는 Brackets에서
  • 58. + 도전 과제 n  socket.io를 사용해 polling하지 않고서 추가/변경/삭제되는 Lamp 목록을 보여준다. n  hard coded된 notice 문구 대신, 특정 Lamp에 문제가 생겼을 경 우 서버에서 경고를 받아 출력한다. n  Action을 추가해, Lamp를 켜고/끄게 만든다. n  bower를 사용해 AngularJS 개발 과정에서 복잡한 프론트엔드 의 존성을 자동으로 관리하게 만든다.
  • 60. + 참고 자료 n  http://docs.aws.amazon.com/lambda/latest/dg/ walkthrough-custom-events.html n  http://ni-c.github.io/heimcontrol.js/ n  http://coenraets.org/blog/2012/10/creating-a-rest-api- using-node-js-express-and-mongodb/ n  https://blog.codecentric.de/en/2013/03/home-automation- with-angularjs-and-node-js-on-a-raspberry-pi/ n  http://mean.io/ n  http://bcho.tistory.com/881
  • 61. + 참고 서적(팩트 서적은 번역 진행 중)
  • 62. +