본문 바로가기

Node.js

[Node] 파일시스템, 버퍼, 스트림 알아보기

fs

- 파일 시스템에 접근하는 모듈

 

📌 fs.readFile

- 파일 읽기 

- 결과물 : 버퍼(buffer) 형태로 출력되어서 사람이 읽을 수 있는 형색으로 변환 ( toString 사용 )

📌 fs.writeFile

- 파일 만들기

 

📌 프로미스 기반의 fs 모듈

- fs는 기본적으로 콜백 형식의 모듈이므로 실무에서 사용하기가 불편

const fs = require('fs').promises;

fs.readFile('./readme.txt')
  .then((data) => {
    console.log(data);
    console.log(data.toString());
  })
  .catch((err) => {
    console.error(err);
  });

 

readFile과 readFileSync 메서드

📌 readFile

- 비동기 메서드 : 백그라운드에서 실행

- 실행순서가 순차적이지 않음

📌 readFileSync 

- 동기 메서드 

- 실행순서가 순차적

- 콜백 함수를 넣는 대신 직접 return 값을 받아와야함

 

비동기 방식으로 하되 순서를 유지하고 싶다면?

이전 readFile의 콜백 다음에 다음 readFile을 넣으면 됨 → BUT 콜백지옥!

 

✨ 콜백지옥은 Promise나 async/await로 어느정도 해결 가능

const fs = require('fs').promises;

console.log('시작');
fs.readFile('./readme2.txt')
  .then((data) => {
    console.log('1번', data.toString());
    return fs.readFile('./readme2.txt');
  })
  .then((data) => {
    console.log('2번', data.toString());
    return fs.readFile('./readme2.txt');
  })
  .then((data) => {
    console.log('3번', data.toString());
    console.log('끝');
  })
  .catch((err) => {
    console.error(err);
  });

 

 


 

위에서 잠깐 언급한 버퍼에 대해 알아보자 (스트림도!)

 

버퍼

- 메모리에 저장된 데이터

- 노드는 파일을 읽을 때 메모리에 파일 크기만큼 공간을 마련해두며 파일 데이터를 메모리에 저장한 뒤 사용자가 조작할 수 있도록 함

 

Buffer

- 버퍼를 직접 다룰 수 있는 클래스

 

Buffer가 제공하는 여러가지 메서드

 from(문자열): 문자열을 버퍼로 바꿀 수 있습니다. length 속성은 버퍼의 크기를 알립니다. 바이트 단위입니다.

 toString(버퍼): 버퍼를 다시 문자열로 바꿀 수 있습니다. 이때 base64나 hex를 인수로 넣으면 해당 인코딩으로도 변환 가능합니다.

 concat(배열): 배열 안에 든 버퍼들을 하나로 합칩니다.

 alloc(바이트): 빈 버퍼를 생성합니다. 바이트를 인수로 넣으면 해당 크기의 버퍼가 생성됩니다.

버퍼의 단점

- 모든 내용을 버퍼에 다 쓴 후에야 다음 동작으로 넘어가므로 파일 읽기, 압축, 파일 쓰기 등의 조작을 연달아 할 때 매번 전체 용량을 버퍼로 처리해야 함.

 

스트림

- 버퍼의 단점 해결

- 버퍼의 크기를 작게 만든 후 여러 번으로 나눠 보내는 방식

 

createReadStream

- 파일을 읽는 스트림 메서드

const fs = require('fs');

const readStream = fs.createReadStream('./readme3.txt', { highWaterMark: 16 });
const data = [];

readStream.on('data', (chunk) => {
  data.push(chunk);
  console.log('data :', chunk, chunk.length);
});

readStream.on('end', () => {
  console.log('end :', Buffer.concat(data).toString());
});

readStream.on('error', (err) => {
  console.log('error :', err);
});

highWaterMark : 버퍼의 크기를 정할 수 있는 옵션

 

createWriteStream

- 파일을 만드는 스트림 메서드

const fs = require('fs');

const writeStream = fs.createWriteStream('./writeme2.txt');
writeStream.on('finish', () => {
  console.log('파일 쓰기 완료');
});

writeStream.write('이 글을 씁니다.\n');
writeStream.write('한 번 더 씁니다.');
writeStream.end();

 

createReadStream으로 파일을 읽고 그 스트림을 전달받아 createWriteStream으로 파일 만들기 ( = 파일 복사와 비슷 )

파이핑하다

- 스트림끼리 연결하는 것을 의미

const fs = require('fs');

const readStream = fs.createReadStream('readme4.txt');
const writeStream = fs.createWriteStream('writeme3.txt');
readStream.pipe(writeStream);

미리 읽기 스트림과 쓰기 스트림 사이를 pipe 메서드로 연결하면 저절로 데이터가 writeStream으로 넘어감

 

 

 


Reference

- Node.js 교과서 개정 2판

 

'Node.js' 카테고리의 다른 글

[Node] REST, HTTP 메서드 개념  (0) 2022.12.11
[Node] 이벤트, 이벤트 메서드  (0) 2022.12.10
[Node] 노드의 내장 모듈들  (0) 2022.12.10
[Node] 노드의 내장 객체들  (0) 2022.12.08
[Node] Node의 동작 방식과 장단점  (0) 2022.12.05