Buffer
이진 데이터를 다루는 데 주로 사용되며, 네트워크, 파일 시스템, 암호화 등 다양한 용도로 사용되는 노드의 내장 클래스 입니다.
노드는 파일을 읽을 때 메모리에 파일 크기만큼 공간을 마련해두며 파일 데이터를 메모리에 저장한 뒤 사용자가 조작할 수 있도록 합니다. 이때 메모리에 저장된 데이터가 바로 버퍼(메모리에 저장된 파일 데이터)입니다.
또한 버퍼 객체는 고정 길이의 바이트 시퀀스를 나타내는 데 사용됩니다. 많은 Node.js API가 버퍼를 지원합니다. Buffer 클래스는 JavaScript Uint8Array 클래스의 하위 클래스이며 추가 사용 사례를 포괄하는 메서드로 확장됩니다. Node.js API는 버퍼가 지원되는 모든 곳에서 일반 Uint8Array를 허용합니다. Buffer 클래스는 전역 범위 내에서 사용할 수 있지만 import 또는 require 문을 통해 이를 명시적으로 참조하는 것이 좋습니다.
** 참고로, 버퍼는 16진수로 주로 표기합니다. 왜 그런걸까요?
버퍼의 내용을 표현할 때 주로 16진수로 표기합니다. 이는 16진수가 이진수를 4비트씩 끊어서 표현하기 때문에, 8비트(1바이트)로 구성된 데이터를 2자리의 16진수로 나타내기에 가장 자연스러운 방법이기 때문입니다.
예를 들어, 4바이트(32비트)의 정수 값이 0x12345678일 경우, 이 값을 버퍼에 저장하면 각 바이트별로 다음과 같이 나타낼 수 있습니다(참고로 1 바이트는 비트가 8개가 보여서 만들어집니다.).
Byte 1: 0x12 (00010010)
Byte 2: 0x34 (00110100)
Byte 3: 0x56 (01010110)
Byte 4: 0x78 (01111000)
위의 표에서 보듯이, 각 바이트는 16진수로 표기되면서, 이진수로 표현하면 8비트로 구성되는 것을 확인할 수 있습니다. 따라서, 버퍼의 내용을 이진수로 표현할 수도 있지만, 주로 16진수로 표기됩니다.
** 2진수를 16진수로 바꾸는 방법은?
<자세한 계산식은 제일 아래 링크를 참고 해보세요. 8 4 2 1 을 이용한 단순한 2진수 -> 16진수 변환 공식을 확인할 수 있습니다. >
2진수를 16진수로 바꾸는 방법은 다음과 같습니다.
- 2진수를 4비트씩 끊습니다. (16진수는 4비트씩으로 표기되기 때문입니다.)
- 끊어진 각 그룹에 대해 16진수 표기법에 따라 값을 계산합니다.
- 계산된 값을 연결하여 16진수로 표기합니다.
예를 들어, 2진수 1101101111101011을 16진수로 바꾸는 과정은 다음과 같습니다.
- 2진수를 4비트씩 끊습니다. 1101 1011 1110 1011
- 끊어진 각 그룹에 대해 16진수 값을 계산합니다.
- 1101은 16진수로 D입니다.
- 1011은 16진수로 B입니다.
- 1110은 16진수로 E입니다.
- 1011은 16진수로 B입니다.
- 계산된 값을 연결하여 16진수로 표기합니다. 따라서, 2진수 1101101111101011은 16진수로 DEBB입니다.
이렇게 2진수를 16진수로 바꾸는 방법은 2진수를 8비트씩 끊어서 10진수로 바꾸는 방법과 유사합니다. 16진수는 2의 거듭제곱인 2의 4승(=16진수 한 자리)을 사용하기 때문에, 2진수를 4비트씩 끊어서 각 그룹을 16진수로 바꾸는 것입니다.
Buffer 클래스의 메서드(주로 사용하는)
1) Buffer.alloc(size ,fill , encoding)
- size : 설정한 인수의 바이트 크기 만큼 새로운 버퍼 생성(ex. 1 을 전달 하면 00 이 생성된다.)
- fill : 전달한 값으로 버퍼를 생성
Buffer.alloc() 메서드는 인수로 전달된 바이트 크기만큼의 새로운 버퍼를 생성합니다. 이 때 생성된 버퍼는 모든 바이트가 0으로 초기화됩니다. encoding 을 비워두면 기본 값은 UTF-8 입니다.
const buf = Buffer.alloc(5);
console.log(buf); // <Buffer 00 00 00 00 00>
** fill 인수에 대한 더 자세한 예를 살펴보려면?
Buffer.alloc() 메서드는 인수로 전달된 size만큼의 크기를 갖는 버퍼를 생성합니다. fill 인수를 전달하여 버퍼를 초기화할 수 있습니다. fill 인수는 0부터 255까지의 숫자 중 하나이거나 문자열일 수 있습니다. 이 값은 버퍼의 모든 바이트에 적용됩니다.
예를 들어, fill 인수를 0으로 설정하여 모든 바이트를 0으로 초기화하는 코드는 다음과 같습니다.
const buf = Buffer.alloc(5, 0);
console.log(buf); // 출력 결과: <Buffer 00 00 00 00 00>
fill 인수로 255를 전달하여 모든 바이트를 ff로 초기화하는 코드는 다음과 같습니다.
const buf = Buffer.alloc(5, 255);
console.log(buf); // 출력 결과: <Buffer ff ff ff ff ff>
fill 인수로 문자열을 전달하여 해당 문자열의 유니코드 값을 갖는 모든 바이트로 초기화하는 코드는 다음과 같습니다.
const buf = Buffer.alloc(5, 'a');
console.log(buf); // 출력 결과: <Buffer 61 61 61 61 61>
위 코드에서 fill 인수로 문자열 'a' 를 전달하여 해당 문자열의 유니코드 값인 97이 모든 바이트에 적용되어, 출력 결과에서 볼 수 있듯이 모든 바이트가 97(16진수로는 0x61)로 초기화됩니다.
2) Buffer.from(string, encoding)
- string : 버퍼로 변환할 문자열
- encoding : 문자열을 어떤 문자셋으로 설정할 것인가(기본값은 UTF-8)
Buffer.from() 메서드는 문자열, 배열 등을 전달받아 새로운 버퍼를 생성합니다. 이 때 생성된 버퍼의 초기값은 전달받은 데이터에 따라 달라집니다. encoding 을 비워두면 기본 값은 UTF-8 입니다.
start와 end 인수를 전달하여 변환할 버퍼의 일부분만 변환할 수 있습니다
const buf1 = Buffer.from('Hello');
console.log(buf1); // <Buffer 48 65 6c 6c 6f>
const buf2 = Buffer.from([0x48, 0x65, 0x6c, 0x6c, 0x6f]);
console.log(buf2); // <Buffer 48 65 6c 6c 6f>
3) Buffer.concat([버퍼1, 버퍼2, ...])
Buffer.concat() 메서드는 여러 개의 버퍼를 하나로 합칩니다.
const buf1 = Buffer.from('Hello');
const buf2 = Buffer.from('World');
const buf3 = Buffer.concat([buf1, buf2]);
console.log(buf3); // <Buffer 48 65 6c 6c 6f 57 6f 72 6c 64>
4) buffer.toString(encoding , start, end)
Buffer.toString() 메서드는 버퍼에 저장된 데이터를 문자열로 변환합니다.
const buf = Buffer.from('Hello'); // <Buffer 48 65 6c 6c 6f>
console.log(buf.toString()); // Hello
5) buffer.write(string, offset, length, encoding)
- string : buffer 에 쓸 문자열
- offset : 해당 버퍼에서 string 을 쓰기 시작할 위치
- length : offset 위치에서 쓰일 문자열의 길이(해당 길이 만큼 문자열이 쓰인다.)
- encoding : 문자셋(지정 안 할 시 기본값은 UTF-8)
offset 인수를 전달하면 버퍼에 문자열을 쓸 시작 위치를 지정할 수 있습니다. length 인수를 전달하면 문자열을 쓸 길이를 지정할 수 있습니다. encoding 인수를 생략하면 기본 인코딩인 'utf-8'이 사용됩니다.
const buffer = Buffer.alloc(10); // 10바이트 크기의 버퍼 생성
// 012345
buffer.write('Hello', 0, 5, 'utf-8'); // 버퍼의 0번 인덱스부터 5글자만큼 'Hello' 문자열을 쓰기
console.log(buffer.toString()); // 출력 결과: "Hello "
위 코드에서 buffer.write() 메서드를 호출하여 Hello 문자열을 버퍼에 씁니다. offset 인수로 0을 전달하여 버퍼의 0번 인덱스부터 쓰기를 시작하며, length 인수로 5를 전달하여 'Hello' 문자열의 첫 5글자만 버퍼에 씁니다. encoding 인수는 생략해도 'utf-8' 인코딩이 기본값으로 사용됩니다.
6) buffer.slice(start, end)
- start : 반환할 버퍼의 시작 위치
- end : 반환할 버퍼의 끝 위치
버퍼의 일부분을 새로운 버퍼로 반환합니다. start와 end 인수를 전달하여 반환할 버퍼의 일부분만 선택할 수 있습니다
- 만일 end를 생략하면 start 인수 부터 버퍼의 끝까지 읽습니다.
const buffer1 = Buffer.from('0123456789');
const buffer2 = buffer1.slice(4, 7); // buffer1의 4번 인덱스부터 6번 인덱스까지의 일부분을 새로운 버퍼(buffer2)로 반환
console.log(buffer2.toString()); // 출력 결과: "456"
slice 는 일반적인 자바스크립트의 slice 문법과 같은 기능을 수행합니다.
위 코드에서 buffer.slice() 메서드를 호출하여 buffer1의 일부분을 새로운 버퍼 buffer2로 반환합니다.즉, start 인수로 4를 전달하여 buffer1의 4번 인덱스부터 시작하고, end 인수로 7을 전달하여 6번 인덱스까지의 일부분을 선택합니다.
7) buffer.copy(target;, targetStart, sourceStart, sourceEnd)
- target: 현재버퍼를 붙여넣을 대상
- targetStart : 현재버퍼를 붙여넣을 시작 위치
- sourceStart : 현재 버퍼에서 복사할 시작 위치
- sourceEnd : 현재 버퍼에서 복사를 끝낼 위치
다른 버퍼(target)에 현재 버퍼를 복사합니다. targetStart와 sourceStart, sourceEnd 인수를 전달하여 복사할 버퍼의 일부분만 선택할 수 있습니다.
const buffer1 = Buffer.from('0123456789'); // 현재 버퍼
const buffer2 = Buffer.alloc(5); // 5바이트 크기의 버퍼 생성(현재 버퍼를 복사해 넣을 타겟)
// target
buffer1.copy(buffer2, 0, 2, 7); // buffer1의 2번 인덱스부터 6번 인덱스까지의 일부분을 buffer2의 0번 인덱스부터 복사하기
console.log(buffer2.toString()); // 출력 결과: "23456"
위 코드에서 buffer.copy() 메서드를 호출하여 buffer1의 일부분을 buffer2로 복사합니다. target 인수로 buffer2를 전달하고, targetStart 인수로 0을 전달하여 복사할 위치를 지정합니다. sourceStart 인수로 2를 전달하여 buffer1의 2번 인덱스부터 시작하고, sourceEnd 인수로 7을 전달하여 6번 인덱스까지의 일부분을 선택합니다.
8) buffer.length
버퍼의 길이를 나타내는 속성입니다. 말 그대로 버퍼의 길이를 반환합니다.
'백엔드 > 노드' 카테고리의 다른 글
[node.js] npx 와 전역설치(-g)의 장.단점 (0) | 2023.03.12 |
---|---|
[node.js] package.json (0) | 2023.03.12 |
[NodeJS] fs 모듈 : 파일 시스템에 접근 시 사용 (0) | 2023.03.07 |
[Node.js] 태스크 큐와 이벤트 큐 (0) | 2023.03.05 |
[Node.js] 노드에서 싱글 스레드/블로킹과 언블로킹/이벤트 루프 .../ (0) | 2023.03.04 |