"일꾼이 일을 잘하려면 먼저 도구를 갈고 닦아야 한다." - 공자, 『논어』.
첫 장 > 프로그램 작성 > Node.js 스트림 이해: 무엇을, 왜, 어떻게 사용하는가

Node.js 스트림 이해: 무엇을, 왜, 어떻게 사용하는가

2024-11-09에 게시됨
검색:661

Understanding Node.js Streams: What, Why, and How to Use Them

Node.js 스트림은 대용량 데이터를 효율적으로 처리하는 데 필수적인 기능입니다. 기존 입출력 메커니즘과 달리 스트림을 사용하면 전체 데이터를 메모리에 로드하는 대신 데이터를 청크로 처리할 수 있으므로 대용량 파일이나 실시간 데이터를 처리하는 데 적합합니다. 이 글에서는 Node.js 스트림이 무엇인지, 왜 유용한지, 어떻게 구현하는지, 그리고 자세한 예제와 사용 사례를 통해 다양한 유형의 스트림에 대해 자세히 알아볼 것입니다.

Node.js 스트림이란 무엇입니까?

간단히 말하면 스트림은 시간이 지남에 따라 한 지점에서 다른 지점으로 이동되는 일련의 데이터입니다. 데이터가 한꺼번에 흐르지 않고 하나씩 흐르는 컨베이어 벨트라고 생각하시면 됩니다.

Node.js Streams도 비슷하게 작동합니다. 데이터를 한꺼번에(한 번에 모두가 아닌) 단위로 읽고 쓸 수 있어 메모리 효율성이 매우 높습니다.

Node.js의 스트림은 EventEmitter 위에 구축되어 이벤트 중심으로 만들어집니다. 몇 가지 중요한 이벤트는 다음과 같습니다.

  • data: 데이터를 소비할 수 있을 때 방출됩니다.
  • end: 더 이상 사용할 수 있는 데이터가 없을 때 발생합니다.
  • error: 읽거나 쓰는 동안 오류가 발생하면 발생합니다.

스트림을 사용하는 이유는 무엇입니까?

스트림은 I/O 처리를 위해 fs.readFile() 또는 fs.writeFile()과 같은 기존 방법에 비해 여러 가지 장점을 제공합니다.

  1. 메모리 효율성: 데이터가 청크로 처리되므로 많은 양의 메모리를 소비하지 않고도 매우 큰 파일을 처리할 수 있습니다.
  2. 성능: 스트림은 비차단 I/O를 제공합니다. 전체 작업이 완료될 때까지 기다리지 않고 데이터를 하나씩 읽거나 쓸 수 있어 프로그램의 응답성이 향상됩니다.
  3. 실시간 데이터 처리: 스트림을 사용하면 라이브 비디오/오디오 또는 API의 대규모 데이터 세트와 같은 실시간 데이터를 처리할 수 있습니다.

Node.js의 스트림 유형

Node.js에는 네 가지 유형의 스트림이 있습니다.

  1. 읽기 가능한 스트림: 데이터를 읽는 데 사용됩니다.
  2. 쓰기 가능한 스트림: 데이터 쓰기용.
  3. 이중 스트림: 동시에 데이터를 읽고 쓸 수 있는 스트림입니다.
  4. 변환 스트림: 출력이 입력의 수정된 버전인 이중 스트림 유형(예: 데이터 압축).

예시를 통해 각 유형을 살펴보겠습니다.

1. 읽기 가능한 스트림

읽기 가능한 스트림은 데이터를 청크 단위로 읽는 데 사용됩니다. 예를 들어, 큰 파일을 읽을 때 읽기 가능한 스트림을 사용하면 전체 파일을 로드하는 대신 작은 데이터 청크를 메모리로 읽을 수 있습니다.

예: 읽기 가능한 스트림을 사용하여 파일 읽기

const fs = require('fs');

// Create a readable stream
const readableStream = fs.createReadStream('largefile.txt', { encoding: 'utf8' });

// Listen for data events and process chunks
readableStream.on('data', (chunk) => {
  console.log('Chunk received:', chunk);
});

// Listen for the end event when no more data is available
readableStream.on('end', () => {
  console.log('No more data.');
});

// Handle error event
readableStream.on('error', (err) => {
  console.error('Error reading the file:', err);
});

설명:

  • fs.createReadStream()은 파일을 청크로 읽기 위한 스트림을 생성합니다.
  • 청크가 준비될 때마다 데이터 이벤트가 트리거되고 더 이상 읽을 데이터가 없으면 종료 이벤트가 트리거됩니다.

2. 쓰기 가능한 스트림

쓰기 가능한 스트림은 데이터를 청크 단위로 쓰는 데 사용됩니다. 모든 데이터를 한 번에 쓰는 대신 파일이나 쓰기 가능한 다른 대상으로 스트리밍할 수 있습니다.

예: 쓰기 가능한 스트림을 사용하여 데이터 쓰기

const fs = require('fs');

// Create a writable stream
const writableStream = fs.createWriteStream('output.txt');

// Write chunks to the writable stream
writableStream.write('Hello, World!\n');
writableStream.write('Streaming data...\n');

// End the stream (important to avoid hanging the process)
writableStream.end('Done writing.\n');

