Float32MLE (Byte Order)

바이트 순서(Byte Order)는 오래 전 컴퓨터공학과에서 배웠던 개념이지만 실무에서는 실제로 고려할 필요가 없었다.

컴퓨터에서 데이터를 메모리에 저장할 때의 바이트 순서는 빅 엔디안과 리틀 엔디방 식으로 나누어지는데 이것은 CPU 아키텍처에 따라 나누어진다고 한다. TCP 네트워크 스펙 상에는 패킷의 바이트 순서는 빅 엔디안으로 구성되며 웹 애플리케이션에서 자주 활용되는 언어인 자바도 이를 감안하여 빅 엔디안을 기본적으로 사용한다. CPU 아키텍처와 다르게 빅 엔디안으로 사용되는 이유는 JVM 이라는 별도의 스택을 기반으로 구동되기 때문이라고 한다. 그러나, SCADA 또는 PLC 장비와 같은 일부 시스템에서는 빅 엔디안 방식이 아닌 리틀 엔디안 또는 미드 리틀 엔디안으로 바이트 순서를 구성하고 있는데 이러한 시스템은 C 언어를 기반으로 만들어지기 때문이다.

일반적인 자바 웹 개발자들이 바이트 순서를 고려하여 비트 연산 또는 시프트 연산을 수행할 경우는 많지 않을 것 같다.

Mid Little Endian, MLE

빅 엔디안와 리틀 엔디안 뿐만 아니라 바이트 순서를 스왑하는 미드 리틀 엔디안은 AB CD의 바이트 순서가 있을때 CD AB로 표현하는 것을 의미한다. 32비트로 구성되는 Float 형식을 미드 리틀 엔디안 방식으로 구성한 것을 Float32MLE 이라고 표기할 수 있다.

Base Convert: IEEE 754 Floating Point

Float32MLE Example

@DisplayName("Endian Test")
class EndianTest {

    @DisplayName("Float32 Mid Little Endian")
    @Test
    void TestFloat32MLE() {
        String hexadecimal = "00004260"; // 00 00 42 60
        byte[] bytes = HexFormat.of().parseHex(hexadecimal);
        float originValue = PooledByteBufAllocator.DEFAULT.buffer()
                .writeBytes(new byte[]{bytes[2], bytes[3]}) // CD (42 60)
                .writeBytes(new byte[]{bytes[0], bytes[1]}) // AB (00 00)
                .readFloat();
        float value = BigDecimal.valueOf(originValue)
                .setScale(1, RoundingMode.HALF_UP)
                .floatValue();
        Assertions.assertEquals(56.0f, value);
    }

}

Netty의 ByteBuf 클래스에서는 빅 엔디안 방식의 readFloat 함수와 리틀 엔디안 방식의 readFloatLE 함수를 제공하고 있다. 그러나, 미드 리틀 엔디안 방식의 경우에는 별도로 제공하지 않으므로 위와 같이 버퍼에 CD AB 순으로 쓰고나서 빅 엔디안 방식으로 읽어야한다.