Node.js 인터뷰 질문 14
질문: Node.js의 Buffer 클래스란 무엇인가요?
답변:
Buffer 클래스는 Node.js에서 바이너리 데이터를 직접 다루기 위한 메커니즘으로, JavaScript가 기본적으로 이진 데이터를 효과적으로 다루지 못하는 한계를 보완합니다. Buffer는 고정된 크기의 메모리 영역을 나타내며, 주로 네트워크 통신, 파일 시스템 작업, 암호화 등에서 원시 데이터를 처리할 때 사용됩니다.
Buffer의 주요 특성
- 바이너리 데이터 처리: 텍스트뿐만 아니라 이미지, 비디오, 오디오 등 모든 형태의 이진 데이터를 처리합니다.
- 고정 크기: Buffer는 생성 시 크기가 결정되며, 나중에 크기를 변경할 수 없습니다.
- C++로 구현: 내부적으로 V8 JavaScript 엔진 외부에서 할당되는 메모리 영역입니다.
- 배열과 유사: 인덱스를 통해 각 바이트에 접근할 수 있습니다.
Buffer 생성하기
// 특정 크기의 버퍼 생성
const buf1 = Buffer.alloc(10); // 10바이트 크기의 버퍼 (0으로 초기화)
// 초기화되지 않은 버퍼 생성 (더 빠름)
const buf2 = Buffer.allocUnsafe(10); // 10바이트 크기의 버퍼 (초기화되지 않음)
// 배열로부터 버퍼 생성
const buf3 = Buffer.from([1, 2, 3, 4, 5]); // [01, 02, 03, 04, 05]
// 문자열로부터 버퍼 생성
const buf4 = Buffer.from("Hello World", "utf8"); // 기본 인코딩은 utf8
Buffer 조작하기
// 버퍼 내용 읽기
const buf = Buffer.from("Hello", "utf8");
console.log(buf[0]); // 72 (ASCII 코드 'H')
console.log(buf.toString()); // 'Hello'
console.log(buf.toString("hex")); // '48656c6c6f' (16진수 표현)
console.log(buf.toString("base64")); // 'SGVsbG8=' (base64 표현)
// 버퍼 내용 쓰기
buf[0] = 74; // 'J'의 ASCII 코드
console.log(buf.toString()); // 'Jello'
// 버퍼 복사
const target = Buffer.alloc(5);
buf.copy(target);
console.log(target.toString()); // 'Jello'
// 버퍼 슬라이싱 (메모리 공유)
const slice = buf.slice(0, 2);
slice[0] = 75; // 'K'의 ASCII 코드
console.log(slice.toString()); // 'Ke'
console.log(buf.toString()); // 'Kello' (원본 버퍼도 변경됨)
// 버퍼 길이
console.log(buf.length); // 5
Buffer와 인코딩
Buffer는 다양한 인코딩 형식을 지원합니다:
const buf = Buffer.from("안녕하세요", "utf8");
// 다양한 인코딩으로 변환
console.log(buf.toString("utf8")); // '안녕하세요'
console.log(buf.toString("base64")); // 7JWI64WV7ZWY7IS47JqUCg==
console.log(buf.toString("hex")); // ec9588eb8595ed9598ec84b8ec9a94
// 다른 인코딩으로 저장된 문자열을 Buffer로 변환
const base64Buf = Buffer.from("7JWI64WV7ZWY7IS47JqU", "base64");
console.log(base64Buf.toString("utf8")); // '안녕하세요'
지원되는 인코딩: utf8
, ascii
, utf16le
, ucs2
, base64
, latin1
, binary
, hex
Buffer 사용 사례
- 파일 시스템 작업:
const fs = require("fs");
// 파일 읽기
fs.readFile("file.txt", (err, data) => {
if (err) throw err;
console.log(data); // <Buffer 48 65 6c 6c 6f 20 57 6f 72 6c 64>
console.log(data.toString()); // 'Hello World'
});
// 파일 쓰기
const buffer = Buffer.from("Hello Node.js");
fs.writeFile("output.txt", buffer, (err) => {
if (err) throw err;
console.log("파일 쓰기 완료");
});
- 네트워크 통신:
const http = require("http");
http
.createServer((req, res) => {
const body = [];
req.on("data", (chunk) => {
body.push(chunk); // chunk는 Buffer 객체
});
req.on("end", () => {
const bodyBuffer = Buffer.concat(body);
console.log(bodyBuffer.toString());
res.end("데이터 수신 완료");
});
})
.listen(3000);
- 이미지 처리:
const fs = require("fs");
// 이미지 파일 읽기
fs.readFile("image.png", (err, data) => {
if (err) throw err;
// 이미지 데이터 조작 (예: 헤더 확인)
if (
data[0] === 0x89 &&
data[1] === 0x50 &&
data[2] === 0x4e &&
data[3] === 0x47
) {
console.log("유효한 PNG 이미지입니다.");
}
// 다른 파일로 저장
fs.writeFile("copy.png", data, (err) => {
if (err) throw err;
console.log("이미지 복사 완료");
});
});
Buffer 메모리 관리
Buffer는 V8 힙 외부에 메모리를 할당하기 때문에, 사용 후에는 가비지 컬렉션에 의해 자동으로 해제됩니다. 그러나 큰 Buffer 작업 시 메모리 사용량에 주의해야 합니다:
// 큰 Buffer 생성 후 참조 해제
let buffer = Buffer.alloc(1024 * 1024 * 50); // 50MB
// 버퍼 사용 후
buffer = null; // 참조 해제하여 가비지 컬렉션 대상이 되게 함
Buffer는 Node.js에서 바이너리 데이터를 효율적으로 처리할 수 있게 해주는 강력한 기능으로, 파일 처리, 네트워크 통신, 암호화 등 다양한 시나리오에서 필수적인 역할을 합니다.