Node.js 첫걸음
처음부터 시작하는 Node.js
SeungHyun Lee
zero2hex@gmail.com
Node.js?
“Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.”
“As an asynchronous event driven JavaScript runtime, Node is designed to build
scalable network applications.”
- nodejs.org
• 크롬의 V8 자바스크립트 엔진을 기반으로 만들어진 자바스크립트 런타임
• 네트워크 어플리케이션 제작을 위한 비동기 이벤트 기반 방식의 자바스크립트 런타임
What is Node.js?
“Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.”
“As an asynchronous event driven JavaScript runtime, Node is designed to build
scalable network applications.”
- nodejs.org
• 크롬의 V8 자바스크립트 엔진을 기반으로 만들어진 자바스크립트 런타임
• 네트워크 어플리케이션 제작을 위한 비동기 이벤트 기반 방식의 자바스크립트 런타임
= 서버사이드 자바스크립트 프레임워크
What is Node.js?
Feature
• Open Source
• Asynchronous & Event-driven
• Non-blocking I/O
• Single threaded
• Chrome’s V8 Engine
Open Source
“Permission is hereby granted, free of charge … without restriction, including without
limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software …”
- LICENSE of node.js
• 수정, 배포 등을 포함한 일체의 권리에 제한을 받지 않고 사용할 수 있는 오픈 소스
• https://github.com/nodejs/node
Asynchronous & Event-driven
• 절차 지향 프로그래밍 : 진입점에서부터 모든 동작이 차례대로 수행
• 이벤트 드리븐 : 입력 혹은 출력(event)이 발생함에 따라 동작이 처리(driven)
• 절차 지향 프로그래밍 방식은 동기적(Synchronous)으로 동작이 처리되는 반면, 이벤
트 드리븐 방식은 비동기적(Asynchronous)으로 동작이 처리됨
• 가장 기본적인 처리 방식으로 콜백(callback)이 존재
Non-blocking I/O
• Blocking : 어떠한 작업이 완료될 때 까지 다른 처리를 막는(blocking) 방식
• Non-blocking : 처리할 작업을 맡겨두고(non-blocking), 결과를 따로 처리하는 방식
• Sync/Asnyc의 개념과 혼동될 수 있으나, Blocking/Non-blocking을 처리하는 방식으
로 Sync/Async를 이용하게 된다.
Single threaded
• Tomcat, Apache : 사용자의 요청에 대해 thread를 생성해 처리
• Node.js : 단일 thread의 event loop 상에서 요청을 처리
• Context switching에 대한 비용 감소
• Multi-thread 환경에서 발생하는 요소 고려에 대한 부담 감소
Single threaded event loop
Chrome’s V8 Engine
• JIT(Just-In-Time) compile
• Efficient garbage collection
• Inline cache
• Hidden classes
Chrome’s V8 Engine
• JIT(Just-In-Time) compile
• Efficient garbage collection
• Inline cache
• Hidden classes
>> 빠르며 고성능의 JavaScript 엔진
Why Node.js?
• Fast
• Single Thread 기반의 비동기 I/O 처리
• CPU가 특정 I/O의 완료를 대기하지 않고, 다른 작업을 처리 할 수 있음
• 위의 이유로 많은 요청을 수용 가능하다
Hello World!
> console.log(“Hello world!”)
Installation (Windows)
• Download on https://nodejs.org/en/download/
• ‘Windows Installer’
• ‘Next’혹은‘Install’,‘Finish’만 선택해 주면 설치 완료
Installation (Linux)
• Download on https://nodejs.org/en/download/
• ‘Source Code’
• GNU make를 위한 의존성 패키지 설치
• configure.sh를 통한 make 설정
• Make
• Install
Installation (Linux)
 wget https://nodejs.org/dist/v4.4.3/node-v4.4.3.tar.gz
 sudo apt-get update && apt-get upgrade
 sudo apt-get install build-essential libssl-dev
 tar -xzf node-v4.4.3.tar.gz
 cd node-v4.4.3
 ./configure
 make
 sudo make install
Hello World
 vim helloword.js // helloworld.js
console.log(“hello world!”)
 node helloworld.js // execute
Hello World
 vim helloword.js // helloworld.js
console.log(“hello world!”)
 node helloworld.js // execute
Simple Server
 vim simple_server.js // simple_server.js
var http = require('http')
http.createServer( (request, response) => {
response.writeHead(200, {'Content-Type': 'text/html'});
response.end('<h1>Hello world!</h1>');
}).listen(3000)
console.log('Server running at http://localhost:3000');
 node simple_server.js // execute (http://localhost:3000)
