본문 바로가기

Programming/Node.js

4. Node 기능 살펴보기 (7) - 버퍼와 스트림 2

node js logo image

 

 

 

 

 

앞선 아티클에서 Buffer 클래스를 사용한 예제를 확인했습니다. 이제 Buffer 클래스의 사용법을 조금 더 자세히 살펴보도록 하겠습니다. 

 

const buffer = Buffer.from('버퍼로 변환할 문자열입니다.');

console.log('from(): ', buffer);
console.log('length: ', buffer.length);
console.log('toString(): ', buffer.toString());

const array = [Buffer.from('단어 ' ), Buffer.from('사이 '), Buffer.from('공백들')];
const buffer2 = Buffer.concat(array);
console.log('concat(): ', buffer2.toString());

const buffer3 = Buffer.alloc(5);
console.log('alloc():', buffer3);

/* 출력
from():  <Buffer eb b2 84 ed 8d bc eb a1 9c 20 eb b3 80 ed 99 98 ed 95 a0 20 eb ac b8 ec 9e 90 ec 97 b4 ec 9e 85 eb 8b 88 eb 8b a4 2e>
length:  39
toString():  버퍼로 변환할 문자열입니다.
concat():  단어 사이 공백들
alloc(): <Buffer 00 00 00 00 00>
*/

 

 

위에서 사용한 몇 Buffer 클래스의 대표적인 메서드는 다음과 같습니다. 

 

· from(문자열) : 문자열을 버퍼로 변경한다. 
· length 속성 : 버퍼의 크기 표시한다.
· toString(버퍼) : 버퍼를 문자열로 다시 변환. base64나 hex를 인수로 넣으면 해당 인코딩으로도 변환 가능
· concat(배열) : 배열 내의 버퍼들을 병합한다.
· alloc(바이트) : 빈 버퍼를 생성하고, 인수로 바이트를 넣어 해당 크기의 버퍼를 생성한다.

 

 

 


 

 

 

readFile 방식의 버퍼의 문제점은 무엇일까요? 단순합니다. 파일의 크기에 따라 메모리에 그만큼의 메모리를 할당해야 합니다. 극단적으로 500MB의 파일을 위해서는 메모리에 500MB의 버퍼를 할당하게 됩니다. 파일을 몇 개만 불러올 경우, 메모리가 순식간에 1GB 넘어가게 되는 것입니다. 

 

서버의 사용자 예측도 어렵고, 버퍼 처리가 완료될 때까지 무작정 기다려야 한다는 점도 불편합니다. 이런 이유로 등장한 것이 바로 '스트림'입니다. 원리는 간단합니다. 버퍼의 크기를 작게 만들고, 이를 여러 번에 걸쳐서 나눠서 보내는 방식인 것입니다. 위에서 말한 500MB의 파일이 있을 경우, 1MB의 버퍼를 이용해 500번에 걸쳐서 보내는 방식입니다. 이를 통해서 메모리 사용을 최소화하는 것이죠. 

 

예제를 만들어 보겠습니다. 파일을 읽어들이는 스트림 메서드는 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);
});

/* 출력
data :  <Buffer ec 9d b4 20 ed 8c 8c ec 9d bc ec 9d 80 20 eb 82> 16
data :  <Buffer 98 eb 88 a0 ec 84 9c 20 ec a0 84 eb 8b ac eb 90> 16
data :  <Buffer 9c eb 8b a4 2e 20 63 68 75 6e 6b 20 ec a1 b0 ea> 16
data :  <Buffer b0 81 20 eb 8b a8 ec 9c 84 eb a1 9c 20 eb 82 98> 16
data :  <Buffer eb 88 84 ec 96 b4 ec a7 84 eb 8b a4 2e> 13
end :  이 파일은 나눠서 전달된다. chunk 조각 단위로 나누어진다.
*/

 

 

위 예제에서 사용된 createReadStream이 대해서 다음 아티클에서 자세히 살펴보겠습니다.