-
[JavaScript] Node.js에서 스트림(Streams)이해하기2024년 12월 29일
- 유니얼
-
작성자
-
2024.12.29.:57
728x90Node.js는 비동기 I/O 처리를 효율적으로 수행하기 위해 **스트림(Stream)**이라는 강력한 개념을 제공합니다. 스트림은 대규모 데이터를 처리하는 데 매우 유용하며, 파일 읽기/쓰기, HTTP 요청/응답, 데이터 전송 등 다양한 작업에서 사용됩니다. 이 글에서는 Node.js의 스트림 개념, 종류, 그리고 사용 예제를 다룹니다.
1. 스트림(Stream)이란?
스트림은 데이터를 조각(청크, Chunk) 단위로 읽고 쓰는 방식을 의미합니다. 스트림을 사용하면 데이터를 한 번에 모두 메모리에 로드하지 않고, 점진적으로 처리할 수 있어 메모리 사용을 최소화할 수 있습니다.
스트림의 주요 특징
- 비동기 처리: 데이터를 처리하는 동안 애플리케이션이 멈추지 않음.
- 메모리 효율성: 대규모 데이터를 처리할 때 전체를 로드하지 않음.
- 유연성: 읽기, 쓰기, 변환, 그리고 파이프라인 형태로 데이터를 처리 가능.
2. Node.js 스트림의 종류
Node.js 스트림은 네 가지 기본 유형으로 나뉩니다.
1) Readable Stream
- 데이터를 읽는 데 사용.
- 예: 파일 읽기, HTTP 요청, 소켓 데이터 수신.
const fs = require('fs'); const readableStream = fs.createReadStream('example.txt'); readableStream.on('data', (chunk) => { console.log('Data chunk:', chunk.toString()); });
2) Writable Stream
- 데이터를 쓰는 데 사용.
- 예: 파일 쓰기, HTTP 응답, 소켓 데이터 송신.
const fs = require('fs'); const writableStream = fs.createWriteStream('output.txt'); writableStream.write('Hello, World!\n'); writableStream.end();
3) Duplex Stream
- 데이터를 읽고 쓰는 데 모두 사용.
- 예: 네트워크 소켓.
const { Duplex } = require('stream'); const duplexStream = new Duplex({ read(size) { this.push('Hello from Duplex Stream!'); this.push(null); // 스트림 끝 }, write(chunk, encoding, callback) { console.log('Writing:', chunk.toString()); callback(); }, }); duplexStream.on('data', (chunk) => console.log(chunk.toString())); duplexStream.write('Hello, Duplex!'); duplexStream.end();
4) Transform Stream
- 데이터를 변환하면서 읽고 씀.
- 예: 압축, 암호화.
const { Transform } = require('stream'); const transformStream = new Transform({ transform(chunk, encoding, callback) { this.push(chunk.toString().toUpperCase()); callback(); }, }); process.stdin.pipe(transformStream).pipe(process.stdout);
3. 스트림 이벤트
Node.js 스트림은 이벤트 기반으로 동작하며, 주로 다음과 같은 이벤트를 사용합니다:
이벤트 이름설명 data 새로운 데이터 청크가 들어올 때 발생 end 모든 데이터가 처리된 후 발생 error 스트림 처리 중 에러가 발생했을 때 발생 finish 쓰기 스트림에서 모든 데이터가 기록된 후 발생 Readable Stream 이벤트 예제
const fs = require('fs'); const readableStream = fs.createReadStream('example.txt'); readableStream.on('data', (chunk) => { console.log('Chunk:', chunk.toString()); }); readableStream.on('end', () => { console.log('No more data to read.'); }); readableStream.on('error', (err) => { console.error('Error:', err); });
4. 스트림의 활용 사례
1) HTTP 요청/응답 처리
Node.js에서 HTTP 요청(Request)와 응답(Response)은 각각 Readable Stream과 Writable Stream으로 동작합니다.
const http = require('http'); http.createServer((req, res) => { if (req.method === 'POST') { let body = []; req.on('data', (chunk) => body.push(chunk)); req.on('end', () => { body = Buffer.concat(body).toString(); res.end(`Received: ${body}`); }); } else { res.end('Send a POST request.'); } }).listen(3000, () => console.log('Server is running on port 3000.'));
2) 파일 복사
Readable Stream과 Writable Stream을 조합해 파일을 복사할 수 있습니다.
const fs = require('fs'); const readableStream = fs.createReadStream('source.txt'); const writableStream = fs.createWriteStream('destination.txt'); readableStream.pipe(writableStream);
3) 데이터 변환
Transform Stream을 사용해 데이터를 변환할 수 있습니다. 아래는 문자열을 대문자로 변환하는 예제입니다.
const { Transform } = require('stream'); const transformStream = new Transform({ transform(chunk, encoding, callback) { this.push(chunk.toString().toUpperCase()); callback(); }, }); process.stdin.pipe(transformStream).pipe(process.stdout);
5. 에러 처리
스트림은 비동기적으로 동작하므로 에러가 발생할 수 있습니다. 모든 스트림에 에러 이벤트 리스너를 등록해야 합니다.
const fs = require('fs'); const readableStream = fs.createReadStream('nonexistent.txt'); readableStream.on('error', (err) => { console.error('Error:', err.message); });
6. 스트림의 장점과 단점
장점
- 메모리 효율성: 대규모 데이터를 한 번에 로드하지 않고 조각 단위로 처리.
- 성능 향상: 데이터가 처리되는 동안 다른 작업을 병렬로 수행 가능.
- 유연성: 읽기, 쓰기, 변환을 조합해 다양한 처리가 가능.
단점
- 복잡성: 이벤트 기반으로 동작하므로 익숙하지 않은 경우 코드가 복잡해질 수 있음.
- 에러 처리 필요: 모든 스트림에서 에러 이벤트를 처리해야 함.
결론
Node.js의 스트림은 데이터 처리의 효율성을 극대화하는 강력한 도구입니다. 이를 통해 대규모 파일 읽기/쓰기, HTTP 요청/응답 처리, 데이터 변환 등 다양한 작업을 메모리 효율적으로 수행할 수 있습니다.
스트림은 Node.js의 기본 기능을 이해하는 핵심 요소 중 하나이므로, 실제 프로젝트에서 이를 적극 활용해 보세요. 추가로 Express.js나 Koa와 같은 프레임워크에서도 스트림을 잘 이해하고 있으면 더욱 유용하게 사용할 수 있습니다.
추가 학습 리소스
https://nodejs.org/api/stream.html#organization-of-this-document
https://nodejs.org/en/learn/modules/anatomy-of-an-http-transaction
반응형다음글이전글이전 글이 없습니다.댓글