5장 Stream API (2/3) - Node.js의 4가지 스트림 소개와 사용법
이 글은 Node.js 디자인 패턴 CH 05 스트림 코딩의 일부를 참고해서 작성하였으며, Node.js에서 코어 모듈로 제공하는 Stream 4종류를 다룬다. Node.js에서의 스트림 자체에 대해서는 5장 Stream API (1/3) - 스트림 개요 및 Readable Stream를 참고하라.
Node.js 스트림 객체
Node.js에서는 4가지의 추상 스트림 클래스를 제공하여 쉽게 스트림을 구현할 수 있게 한다. 이 클래스들은 core 모듈에서 제공하므로 추가 의존성이 필요하지 않다.
Name | 목적 | dataSource 가능 |
---|---|---|
stream.Readable | 외부 데이터 읽기 (dataSource에서 꺼내는 형태) | True |
stream.Writable | 내부 데이터 외부로 전송하기 (dataSource로 써주는 형태) | False |
stream.Duplex | Readable + Writable 스트림. | True |
stream.Transform | 외부 데이터 읽기 => 데이터 변조하기 => 외부로 전송하기 | True |
Node.js의 두 버전의 스트림 API
Node.js에는 두 가지의 Stream API가 있다.
API Version | Name | Event Name | Description |
---|---|---|---|
Stream v1 | Flowing Mode | on('data') |
무조건 해당 데이터를 처리해야 함. 버퍼 크기 등의 문제로 처리하지 못 하는 경우 해당 데이터를 되살릴 방법이 없음. |
Stream v2 | Non-Flowing Mode | on('readable') |
곧바로 데이터를 처리하지 않아도 됨. 백 프래셔를 지원함. |
Back Pressure: Event 송신자의 처리량이 Event를 수신하는 측의 처리량을 넘기는 경우 송신자의 전송 속도를 줄여야 하는 경우가 생기는 데 이를 해결하는 메커니즘을 Back Pressure라고 한다.
송신자-수신자 처리량 차이 발생 오류 백프래셔 필요 송신자 전송량 < 수신자 처리량 없음 False 송신자 전송량 > 수신자 처리량 처리하지 못하는 데이터에 대한 정의되지 않은 동작 등 손실 발생 가능 True Stream v2의 백 프래셔:
Node.js의 버퍼가 알아서 버퍼링을 해주며, 버퍼 한계치를 넘으면 OS에서 패킷을 drop시켜 sender 입장에서 전송 속도를 늦추게 함. 이 기능을 자동으로 지원. (v1도 가능하다고 함. 다만 더 어렵다고 함.)출처: What are the differences between readable and data event of process.stdin stream?
추가 참고:
1. Readable 스트림
Readable 스트림은 데이터를 읽어들이는 게 목적이다.
1-1. 사용 예시:
stream.read()
함수를 사용하면 chunk를 반환한다.
1 | const RandomStream = require("./randomStream"); |
1-2. Readable 구현 코드
Readable Stream은 _read
함수를 구현하면 된다.
1 | const stream = require('stream'); // 코어 모듈 (stream) |
2. Writable 스트림
Writable 스트림은 데이터를 생성하는 게 목적이다. (ex) HTTP response 생성
2-1. 사용 예시
stream.write
함수를 사용하면 스트림에 내용을 쓸 수 있다.
1 | // res가 Writable Stream 이다 :) |
2-2. Writable 구현 코드
(윗 코드와는 상관 없음.) Writable Stream은 _write
함수를 구현하면 된다.
1 | class ToFileStream extends stream.Writable { |
2-3. 백 프래셔 예제
백 프래셔란 Read보다 Write가 빠를 때 병목이 생기는 것을 방지하는 메커니즘이다.
1 | require("http") |
3. Duplex Stream
Duplex Stream은 Readable + Writable 그 이상 그 이하도 아니며 따라서 설명을 생략한다.
4. Transform Stream
Transform 스트림은 읽어들인 데이터를 변조해 내보내는 스트림이다. 스트림이니만큼 chunk 단위로 데이터가 오므로 변환에 유의해야 한다.
4-1. 사용 예시
1 | const ReplaceStream = require("./replaceStream"); |
4-2. Transform 구현 코드
스트림 상에서 문자열 일부를 치환하는 코드이다. (어렵다.)
1 | class ReplaceStream extends stream.Transform { |
TODO: (전부 다 책에서 나온 내용)
스트림 간의 Pipelining(조합) 소개
스트림 기반 비동기 제어 소개 (순차/비순차/제한된 비순차)
스트림 fork, merge
스트림 멀티플렉싱, 디멀티플렉싱
소스 코드 출처: Node.js 디자인 패턴
스트림 파트는 내가 스트림에 대한 경험도 거의 없고 책에서 설명하는 내용이 어려워서 내 생각을 넣어 포스팅하기가 매우 어려웠다. 내용을 간략히 정리하는 선에서 마쳐야 할 것 같아 아쉽다.
5장 Stream API (2/3) - Node.js의 4가지 스트림 소개와 사용법