Stream은 전체 데이터 세트를 메모리에 로드할 필요 없이 소스에서 데이터를 읽거나 데이터를 청크 단위로 대상에 쓰는 데 사용되는 Node.js의 핵심 구성 요소이다. 대용량 데이터를 처리하거나 시간이 지남에 따라 데이터가 도착할 때 강력한 도구이다.
스트림은 EventEmitter
소스에서 데이터를 읽거나 연속적으로 대상에 데이터를 쓸 수 있는 데이터 채널의 인스턴스이며 데이터 채널로 간주될 수 있다. 스트림에는 네 가지 기본 유형이 있다.
Readable Streams
: 파일에서 읽을 때와 같이 데이터 읽기를 허용한다.
Writable Streams
: 파일에 쓸 때와 같이 데이터 쓰기를 허용한다.
Duplex Streams
: TCP 소켓처럼 읽기 및 쓰기가 모두 가능하다.
Transform Streams
: 데이터를 쓰고 읽을 때 데이터를 수정하거나 변환할 수 있는 이중 스트림이다.
성능 및 효율성
: 데이터를 한꺼번에 읽거나 쓰는 대신 스트림은 데이터를 여러 덩어리로 나누어 많은 메모리를 소비하지 않고도 데이터를 처리할 수 있다.
시간 민감도
: 처리를 시작하는 데 사용할 수 있는 전체 데이터 세트가 필요하지 않은 비디오 스트리밍과 같은 실시간 데이터 처리에 적합하다.
큰 물병(데이터 원본)과 작은 컵(버퍼)을 상상하자. 주전자의 내용물 전체를 용기(메모리)에 한꺼번에 붓는 대신, 주전자가 빌 때까지 컵에 물을 부은 다음 컵에서 목적지로 물을 붓는다. 스트림도 비슷하게 작동하여 데이터를 한꺼번에 처리하지 않고 청크로 처리한다.
Writable Stream
const fs = require('fs');
const writeStream = fs.createWriteStream('outputFile.txt');
writeStream.write('Hello, Streams!');
writeStream.end();
Readable Stream
const fs = require('fs');
const readStream = fs.createReadStream('largeFile.txt', 'utf8');
readStream.on('data', (chunk) => {
console.log(chunk);
});
Piping Streams
가장 강력한 기능 중 하나는 스트림을 "파이프"하여 한 스트림의 출력을 가져와 다른 스트림의 입력으로 만드는 기능
const fs = require('fs');
const readStream = fs.createReadStream('largeFile.txt');
const writeStream = fs.createWriteStream('outputFile.txt');
readStream.pipe(writeStream);
Stream은 한 번만 사용할 수 있다.
: 스트림의 데이터가 사용되면 동일한 스트림을 재사용하여 데이터를 다시 읽을 수 없다. 즉, 여러 장소에서 동일한 스트림을 사용해야 하는 경우 스트림을 복제하거나 캐시하는 방법을 찾아야 한다.
const fs = require('fs');
const readStream = fs.createReadStream('example.txt');
readStream.on('data', chunk => {
console.log(chunk.toString());
});
readStream.on('end', () => {
readStream.on('data', chunk => {
console.log(chunk.toString()); // 나오지 않음
});
});
오류 처리
: 스트림에서 오류가 발생할 수 있으므로 이러한 오류를 처리하는 것이 중요하다. error
이벤트를 수신하는 것이 이를 관리하는 일반적인 방법이다.
stream.on('error', err => {
console.error('에러', err);
});
Stream 닫기
: 스트림, 특히 쓰기 가능한 스트림 작업이 완료되면 닫아야 한다. 쓰기 가능한 스트림을 닫지 않으면 데이터가 완전히 기록되지 않을 수 있다.
const writeStream = fs.createWriteStream('output.txt');
writeStream.write('Hello, World!');
writeStream.end(() => {
console.log('Writing is complete.');
});
HighWaterMark
: 버퍼링해야 하는 데이터 양(바이트 단위)을 결정하기 위해 스트림에 설정할 수 있는 구성 옵션이다.
const readStream = fs.createReadStream('example.txt', {
highWaterMark: 16,
});
스트림은 Node.js의 기본이며, 특히 대규모 데이터세트를 처리할 때 데이터를 청크로 처리하는 효율적인 방법을 제공한다. 스트림을 이해하고 활용함으로써 애플리케이션의 성능과 응답성을 크게 향상시킬 수 있다.