프론트엔드 개발/Node.js
Stream, Pipe
하이고니
2023. 2. 6. 15:19
100GB 정도 되는 큰 파일을 핸들링하기 위해서는,
메모리 상에 100GB의 파일을 담을 수 있는 공간을 마련해야 한다.
이 문제를 해결하기 위해 Stream이 등장했다.
Data => Buffer => Stream => User
데이터를 chunk 단위로 쪼개서, 재생을 하기 위한 최소한의 단위만 확보되면 User가 영상을 시청할 수 있게 된다.
readStream
// hello.txt
// 내용은 'hello world'
const fs = require('fs');
const readStream = fs.createReadStream('./hello.txt', { highWaterMark: 1 })
// 1바이트 단위로 쪼개서 가져온다.
readStream.on('data', (chunk) => {
console.log(chunk); // <Buffer 68> ... <Buffer 64>
});
readStream.on('end', () => { // 파일을 모두 읽으면 실행되는 이벤트 함수
console.log('파일을 모두 읽어왔습니다');
});
// hello.txt
// 내용은 'hello world'
const fs = require('fs');
const readStream = fs.createReadStream('./hello.txt', { highWaterMark: 1 })
const data = [];
readStream.on('data', (chunk) => {
console.log(chunk); // <Buffer 68> ... <Buffer 64>
data.push(chunk);
});
readStream.on('end', () => { // 파일을 모두 읽으면 실행되는 이벤트 함수
console.log(Buffer.concat(data).toString()); // 버퍼를 하나의 배열로 만들고 String으로 // hello world
console.log('파일을 모두 읽어왔습니다');
});
writeStream
const writeStream = fs.createWriteStream('./newFile.vim'); // 이 파일에 Stream을 이용해서 데이터를 작성
writeStream.write('첫 번째 문장입니다. \n')
writeStream.write('두 번째 문장입니다. \n')
writeStream.write('세 번째 문장입니다. \n')
writeStream.on('end', () => {
console.log('모든 문장을 작성하였습니다.');
})
readFileSync를 통한 bigFile 읽기
const bigFile = [];
for (let i = 0; i < 30000000; i++) {
bigData.push('안녕하세요');
}
// 파일 만든 후
fs.writeFileSync('./bigFile.txt', bigFile.join('')); // 430MB
console.log('Start: ', process.memoryUsage().rss); // 31MB 정도의 메모리 사용
const readData = fs.readFileSync('./bigFile.txt');
console.log('End: ', process.memoryUsage().rss); // 480MB 정도의 메모리 사용
readStream을 통한 bigFile 읽기
const readStream = fs.createReadStream('./bigFile.txt', {highWaterMark: 16000});
readStream.on('data', (chunk) => {
})
readStream.on('end', () => {
console.log('모든 파일을 읽어왔습니다.');
console.log('End: ', process.memoryUsage().rss); // 61MB 정도의 메모리 사용
})
Pipe
Stream으로 생성된 객체를 연결해서 데이터를 그대로 전달 (읽으면서 쓰기)
Buffer => Stream => Pipe
readStream => Pipe => writeStream
console.log('Start: ', process.memoryUsage().rss); // 31MB
const readStream = fs.createReadStream('./bigFile.txt', {highWaterMark: 16000});
const writeStream = fs.createWriteStream('./newBigFile.txt');
readStream.pipe(writeStream);
readStream.on('end', () => {
console.log('Close: 모든 파일 읽기가 완료되었습니다.');
console.log('End: ', process.memoryUsage().rss); // 53MB
})