add user agent parser and update build configuration
This commit is contained in:
156
docs/ByteBuffer.md
Normal file
156
docs/ByteBuffer.md
Normal file
@@ -0,0 +1,156 @@
|
||||
# **ByteBuffer란?**
|
||||
|
||||
`ByteBuffer`는 Java NIO(Non-blocking I/O)에서 **바이트 데이터를 효율적으로 다룰 수 있도록 제공하는 클래스**이다.
|
||||
기존의 `InputStream` 및 `OutputStream` 기반의 **blocking I/O**와 달리, **비동기적(Non-blocking)**으로 데이터를 처리할 수 있는 구조를 제공한다.
|
||||
|
||||
이 클래스는 **버퍼(Buffer)**라는 개념을 사용하여 데이터를 읽고 쓸 때 **직접 메모리에서 조작**할 수 있도록 하며, 성능 최적화에 유리하다.
|
||||
특히 **파일 I/O, 네트워크 전송, 바이너리 데이터 처리** 등에서 활용된다.
|
||||
|
||||
---
|
||||
|
||||
## **1. ByteBuffer의 주요 특징**
|
||||
✔ **고정된 크기의 버퍼**를 사용하여 데이터를 읽고 쓴다.
|
||||
✔ **Direct Buffer(직접 버퍼)와 Heap Buffer(힙 버퍼)** 두 가지 방식이 있다.
|
||||
✔ **데이터를 읽고 쓰는 포인터(위치, 한계, 용량)가 존재**하여 데이터 흐름을 효율적으로 관리한다.
|
||||
✔ **채널(Channel)과 함께 사용하여 고성능 I/O 처리**가 가능하다.
|
||||
|
||||
---
|
||||
|
||||
## **2. ByteBuffer의 구조**
|
||||
`ByteBuffer`는 데이터를 저장하는 **고정된 크기의 메모리 공간**을 가지며, 다음과 같은 **3가지 중요한 속성**을 갖는다.
|
||||
|
||||
| 속성 | 설명 |
|
||||
|------|------|
|
||||
| **position** | 현재 읽거나 쓸 위치 (0부터 시작) |
|
||||
| **limit** | 읽거나 쓸 수 있는 최대 위치 |
|
||||
| **capacity** | 버퍼의 전체 크기 (변경 불가) |
|
||||
|
||||
### **🔹 주요 속성 변화 예시**
|
||||
```java
|
||||
ByteBuffer buffer = ByteBuffer.allocate(10);
|
||||
System.out.println("초기 상태: " + buffer);
|
||||
// 출력: java.nio.HeapByteBuffer[pos=0 lim=10 cap=10]
|
||||
```
|
||||
위 상태에서 데이터를 `put()`하면 `position`이 증가하고, `flip()`을 호출하면 `position`이 0으로 초기화되어 데이터를 `get()`으로 읽을 준비를 한다.
|
||||
|
||||
---
|
||||
|
||||
## **3. ByteBuffer의 주요 메서드 정리**
|
||||
|
||||
| 메서드 | 설명 |
|
||||
|--------|------|
|
||||
| `allocate(int capacity)` | 힙 메모리에 지정한 크기의 버퍼 생성 |
|
||||
| `allocateDirect(int capacity)` | OS의 직접 메모리에 버퍼 생성 (성능 최적화) |
|
||||
| `put(byte b)` | 한 바이트 추가 |
|
||||
| `put(byte[] src)` | 바이트 배열을 버퍼에 추가 |
|
||||
| `get()` | 현재 위치의 바이트를 가져오고 `position`을 증가 |
|
||||
| `get(byte[] dst)` | 데이터를 바이트 배열로 가져옴 |
|
||||
| `flip()` | **쓰기 모드 → 읽기 모드** 변경 (`position=0`, `limit=현재 position`) |
|
||||
| `clear()` | 버퍼를 초기화 (`position=0`, `limit=capacity`) |
|
||||
| `rewind()` | **읽기 모드에서 처음부터 다시 읽기** (`position=0`, `limit` 유지) |
|
||||
| `compact()` | 아직 읽지 않은 데이터는 유지한 채, 새로운 데이터를 쓸 수 있도록 `position`을 조정 |
|
||||
| `mark()` | 현재 `position`을 저장 |
|
||||
| `reset()` | 저장한 `mark` 위치로 `position`을 되돌림 |
|
||||
|
||||
---
|
||||
|
||||
## **4. ByteBuffer 사용 예제**
|
||||
|
||||
### **(1) ByteBuffer 생성과 데이터 추가 (`put()`, `flip()`, `get()`)**
|
||||
```java
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class ByteBufferExample {
|
||||
public static void main(String[] args) {
|
||||
// 10바이트 크기의 버퍼 생성
|
||||
ByteBuffer buffer = ByteBuffer.allocate(10);
|
||||
|
||||
// 데이터 추가 (쓰기 모드)
|
||||
buffer.put((byte) 1);
|
||||
buffer.put((byte) 2);
|
||||
buffer.put((byte) 3);
|
||||
System.out.println("데이터 추가 후: " + buffer);
|
||||
|
||||
// 읽기 모드로 변경 (flip)
|
||||
buffer.flip();
|
||||
System.out.println("flip() 후: " + buffer);
|
||||
|
||||
// 데이터 읽기
|
||||
System.out.println("읽은 데이터: " + buffer.get()); // 1
|
||||
System.out.println("읽은 데이터: " + buffer.get()); // 2
|
||||
System.out.println("get() 후: " + buffer);
|
||||
}
|
||||
}
|
||||
```
|
||||
✔ `flip()`을 호출하면 `position`이 0이 되어 데이터를 읽을 준비를 한다.
|
||||
✔ `get()`을 호출할 때마다 `position`이 증가하여 다음 데이터를 읽을 수 있다.
|
||||
|
||||
---
|
||||
|
||||
### **(2) `compact()`와 `clear()` 차이점**
|
||||
```java
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class ByteBufferCompactClearExample {
|
||||
public static void main(String[] args) {
|
||||
ByteBuffer buffer = ByteBuffer.allocate(10);
|
||||
buffer.put((byte) 10);
|
||||
buffer.put((byte) 20);
|
||||
buffer.put((byte) 30);
|
||||
|
||||
buffer.flip(); // 읽기 모드 전환
|
||||
System.out.println("flip() 후: " + buffer);
|
||||
|
||||
System.out.println("읽은 데이터: " + buffer.get()); // 10
|
||||
System.out.println("읽은 데이터: " + buffer.get()); // 20
|
||||
|
||||
buffer.compact(); // 읽지 않은 데이터 유지한 채 쓰기 모드 변경
|
||||
System.out.println("compact() 후: " + buffer);
|
||||
|
||||
buffer.clear(); // 완전히 초기화
|
||||
System.out.println("clear() 후: " + buffer);
|
||||
}
|
||||
}
|
||||
```
|
||||
✔ **`compact()`는 읽지 않은 데이터를 유지하고 `position`을 이동**
|
||||
✔ **`clear()`는 전체를 초기화하고 `position=0`으로 변경**
|
||||
|
||||
---
|
||||
|
||||
### **(3) DirectBuffer 사용 (`allocateDirect()`)**
|
||||
```java
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class DirectByteBufferExample {
|
||||
public static void main(String[] args) {
|
||||
// DirectBuffer 생성
|
||||
ByteBuffer directBuffer = ByteBuffer.allocateDirect(10);
|
||||
|
||||
directBuffer.put((byte) 42);
|
||||
directBuffer.flip();
|
||||
|
||||
System.out.println("DirectBuffer 데이터: " + directBuffer.get()); // 42
|
||||
}
|
||||
}
|
||||
```
|
||||
✔ `allocateDirect()`를 사용하면 **JVM의 힙 메모리가 아닌 OS의 직접 메모리에 할당**하여 성능을 높일 수 있다.
|
||||
✔ 다만, **GC(가비지 컬렉터)가 자동으로 해제하지 않기 때문에 직접 관리해야 한다.**
|
||||
|
||||
---
|
||||
|
||||
## **5. ByteBuffer vs. 일반 배열**
|
||||
| 비교 항목 | `ByteBuffer` | 일반 `byte[]` 배열 |
|
||||
|----------|-------------|----------------|
|
||||
| 메모리 할당 | 힙(Heap) 또는 직접 메모리(Direct) | 힙 메모리 |
|
||||
| 데이터 조작 | position/limit을 활용한 조작 | 단순한 인덱스 접근 |
|
||||
| 성능 | `allocateDirect()` 사용 시 속도 향상 | 단순 배열보다 속도가 느릴 수 있음 |
|
||||
| 가비지 컬렉션 | DirectBuffer는 수동 해제 필요 | 자동 관리 |
|
||||
|
||||
✔ **파일 I/O, 네트워크 프로그래밍에서는 `ByteBuffer`를 사용**하는 것이 효율적이다.
|
||||
✔ **단순한 배열 조작이라면 `byte[]`가 더 간단하다.**
|
||||
|
||||
---
|
||||
|
||||
## **6. 결론**
|
||||
`ByteBuffer`는 **Java NIO에서 고성능 I/O 처리를 위한 핵심 클래스**로, 데이터를 읽고 쓰는 방식이 기존의 `InputStream`보다 **더 유연하고 효율적**이다.
|
||||
특히 **파일 I/O, 네트워크 전송, 바이너리 데이터 처리**에 적합하며, **DirectBuffer**를 사용하면 성능을 극대화할 수 있다.
|
||||
Reference in New Issue
Block a user