// Listen for the finish event
writableStream.on('finish', () => {
  console.log('Data has been written to output.txt');
});

// Handle error event
writableStream.on('error', (err) => {
  console.error('Error writing to the file:', err);
});

설명:

  • fs.createWriteStream()은 쓰기 가능한 스트림을 생성합니다.
  • write() 메서드를 사용하여 데이터가 스트림에 기록됩니다.
  • 모든 데이터가 기록되면 종료 이벤트가 트리거되고 end() 메소드는 스트림의 끝을 표시합니다.

3. 이중 스트림

이중 스트림은 데이터를 읽고 쓸 수 있습니다. 이중 스트림의 일반적인 예는 데이터를 동시에 보내고 받을 수 있는 네트워크 소켓입니다.

예: 이중 스트림

const { Duplex } = require('stream');

const duplexStream = new Duplex({
  write(chunk, encoding, callback) {
    console.log(`Writing: ${chunk.toString()}`);
    callback();
  },
  read(size) {
    this.push('More data');
    this.push(null);  // End the stream
  }
});

// Write to the duplex stream
duplexStream.write('Hello Duplex!\n');

// Read from the duplex stream
duplexStream.on('data', (chunk) => {
  console.log(`Read: ${chunk}`);
});

설명:

  • 쓰기를 위한 쓰기 방법과 읽기를 위한 읽기 방법을 정의합니다.
  • 이중 스트림은 읽기와 쓰기를 동시에 처리할 수 있습니다.

4. 스트림 변환

변환 스트림은 스트림을 통과할 때 데이터를 수정합니다. 예를 들어 변환 스트림은 데이터를 압축, 암호화 또는 조작할 수 있습니다.

예: 변환 스트림(대문자 텍스트)

const { Transform } = require('stream');

// Create a transform stream that converts data to uppercase
const transformStream = new Transform({
  transform(chunk, encoding, callback) {
    this.push(chunk.toString().toUpperCase());
    callback();
  }
});

// Pipe input to transform stream and then output the result
process.stdin.pipe(transformStream).pipe(process.stdout);

설명:

  • stdin에서 입력된 데이터는 변환 메소드에 의해 대문자로 변환된 후 stdout으로 출력됩니다.

배관 스트림

Node.js 스트림의 주요 기능 중 하나는 파이프되는 기능입니다. 파이핑을 사용하면 스트림을 서로 연결하여 한 스트림의 출력을 다른 스트림의 입력으로 전달할 수 있습니다.

예: 읽기 가능한 스트림을 쓰기 가능한 스트림으로 파이핑

const fs = require('fs');

// Create a readable stream for the input file
const readableStream = fs.createReadStream('input.txt');

// Create a writable stream for the output file
const writableStream = fs.createWriteStream('output.txt');

// Pipe the readable stream into the writable stream
readableStream.pipe(writableStream);

// Handle errors
readableStream.on('error', (err) => console.error('Read error:', err));
writableStream.on('error', (err) => console.error('Write error:', err));

설명:

  • pipe() 메서드는 읽기 가능한 스트림을 쓰기 가능한 스트림에 연결하여 input.txt에서 output.txt로 직접 데이터 청크를 보냅니다.

Node.js 스트림의 실제 사용 사례

  1. 대형 파일 읽기 및 쓰기: 전체 파일을 메모리로 읽는 대신 스트림을 사용하면 파일을 작은 덩어리로 처리할 수 있습니다.
  2. 실시간 데이터 처리: 스트림은 오디오/비디오 처리, 채팅 애플리케이션 또는 라이브 데이터 피드와 같은 실시간 애플리케이션에 이상적입니다.
  3. HTTP 요청/응답: Node.js의 HTTP 요청과 응답은 스트림이므로 들어오는 데이터를 쉽게 처리하거나 점진적으로 데이터를 보낼 수 있습니다.

결론

Node.js 스트림은 데이터를 청크로 작업하여 I/O 작업을 처리하는 강력하고 효율적인 방법을 제공합니다. 대용량 파일을 읽거나, 소스 간에 데이터를 파이핑하거나, 즉시 데이터를 변환하는 경우 스트림은 메모리 효율적이고 성능이 뛰어난 솔루션을 제공합니다. 애플리케이션에서 읽기 가능, 쓰기 가능, 이중 및 변환 스트림을 활용하는 방법을 이해하면 애플리케이션의 성능과 확장성을 크게 향상시킬 수 있습니다.

릴리스 선언문 이 기사는 https://dev.to/imsushant12/understanding-nodejs-streams-what-why-and-how-to-use-them-53da?1에서 복제됩니다. 침해가 있는 경우, Study_golang@163으로 문의하시기 바랍니다. .com에서 삭제하세요
최신 튜토리얼 더>

부인 성명: 제공된 모든 리소스는 부분적으로 인터넷에서 가져온 것입니다. 귀하의 저작권이나 기타 권리 및 이익이 침해된 경우 자세한 이유를 설명하고 저작권 또는 권리 및 이익에 대한 증거를 제공한 후 이메일([email protected])로 보내주십시오. 최대한 빨리 처리해 드리겠습니다.

Copyright© 2022 湘ICP备2022001581号-3