하이고니 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
})