프로그래밍 언어/Java

[Java] ByteBuffer 사용 시 `flip()`을 호출해야 하는 이유

kchs0529 2025. 3. 26. 18:18

Java의 ByteBuffer를 사용할 때, 데이터를 저장한 후 바로 출력하거나 반환하면 예상과 다른 결과가 발생할 수 있다.
이는 Buffer쓰기 모드읽기 모드를 명확히 구분하기 때문이다.
이 문서에서는 flip() 메서드가 필요한 이유와 사용 방법을 설명한다.


🔹 Buffer의 동작 방식

ByteBuffer는 내부적으로 position, limit, capacity 세 가지 속성을 관리한다.

  • position: 현재 읽기 또는 쓰기 위치
  • limit: 읽거나 쓸 수 있는 최대 위치
  • capacity: 버퍼의 전체 크기

📌 데이터를 쓰는 과정

  1. position은 0에서 시작한다.
  2. put() 메서드를 호출할 때마다 position이 증가한다.
  3. 데이터를 모두 입력하면 position은 마지막 데이터를 가리키게 된다.
ByteBuffer buffer = ByteBuffer.allocate(10);

buffer.put((byte) 1);
buffer.put((byte) 2);
buffer.put((byte) 3);
buffer.put((byte) 4);

System.out.println("쓰기 완료 후 position: " + buffer.position()); // 4

flip() 없이 데이터를 읽을 경우

while (buffer.hasRemaining()) {
    System.out.print(buffer.get() + " "); // 출력되지 않거나, 이상한 값이 나올 수 있음
}

🚨 이유

  • position = 4, limit = 10 상태가 된다.
  • hasRemaining()position < limit일 때만 true를 반환한다.
  • 현재 position이 이미 데이터 끝을 가리키고 있어, 읽을 수 있는 데이터가 없다고 판단된다.

flip()을 호출하면?

flip() 메서드를 호출하면 다음과 같이 상태가 변경된다:

  • limit이 현재 position 값으로 설정된다.
  • position은 0으로 초기화된다.

즉, 처음부터 limit까지 읽을 수 있도록 읽기 모드로 전환된다.

buffer.flip(); // position = 0, limit = 4

while (buffer.hasRemaining()) {
    System.out.print(buffer.get() + " "); // 1 2 3 4 출력
}

🔹 flip()이 필요한 이유

  • 데이터를 쓴 뒤에는 읽기 모드로 전환해야 한다.
  • flip()을 호출하지 않으면, position이 끝을 가리키므로 데이터를 읽을 수 없다.
  • flip()은 읽을 수 있는 데이터 범위를 명확히 설정한다.
  • 네트워크 전송, 파일 저장 등의 I/O 작업 시에도 정확한 데이터만 전송하기 위해 필수로 사용해야 한다.

🔹 clear()와의 차이점

  • clear()는 position을 0으로, limit을 capacity로 설정한다.
  • 이는 쓰기 초기화 목적이며, 데이터를 읽기 위한 상태로 만드는 것이 아니다.
  • 기존 데이터는 남아 있지만 덮어쓰기가 가능하도록 된다.

상황 필요한 메서드 설명
데이터를 쓴 후 읽을 때 flip() 읽기 모드로 전환
버퍼를 초기화하여 다시 쓸 때 clear()  쓰기 모드로 초기화

데이터를 반환하거나 출력할 경우에는 반드시 flip을 호출해야 한다.
그렇지 않으면 데이터를 정상적으로 읽지 못하거나, 빈 값이 반환될 수 있다.