Nodejs 디자인 패턴(3)-Stream Coding

업데이트:

스트림

node.js 와 같은 이벤트 기반 플랫폼에서 입출력을 처리하는 효율적인 방법은 실시간으로 가능한 순간 바로 입력을 사용하고 어플리케이션에서 출력이 생성되는 즉시 내보내는 것입니다. 스트림을 사용하면 리소스에서 도착하자마자 데이터를 처리할 수 있습니다.

공간 효율성

V8의 버퍼는 0x3FFFFFFF 바이트보다 클 수 없습니다. 이보다 큰 파일을 모드 읽은 후 커다란 버퍼를 반환하는 API는 적절하지 않습니다.

시간 효율성

다음 코드와 같이 클라이언트에서 스트림을 사용하면 파일 시스템에서 데이터 덩어리를 읽는 즉시 압축하고 보낼 수 있습니다. 서버에서는 원격 peer에서 수신된 즉시 모든 덩어리를 압축 해제할수 있습니다.

// Server
const http = require('http');
const fs = require('fs');
const zlib = require('zlib');

const server = http.createServer((req, res) => {
  const filename = req.headers.filename;
  console.log('File request received: ' + filname);
  req
 	.pipe(zlib.createGunzip())
 	.pipe(fs.createWriteStream(filename))
 	.on('finish', ()=> {
    	res.writeHead(201, {'Content-Type' : 'text/plain'});
    	res.end("That's it\n");
    	console.log("file saved");
  })
})

server.listen(3000, () => console.log('Listen...'))
const fs = require('fs');
const zlib = require('zlib');
const http = require('http');
const path = require('path');
const file = process.argv[2];
const server = process.argv[3];

const options = {
  hostname : server,
  port : 3000,
  path : '/',
  method : 'PUT',
  headers = {
  	filename : path.basename(file),
    Content-Type : 'application/octet-stream',
    Content-Encoding : 'gzip'
	}
}

const req = http.request(options, res => {
  console.log('Server response: '+ res.statusCode);
});

fs.createReadStream(file)
.pipe(zlib.createGzip())
.pipe(req)
.on('finish', () => {
  console.log('File sent');
});

스트림을 사용하면 전체 파일을 읽을 때까지 기다리지 않고 첫 번째 데이터 덩어리를 수신하자마자 조립 라인이 시작됩니다. 데이터의 다음 덩어리가 사용 가능한 상태가 될 때, 이전 작업들이 완료될 때까지 기다릴 필요가 없습니다. 대신 조립 라인은 병렬로 실행됩니다.

이는 각 작업이 비동기적이면서 node.js에 의해 병렬로 실행될수 있기 때문에 완벽히 작동합니다.

유일한 제약은 데이터 덩어리가 각 단계에 도착하는 순서가 보존되어야 한다는 것입니다.

결합성

위에서 pipe() 메소드를 통해 단일 기능을 담당하는 서로 다른 프로세스 유닛들을 연결할 수 있는지 보았습니다. 유일한 전제 조건은 파이프라인의 다음 스트림이 이전 스트림에 의해 생성되어 전달된 데이터 타입을 지원해야 한다는 것입니다.

이미 존재하는 파이프라인에 간단히 변환 스트림을 끼워넣어 스트림을 재사용할 수 있습니다. 스트림을 사용하면 더 깨끗하고 모듈화된 코드를 만들 수 있습니다.

const crypto = require('crypto');
//...
fs.createReadStream(file)
	.pipe(zlib.createGzip())
	.pipe(crypto.createCipher('aes102', 'a_shared_secret')
	.pipe(req)
	.on('finish', () => console.log('File Sent'))

댓글남기기