본문 바로가기
Etc2026년 8월 7일6분 읽기

엔디안 — 바이트 순서가 빅/리틀로 갈리는 이유

YS
김영삼
조회 4
엔디안 — 바이트 순서가 빅/리틀로 갈리는 이유

엔디안(endianness)은 여러 바이트로 이뤄진 수를 메모리나 파일에 저장할 때 바이트를 어느 순서로 늘어놓느냐는 규칙이다. 큰 자리(상위 바이트)를 앞에 두면 빅 엔디안, 작은 자리를 앞에 두면 리틀 엔디안이다. 평소엔 안 보이다가, 바이너리 데이터를 직접 다루는 순간 튀어나온다.

고수준 언어만 쓰면 평생 모르고 살 수도 있다. 하지만 파일 포맷을 파싱하거나, 네트워크로 정수를 던지거나, 서로 다른 CPU 사이에 데이터를 주고받는 순간 반드시 만난다. 나는 이걸 이미지 헤더 파싱하다가 처음 정면으로 부딪혔다.

같은 숫자, 다른 바이트 배열

32비트 정수 0x12345678을 메모리에 저장한다고 하자. 이 수는 네 바이트다: 12 34 56 78. 낮은 주소부터 어떻게 채우느냐가 엔디안이다.

주소빅 엔디안리틀 엔디안
낮음 →1278
3456
5634
→ 높음7812

빅 엔디안은 사람이 숫자 쓰는 순서(큰 자리부터)와 같아 직관적이다. 리틀 엔디안은 거꾸로다. 그런데 우리가 매일 쓰는 x86/x86-64와 대부분의 ARM은 리틀 엔디안이다. 그래서 실제로는 뒤집힌 순서가 표준처럼 느껴진다.

내 CPU 엔디안 확인하기

말로만 들으면 안 와닿는다. 직접 확인해보는 게 최고다. C로는 정수의 첫 바이트를 들여다보면 된다.

#include <stdio.h>
int main(void) {
    unsigned int x = 0x12345678;
    unsigned char *p = (unsigned char *)&x;
    // 첫 바이트가 0x78이면 리틀, 0x12면 빅
    printf("%02x\n", p[0]);
    return 0;
}

대부분의 데스크톱/서버에서 이 코드는 78을 찍는다. 리틀 엔디안이라는 뜻이다. 파이썬이라면 더 간단하다.

import sys
print(sys.byteorder)   # 'little' 또는 'big'
# 정수를 원하는 엔디안 바이트로
(0x12345678).to_bytes(4, "big")     # b'\x12\x34\x56\x78'
(0x12345678).to_bytes(4, "little")  # b'\x78\x56\x34\x12'

어디서 만나게 되나

엔디안이 실제로 문제가 되는 지점은 정해져 있다. 바이트가 시스템 경계를 넘을 때다.

  • 네트워크 프로토콜: TCP/IP는 빅 엔디안을 쓴다. 그래서 "네트워크 바이트 순서"가 곧 빅 엔디안이고, htons/htonl 같은 변환 함수가 존재한다. 리틀 엔디안 머신에서 포트 번호를 그냥 보내면 뒤집혀 나간다.
  • 바이너리 파일 포맷: PNG·JPEG·클래스 파일은 빅 엔디안, BMP·WAV·많은 데이터 포맷은 리틀 엔디안이다. 명세를 안 읽고 파싱하면 값이 엉뚱하게 나온다.
  • 이기종 시스템 간 데이터 교환: 한쪽에서 memcpy로 구조체를 통째로 저장하고 다른 엔디안 머신에서 읽으면 수가 깨진다.
솔직히 처음엔 "요즘 세상에 빅 엔디안 CPU가 어디 있다고" 싶었다. 그런데 엔디안은 CPU만의 문제가 아니다. 파일 포맷프로토콜이 각자 엔디안을 정해두기 때문에, 리틀 엔디안 머신만 써도 계속 마주친다.

실무 원칙: 명시적 변환

교훈은 하나다. 바이너리를 읽고 쓸 땐 절대 "그냥 메모리 그대로"에 의존하지 말고 엔디안을 명시하라. 파이썬 struct의 포맷 문자가 좋은 예다.

import struct
struct.pack(">I", 305419896)  # > = 빅 엔디안
struct.pack("<I", 305419896)  # < = 리틀 엔디안
struct.pack("!I", 305419896)  # ! = 네트워크(=빅)

포맷 앞에 >, <, !를 붙여 순서를 못 박는 습관을 들이면, 코드가 어느 머신에서 돌든 결과가 같다.

자주 묻는 질문

내 컴퓨터는 어떤 엔디안인가요?

거의 확실히 리틀 엔디안입니다. x86, x86-64, 그리고 일반적인 ARM 데스크톱·서버·모바일 칩이 모두 리틀 엔디안으로 동작합니다. 파이썬에서 sys.byteorder를 출력하거나 C로 정수의 첫 바이트를 확인해 직접 검증할 수 있습니다.

네트워크 바이트 순서가 왜 빅 엔디안인가요?

초기 인터넷 프로토콜이 빅 엔디안으로 표준화됐기 때문입니다. 관례상 "네트워크 바이트 순서"는 빅 엔디안을 뜻하며, 리틀 엔디안 머신은 정수를 보내기 전에 htonl/htons로 변환해야 값이 올바르게 전달됩니다.

고수준 언어만 써도 엔디안을 알아야 하나요?

일반적인 산술이나 문자열 처리에서는 몰라도 됩니다. 하지만 바이너리 파일을 파싱하거나, 저수준 프로토콜을 구현하거나, 바이트 버퍼에서 정수를 꺼내는 순간 반드시 필요합니다. 그럴 때는 structDataView처럼 엔디안을 명시하는 API를 쓰세요.

바이트 순서를 어떻게 바꾸나요?

언어별 유틸리티를 쓰면 됩니다. 파이썬은 int.from_bytes/to_bytes에 순서를 지정하거나 struct 포맷 접두어(>, <)를 쓰고, C는 htonl·ntohl, 자바스크립트는 DataViewlittleEndian 인자를 사용합니다. 직접 바이트를 뒤집기보다 표준 함수를 쓰는 편이 안전합니다.

댓글 0

아직 댓글이 없습니다.
Ctrl+Enter로 등록