분류 Nodejs

Node.js의 스트림 이해

컨텐츠 정보

  • 조회 396 (작성일 )

본문

스트림은 Node 응용 프로그램을 강화하는 기본 개념 중 하나입니다.


https://nodesource.com/blog/understanding-streams-in-nodejs 


스트림이란 무엇입니까? 


스트림은 Node.js 애플리케이션을 구동하는 기본 개념 중 하나입니다. 이들은 데이터 처리 방법이며 입력을 순차적으로 출력으로 읽거나 쓰는 데 사용됩니다.

스트림은 파일 읽기 / 쓰기, 네트워크 통신 또는 모든 종류의 종단 간 정보 교환을 효율적으로 처리하는 방법입니다.


스트림을 독특하게 만드는 것은 전통적인 방식으로 파일을 한 번에 메모리로 한 번에 읽는 프로그램 대신 데이터를 한 조각씩 읽음으로써 모든 내용을 메모리에 저장하지 않고 내용을 처리한다는 것입니다.


따라서 대량의 데이터를 처리 할 때 스트림이 실제로 강력 해집니다. 예를 들어 파일 크기가 여유 메모리 공간보다 클 수 있으므로 처리하기 위해 전체 파일을 메모리로 읽을 수 없습니다. 그 곳에서 스트림이 구출됩니다!


스트림을 사용하여 더 작은 청크 데이터를 처리하면 더 큰 파일을 읽을 수 있습니다.


예를 들어 YouTube 나 Netflix와 같은 "스트리밍"서비스를 예로 들어 보겠습니다. 이러한 서비스를 통해 비디오 및 오디오 피드를 한 번에 모두 다운로드 할 수는 없습니다. 대신, 브라우저는 비디오를 연속적인 덩어리 흐름으로 수신하여 수신자가 거의 즉시 시청 및 / 또는 청취를 시작할 수 있게 합니다.


그러나 스트림은 미디어 또는 빅 데이터 작업에만 국한되지 않습니다. 또한 코드에서 '구성 성'의 힘을 제공합니다. 구성 성을 염두에 두고 설계하면 여러 가지 구성 요소를 특정 방식으로 결합하여 동일한 유형의 결과를 얻을 수 있습니다. Node.js에서는 스트림을 사용하여 다른 작은 코드 조각과 데이터를 주고 받음으로써 강력한 코드 조각을 작성할 수 있습니다.


스트리밍 해야 하는 이유 


스트림은 기본적으로 다른 데이터 처리 방법에 비해 두 가지 주요 이점을 제공합니다.

  1. 메모리 효율성 : 처리하기 전에 많은 양의 데이터를 메모리에 로드 할 필요가 없습니다.
  2. 시간 효율성 : 전체 페이로드가 전송 될 때까지 처리를 기다릴 필요없이 데이터를 처리하는 데 걸리는 시간이 상당히 단축됩니다.

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


  1. 쓰기 가능 : 데이터를 쓸 수 있는 스트림. 예를 들어 fs.createWriteStream()을 사용하면 스트림을 사용하여 파일에 데이터를 쓸 수 있습니다.
  2. 읽기 가능 : 데이터를 읽을 수 있는 스트림. 예를 들면 다음과 같습니다. fs.createReadStream()을 사용하면 파일 내용을 읽을 수 있습니다. 
  3. 이중 : 읽기 가능 및 쓰기 가능 스트림 예를 들어, net.Socket
  4. 변환 : 데이터를 읽고 읽을 때 데이터를 수정하거나 변환 할 수있는 스트림입니다. 예를 들어, 파일 압축 인스턴스에서 압축 된 데이터를 작성하고 압축 해제 된 데이터를 파일과 주고 받을 수 있습니다.

Node.js로 이미 작업했다면 스트림을 발견했을 수 있습니다. 예를 들어 Node.js 기반 HTTP 서버에서 요청은 읽기 가능한 스트림이고 응답은 쓰기 가능한 스트림입니다. fs 모듈을 사용했을 수 있습니다. 읽기 및 쓰기 가능 파일 스트림 모두에 대해 작업 할 수 있습니다. Express를 사용할 때마다 스트림을 사용하여 클라이언트와 상호 작용하고 TCP 소켓으로 인해 TLS 스택 및 기타 연결은 모두 Node.js를 기반으로 하므로 작업 할 수 있는 모든 데이터베이스 연결 드라이버에서 스트림이 사용됩니다.


실용적인 예 


읽을 수 있는 스트림을 만드는 방법 


먼저 Readable 스트림이 필요하고 초기화합니다.


const Stream = require('stream') const readableStream = new Stream.Readable() 


스트림이 초기화되었으므로 데이터를 전송할 수 있습니다.


readableStream.push('ping!') readableStream.push('pong!') 


async iterator 


스트림 작업시 비동기 반복기를 사용하는 것이 좋습니다. Axel Rauschmayer 박사에 따르면 비동기 반복은 데이터 컨테이너의 내용을 비동기 적으로 검색하는 프로토콜입니다 (항목을 검색하기 전에 현재 "작업"이 일시 중지 될 수 있음). 또한 스트림 비동기 반복기 구현은 '읽기'이벤트를 사용한다는 점을 언급하는 것이 중요합니다.


읽을 수 있는 스트림에서 읽을 때 비동기 반복자를 사용할 수 있습니다.


import * as fs from 'fs'; async function logChunks(readable) { for await (const chunk of readable) { console.log(chunk); } } const readable = fs.createReadStream( 'tmp/test.txt', {encoding: 'utf8'}); logChunks(readable); // Output: // 'This is a test!\n' 


읽을 수 있는 스트림의 내용을 문자열로 수집 할 수도 있습니다.


import {Readable} from 'stream'; async function readableToString2(readable) { let result = ''; for await (const chunk of readable) { result += chunk; } return result; } const readable = Readable.from('Good morning!', {encoding: 'utf8'}); assert.equal(await readableToString2(readable), 'Good morning!'); 


이 경우 Promise를 반환하려고 했기 때문에 비동기 함수를 사용해야 했습니다.


비동기식 함수를 EventEmitter와 함께 사용하지 않는 것이 중요합니다. 현재 이벤트 핸들러 내에서 거부 될 때 거부 할 수있는 방법이 없기 때문에 버그 및 메모리 누수를 추적하기 어렵습니다. 현재 가장 좋은 방법은 비동기 함수의 내용을 try / catch 블록으로 항상 감싸고 오류를 처리하는 것이지만 오류가 발생하기 쉽습니다. 이 풀 요청은 노드 코어에 도달하면 이 문제를 해결하는 것을 목표로 합니다.