node.js 유용한 모듈 (3) - lazy
이 글은 node.js modules you should know about 시리즈의 세번째 연재다.
이번 연재에서 소개할 모듈은 내가 직접 작성한 node-lazy이라는 lazy 리스트 모듈(역자주: 적절한 번역 용어가 떠오르지 않아냥 lazy라고 했습니다)이다.
기본적으로 여러분은 새로운 lazy 객체를 생성하고, data
이벤트(event emitter)를 통해 실제 data를 lazy 객체에 전달한다. 그런 다음 다양한 Functional Programming 메서드들을 이용한 체이닝을 통해 이러한 데이터를 처리할 수 있다.
여기 간단한 에제가 있다. 이 예제에서 우리는 새로운 lazy 객체를 생성하고 짝수만 리턴하는 filter
를 정의했다. 그리고 5개의 요소들을 take
한 다음, 그것들을 map
했다. 마지막으로 결과값을 리스트로 join
했다(스레드의 join 메서드를 연상해라).
var Lazy = require('lazy');
var lazy = new Lazy;
lazy
.filter(function (item) {
return item % 2 == 0
})
.take(5)
.map(function (item) {
return item*2;
})
.join(function (xs) {
console.log(xs);
});
data
이벤트가 발생하면 위 예제 코드를 통해 리턴된 객체로 실제 데이터가 넘어 가고, 그것들은 로직대로 처리될 것이다.
예를 들어, 다음과 같이 실행 코드를 작성했다면,
[0,1,2,3,4,5,6,7,8,9,10].forEach(function (x) {
lazy.emit('data', x);
});
setTimeout(function () { lazy.emit('end') }, 100);
이제 5개의 원소가 체이닝의 끝에 도달하면 console.log
에 의해 결과값이 출력될 것이다.
결과는 다음과 같다 : [0, 4, 8, 12, 16]
다음은 node-iptables(나의 또다른 모듈)에서 사용된 실전 예제이다.
var Lazy = require('lazy');
var spawn = require('child_process').spawn;
var iptables = spawn('iptables', ['-L', '-n', '-v']);
Lazy(iptables.stdout)
.lines
.map(String)
.skip(2) // skips the two lines that are iptables header
.map(function (line) {
// packets, bytes, target, pro, opt, in, out, src, dst, opts
var fields = line.trim().split(/\s+/, 9);
return {
parsed : {
packets : fields[0],
bytes : fields[1],
target : fields[2],
protocol : fields[3],
opt : fields[4],
in : fields[5],
out : fields[6],
src : fields[7],
dst : fields[8]
},
raw : line.trim()
};
});
이 코드 조각은 iptables -L -n -v
에서 얻은 출력값을 나중에 활용하기 위해서 자료구조 형태로 변환한다.
우선 기존 스트림 ( iptables.stdout
스트림)으로부터 새로운 Lazy 객체를 생성한다. 다음으로 스트림을 \n
문자로 구분하기 위해 특별한 lines
getter를 호출해서 라인 단위의 스트림으로 변경한다. 이후 스트림은 String
생성자를 통해 문자열로 변경된다. 다음으로 맨앞 두 라인은 skip(2)
에 의해 스킵되고, 이외 라인들은 map
에 의해 자료 구조 형태로 변환된다.
node-lazy를 이용하면 무한 범위를 포함한 모든 범위의 숫자 리스트를 생성할 수 있다. 다음 ranges.js를 살펴보자.
var Lazy = require('lazy');
Lazy.range('1..20').join(function (xs) {
console.log(xs);
});
Lazy.range('444..').take(10).join(function (xs) {
console.log(xs);
});
Lazy.range('2,4..20').take(10).join(function (xs) {
console.log(xs);
});
실행 결과는 다음과 같다.
$ node ranges.js [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 ] [ 2, 4, 6, 8, 10, 12, 14, 16, 18 ] [ 444, 445, 446, 447, 448, 449, 450, 451, 452, 453 ]
아래는 node-lazy로 생성할 수 있는 다양한 숫자 범위들의 예이다.
Lazy.range('10..') - infinite range starting from 10 Lazy.range('(10..') - infinite range starting from 11 Lazy.range(10) - range from 0 to 9 Lazy.range(-10, 10) - range from -10 to 9 (-10, -9, ... 0, 1, ... 9) Lazy.range(-10, 10, 2) - range from -10 to 8, skipping every 2nd element (-10, -8, ... 0, 2, 4, 6, 8) Lazy.range(10, 0, 2) - reverse range from 10 to 1, skipping every 2nd element (10, 8, 6, 4, 2) Lazy.range(10, 0) - reverse range from 10 to 1 Lazy.range('5..50') - range from 5 to 49 Lazy.range('50..44') - range from 50 to 45 Lazy.range('1,1.1..4') - range from 1 to 4 with increment of 0.1 (1, 1.1, 1.2, ... 3.9) Lazy.range('4,3.9..1') - reverse range from 4 to 1 with decerement of 0.1 Lazy.range('[1..10]') - range from 1 to 10 (all inclusive) Lazy.range('[10..1]') - range from 10 to 1 (all inclusive) Lazy.range('[1..10)') - range grom 1 to 9 Lazy.range('[10..1)') - range from 10 to 2 Lazy.range('(1..10]') - range from 2 to 10 Lazy.range('(10..1]') - range from 9 to 1 Lazy.range('(1..10)') - range from 2 to 9 Lazy.range('[5,10..50]') - range from 5 to 50 with a step of 5 (all inclusive)
lazy는 다음과 같이 npm을 통해 설치할 수 있다.
npm install lazy
If you love these articles, subscribe to my blog for more, follow me on Twitter to find about my adventures, and watch me produce code on GitHub!