Simple Server
HTTP Server
require(‘http’)
Simple Server
var http = require('http')
http.createServer( (request, response) => {
response.writeHead(200, {'Content-Type': 'text/html'});
response.end('<h1>Hello world!</h1>');
}).listen(3000)
console.log('Server running at http://localhost:3000');
Simple Server
var http = require('http')
http.createServer( (request, response) => {
response.writeHead(200, {'Content-Type': 'text/html'});
response.end('<h1>Hello world!</h1>');
}).listen(3000)
console.log('Server running at http://localhost:3000');
Simple Server
var http = require('http')
http.createServer( (request, response) => {
response.writeHead(200, {'Content-Type': 'text/html'});
response.end('<h1>Hello world!</h1>');
}).listen(3000)
console.log('Server running at http://localhost:3000');
=> HTTP Module
HTTP Module
• HTTP 웹 서버와 관련된 기능을 담고있는 모듈
• HTTP Module은 다음과 같은 클래스를 포함
• 요청(Request)와 응답(Response)를 처리할 수 있는 Server
• 클라이언트의 요청에 대한 정보를 담는 IncomingMessage
• 서버의 처리 결과에 대한 정보를 담는 ServerResponse
• 다른 서버와의 통신 기능을 수행할 수 있는 ClientRequest
참고 : https://nodejs.org/api/http.html
• TCP/IP 기반으로 웹 상에서 정보를 주고받을 수 있는 프로토콜
• 클라이언트와 서버 사이에 이루어지는 요청/응답(request/response) 프로토콜
• OSI 7 Layer 중 Application Layer에 해당
• HTML 페이지를 전달하는데 주로 사용
HTTP
참고 : RFC 2616 (https://tools.ietf.org/html/rfc2616)
HTTP Communication
출처 : http://www.slideshare.net/origamiaddict/http-40249449
TCP Connection
(Transport layer)
HTTP Connection
(Application layer)
HTTP Message Structure
• HTTP 메시지는 크게 Request와 Response로 나뉘어짐
• 각 메시지는 Header와 Body로 구성
• Header는 커넥션 및 쿠키, 파일 종류 등 통신에 필요한 각종 정보를 서술
• Body는 실제 본문으로서 전송할 데이터를 서술
• 메시지 전문은 아래와 같이 구성
Request-Line | Status-Line
*(message-header CRLF)
CRLF
[ message-body ]
참고 : https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
HTTP Message Structure
HTTP/1.1 200 OK
Server: GitHub.com
Date: Wed, 29 Jun 2016 06:16:00 GMT
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Status: 200 OK
Cache-Control: no-cache
X-UA-Compatible: IE=Edge,chrome=1
X-Runtime: 0.019390
<!DOCTYPE html>
<html lang="en" class=" is-copy-enabled is-u2f-enabled">
<head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# object: http://ogp.me/ns/object# article:
http://ogp.me/ns/article# profile: http://ogp.me/ns/profile#">
<meta charset='utf-8'>
<link crossorigin="anonymous" href="https://assets-cdn.github.com/assets/frameworks-
fef7fdfe41dd435c6d82f93b486dc62bc095ebd12cd24fa2a817c8bb45dc073e.css" integrity="sha256-
/vf9/kHdQ1xtgvk7SG3GK8CV69Es0k+iqBfIu0XcBz4=" media="all" rel="stylesheet" />
…
Message Headers
Message Body
참고 : https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
Simple Server
var http = require('http')
http.createServer( (request, response) => {
response.writeHead(200, {'Content-Type': 'text/html'});
response.end('<h1>Hello world!</h1>');
}).listen(3000)
console.log('Server running at http://localhost:3000');
Simple Server
var http = require('http')
http.createServer( (request, response) => {
response.writeHead(200, {'Content-Type': 'text/html'}); // Message Header 작성
response.end('<h1>Hello world!</h1>'); // Message Body 작성
}).listen(3000)
console.log('Server running at http://localhost:3000');
HTTP server
var http = require('http') // ‘http’ 모듈 로드
var server = http.createServer( (request, response) => { // server 객체 생성
response.writeHead(200, {'Content-Type': 'text/html'});
response.end('<h1>Hello world!</h1>');
}).on('request', function() { // ‘request’ 이벤트에 콜백 매핑
console.log('Request On');
}).on('connection', function() { // ‘connection’ 이벤트에 콜백 매핑
console.log('Connection On');
}).on('close', function() { // ‘close’ 이벤트에 콜백 매핑
console.log('Close On');
}).listen(3000); // 서버 실행
console.log('Server running at http://localhost:3000');
HTTP server
Serving static files
var http = require('http')
var fs = require('fs') // ‘fs’ 모듈 로드
var server = http.createServer( (request, response) => {
fs.readFile('index.html', function(error, data) { // 파일 읽기
response.writeHead(200, {'Content-Type': 'text/html'}); // Header 작성
response.end(data); // 파일 전송
});
}).listen(3000);
console.log('Server running at http://localhost:3000');
Serving static files
var http = require('http')
…
// text/html 형식의 파일을 전송 할 것이라 명시
response.writeHead(200, {‘Content-Type’: ‘text/html’});
…
console.log('Server running at http://localhost:3000');
Serving static files
Page Rendering
require(‘ejs’) / require(‘jade’)
Web Page Presentation
• 사용자의 요청에 따라 HTML 페이지를 보여주기 위해서는?
var http = require('http')
var server = http.createServer( request, response => {
response.writeHead(200, {'Content-Type': 'text/html'});
response.end(‘<html>
<head><title>Hello world!</title></head>
<body>
<h1>Welcome to Node.js</h1>
<p>example page…</p>
</body>
</html>’);
}).listen(3000);
• 웹 페이지 소스를 하드 코딩으로 작성 == 번거롭다
Web Page Presentation
• 사용자의 요청에 따라 HTML 페이지를 보여주기 위해서는?
var http = require('http')
var server = http.createServer( request, response => {
response.writeHead(200, {'Content-Type': 'text/html'});
response.end(‘<html>
<head><title>Hello world!</title></head>
<body>
<h1>Welcome to Node.js</h1>
<p>example page…</p>
</body>
</html>’);
}).listen(3000);
• 웹 페이지 소스를 하드 코딩으로 작성 == 번거롭다
Web Page Presentation
• 사용자의 요청에 따라 HTML 페이지를 보여주기 위해서는?
var http = require('http')
var server = http.createServer( request, response => {
response.writeHead(200, {'Content-Type': 'text/html'});
response.end(‘<html>
<head><title>Hello world!</title></head>
<body>
<h1>Welcome to Node.js</h1>
<p>example page…</p>
</body>
</html>’);
}).listen(3000);
• 웹 페이지 소스를 하드 코딩으로 작성 == 번거롭다
Web Page Presentation
• 사용자의 요청에 따라 HTML 페이지를 보여주기 위해서는?
var http = require('http')
var server = http.createServer( request, response => {
response.writeHead(200, {'Content-Type': 'text/html'});
response.end(‘<html>
<head><title>Hello world!</title></head>
<body>
<h1>Welcome to Node.js</h1>
<p>example page…</p>
</body>
</html>’);
}).listen(3000);
• 웹 페이지 소스를 하드 코딩으로 작성 == 번거롭다
Web Page Presentation
• 사용자의 요청에 따라 HTML 페이지를 보여주기 위해서는?
var http = require('http')
var server = http.createServer( request, response => {
response.writeHead(200, {'Content-Type': 'text/html'});
response.end(‘<html>
<head><title>Hello world!</title></head>
<body>
<h1>Welcome to Node.js</h1>
<p>example page…</p>
</body>
</html>’);
}).listen(3000);
• 웹 페이지 소스를 하드 코딩으로 작성 == 번거롭다
Page Rendering
• Business Logic과 Presentation Logic을 구분하는 것이 기본 개념
• View를 EJS 문법(EJS) 및 HAML(Pug)에 따라 제작
• 만들어진 View는 Template Engine을 통해 렌더링
• Template Engine에는 Pug(Jade), EJS, Dust, Mustache 등이 존재
참고 : http://paularmstrong.github.io/node-templates
참고 :
https://github.com/pugjs/pug
https://github.com/pugjs/pug/issues/2184
• HAML(HTML Abstract Markup Language)의 영향을 받은 Template Engine
• 본 명칭은 Jade로 이쪽이 더 많이 알려져 있으나, 네이밍 이슈로 최근 개명됨
• 들여쓰기를 통해 계층 구조를 표현
• 들여쓰기가 잘못 될 시 전혀 다른 결과 혹은 오류를 발생
Pug (Jade)
Syntax
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<title>Pug</title>
<script type="text/javascript">
if (foo) bar(1 + 5)
</script>
</head>
<body>
<h1>Pug - node template engine</h1>
<div id="container" class="col">
<p>You are amazing</p>
<p>Pug is a terse and simple
templating language with a strong focus on
performance and powerful features.</p>
</div>
</body>
</html>
참고 : http://jade-lang.com
Pug
doctype html
html(lang="en")
head
title= pageTitle
script(type='text/javascript').
if (foo) bar(1 + 5)
body
h1 Pug - node template engine
#container.col
if youAreUsingPug
p You are amazing
else
p Get on it!
p.
Pug is a terse and simple templating
language with a strong focus on
performance and powerful features.
Install Pug package
• Pug는 외부 모듈이므로 실행 전 NPM을 이용해 설치를 진행
 npm install pug
If Jade…?
 npm install jade
Simple Pug
var http = require('http');
var pug = require('pug');
var fs = require('fs');
http.createServer(function (request, response) {
fs.readFile('index.pug', 'utf8', function (error, data) {
var fn = pug.compile(data);
response.writeHead(200, {'Content-Type': 'text/html'});
response.end(fn());
});
}).listen(3000);
console.log('Server running at http://localhost:3000');
참고 : http://jade-lang.com/api/
Simple Pug
var http = require('http');
var pug = require('pug'); // ‘pug’ 모듈 로드
var fs = require('fs');
http.createServer(function (request, response) {
fs.readFile('index.pug', 'utf8', function (error, data) {
var fn = pug.compile(data); // HTML 코드 제너레이터 생성
response.writeHead(200, {'Content-Type': 'text/html'});
response.end(fn()); // 제너레이터를 이용해 응답
});
}).listen(3000);
console.log('Server running at http://localhost:3000');
참고 : http://jade-lang.com/api/
Simple Pug
var http = require('http');
var pug = require('pug'); // ‘pug’ 모듈 로드
var fs = require('fs');
http.createServer(function (request, response) {
response.writeHead(200, {'Content-Type': 'text/html'});
response.end(pug.renderFile('index.pug')); // 파일명을 이용한 코드 생성
}).listen(3000);
console.log('Server running at http://localhost:3000');
참고 : http://jade-lang.com/api/
Simple Pug
Passing Parameters
var http = require('http');
var pug = require('pug');
var fs = require('fs');
http.createServer(function (request, response) {
fs.readFile('index.pug', 'utf8', function (error, data) {
var fn = pug.compile(data);
var params = { pageTitle: 'Hello, Pug', youAreUsingPug: true }; // 넘겨줄 변수 목록
response.writeHead(200, { 'Content-Type‘ : 'text/html‘ });
response.end(fn(params)); // 함께 컴파일
});
}).listen(3000);
console.log('Server running at http://localhost:3000');
참고 : http://jade-lang.com/api/
Passing Parameters
Database
Necessity of Database
• 특정 사람들만 글을 읽고 쓸 수 있는 게시판 제작
• 각 사람들에게 계정을 주고 권한을 부여
• 로그인 한 사용자들만 글을 쓰고 읽기가 가능
Q : 사용자 정보를 저장해 둘 곳?
Necessity of Database
• 특정 사람들만 글을 읽고 쓸 수 있는 게시판 제작
• 각 사람들에게 계정을 주고 권한을 부여
• 로그인 한 사용자들만 글을 쓰고 읽기가 가능
Q : 사용자 정보를 저장해 둘 곳?
A : Database
Database?
• 데이터 중복의 최소화
• 데이터의 무결성
• DBMS (DataBase Management System)
• 복수 사용자 관리
• 다수의 사용자에 의해 접근 = 동일한 데이터의 동시 사용 또는 변경
• 데이터의 일관성 보장 필요
• 허용된 권한을 통해서만 데이터로 접근 가능
• 복수의 연결 및 자원 관리
Language of Database
• SQL
• DB와 의사소통을 하기 위한 표준 언어
• DB 및 데이터의 읽기, 쓰기(생성), 수정, 삭제, 관리 등의 기능을 수행
• DDL (Data Definition Language)
• 데이터베이스의 구조 정의 또는 변경.
• DML (Data Manupulation Language)
• 데이터의 삽입, 삭제, 검색, 수정.
• DCL (Data Control Language)
• 데이터베이스에 대한 권한 제어.
MySQL on Node.js
require(mysql)
Basic Usage
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'localhost',
user : 'me',
password : 'secret',
database : 'my_db'
});
connection.connect();
connection.query('SELECT 1 + 1 AS solution', function(err, rows, fields) {
if (err) throw err;
console.log('The solution is: ', rows[0].solution);
});
connection.end();
Connect
Query
Disconnect
Basic Usage
Express
require(‘express’)
Express
“Express is a minimal and flexible Node.js web application framework that provides a
robust set of features for web and mobile applications.”
- expressjs.com
• Express : Node.js를 기반으로 한 가볍고 유연한 Web Application Framework
• Main features
• Routing
• Managing middlewares
• Serving static files
참고 : Express (http://expressjs.com)
Express & Connect
• ‘Connect’는 미들웨어(Middleware)를 기반으로 Node.js의 HTTP 서버 기능을 확장
해 주는 모듈 (extensible HTTP server framework for node using "plugins" known
as middleware)
• 초기‘Express’는 Connect를 기반으로 설계
• 이로 인해 여러 문제가 발생 (Connect에 대한 의존성, 성능 이슈 등)
• 위의 문제를 해결하기 위해 Express 4.0 버전부터 의존성을 제거하고 독자적인
Router를 가지게 됨
참고 : Express GitHub (https://github.com/expressjs/express/wiki/Migrating-from-3.x-to-4.x)
Routing?
• 클라이언트가 요청한 각각의 경로(URL)에 대한 처리는 어떻게 할까
• http://localhost:3000/
• http://localhost:3000/hello
• http://localhost:3000/world
• ….
Routing?
• 클라이언트가 요청한 각각의 경로(URL)에 대한 처리는 어떻게 할까
• http://localhost:3000/
• http://localhost:3000/hello
• http://localhost:3000/world
• ….
=> 마지막 컴포넌트(/, /hello, /world)를 구하고, 각각에 대한 로직을 구성
Routing on Node.js
var http = require('http');
var url = require('url');
http.createServer( function (req, res) {
var pathname = url.parse(request.url).pathname;
if(pathname == '/') {
response.writeHead(200, { 'Content-Type': 'text/html' });
response.end('routing: /');
} else if(pathname == '/hello') {
response.writeHead(200, { 'Content-Type': 'text/html' });
response.end('routing: /hello');
} else if(pathname == '/world') {
response.writeHead(200, { 'Content-Type': 'text/html' });
response.end('routing: /world');
}
}).listen(3000);
Routing on Node.js
var http = require('http');
var url = require('url');
http.createServer( function (req, res) {
var pathname = url.parse(request.url).pathname;
if(pathname == '/') {
response.writeHead(200, { 'Content-Type': 'text/html' });
response.end('routing: /');
} else if(pathname == '/hello') {
response.writeHead(200, { 'Content-Type': 'text/html' });
response.end('routing: /hello');
} else if(pathname == '/world') {
response.writeHead(200, { 'Content-Type': 'text/html' });
response.end('routing: /world');
}
}).listen(3000);
/
/hello
/world
Routing
• if-else / switch-case 문을 이용한 분기 처리는 분기가 많아질수록 비효율적
• 또한 자칫 스파게티 코드가 되기 쉬움
• Routing 기능만을 독립적으로 수행하고, 로직을 주입할 수 있도록 하자
Routing
• if-else / switch-case 문을 이용한 분기 처리는 분기가 많아질수록 비효율적
• 또한 자칫 스파게티 코드가 되기 쉬움
• Routing 기능만을 독립적으로 수행하고, 로직을 주입할 수 있도록 하자
=> Router (라우터)
Routing on Express
var express = require('express');
var app = express();
app.get('/', function (req, res) {
res.send('Hello World!');
}).post('/', function (req, res) {
res.send('Got a POST request');
}).put('/user', function (req, res) {
res.send('Got a PUT request at /user');
}).delete('/user', function (req, res) {
res.send('Got a DELETE request at /user');
}).listen(3000, function () {
console.log('Example app listening on port 3000!');
});
Routing on Express
var express = require('express'); // express 모듈 로드
var app = express();
app.get('/', function (req, res) { // ‘/’의 GET 메서드에 대한 분기
res.send('Hello World!');
}).post('/', function (req, res) { // ‘/’의 POS 메서드에 대한 분기
res.send('Got a POST request');
}).put('/user', function (req, res) { // ‘/’의 PUT 메서드에 대한 분기
res.send('Got a PUT request at /user');
}).delete('/user', function (req, res) { // ‘/’의 DELETE 메서드에 대한 분기
res.send('Got a DELETE request at /user');
}).listen(3000, function () {
console.log('Example app listening on port 3000!');
});
Page Rendering
// app.js
var express = require('express');
var app = express();
app.set('view engine', ‘jade');
app.get('/', function (req, res) {
// View engine을 이용해 Page rendering
res.render('index', { title: 'Hey', message: 'Hello there!'});
}).listen(3000, function () {
console.log('Server running at http://localhost:3000');
});
// index.jade
html
head
title!= title
body
h1!= message
Page Rendering
// app.js
var express = require('express');
var app = express();
app.set('view engine', ‘jade'); // jade 엔진을 사용하도록 설정
app.get('/', function (req, res) {
// View engine을 이용해 Page rendering
res.render('index', { title: 'Hey', message: 'Hello there!'});
}).listen(3000, function () {
console.log('Server running at http://localhost:3000');
});
// index.jade
html
head
title!= title
body
h1!= message
Page Rendering
Using Middleware
var express = require('express');
var app = express();
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
app.use(cookieParser());
app.use(bodyParser());
app.use(function (req, res, next) {
console.log('Time:', Date.now());
next();
});
app.get('/', function (req, res) {
// ...
});
Using Middleware
var express = require('express');
var app = express();
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
app.use(cookieParser()); // Connect의 Cookie Parser 모듈을 주입
app.use(bodyParser()); // Connect의 Body Parser 모듈을 주입
app.use(function (req, res, next) { // 사용자 정의 모듈을 주입
console.log('Time:', Date.now());
next();
});
app.get('/', function (req, res) {
// ...
});
Q & A
End.

Node.js 첫걸음

  • 1.
    Node.js 첫걸음 처음부터 시작하는Node.js SeungHyun Lee zero2hex@gmail.com
  • 2.
  • 3.
    “Node.js® is aJavaScript runtime built on Chrome's V8 JavaScript engine.” “As an asynchronous event driven JavaScript runtime, Node is designed to build scalable network applications.” - nodejs.org • 크롬의 V8 자바스크립트 엔진을 기반으로 만들어진 자바스크립트 런타임 • 네트워크 어플리케이션 제작을 위한 비동기 이벤트 기반 방식의 자바스크립트 런타임 What is Node.js?
  • 4.
    “Node.js® is aJavaScript runtime built on Chrome's V8 JavaScript engine.” “As an asynchronous event driven JavaScript runtime, Node is designed to build scalable network applications.” - nodejs.org • 크롬의 V8 자바스크립트 엔진을 기반으로 만들어진 자바스크립트 런타임 • 네트워크 어플리케이션 제작을 위한 비동기 이벤트 기반 방식의 자바스크립트 런타임 = 서버사이드 자바스크립트 프레임워크 What is Node.js?
  • 5.
    Feature • Open Source •Asynchronous & Event-driven • Non-blocking I/O • Single threaded • Chrome’s V8 Engine
  • 6.
    Open Source “Permission ishereby granted, free of charge … without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software …” - LICENSE of node.js • 수정, 배포 등을 포함한 일체의 권리에 제한을 받지 않고 사용할 수 있는 오픈 소스 • https://github.com/nodejs/node
  • 7.
    Asynchronous & Event-driven •절차 지향 프로그래밍 : 진입점에서부터 모든 동작이 차례대로 수행 • 이벤트 드리븐 : 입력 혹은 출력(event)이 발생함에 따라 동작이 처리(driven) • 절차 지향 프로그래밍 방식은 동기적(Synchronous)으로 동작이 처리되는 반면, 이벤 트 드리븐 방식은 비동기적(Asynchronous)으로 동작이 처리됨 • 가장 기본적인 처리 방식으로 콜백(callback)이 존재
  • 8.
    Non-blocking I/O • Blocking: 어떠한 작업이 완료될 때 까지 다른 처리를 막는(blocking) 방식 • Non-blocking : 처리할 작업을 맡겨두고(non-blocking), 결과를 따로 처리하는 방식 • Sync/Asnyc의 개념과 혼동될 수 있으나, Blocking/Non-blocking을 처리하는 방식으 로 Sync/Async를 이용하게 된다.
  • 9.
    Single threaded • Tomcat,Apache : 사용자의 요청에 대해 thread를 생성해 처리 • Node.js : 단일 thread의 event loop 상에서 요청을 처리 • Context switching에 대한 비용 감소 • Multi-thread 환경에서 발생하는 요소 고려에 대한 부담 감소
  • 10.
  • 11.
    Chrome’s V8 Engine •JIT(Just-In-Time) compile • Efficient garbage collection • Inline cache • Hidden classes
  • 12.
    Chrome’s V8 Engine •JIT(Just-In-Time) compile • Efficient garbage collection • Inline cache • Hidden classes >> 빠르며 고성능의 JavaScript 엔진
  • 13.
    Why Node.js? • Fast •Single Thread 기반의 비동기 I/O 처리 • CPU가 특정 I/O의 완료를 대기하지 않고, 다른 작업을 처리 할 수 있음 • 위의 이유로 많은 요청을 수용 가능하다
  • 14.
  • 15.
    Installation (Windows) • Downloadon https://nodejs.org/en/download/ • ‘Windows Installer’ • ‘Next’혹은‘Install’,‘Finish’만 선택해 주면 설치 완료
  • 16.
    Installation (Linux) • Downloadon https://nodejs.org/en/download/ • ‘Source Code’ • GNU make를 위한 의존성 패키지 설치 • configure.sh를 통한 make 설정 • Make • Install
  • 17.
    Installation (Linux)  wgethttps://nodejs.org/dist/v4.4.3/node-v4.4.3.tar.gz  sudo apt-get update && apt-get upgrade  sudo apt-get install build-essential libssl-dev  tar -xzf node-v4.4.3.tar.gz  cd node-v4.4.3  ./configure  make  sudo make install
  • 18.
    Hello World  vimhelloword.js // helloworld.js console.log(“hello world!”)  node helloworld.js // execute
  • 19.
    Hello World  vimhelloword.js // helloworld.js console.log(“hello world!”)  node helloworld.js // execute
  • 20.
    Simple Server  vimsimple_server.js // simple_server.js var http = require('http') http.createServer( (request, response) => { response.writeHead(200, {'Content-Type': 'text/html'}); response.end('<h1>Hello world!</h1>'); }).listen(3000) console.log('Server running at http://localhost:3000');  node simple_server.js // execute (http://localhost:3000)
  • 21.
  • 22.
  • 23.
    Simple Server var http= require('http') http.createServer( (request, response) => { response.writeHead(200, {'Content-Type': 'text/html'}); response.end('<h1>Hello world!</h1>'); }).listen(3000) console.log('Server running at http://localhost:3000');
  • 24.
    Simple Server var http= require('http') http.createServer( (request, response) => { response.writeHead(200, {'Content-Type': 'text/html'}); response.end('<h1>Hello world!</h1>'); }).listen(3000) console.log('Server running at http://localhost:3000');
  • 25.
    Simple Server var http= require('http') http.createServer( (request, response) => { response.writeHead(200, {'Content-Type': 'text/html'}); response.end('<h1>Hello world!</h1>'); }).listen(3000) console.log('Server running at http://localhost:3000'); => HTTP Module
  • 26.
    HTTP Module • HTTP웹 서버와 관련된 기능을 담고있는 모듈 • HTTP Module은 다음과 같은 클래스를 포함 • 요청(Request)와 응답(Response)를 처리할 수 있는 Server • 클라이언트의 요청에 대한 정보를 담는 IncomingMessage • 서버의 처리 결과에 대한 정보를 담는 ServerResponse • 다른 서버와의 통신 기능을 수행할 수 있는 ClientRequest 참고 : https://nodejs.org/api/http.html
  • 27.
    • TCP/IP 기반으로웹 상에서 정보를 주고받을 수 있는 프로토콜 • 클라이언트와 서버 사이에 이루어지는 요청/응답(request/response) 프로토콜 • OSI 7 Layer 중 Application Layer에 해당 • HTML 페이지를 전달하는데 주로 사용 HTTP 참고 : RFC 2616 (https://tools.ietf.org/html/rfc2616)
  • 28.
    HTTP Communication 출처 :http://www.slideshare.net/origamiaddict/http-40249449 TCP Connection (Transport layer) HTTP Connection (Application layer)
  • 29.
    HTTP Message Structure •HTTP 메시지는 크게 Request와 Response로 나뉘어짐 • 각 메시지는 Header와 Body로 구성 • Header는 커넥션 및 쿠키, 파일 종류 등 통신에 필요한 각종 정보를 서술 • Body는 실제 본문으로서 전송할 데이터를 서술 • 메시지 전문은 아래와 같이 구성 Request-Line | Status-Line *(message-header CRLF) CRLF [ message-body ] 참고 : https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
  • 30.
    HTTP Message Structure HTTP/1.1200 OK Server: GitHub.com Date: Wed, 29 Jun 2016 06:16:00 GMT Content-Type: text/html; charset=utf-8 Transfer-Encoding: chunked Status: 200 OK Cache-Control: no-cache X-UA-Compatible: IE=Edge,chrome=1 X-Runtime: 0.019390 <!DOCTYPE html> <html lang="en" class=" is-copy-enabled is-u2f-enabled"> <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# object: http://ogp.me/ns/object# article: http://ogp.me/ns/article# profile: http://ogp.me/ns/profile#"> <meta charset='utf-8'> <link crossorigin="anonymous" href="https://assets-cdn.github.com/assets/frameworks- fef7fdfe41dd435c6d82f93b486dc62bc095ebd12cd24fa2a817c8bb45dc073e.css" integrity="sha256- /vf9/kHdQ1xtgvk7SG3GK8CV69Es0k+iqBfIu0XcBz4=" media="all" rel="stylesheet" /> … Message Headers Message Body 참고 : https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
  • 31.
    Simple Server var http= require('http') http.createServer( (request, response) => { response.writeHead(200, {'Content-Type': 'text/html'}); response.end('<h1>Hello world!</h1>'); }).listen(3000) console.log('Server running at http://localhost:3000');
  • 32.
    Simple Server var http= require('http') http.createServer( (request, response) => { response.writeHead(200, {'Content-Type': 'text/html'}); // Message Header 작성 response.end('<h1>Hello world!</h1>'); // Message Body 작성 }).listen(3000) console.log('Server running at http://localhost:3000');
  • 33.
    HTTP server var http= require('http') // ‘http’ 모듈 로드 var server = http.createServer( (request, response) => { // server 객체 생성 response.writeHead(200, {'Content-Type': 'text/html'}); response.end('<h1>Hello world!</h1>'); }).on('request', function() { // ‘request’ 이벤트에 콜백 매핑 console.log('Request On'); }).on('connection', function() { // ‘connection’ 이벤트에 콜백 매핑 console.log('Connection On'); }).on('close', function() { // ‘close’ 이벤트에 콜백 매핑 console.log('Close On'); }).listen(3000); // 서버 실행 console.log('Server running at http://localhost:3000');
  • 34.
  • 35.
    Serving static files varhttp = require('http') var fs = require('fs') // ‘fs’ 모듈 로드 var server = http.createServer( (request, response) => { fs.readFile('index.html', function(error, data) { // 파일 읽기 response.writeHead(200, {'Content-Type': 'text/html'}); // Header 작성 response.end(data); // 파일 전송 }); }).listen(3000); console.log('Server running at http://localhost:3000');
  • 36.
    Serving static files varhttp = require('http') … // text/html 형식의 파일을 전송 할 것이라 명시 response.writeHead(200, {‘Content-Type’: ‘text/html’}); … console.log('Server running at http://localhost:3000');
  • 37.
  • 38.
  • 39.
    Web Page Presentation •사용자의 요청에 따라 HTML 페이지를 보여주기 위해서는? var http = require('http') var server = http.createServer( request, response => { response.writeHead(200, {'Content-Type': 'text/html'}); response.end(‘<html> <head><title>Hello world!</title></head> <body> <h1>Welcome to Node.js</h1> <p>example page…</p> </body> </html>’); }).listen(3000); • 웹 페이지 소스를 하드 코딩으로 작성 == 번거롭다
  • 40.
    Web Page Presentation •사용자의 요청에 따라 HTML 페이지를 보여주기 위해서는? var http = require('http') var server = http.createServer( request, response => { response.writeHead(200, {'Content-Type': 'text/html'}); response.end(‘<html> <head><title>Hello world!</title></head> <body> <h1>Welcome to Node.js</h1> <p>example page…</p> </body> </html>’); }).listen(3000); • 웹 페이지 소스를 하드 코딩으로 작성 == 번거롭다
  • 41.
    Web Page Presentation •사용자의 요청에 따라 HTML 페이지를 보여주기 위해서는? var http = require('http') var server = http.createServer( request, response => { response.writeHead(200, {'Content-Type': 'text/html'}); response.end(‘<html> <head><title>Hello world!</title></head> <body> <h1>Welcome to Node.js</h1> <p>example page…</p> </body> </html>’); }).listen(3000); • 웹 페이지 소스를 하드 코딩으로 작성 == 번거롭다
  • 42.
    Web Page Presentation •사용자의 요청에 따라 HTML 페이지를 보여주기 위해서는? var http = require('http') var server = http.createServer( request, response => { response.writeHead(200, {'Content-Type': 'text/html'}); response.end(‘<html> <head><title>Hello world!</title></head> <body> <h1>Welcome to Node.js</h1> <p>example page…</p> </body> </html>’); }).listen(3000); • 웹 페이지 소스를 하드 코딩으로 작성 == 번거롭다
  • 43.
    Web Page Presentation •사용자의 요청에 따라 HTML 페이지를 보여주기 위해서는? var http = require('http') var server = http.createServer( request, response => { response.writeHead(200, {'Content-Type': 'text/html'}); response.end(‘<html> <head><title>Hello world!</title></head> <body> <h1>Welcome to Node.js</h1> <p>example page…</p> </body> </html>’); }).listen(3000); • 웹 페이지 소스를 하드 코딩으로 작성 == 번거롭다
  • 44.
    Page Rendering • BusinessLogic과 Presentation Logic을 구분하는 것이 기본 개념 • View를 EJS 문법(EJS) 및 HAML(Pug)에 따라 제작 • 만들어진 View는 Template Engine을 통해 렌더링 • Template Engine에는 Pug(Jade), EJS, Dust, Mustache 등이 존재 참고 : http://paularmstrong.github.io/node-templates
  • 45.
    참고 : https://github.com/pugjs/pug https://github.com/pugjs/pug/issues/2184 • HAML(HTMLAbstract Markup Language)의 영향을 받은 Template Engine • 본 명칭은 Jade로 이쪽이 더 많이 알려져 있으나, 네이밍 이슈로 최근 개명됨 • 들여쓰기를 통해 계층 구조를 표현 • 들여쓰기가 잘못 될 시 전혀 다른 결과 혹은 오류를 발생 Pug (Jade)
  • 46.
    Syntax HTML <!DOCTYPE html> <html lang="en"> <head> <title>Pug</title> <scripttype="text/javascript"> if (foo) bar(1 + 5) </script> </head> <body> <h1>Pug - node template engine</h1> <div id="container" class="col"> <p>You are amazing</p> <p>Pug is a terse and simple templating language with a strong focus on performance and powerful features.</p> </div> </body> </html> 참고 : http://jade-lang.com Pug doctype html html(lang="en") head title= pageTitle script(type='text/javascript'). if (foo) bar(1 + 5) body h1 Pug - node template engine #container.col if youAreUsingPug p You are amazing else p Get on it! p. Pug is a terse and simple templating language with a strong focus on performance and powerful features.
  • 47.
    Install Pug package •Pug는 외부 모듈이므로 실행 전 NPM을 이용해 설치를 진행  npm install pug
  • 48.
    If Jade…?  npminstall jade
  • 49.
    Simple Pug var http= require('http'); var pug = require('pug'); var fs = require('fs'); http.createServer(function (request, response) { fs.readFile('index.pug', 'utf8', function (error, data) { var fn = pug.compile(data); response.writeHead(200, {'Content-Type': 'text/html'}); response.end(fn()); }); }).listen(3000); console.log('Server running at http://localhost:3000'); 참고 : http://jade-lang.com/api/
  • 50.
    Simple Pug var http= require('http'); var pug = require('pug'); // ‘pug’ 모듈 로드 var fs = require('fs'); http.createServer(function (request, response) { fs.readFile('index.pug', 'utf8', function (error, data) { var fn = pug.compile(data); // HTML 코드 제너레이터 생성 response.writeHead(200, {'Content-Type': 'text/html'}); response.end(fn()); // 제너레이터를 이용해 응답 }); }).listen(3000); console.log('Server running at http://localhost:3000'); 참고 : http://jade-lang.com/api/
  • 51.
    Simple Pug var http= require('http'); var pug = require('pug'); // ‘pug’ 모듈 로드 var fs = require('fs'); http.createServer(function (request, response) { response.writeHead(200, {'Content-Type': 'text/html'}); response.end(pug.renderFile('index.pug')); // 파일명을 이용한 코드 생성 }).listen(3000); console.log('Server running at http://localhost:3000'); 참고 : http://jade-lang.com/api/
  • 52.
  • 53.
    Passing Parameters var http= require('http'); var pug = require('pug'); var fs = require('fs'); http.createServer(function (request, response) { fs.readFile('index.pug', 'utf8', function (error, data) { var fn = pug.compile(data); var params = { pageTitle: 'Hello, Pug', youAreUsingPug: true }; // 넘겨줄 변수 목록 response.writeHead(200, { 'Content-Type‘ : 'text/html‘ }); response.end(fn(params)); // 함께 컴파일 }); }).listen(3000); console.log('Server running at http://localhost:3000'); 참고 : http://jade-lang.com/api/
  • 54.
  • 55.
  • 56.
    Necessity of Database •특정 사람들만 글을 읽고 쓸 수 있는 게시판 제작 • 각 사람들에게 계정을 주고 권한을 부여 • 로그인 한 사용자들만 글을 쓰고 읽기가 가능 Q : 사용자 정보를 저장해 둘 곳?
  • 57.
    Necessity of Database •특정 사람들만 글을 읽고 쓸 수 있는 게시판 제작 • 각 사람들에게 계정을 주고 권한을 부여 • 로그인 한 사용자들만 글을 쓰고 읽기가 가능 Q : 사용자 정보를 저장해 둘 곳? A : Database
  • 58.
    Database? • 데이터 중복의최소화 • 데이터의 무결성 • DBMS (DataBase Management System) • 복수 사용자 관리 • 다수의 사용자에 의해 접근 = 동일한 데이터의 동시 사용 또는 변경 • 데이터의 일관성 보장 필요 • 허용된 권한을 통해서만 데이터로 접근 가능 • 복수의 연결 및 자원 관리
  • 59.
    Language of Database •SQL • DB와 의사소통을 하기 위한 표준 언어 • DB 및 데이터의 읽기, 쓰기(생성), 수정, 삭제, 관리 등의 기능을 수행 • DDL (Data Definition Language) • 데이터베이스의 구조 정의 또는 변경. • DML (Data Manupulation Language) • 데이터의 삽입, 삭제, 검색, 수정. • DCL (Data Control Language) • 데이터베이스에 대한 권한 제어.
  • 60.
  • 61.
    Basic Usage var mysql= require('mysql'); var connection = mysql.createConnection({ host : 'localhost', user : 'me', password : 'secret', database : 'my_db' }); connection.connect(); connection.query('SELECT 1 + 1 AS solution', function(err, rows, fields) { if (err) throw err; console.log('The solution is: ', rows[0].solution); }); connection.end(); Connect Query Disconnect
  • 62.
  • 63.
  • 64.
    Express “Express is aminimal and flexible Node.js web application framework that provides a robust set of features for web and mobile applications.” - expressjs.com • Express : Node.js를 기반으로 한 가볍고 유연한 Web Application Framework • Main features • Routing • Managing middlewares • Serving static files 참고 : Express (http://expressjs.com)
  • 65.
    Express & Connect •‘Connect’는 미들웨어(Middleware)를 기반으로 Node.js의 HTTP 서버 기능을 확장 해 주는 모듈 (extensible HTTP server framework for node using "plugins" known as middleware) • 초기‘Express’는 Connect를 기반으로 설계 • 이로 인해 여러 문제가 발생 (Connect에 대한 의존성, 성능 이슈 등) • 위의 문제를 해결하기 위해 Express 4.0 버전부터 의존성을 제거하고 독자적인 Router를 가지게 됨 참고 : Express GitHub (https://github.com/expressjs/express/wiki/Migrating-from-3.x-to-4.x)
  • 66.
    Routing? • 클라이언트가 요청한각각의 경로(URL)에 대한 처리는 어떻게 할까 • http://localhost:3000/ • http://localhost:3000/hello • http://localhost:3000/world • ….
  • 67.
    Routing? • 클라이언트가 요청한각각의 경로(URL)에 대한 처리는 어떻게 할까 • http://localhost:3000/ • http://localhost:3000/hello • http://localhost:3000/world • …. => 마지막 컴포넌트(/, /hello, /world)를 구하고, 각각에 대한 로직을 구성
  • 68.
    Routing on Node.js varhttp = require('http'); var url = require('url'); http.createServer( function (req, res) { var pathname = url.parse(request.url).pathname; if(pathname == '/') { response.writeHead(200, { 'Content-Type': 'text/html' }); response.end('routing: /'); } else if(pathname == '/hello') { response.writeHead(200, { 'Content-Type': 'text/html' }); response.end('routing: /hello'); } else if(pathname == '/world') { response.writeHead(200, { 'Content-Type': 'text/html' }); response.end('routing: /world'); } }).listen(3000);
  • 69.
    Routing on Node.js varhttp = require('http'); var url = require('url'); http.createServer( function (req, res) { var pathname = url.parse(request.url).pathname; if(pathname == '/') { response.writeHead(200, { 'Content-Type': 'text/html' }); response.end('routing: /'); } else if(pathname == '/hello') { response.writeHead(200, { 'Content-Type': 'text/html' }); response.end('routing: /hello'); } else if(pathname == '/world') { response.writeHead(200, { 'Content-Type': 'text/html' }); response.end('routing: /world'); } }).listen(3000); / /hello /world
  • 70.
    Routing • if-else /switch-case 문을 이용한 분기 처리는 분기가 많아질수록 비효율적 • 또한 자칫 스파게티 코드가 되기 쉬움 • Routing 기능만을 독립적으로 수행하고, 로직을 주입할 수 있도록 하자
  • 71.
    Routing • if-else /switch-case 문을 이용한 분기 처리는 분기가 많아질수록 비효율적 • 또한 자칫 스파게티 코드가 되기 쉬움 • Routing 기능만을 독립적으로 수행하고, 로직을 주입할 수 있도록 하자 => Router (라우터)
  • 72.
    Routing on Express varexpress = require('express'); var app = express(); app.get('/', function (req, res) { res.send('Hello World!'); }).post('/', function (req, res) { res.send('Got a POST request'); }).put('/user', function (req, res) { res.send('Got a PUT request at /user'); }).delete('/user', function (req, res) { res.send('Got a DELETE request at /user'); }).listen(3000, function () { console.log('Example app listening on port 3000!'); });
  • 73.
    Routing on Express varexpress = require('express'); // express 모듈 로드 var app = express(); app.get('/', function (req, res) { // ‘/’의 GET 메서드에 대한 분기 res.send('Hello World!'); }).post('/', function (req, res) { // ‘/’의 POS 메서드에 대한 분기 res.send('Got a POST request'); }).put('/user', function (req, res) { // ‘/’의 PUT 메서드에 대한 분기 res.send('Got a PUT request at /user'); }).delete('/user', function (req, res) { // ‘/’의 DELETE 메서드에 대한 분기 res.send('Got a DELETE request at /user'); }).listen(3000, function () { console.log('Example app listening on port 3000!'); });
  • 74.
    Page Rendering // app.js varexpress = require('express'); var app = express(); app.set('view engine', ‘jade'); app.get('/', function (req, res) { // View engine을 이용해 Page rendering res.render('index', { title: 'Hey', message: 'Hello there!'}); }).listen(3000, function () { console.log('Server running at http://localhost:3000'); }); // index.jade html head title!= title body h1!= message
  • 75.
    Page Rendering // app.js varexpress = require('express'); var app = express(); app.set('view engine', ‘jade'); // jade 엔진을 사용하도록 설정 app.get('/', function (req, res) { // View engine을 이용해 Page rendering res.render('index', { title: 'Hey', message: 'Hello there!'}); }).listen(3000, function () { console.log('Server running at http://localhost:3000'); }); // index.jade html head title!= title body h1!= message
  • 76.
  • 77.
    Using Middleware var express= require('express'); var app = express(); var cookieParser = require('cookie-parser'); var bodyParser = require('body-parser'); app.use(cookieParser()); app.use(bodyParser()); app.use(function (req, res, next) { console.log('Time:', Date.now()); next(); }); app.get('/', function (req, res) { // ... });
  • 78.
    Using Middleware var express= require('express'); var app = express(); var cookieParser = require('cookie-parser'); var bodyParser = require('body-parser'); app.use(cookieParser()); // Connect의 Cookie Parser 모듈을 주입 app.use(bodyParser()); // Connect의 Body Parser 모듈을 주입 app.use(function (req, res, next) { // 사용자 정의 모듈을 주입 console.log('Time:', Date.now()); next(); }); app.get('/', function (req, res) { // ... });
  • 79.
  • 80.