• 티스토리 홈
  • 프로필사진
    유니얼
  • 방명록
  • 공지사항
  • 태그
  • 블로그 관리
  • 글 작성
유니얼
  • 프로필사진
    유니얼
    • 분류 전체보기 (295)
      • Unity (17)
        • 게임 개발 (5)
      • Unreal (24)
        • 게임 개발 (20)
      • DirectX (36)
      • 코딩테스트 (91)
        • 프로그래머스 (25)
        • 백준 (66)
      • Google Workspace (1)
      • Programing (102)
        • C# (68)
        • C++ (24)
        • JavaScript (10)
      • 게임 서버 프로그래밍 (17)
      • Web (6)
        • 슈퍼코딩 (6)
  • 방문자 수
    • 전체:
    • 오늘:
    • 어제:
  • 최근 댓글
    등록된 댓글이 없습니다.
  • 최근 공지
    등록된 공지가 없습니다.
# Home
# 공지사항
#
# 태그
# 검색결과
# 방명록
  • [JavaScript] Node.js에서 스트림(Streams)이해하기
    2024년 12월 29일
    • 유니얼
    • 작성자
    • 2024.12.29.:57
    728x90

    Node.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. 스트림의 장점과 단점

    장점

    1. 메모리 효율성: 대규모 데이터를 한 번에 로드하지 않고 조각 단위로 처리.
    2. 성능 향상: 데이터가 처리되는 동안 다른 작업을 병렬로 수행 가능.
    3. 유연성: 읽기, 쓰기, 변환을 조합해 다양한 처리가 가능.

    단점

    1. 복잡성: 이벤트 기반으로 동작하므로 익숙하지 않은 경우 코드가 복잡해질 수 있음.
    2. 에러 처리 필요: 모든 스트림에서 에러 이벤트를 처리해야 함.

    결론

    Node.js의 스트림은 데이터 처리의 효율성을 극대화하는 강력한 도구입니다. 이를 통해 대규모 파일 읽기/쓰기, HTTP 요청/응답 처리, 데이터 변환 등 다양한 작업을 메모리 효율적으로 수행할 수 있습니다.

    스트림은 Node.js의 기본 기능을 이해하는 핵심 요소 중 하나이므로, 실제 프로젝트에서 이를 적극 활용해 보세요. 추가로 Express.js나 Koa와 같은 프레임워크에서도 스트림을 잘 이해하고 있으면 더욱 유용하게 사용할 수 있습니다.

    추가 학습 리소스

    https://nodejs.org/api/stream.html#organization-of-this-document

     

    Stream | Node.js v23.5.0 Documentation

     

    nodejs.org

    https://nodejs.org/en/learn/modules/anatomy-of-an-http-transaction

     

    Node.js — Anatomy of an HTTP Transaction

    Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.

    nodejs.org

    반응형
    다음글
    다음 글이 없습니다.
    이전글
    이전 글이 없습니다.
    댓글
조회된 결과가 없습니다.
스킨 업데이트 안내
현재 이용하고 계신 스킨의 버전보다 더 높은 최신 버전이 감지 되었습니다. 최신버전 스킨 파일을 다운로드 받을 수 있는 페이지로 이동하시겠습니까?
("아니오" 를 선택할 시 30일 동안 최신 버전이 감지되어도 모달 창이 표시되지 않습니다.)
목차
표시할 목차가 없습니다.
    • 안녕하세요
    • 감사해요
    • 잘있어요

    티스토리툴바