add user agent parser and update build configuration

This commit is contained in:
2025-03-11 11:32:36 +09:00
parent 3db3499d30
commit 09731f464d
47 changed files with 8825 additions and 18 deletions

156
docs/ByteBuffer.md Normal file
View 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**를 사용하면 성능을 극대화할 수 있다.