C++로 작성된 DLL을 이용해 Callback 데이터를 node.js기반의 프로그램으로 받아오는 작업을 진행하면서 rxjs라는 모듈을 사용해보았습니다. reactive의 필수 개념인 steam을 학습해보면서 공부한 내용을 기록해두려고 합니다.
Node.js Streams는 많은 데이터를 다루는 경우, 빠르고 효율적인 방법으로 데이터를 처리할 수 있게 해주는 기능입니다. 이번 글에서는 Node.js Streams의 개요, API 및 사용 예시에 대해 알아보겠습니다.
스트림 개요
Node.js Streams는 "데이터 처리를 위한 추상 인터페이스"입니다. 이는 데이터 처리의 다양한 측면을 추상화하여 처리를 단순화합니다. 스트림은 데이터의 흐름을 의미하며, 처리해야 할 데이터를 스트림으로 바꾸어 처리하면 더욱 효율적입니다.
스트림은 Readable, Writable, Duplex 및 Transform 스트림으로 구성됩니다. Readable 스트림은 읽기 전용 데이터를 생성하고, Writable 스트림은 쓰기 전용 데이터를 소비합니다. Duplex 스트림은 읽기 및 쓰기 모두 가능한 스트림이며, Transform 스트림은 데이터를 변환하는 스트림입니다.
스트림 API
Node.js는 기본적인 스트림 API를 제공합니다. 이 API는 스트림을 생성하고 조작하는 데 사용됩니다.
스트림을 생성하려면, 우선 생성하려는 스트림의 유형을 결정해야 합니다. 스트림의 종류에 따라 다른 API가 사용됩니다.
스트림을 조작하려면, 데이터를 읽거나 쓰는 작업을 수행합니다. Readable 스트림에서 데이터를 읽을 때, "data" 이벤트를 등록해야 합니다. Writable 스트림에서 데이터를 쓸 때는 write() 메서드를 사용합니다.
스트림의 상태와 에러 처리 방법도 중요합니다. Readable 스트림은 "end" 이벤트를 발생시켜 처리가 완료되었음을 알리며, Writable 스트림에서는 "finish" 이벤트를 발생시켜 처리가 완료되었음을 알립니다. 스트림에서 에러가 발생하면 "error" 이벤트를 처리하여 대처할 수 있습니다.
스트림 사용 예시
스트림은 파일 시스템, HTTP 요청 및 응답, 데이터베이스 연결 등 다양한 분야에서 사용됩니다. 스트림을 사용하여 파일 시스템에서 데이터를 읽고 쓰는 방법, HTTP 요청 및 응답에서 스트림 사용, 데이터베이스와의 스트림 통신 등을 살펴보겠습니다.
FileStream예시
파일 시스템에서 스트림을 사용하는 방법 중 하나는 fs 모듈의 createReadStream() 및 createWriteStream() 메소드를 사용하는 것입니다. createReadStream()은 파일을 열고 파일의 데이터를 읽는 Readable 스트림을 생성하며, createWriteStream()은 파일을 열고 데이터를 쓰는 Writable 스트림을 생성합니다.
예를 들어, "input.txt" 파일에서 데이터를 읽고 "output.txt" 파일로 쓰는 스트림을 생성하려면 다음과 같이 작성할 수 있습니다.
const fs = require('fs');
const readStream = fs.createReadStream('input.txt');
const writeStream = fs.createWriteStream('output.txt');
readStream.pipe(writeStream);
위의 코드에서는 먼저 "input.txt" 파일에서 데이터를 읽는 Readable 스트림을 생성하고, "output.txt" 파일로 데이터를 쓰는 Writable 스트림을 생성합니다. 그러고 나서 pipe() 메서드를 사용하여 두 스트림을 연결합니다. pipe() 메서드는 데이터를 읽는 스트림에서 데이터를 읽고 쓰는 스트림으로 데이터를 전송합니다. 따라서 위의 코드에서는 "input.txt" 파일에서 데이터를 읽고, "output.txt" 파일에 데이터를 쓰게 됩니다.
HTTP 예시
Node.js에서 HTTP 요청 및 응답에서도 스트림을 사용할 수 있습니다. HTTP 요청 및 응답에서 스트림을 사용하면, 클라이언트 브라우저에서 데이터를 읽을 때까지 모든 데이터를 기다리지 않아도 되므로, 서버 응답 시간을 줄일 수 있습니다.
아래는 Node.js에서 HTTP 서버를 생성하고, 클라이언트에서 요청한 데이터를 처리하는 예시 코드입니다.
const http = require('http');
const server = http.createServer((req, res) => {
if (req.method === 'POST') {
req.pipe(res);
}
});
server.listen(3000);
위의 코드에서는, HTTP 서버를 생성하고 클라이언트에서 POST 요청을 보내면, 요청에서 받은 데이터를 그대로 클라이언트에게 응답으로 보내도록 구성하였습니다. 이 때, req.pipe(res)를 사용하여 Readable 스트림(req)에서 받은 데이터를 Writable 스트림(res)으로 전송합니다.
MongoDB Stream 예시
MongoDB와 같은 NoSQL 데이터베이스에서는 스트림을 사용하여 데이터베이스와의 통신을 단순화할 수 있습니다. Node.js에서 MongoDB와의 스트림 통신을 위해 mongoose 라이브러리를 사용할 수 있습니다.
아래는 mongoose를 사용하여 MongoDB에서 데이터를 읽고 쓰는 예시 코드입니다.
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
// User 스키마 정의
const userSchema = new Schema({
name: String,
email: String,
age: Number,
});
// User 모델 생성
const User = mongoose.model('User', userSchema);
// MongoDB에 연결
mongoose.connect('mongodb://localhost/my_database', { useNewUrlParser: true });
// 데이터 검색을 위한 Readable 스트림 생성
const stream = User.find({ age: { $gte: 18 } }).stream();
// 'data' 이벤트 핸들링
stream.on('data', function (doc) {
console.log(doc);
});
// 'end' 이벤트 핸들링
stream.on('end', function () {
console.log('모든 데이터 검색 완료!');
});
// 'error' 이벤트 핸들링
stream.on('error', function (err) {
console.log('Error: ' + err);
});
위의 코드에서는, mongoose.connect() 메소드를 사용하여 MongoDB에 연결합니다. 그러고 나서, User 모델을 생성하고 User.find() 메서드를 사용하여 데이터베이스에서 데이터를 검색합니다. User.find() 메서드는 Readable 스트림을 반환하므로, 데이터를 가져올 때마다 'data' 이벤트가 발생합니다. 이렇게 'data' 이벤트를 수신하여 데이터를 처리할 수 있습니다.
User 모델에서 데이터를 검색하고 쓰는 데에는 스트림이 필요하지 않을 수 있지만, Node.js에서 대량의 데이터를 다루는 경우에는 스트림을 사용하여 효율적으로 처리할 수 있습니다.
스트림 처리 예외 처리
스트림은 다양한 이유로 종료될 수 있습니다. 파일의 끝에 도달하거나, 네트워크 연결이 끊어지거나, 처리 중 예외가 발생하는 경우 등이 그러한 예시입니다.
스트림에서 예외를 처리하려면, 'error' 이벤트를 처리해야 합니다. Readable 및 Writable 스트림에서 'error' 이벤트는 예외가 발생할 때마다 호출됩니다.
const fs = require('fs');
const readStream = fs.createReadStream('input.txt');
const writeStream = fs.createWriteStream('output.txt');
readStream.on('error', (err) => {
console.log(`Error: ${err.message}`);
});
writeStream.on('error', (err) => {
console.log(`Error: ${err.message}`);
});
readStream.pipe(writeStream);
위의 코드에서는 'error' 이벤트를 사용하여 파일 시스템에서 스트림을 생성하고 처리합니다. 'error' 이벤트에서는 예외 처리를 수행하며, 예외가 발생한 이유와 함께 에러 메시지를 출력합니다.
또한, 'finish' 이벤트는 Writable 스트림에서 모든 데이터가 쓰여졌을 때 발생합니다. 이 이벤트를 사용하여 모든 데이터가 성공적으로 처리되었는지 확인할 수 있습니다.
이번 포스팅에서는 Node.js 스트림에 대해 알아보았습니다. 스트림은 Node.js에서 데이터 처리를 위한 중요한 기능 중 하나입니다. 스트림을 사용하면 데이터를 처리하고 전송하는 데 필요한 리소스를 효율적으로 사용할 수 있습니다. 이를 위해 스트림 API를 사용하여 데이터를 읽고 쓸 수 있으며, 스트림을 사용하는 다양한 예시를 살펴봤습니다.
스트림을 사용하면 데이터를 다룰 때 메모리 사용량을 줄이고, 데이터 처리 속도를 높일 수 있으며, 파일과 같은 대용량 데이터를 처리할 때 유용합니다. 스트림은 데이터 처리를 위한 Node.js의 강력한 기능 중 하나이므로, Node.js 애플리케이션을 개발하거나 데이터 처리를 위한 서버를 구축할 때 이 기능을 적극적으로 활용하면 좋습니다.
참고: https://www.freecodecamp.org/news/node-js-streams-everything-you-need-to-know-c9141306be93/
다음글
'Backend > Node.js' 카테고리의 다른 글
[Node.js] RxJS란 (0) | 2023.02.18 |
---|---|
[Node.js] 스트림이란 (Stream) ② (0) | 2023.02.18 |
[Javascript] 2차원 배열을 1차원 배열로 만들 (0) | 2023.02.08 |
[FP] fp-ts 란 (0) | 2023.02.07 |
[Node.js] npm install 옵션 (0) | 2022.11.16 |