핵심 정리
const buf = Buffer.from("hello world", "utf8");
console.log(buf.length); // 11 bytes
console.log(buf.toString("hex")); // 68656c6c6f20776f726c64
console.log(buf.toString("base64")); // aGVsbG8gd29ybGQ=
const fixed = Buffer.alloc(8);
fixed.writeUInt32BE(0xdeadbeef, 0);
console.log(fixed.toString("hex")); // deadbeef00000000버퍼 기초
먼저 구분해 둘 기본형은 아래입니다.
- 문자열 -> 바이트:
Buffer.from(str, "utf8") - 안전한 새 버퍼:
Buffer.alloc(size) - 빠르지만 초기화 안 된 버퍼:
Buffer.allocUnsafe(size) - 인코딩 출력:
buf.toString("hex"),buf.toString("base64") - 일부 구간 뷰:
subarray(...)
Buffer는 문자 수가 아니라 바이트 수를 다룬다
buf.length는 문자열 길이가 아니라 실제 바이트 길이입니다. 멀티바이트 문자를 다루거나 네트워크 프로토콜, 파일 헤더를 읽을 때 이 차이가 중요합니다.
const text = "가a";
const buf = Buffer.from(text, "utf8");
console.log(text.length); // 2 characters
console.log(buf.length); // 4 bytes기본값은 Buffer.from()과 Buffer.alloc()
입력이 있으면 Buffer.from(), 크기만 정해져 있으면 Buffer.alloc()이 기본입니다. 새 버퍼를 만들 때는 일단 이 둘로 시작하면 됩니다.
allocUnsafe()는 성능 카드이지 기본 카드가 아니다
초기화를 건너뛰어서 빠르지만, 내용을 채우기 전에 외부로 흘리면 위험합니다. 응답 본문이나 로그에 나갈 가능성이 있으면 피하는 편이 낫습니다.
Buffer는 Uint8Array처럼도 동작한다
Buffer는 TypedArray 계열과 자연스럽게 맞물립니다. Web API, 암호화, 스트림, 파일 I/O 경계에서 바이트 컨테이너로 계속 등장합니다.
slice()보다 subarray() 감각을 같이 잡아 둔다
Buffer는 메모리 일부를 복사하지 않고 같은 바탕 데이터를 보는 뷰를 자주 씁니다.
프로토콜 파싱이나 헤더 분리에서는 "새 버퍼를 만든다"보다 "같은 바이트를 다른 구간으로 본다"는 감각이 더 중요합니다.
const packet = Buffer.from("deadbeef", "hex");
const header = packet.subarray(0, 2);
header[0] = 0xaa;
console.log(packet.toString("hex")); // aaadbeef부분 버퍼를 잘라 쓸 때 원본까지 같이 바뀔 수 있다는 점을 기억해야, "분리했다"고 생각하고 수정했다가 원본 패킷을 망가뜨리는 실수를 줄일 수 있습니다.
언제 Buffer를 직접 쓰나
체크포인트
- 문자열 -> 바이트:
Buffer.from(str, "utf8") - 안전한 새 버퍼:
Buffer.alloc(size) - 빠르지만 위험한 버퍼:
Buffer.allocUnsafe(size) - 인코딩 변환:
buf.toString("hex"),buf.toString("base64") - 부분 뷰:
subarray(...) - 문자 수가 아니라 바이트 수 기준으로 읽는다
- 잘라낸 뷰는 복사본이 아니라 같은 메모리를 볼 수 있다
주의할 점
Buffer.allocUnsafe()는 채우기 전에 외부로 흘리면 안 된다. 이름 그대로 초기화되지 않은 메모리를 돌려줄 수 있어서, 응답이나 로그로 내보내면 민감한 데이터가 섞일 수 있다.
참고 링크
1 sources