3์ฅ์์๋ ์๋์ ๊ฐ์ ๋ด์ฉ์ ๋ค๋ฃน๋๋ค.
๏ก Organizing your code into modules
๏ก Coding conventions
๏ก Handling one-off events with callbacks
๏ก Handling repeating events with event emitters
๏ก Implementing serial and parallel flow control
๏ก Leveraging flow-control tools
3.1 ๋ชจ๋์ ์ด์ฉํ ์ฝ๋ ์ฌ์ฌ์ฉ ๋ฐ ์ ๋ฆฌ
PHP๋ Ruby๊ฐ์ ์ธ์ด์์ importํ๋ฉด global scope์ ์ํฅ์ ๋ฏธ์น๋ค.
์ด๋ฐ ๊ฒ์ ํผํ๊ธฐ ์ํด์ PHP๋ namespaces๋ฅผ ์ฌ์ฉํ๊ณ , Ruby๋ modules๋ฅผ ์ฌ์ฉํ๋ค.
ํ์ง๋ง namespaces๋ฅผ ์ฌ์ฉํ๋ค๊ณ ํด๋ overwrite์ ๊ฐ๋ฅ์ฑ์ ์์ ํ ๋ฐฐ์ ํ ์๋ ์๋ค.
Node์์๋ ์ด๋ฐ ์ํ์ ์์ ํ ๋ฐฐ์ ํ๋ค.
์ฐ์ Node์ module์ gloabl scope๋ฅผ ๋ณ๊ฒฝํ์ง ์๋๋ค. ๋ํ, module์ ๋ง๋ค ๋ ๊ฐ๋ฐ์๊ฐ ์ด๋ค ๊ธฐ๋ฅ, ๋ณ์๋ฅผ ์ธ๋ถ์์ ์ฌ์ฉ๊ฐ๋ฅ ํ๊ฒ ํ ์ง ์ ํ ํ ์ ์๋ค. ( ์ด๊ฑด ์๋ฐ์์ ์ ๊ทผ์ ํ์, public ๋๋ private,๋ฅผ ์๊ฐํ๋ฉด ๋๋ค. )
Node์์๋ ์ธ๋ถ์ ๋ ธ์ถ์ํค๋ ๊ฒ์ exportํ๋ค๊ณ ํ๋ค. ( public์ผ๋ก ๋ง๋ ๋ค๋ ๊ฒ์ ์๋ฏธํจ )
export์ ๋ฐฉ๋ฒ์ ์ฒซ์งธ, ๋ ์ด์์ ๊ธฐ๋ฅ ๋ฐ ๋ณ์๋ฅผ exportํ ๋์๋ exports๊ฐ์ฒด์ ์์ฑ์ ์ธํ ํด์ฃผ๋ฉด ๋๋ค. ๋์งธ, ํ๋์ ๊ธฐ๋ฅ์ด๋ ๋ณ์๋ง exportํ ๋์๋ module.exports ์์ฑ์ ์ด์ฉํ๋ค.
3.1.1 ๋ชจ๋ ์์ฑํ๊ธฐ
๋ชจ๋์ a.ํ๋์ ํ์ผ์ด๊ฑฐ๋, b.๋๋ ํ ๋ฆฌ๋ด์ ํ๋ ์ด์์ ํ์ผ๋ก ๊ตฌ์ฑ๋ ์ ์๋ค.
๋๋ ํ ๋ฆฌ ๊ตฌ์กฐ์ผ ๊ฒฝ์ฐ์๋ ๋๋ ํ ๋ฆฌ ๋ด๋ถ์ index.jsํ์ผ์ mainํ์ผ๋ก ์ฌ์ฉํ๋ค. ( ์ด ํ์ผ ๋ช ์ overridden ๊ฐ๋ฅํ๋ค. )
ํ๋์ ํ์ผ์ ๋ชจ๋๋ก ๋ง๋ค ๋์๋ ์๋์ฒ๋ผ ์ ์ํ๋ค.
--------------- convert.js -------------
var num = 0.5;
exports.convertNum = function(myNum) {
return Math.round(myNum / num);
}
----------------------------------------
์ ์ฝ๋๋ฅผ ๋ณด๋ฉด exports์ ์์ฑ์ผ๋ก convertNum ํจ์๋ฅผ ์ ์ํ๋ค. ์ด๋ ์ธ๋ถ์์ ์ ๊ทผ์ด ๊ฐ๋ฅํ public ํจ์์ด๋ค. ํ์ง๋ง num ๋ณ์๋ exports์์ฑ์ผ๋ก ์ ์ํ์ง ์์์ผ๋ฏ๋ก convert.jsํ์ผ ๋ด์์๋ง ์ ๊ทผ ๊ฐ๋ฅํ private ๋ณ์์ด๋ค.
์ด๋ ๊ฒ ๋ง๋ค์ด์ง ๋ชจ๋์ test-convert.js ํ์ผ์์ ์ฌ์ฉํ๋ ค๋ฉด ์๋์ฒ๋ผ ํ ์ ์๋ค.
--------------- test-convert.js -------------
var convert = require('./convert');
console.log(convert.convertNum(5));
-----------------------------------------
์ฌ๊ธฐ์ require()์ ๋ช ์ํ "./convert"๋ ํ์ฌ ๋๋ ํ ๋ฆฌ์ convert.jsํ์ผ์ importํ๋ค๋ ์๋ฏธ์ด๋ค. "./"๋ฅผ ๋ถ์ด์ง ์์ผ๋ฉด ์ค๋ฅ๊ฐ ๋๋ค. requireํ ๋ core module์ ๋ํด์๋ ์๋๊ฒฝ๋ก๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ๋ฐ๋ก ๋ชจ๋๋ช ๋ง ๋ช ์ํ๋๋ก ๋์ด์๋๋ฐ convert.js๋ core module์ด ์๋๋ผ ๋ฐฉ๊ธ ์ฐ๋ฆฌ๊ฐ ๋ง๋ module์ด๊ธฐ ๋๋ฌธ์ด๋ค.
require()๋ convert.js์ ๋ช
์ํ exports์ ์์ฑ์ returnํ๋ค. ๋ฐ๋ผ์ var convert์๋ convert.js(๋ชจ๋)์์ ์ ์ํ exports ๊ฐ์ฒด์ ๋ด์ฉ,์ฆ, convertNum ํจ์๊ฐ ํ ๋น๋์๋ค๊ณ ํ ์ ์๋ค.
3.1.2 module.exports ์ฌ์ฉํ๊ธฐ ( single ๋ณ์, ํจ์, ๊ฐ์ฒด export ์ ์ฌ์ฉ )
module์ ๊ฐ์ฒด์งํฅ ๊ด์ ์์ ์ฌ์ฉํ๊ณ ์ ํ ๋์๋ ์์ฑ์ ํจ์๋ฅผ returnํ๋๋ก ํ ๋ค ์๋์ฒ๋ผ ์ฌ์ฉํ ์๋ ์์ ๊ฒ์ด๋ค.
---------------- convert.js --------------
var Convert = function (num){
this.num = num;
}
Convert.prototype.convertNum = function(myNum) {
return Math.round(myNum / num);
}
// exports = Convert; ( ์ด๋ ๊ฒ ์ฌ์ฉ ๊ธ์ง )
module.exports = Convert;
---------------------------------------
------------- test-convert2.js ------------
var Convert = require('./convert');
var num = 0.5
var convert = new Convert(num);
console.log(convert.convertNum(5));
---------------------------------------
์ ์ฝ๋์์ ์ค์ํ ๋ถ๋ถ์ module.exports = Convert; ๋ผ์ธ์ด๋ค.
์ฒซ ์์ ์์ exports๋ฅผ ์ด์ฉํด์ property๊ฐ์ ์ค์ ํจ์ผ๋ก์จ convert๋ชจ๋์์ ์ ์ํ convertNum() ํจ์๋ฅผ ์ฌ์ฉํ ์ ์์๋ค. ์ด๋ exports๊ฐ module.exports๋ฅผ ์ฐธ์กฐํ๋ global๋ณ์์๊ธฐ์ ๊ฐ๋ฅํ๋ค. ๋ฐ๋ผ์ exports = Convert; ๋ผ๊ณ ํด๋ฒ๋ฆฌ๋ฉด exports๋ ๋์ด์ module.exports๋ฅผ ์ฐธ์กฐํ๋ ๋ณ์๊ฐ ์๋๊ฒ์ด ๋๋ค.
3.1.3 node_modules ๋๋ ํ ๋ฆฌ
์์์ module์ requireํ ๋ core module์ด ์๋๋ฉด ์๋ ๊ฒฝ๋ก๋ฅผ ์ ์ด์ฃผ๊ณ , core module์ด๋ฉด ๊ทธ๋ฅ ์ด๋ฆ์ ์จ๋ ๋๋ค๊ณ ํ๋ค.
๊ทธ๋ฌ๋ฉด ๋ด๋ถ์ ์ผ๋ก ์ด๋ค ๋ก์ง์ ํ๊ธธ๋ core module์ ์ด๋ฆ๋ง ์ ์ด๋ ๋๋ ๊ฑธ๊น? Node๊ฐ module์ ์ฐพ๋ ๋ก์ง์ ์๋์ ๊ฐ๋ค.
์, ๊ทธ๋ผ ๋ด๊ฐ ๋ง๋ ๋ชจ๋์ ์๋๊ฒฝ๋ก ์ง์ ์ ํ์ง ์๊ณ ์ฐ๋ ค๋ฉด ์ด๋ป๊ฒ ํ๋ฉด ๋ ๊น?
๊ทธ๋ฅ node_modules ์์ ๋ฃ์ด๋ฒ๋ฆฌ๋ฉด ๋๋ค. ์ค์ ๋ก npm(Node Package Manager)๋ฅผ ์ด์ฉํ์ฌ install์ ํ๋ฉด node_modules ๋๋ ํ ๋ฆฌ์ ์ค์น๊ฐ ๋๋ค.
3.1.4 ์ฃผ์์ฌํญ
์ฒซ๋ฒ์งธ ์ฃผ์์ฌํญ์ ๋๋ ํ ๋ฆฌ module ์ฌ์ฉ์ ์ฃผ์์ฌํญ์ด๋ค.
๋๋ ํ ๋ฆฌ ๋ฌถ์์ผ๋ก module์ ๋ง๋ค์์ ๋์๋ package.json์ ๋ช ์ํ์ง ์๋ํ index.jsํ์ผ์ด ์กด์ฌํด์ผํ๋ค.
์๋ ๊ทธ๋ฆผ์ connect module์ ์ค์นํ์ ๋ ๋ณผ ์ ์๋ ํจํค์ง ํธ๋ฆฌ์ด๋ค.
connect ๋๋ ํ ๋ฆฌ ์์ index.js๋ผ๋ ํ์ผ์ด ์๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
์ด์ ์ด ํ์ผ๋ช ์ index.js ๊ฐ ์๋ index_2.js ๋ก ๋ฐ๊ฟ๋ณด์.
๊ทธ๋ฆฌ๊ณ ํ
์คํธ ํ๋ก๊ทธ๋จ์ ํ๋ ๋ง๋ค์ด์ require('connect'); ํ ์ค๋ง ์
๋ ฅํด๋ณด๊ณ ์คํํด๋ณด์.
๊ทธ๋ผ ์ค๋ฅ๊ฐ ๋ ๊ฒ์ด๋ค.
์ผ๋ฐ์ ์ผ๋ก ๋๋ ํ ๋ฆฌ ๊ตฌ์กฐ์ module์์๋ index.js ๋ผ๋ ํ์ผ๋ช ์ ์ฌ์ฉํ์ง๋ง, ๊ตณ์ด ๋ฐ๊พธ๊ณ ์ถ๋ค๋ฉด package.json ํ์ผ์ ๋ช ์ํด์ฃผ๋ฉด ๋๋ค.
package.json ํ์ผ์ ์ด์ด์ "main" ์ ์ฐพ์๋ณด์. ์๋ง ์์ ๊ฒ์ด๋ค. ์๋์ฒ๋ผ main์์ฑ์ ๋ฃ์ด๋ณด์.
{ // package.json 1๋ฒ์งธ ๋ผ์ธ
"main":"index_2.js"
--์๋ต--
} // package.json ๋ง์ง๋ง ๋ผ์ธ
์ด์ ๋ค์ ์คํํด๋ณด๋ฉด ์๋ฌ์์ด ์คํ๋๋ ๊ฒ์ ํ์ธํ ์ ์๋ค. ( core module์ด๋ ํ์ผ๋ช ์ ๋ค์ index.js๋ก ๋ฐ๊ฟ์ฃผ์. Now~~ )
์ฐธ๊ณ ๋ก ์๋ ๊ทธ๋ฆผ์ directory ํํ์ module์ requireํ์ ๋ ์ฒ๋ฆฌ๋๋ ๋ก์ง์ด๋ค.
๋ ๋ฒ์งธ ์ฃผ์์ฌํญ์ "monkey patching"์ด๋ค. ์์ญ์ด ํจ์น? ์ด๋ฆ์ด ์ฐธ ํฌํํ๋ค.
monkey patching์ module์ ๊ฐ์ฒด๋ก cachingํ๋ Node์ ๋ฅ๋ ฅ ๋๋ฌธ์ ๊ฐ๋ฅํ ๊ฒ์ผ๋ก, ๋ง์ฝ ์ ํ๋ฆฌ์ผ์ด์ ์์ ์๋ก ๋ค๋ฅธ ๋ ํ์ผ์ด ํ๋์ module์ requireํ๋ค๊ณ ๊ฐ์ ํด๋ณด์. ์ด ๋ ๋์ผํ module์ ๋ ๋ฒ requireํ๋ค๊ณ ํด์ moduleํ์ผ์ ๋ ๋ฒ ์ฝ์ด๋ค์ผ ํ์๊ฐ ์๋๋ก Node์์ ์บ์์ ๋ฃ์ด๋๋ค. ํ์ง๋ง, ์ด ๋๋ฒ ์งธ require์์ ์ด ์บ์์ ๋ค์ด์๋ module์ ๋ณด๋ฅผ ๋ณ๊ฒฝ(alter)ํ ์ ์๋ ๊ธฐํ๋ฅผ ๊ฐ๊ฒ ๋๋ค. ์ด๋ ๊ฒ ๋ณ๊ฒฝํ๋ ๊ฒ์ monkey patching์ด๋ผ๊ณ ํ๋๋ฐ, ์ด๊ฒ์ ์ ์ด์ฉํ๋ฉด module์ด ๋ค๋ฅธ module์ ๋์(behavior)๋ฅผ ์์ ํ ์ ์์ ๋ฟ ์๋๋ผ ๊ฐ๋ฐ์๊ฐ ๋ค๋ฅธ ๋ฒ์ ์ module์ ๋ง๋ค ํ์๊ฐ ์๋๋ก ํด์ค๋ค. ( ์ด๊ฑด ๋์ BCI๋ผ๊ณ ์ดํดํ๋ค. )
3.2 ๋น๋๊ธฐ์ ํ๋ก๊ทธ๋๋ฐ ํ ํฌ๋
3.2.1 Callbackํจ์๋ฅผ ์ด์ฉํ one-off ์ด๋ฒคํธ ํธ๋ค๋ง
var fs = require('fs');
fs.readFile('./blah.txt', function(err, data) {
if (err) { throw err };
// do something
});
3.2.2 EventEmitter๋ฅผ ์ด์ฉํ ๋ฐ๋ณต ์ด๋ฒคํธ ํธ๋ค๋ง
var net = require('net');
var server = net.createServer(function(socket) {
socket.on('data', function(data) {
socket.write(data);
});
});
server.listen(8080);
1ํ์ฑ ์ด๋ฒคํธ ์ฒ๋ฆฌ์ once ์ฌ์ฉ.
var net = require('net');
var server = net.createServer(function(socket) {
socket.once ('data', function(data) {
socket.write(data);
});
});
server.listen(8080);
EventEmitter ํ์ฅํ๊ธฐ
function Watcher(watchDir, processedDir) {
this.watchDir = watchDir;
this.processedDir = processedDir;
}
var events = require('events'), util = require('util');
util.inherits(Watcher, events.EventEmitter); // == Watcher.prototype = new events.EventEmitter();
var fs = require('fs'), watchDir = './watch', processedDir = './done';
Watcher.prototype.watch = function() {
var watcher = this;
fs.readdir(this.watchDir, function(err, files) {
if (err) throw err;
for(var index in files) {
watcher.emit('process', files[index]);
}
})
}
Watcher.prototype.start = function() {
var watcher = this;
fs.watchFile(watchDir, function() {
watcher.watch();
});
}
var watcher = new Watcher(watchDir, processedDir);
watcher.on('process', function process(file) {
var watchFile = this.watchDir + '/' + file;
var processedFile = this.processedDir + '/' + file.toLowerCase();
fs.rename(watchFile, processedFile, function(err) {
if (err) throw err;
});
});
watcher.start();
3.2.3 ๋น๋๊ธฐ์ ์ดํ ๊ฐ๋ฐ์ ์ฃผ์ํ ์
๋๊ธฐ์์์๋ ํ๋ก๊ทธ๋จ์ ์คํ ์์๊ฐ ๋ช ํํ์ง๋ง ๋น๋๊ธฐ์์์๋ ์คํ ์์๊ฐ ๋ช ํํ์ง ์๋ค.
Node์ event loop๋ ๋น๋๊ธฐ ๋ก์ง์ด ์์ ํ ์๋ฃ๋์๋์ง ์ถ์ ์ ํฉ๋๋ค. ์๋ฌด๋ฆฌ ๋น๋๊ธฐ ๋ก์ง์ด๋ผ๋ ์์ ํ ๋๋์ง ์์๋ค๋ฉด ํ๋ก์ธ์ค๋ ์ข ๋ฃ๋์ง ์์ต๋๋ค.
[ Javascript ์ Closure์ ๋ํ ๊ฐ๋ ๋งํฌ ]
3.3 ๋น๋๊ธฐ์ ๋ก์ง์ ์์๋๋ก ์ฒ๋ฆฌํ๊ธฐ
Nimble ์ ์ด์ฉํ sequencing ์ฒ๋ฆฌ
Nimble ์ด์ธ์๋ Step, Seq์ ๊ฐ์ module์ด ์ด๋ฏธ ์กด์ฌํจ. ๊ฐ์ ธ๋ค ์ฐ๋ฉด ๋จ.
[[๊ถ๊ธ์ฆ ๋ค.....]]
1. ์์กด์ฑ๋ชจ๋ package.json ํ์ผ๋ช ์ ๋ค๋ฅธ๊ฑธ๋ก ๋ฐ๊ฟ ์ ์๋??
npmjs.com์์ ๋งํ๋ npm์์ ๋งํ๋ package๋ผ ํจ์ ์๋์ ๊ฐ์ต๋๋ค.
A package is any of:
- a) a folder containing a program described by a
package.json
file - b) a gzipped tarball containing (a)
- c) a url that resolves to (b)
- d) a
<name>@<version>
that is published on the registry with (c) - e) a
<name>@<tag>
that points to (d) - f) a
<name>
that has alatest
tag satisfying (e) - g) a
git
url that, when cloned, results in (a).
๋ํ module์ด๋ผ ํจ์
- A folder with a
package.json
file containing amain
field. - A folder with an
index.js
file in it. - A JavaScript file.
๋ก ์ ์๋ฅผ ํ๊ณ ์์ต๋๋ค.
๋ฐ๋ผ์, package.json ํ์ผ์ ๋ค๋ฅธ ํ์ผ๋ช
์ผ๋ก ์ฌ์ฉํ ๋ค๋ ๊ฒ์ ๋ถ๊ฐ๋ฅํฉ๋๋ค.
์ถ์ฒ : https://docs.npmjs.com/how-npm-works/packages
2. ์ด๋ฒคํธ ๋ฃจํ = ๋ฉํฐ์ฐ๋ ๋????, ๋น๋๊ธฐ์ ๋ฉํฐ์ฐ๋ ๋์ ์ฐจ์ด์ ??
์ด๋ฒคํธ ๋ฃจํ๋ ๊ฒฐ๊ตญ ๋ฉํฐ์ฐ๋ ๋, ํด๋ง๊ณผ ๊ฐ์ ๊ธฐ์ ์ ์ฌ์ฉํ๋ ๊ฒ์ด๋ผ๋ ๊ฒฐ๋ก ์
๋๋ค.
์๋๋ ์ฐธ์กฐํ ๋งํ ๋งํฌ๋ค์ ๋๋ค.
http://jeremyko.blogspot.kr/2012/12/nodejs-thread-poollibuv.html ( ํ๊ธ ๋ธ๋ก๊ทธ )
http://nikhilm.github.io/uvbook/basics.html#event-loops
3. monkey patching - ์ ์ฒซ ๋ฒ์งธ requireํ ๋ ์์ ๊ฐ๋ฅX ?
์ด๊ฑด ์ฌ์ค ์ง๋ฌธ ์์ฒด๊ฐ ์๋ชป๋์๋ ๊ฒ ๊ฐ๋ค. monkey patching์ ๋ํด์๋ ์๋ ๋งํฌ์ ์ค๋ช ์ด ๋์์๋ค.
http://fredkschott.com/post/2014/09/nodejs-dangerous-module-design-patterns/
๊ฒฐ๊ตญ monkey patching ์ด๋ผ๋ ๊ฒ์ ๊ธฐ์กด์ ์๋ ๊ฒ์ overwriteํ๋ค๋ ๊ฒ์ธ๋ฐ require๋ฅผ ์ฒ์ ํ ๋์๋ overwriteํ ๊ฒ ์์ผ๋๊น ๋์ผํ ๋ชจ๋์ ๋ค๋ฅธ ํ์ผ์์ ๋ require ํ ๋์ ์์ ํ ์ ์๋ ๊ธฐํ๋ฅผ ์ค๋ค๊ณ ์ฑ ์์ ์ค๋ช ์ ํ ๊ฒ ๊ฐ๋ค. ์ด "์์ญ์ด ํจ์น"์ ๋ํด์๋ ์ฑ ์์ ์์ธํ๊ฒ ์ค๋ช ์ ์ํ๊ณ ์๋๋ฐ ์ ๋งํฌ์์ ์ค๋ช ํ๋ ๊ฒ์ ๋ณด๋ฉด ๊ทธ ์ํ์ฑ ๋๋ฌธ์ ๊ทธ๋ฐ๊ฒ ์๋๊ฐ ์ถ๋ค. ๊ฐ๋ ์ฑ๋ ๋จ์ด์ง ๊ฒ ๊ฐ๊ณ ..
'๐ป Programming' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Git] ํ๊ทธ ์ญ์ ํ๊ธฐ (removing git tag) (0) | 2018.01.24 |
---|---|
[ Node.js in Action ] 13์ฅ ์์ฝ (0) | 2017.06.03 |
[ Node.js In Action ] 1์ฅ ์์ฝ (0) | 2017.06.03 |
[Node.js] ํํ ๋ฆฌ์ผ - ์ค์นํ๊ธฐ ๋ถํฐ ์ด๊ฐ๋จ ์น์ฌ์ดํธ ๊ตฌ์ฑํ๊ธฐ ๊น์ง (0) | 2017.06.03 |
[Spring Error] No converter found for return value of type: class java.util.ArrayList (0) | 2016.11.27 |