Node.js 사용 방법
Post date: Mar 29, 2018 2:11:39 AM
[Global Objects]
- global 혹은 GLOBAL 객체를 이용해 전역 변수(global variable) 사용 가능
- console: console 제어, https://nodejs.org/api/console.html
Console에 log 표시: console.log()
- process: program과 관련된 정보 획득, https://nodejs.org/api/process.html
Node.js version 얻기: console.log(process.version);
Memory 사용 현황: console.log(process.memoryUsage());
- module: 사용자 module 만들기, https://nodejs.org/api/modules.html
[Module 만들기]
module.exports와 exports의 차이는 구별해야 함
= JS 관점으로 쓰면 다음과 같음: module.exports와 exports는 동일한 empty object를 가르키고 있음
= require()은 해당 file의 module.exports를 가져옴
let module = new Module(); module.exports = {};
let exports = module.exports;
- exports 사용: 여러 개의 method 정의 가능(exports는 기본적으로 module.exports와 동일; exports에는 함수 할당 불가능)
circle.js
const PI = Math.PI; // const {PI} = Math;
exports.area = function (r) {
return PI * r * r;
}; // exports.area = (r) => PI*(r**2);
exports.circumference = function (r) {
return 2 * PI * r;
}; // exports.circumference = (r) => 2*PI*r;
foo.js
let circle = require('./circle.js');
console.log('The area of a circle of radius 4 is ' + circle.area(4));
= require() 함수를 쓴 경우에 package.json이 있으면 오류 발생: package.json을 지우고 js를 실행해야 함
- module.exports 사용: 하나의 method만 정의 가능(Node.js는 exports보다 module.exports에 우선권을 부여함; module.exports에는 함수 할당 가능)
square.js
module.exports = function(width) {
return {
area: function() {
return width * width;
}};
}
foo.js
let square = require('./square.js');
let mySquare = square(2);
console.log('The area of my square is ' + mySquare.area());
- Default export 사용: ES6에서만 사용 가능
ellipse.js
const PI = Math.PI;
export default function(a, b) {
return {
area: function() {
return PI*a*b;
}
};
};
foo.js
import ellipse from './ellipse.js';
let myEllipse = ellipse(2, 3);
console.log(myEllipse.area());
= foo.js가 정상적으로 실행되려면 package.json이 아래와 같이 정의되어야 함
{
"type": "module"
}
- Named export 사용: ES6에서만 사용 가능
ellipse.js
const PI = Math.PI;
const sq2 = Math.sqrt(2);
function myFun(a, b) {
return {
area: function() {
return PI*a*b;
}
};
}
export {sq2, myFun};
foo.js
import {sq2, myFun} from './ellipse.js';
let myEllipse = myFun(2, 3);
console.log(sq2);
console.log(myEllipse.area());
= foo.js가 정상적으로 실행되려면 package.json이 아래와 같이 정의되어야 함
{
"type": "module"
}
[Node.js Modules]
- os: server가 구동되는 OS 특성 제공, https://nodejs.org/api/os.html
불러오기: const os = require('os');
CPU: os.cpus()
- fs: file system 관리 기능 제공, https://nodejs.org/api/fs.html
불러오기: const fs = require('fs');
동기적 file 읽기: let text = fs.readFileSync('text.txt', 'utf8');
비동기적 file 읽기: fs.readFile('text.txt', 'utf8', function (err, data) { console.log(data); let str = data; });
= 동기 읽기에서는 blocking이 있어서 callback이 없음; 반면에 비동기 읽기는 non-blocking이어서 callback이 가능함
= Web server가 구동일 때는 절대 readFileSync()를 쓰지 말고 readFile()을 써야 함
동기적 file 쓰기: let data = 'test'; fs.writeFileSync('text.txt', data, 'utf8');
비동기적 file 쓰기: let data = 'test'; fs.writeFile('text.txt', data, 'utf8', function (err) { console.log('File 쓰기'); });
동기적으로 file이 존재하는지 확인: fs.existsSync('text.txt');
- http: HTTP 함수 제공, https://nodejs.org/api/http.html
- url: URL 함수 제공, https://nodejs.org/api/url.html
- querystring: URL query string 함수 제공, https://nodejs.org/api/querystring.html
Node.js에서 위 code를 그대로 실행하면 어떤 경우 "undefined"가 나옴
= 예) node에 들어가서 let a = 1; 이라 쓰면 undefined이 나옴
= "undefined"가 나와도 문제 없음: 이는 명령어 실행 결과의 return이 없다는 의미라서 전혀 문제가 안됨
[단순 Server 구성]
const http = require('http');
// req: request. 웹 요청 매개변수, res: response. 웹 응답 매개변수
server = http.createServer(function (req, res) {
// writeHead: 응답 헤더를 작성합니다.
// 200: 응답 성공, text/html: HTML 문서
res.writeHead(200, {'Content-Type': 'text/html'});
// write & end: 응답 본문을 작성합니다.
res.write('Hello World!');
res.write('<br>Hello ICE!');
res.end(); // res.end('Hello World!<br>Hello ICE!')도 가능
});
// listen: 매개변수로 포트와 호스트를 지정합니다.
server.listen(8000, '127.0.0.1'); // 127.0.0.1 대신 localhost 사용 가능
//server.listen(80, 'localhost'); // 80 port는 HTTP 기본 port
console.log('Server running at http://127.0.0.1:8000');
[ Module 이용한 Server 구성]
- MyServer.js
Ver 0.1
const http = require('http');
const sHost = 'localhost';
const nPort = 8000;
function start() {
function onRequest(req, res) {
console.log('Request received.');
res.writeHead(200, { 'Content-Type': 'text/html' });
res.write('Hello World!');
res.write('<br>Hello ICE!');
res.end();
}
http.createServer(onRequest).listen(nPort, sHost);
console.log('Server running at http://' + sHost + ':' + nPort);
}
exports.start = start;
Ver 0.2
const http = require('http');
const url = require('url');
const sHost = 'localhost';
const nPort = 8000;
const sBaseUrl = 'http://' + sHost + ':' + nPort;
function start(route) {
function onRequest(req, res) {
console.log('Request received.');
//let sPathname = url.parse(req.url).pathname;
let sPathname = new url.URL(req.url, sBaseUrl).pathname;
console.log('Request for ' + sPathname + ' received.');
route(sPathname);
res.writeHead(200, { 'Content-Type': 'text/html' });
res.write('Hello World!');
res.write('<br>Hello ICE!');
res.end();
}
http.createServer(onRequest).listen(nPort, sHost);
console.log('Server running at http://' + sHost + ':' + nPort);
}
exports.start = start;
Ver 0.3
const http = require('http');
const url = require('url');
const sHost = 'localhost';
const nPort = 8000;
const sBaseUrl = 'http://' + sHost + ':' + nPort;
function start(route, handle) {
function onRequest(req, res) {
console.log('Request received.');
let sPathname = new url.URL(req.url, sBaseUrl).pathname;
console.log('Request for ' + sPathname + ' received.');
let content = route(sPathname, handle);
res.writeHead(200, { 'Content-Type': 'text/html' });
res.write(content);
res.end();
}
http.createServer(onRequest).listen(nPort, sHost);
console.log('Server running at http://' + sHost + ':' + nPort);
}
exports.start = start;
Ver 0.4
const http = require('http');
const url = require('url');
const sHost = 'localhost';
const nPort = 8000;
const sBaseUrl = 'http://' + sHost + ':' + nPort;
function start(route, handle) {
function onRequest(req, res) {
console.log('Request received.');
let sPathname = new url.URL(req.url, sBaseUrl).pathname;
console.log('Request for ' + sPathname + ' received.');
route(sPathname, handle, res);
}
http.createServer(onRequest).listen(nPort, sHost);
console.log('Server running at http://' + sHost + ':' + nPort);
}
exports.start = start;
Ver 0.5
const http = require('http');
const url = require('url');
const sHost = 'localhost';
const nPort = 8000;
const sBaseUrl = 'http://' + sHost + ':' + nPort;
function start(route, handle) {
function onRequest(req, res) {
console.log('Request received.');
let sPathname = new url.URL(req.url, sBaseUrl).pathname;
let sPostData = '';
console.log('Request for ' + sPathname + ' received.');
req.setEncoding('utf8');
req.addListener('data', function (chunk) {
sPostData += chunk;
console.log('chunk: ' + chunk);
});
req.addListener('end', function () {
route(sPathname, handle, res, sPostData);
});
}
http.createServer(onRequest).listen(nPort, sHost);
console.log('Server running at http://' + sHost + ':' + nPort);
}
exports.start = start;
- MyRouter.js
Ver 0.2
function route(pathname) {
console.log("Routing a request for " + pathname);
}
exports.route = route;
Ver 0.3
function route(pathname, handle) {
console.log("Routing a request for " + pathname);
if (typeof handle[pathname] === 'function') {
return handle[pathname]();
} else {
console.log('No handler for ' + pathname);
return '404 not found';}}
exports.route = route;
Ver 0.4
function route(pathname, handle, res) {
console.log("Routing a request for " + pathname);
if (typeof handle[pathname] === 'function') {
handle[pathname](res);
} else {
console.log('No handler for ' + pathname);
res.writeHead(404, { 'Content-Type': 'text/html' });
res.write('404 not found');
res.end();}}
exports.route = route;
Ver 0.5
function route(pathname, handle, res, postData) {
console.log("Routing a request for " + pathname);
if (typeof handle[pathname] === 'function') {
handle[pathname](res, postData);
} else {
console.log('No handler for ' + pathname);
res.writeHead(404, { 'Content-Type': 'text/html' });
res.write('404 not found');
res.end();}}
exports.route = route;
- MyHandlers.js
Ver 0.3
function start() {
console.log('Request handler \'start\'');
return 'Hello Start!';
}
function hello() {
console.log('Request handler \'hello\'');
return 'Hello Hello!';
}
exports.start = start;
exports.hello = hello;
Ver 0.4
function sleep(milliSec) {
let timeStart = new Date().getTime();
while (new Date().getTime() < timeStart + milliSec);
}
function start(res) {
console.log('Request handler \'start\'');
// Blocking function
// sleep(10000);
// Non-blocking function
setTimeout(function () {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.write('Hello Start!');
res.end();
}, 10000); // 10초 기다리고 callback 실행
}
function hello(res) {
console.log('Request handler \'hello\'');
res.writeHead(200, { 'Content-Type': 'text/html' });
res.write('Hello Hello!');
res.end();
}
exports.start = start;
exports.hello = hello;
Ver 0.5
const queryString = require('querystring');
function start(res) {
console.log('Request handler \'start\'');
let sBody = '<html>' + '<head>' +
'<meta http-equiv="Content-Type" content="text/html" charset="UTF-8" />' +
'</head>' + '<body>' +
'이름과 별명을 입력하세요.<br>' +
'<form action="/hello" method="post">' +
'<input type="text" name="myName" /><br>' +
'<input type="text" name="myNick" /><br>' +
'<button type="submit">입력 완료</button>' +
'</form>' + '</body>' + '</html>';
res.writeHead(200, { 'Content-Type': 'text/html' });
res.write(sBody);
res.end();
}
function hello(res, postData) {
console.log('Request handler \'hello\'');
let sBody = '<html>' + '<head>' +
'<meta http-equiv="Content-Type" content="text/html" charset="UTF-8" />' +
'</head>' + '<body>' +
'안녕하세요, ' + queryString.parse(postData).myName +
'(별명: ' + queryString.parse(postData).myNick + ')님!' +
'</body>' + '</html>';
res.writeHead(200, { 'Content-Type': 'text/html' });
res.write(sBody);
res.end();
}
exports.start = start;
exports.hello = hello;
여러 button 사용예
(formaction 이용)
= <form></form>을 여러 번 사용해도 동작함
<button type="submit" formaction="/hello">입력 완료</button>
<button type="submit" formaction="/start">입력 취소</button>
- Index.js
Ver 0.1
const myServer = require('./MyServer');
myServer.start();
Ver 0.2
const myServer = require('./MyServer');
const myRouter = require('./MyRouter');
myServer.start(myRouter.route);
Ver 0.3, 0.4, 0.5
const myServer = require('./MyServer');
const myRouter = require('./MyRouter');
const myHandlers = require('./MyHandlers');
let handle = {};
handle['/'] = myHandlers.start;
handle['/start'] = myHandlers.start;
handle['/hello'] = myHandlers.hello;
myServer.start(myRouter.route, handle);
[Node.js 함수]
- require() 함수
Module을 import(inlcude)하기 위한 함수
module.exports(혹은 exports)에 정의된 객체가 import됨
require 입력의 파일 이름에서 '.js'는 생략 가능
require 입력에 경로 표현 가능
[참고 문헌]
- Node.js: https://opentutorials.org/module/938
- Build a simple Twitter Bot with Node.js in just 38 lines of code