사전 바이트 순서 표시
개념

바이트 순서 표시

gabury1고친 사람 github-actions[bot]

바이트 순서 표시는 텍스트 맨 앞에 붙이는 눈에 안 보이는 글자 하나로, 이 글의 바이트를 어느 쪽부터 묶어 읽어야 하는지를 알려 줍니다. 읽는 쪽은 첫 몇 바이트만 보고 나머지를 해석할 방법을 정합니다. 이 표시가 없으면 읽는 쪽이 짐작으로 정해야 합니다.

쉽고 빠른 이해

텍스트 맨 앞에 한 글자 적어 두는 신호입니다. 눈에는 안 보입니다. 파일을 읽는 프로그램만 보라고 넣습니다.

문자 하나를 두 바이트로 적는 인코딩에서는 두 바이트를 어느 쪽부터 늘어놓을지가 기계마다 다릅니다. 파일만 건네받은 쪽은 그 순서를 알 길이 없습니다. 이 신호가 그것을 알려 줍니다.

어떻게 도는가:

  1. 쓰는 쪽이 맨 앞에 약속된 글자 하나를 적습니다
  2. 읽는 쪽이 첫 바이트들을 보고 순서와 인코딩을 정합니다
  3. 그 글자를 떼어 내고 나머지를 본문으로 넘깁니다

글자를 한 바이트씩 이어 붙이는 인코딩에는 순서를 고를 일이 없어 보통 안 붙입니다. 두 바이트씩 묶어 적는 파일에만 필요합니다.

대가도 있습니다. 읽는 쪽이 3번을 빠뜨리면 이 글자가 본문 첫 글자로 남습니다. 눈에 안 보이는 글자라서 값이 왜 안 맞는지 화면만 봐서는 못 찾습니다.

상세

노래를 녹음할 때 맨 앞에 넣는 「하나, 둘, 셋, 넷」 박자 세기를 떠올리면 가깝습니다. 뒤에 올 연주를 어떤 박자로 들어야 할지 알려 주는 소리가 연주와 같은 트랙에 함께 담깁니다. 편집하는 쪽이 그 앞부분을 잘라 내지 않으면 듣는 사람에게 곡의 첫머리로 들립니다.

바이트 순서 표시는 Unicode 문자 하나입니다. 유니코드는 글자마다 번호를 하나씩 매깁니다. 그 번호는 「U+」 뒤에 십육진수로 적습니다. 이 문자의 번호는 U+FEFF 입니다.

화면에는 아무것도 그리지 않습니다. 영어로는 BOM(Byte Order Mark)이라고 줄여 부릅니다. 보통 글자와 달리 본문에 담을 내용이 아니라 읽는 쪽에 주는 신호입니다. 이 신호는 파일 밖에 따로 붙는 꼬리표가 아니라 본문 바이트에 섞여 들어갑니다. 이 문자를 텍스트 맨 앞에 하나 적어 두기로 한 약속이 바이트 순서 표시입니다.

두 바이트를 늘어놓는 순서

문자 인코딩 가운데는 문자 하나를 두 바이트로 적는 것이 있습니다. UTF-16(Unicode Transformation Format 16-bit, 유니코드 변환 형식 16비트)이 그렇습니다.

두 바이트를 늘어놓을 때 큰 쪽 바이트를 먼저 적는 기계가 있습니다. 작은 쪽을 먼저 적는 기계도 있습니다. 이 차이를 엔디언이라고 부릅니다.

파일 안에는 그 순서가 적혀 있지 않습니다. 그래서 파일만 건네받은 쪽은 두 바이트를 어떻게 묶어 읽어야 하는지 알 수 없습니다. 거꾸로 읽으면 글자마다 전혀 다른 번호가 나와 화면이 깨집니다.

맨 앞에 U+FEFF 하나를 적어 두면 그 문제가 풀립니다. 「hi」 두 글자를 담은 파일로 보겠습니다.

h 의 번호는 십육진수로 68(U+0068), i 는 69 입니다. 두 바이트로 적으면 빈 바이트 00 이 하나씩 딸려 붙습니다. 그 네 바이트가 순서에 따라 이렇게 갈립니다. 아래 표의 바이트 값도 모두 십육진수입니다.

적은 방법 앞 두 바이트 그 뒤
UTF-16 · 큰 쪽부터 FE FF 00 68 00 69
UTF-16 · 작은 쪽부터 FF FE 68 00 69 00

읽는 쪽은 앞 두 바이트가 FE FF 인지 FF FE 인지만 보면 나머지를 어떻게 묶을지 알아냅니다. 이 문자가 표시로 뽑힌 까닭은 뒤집은 번호인 U+FFFE 가 어떤 문자에도 배정되지 않기 때문입니다. 뒤집힌 표시를 본문 글자로 착각할 일이 없습니다.

UTF-8 에서 맡는 다른 역할

UTF-8(Unicode Transformation Format 8-bit, 유니코드 변환 형식 8비트)은 한 바이트씩 이어 붙이는 인코딩이라 순서를 고를 일이 없습니다. 그런데도 같은 문자를 UTF-8 로 적어 맨 앞에 붙이는 일이 있습니다. 세 바이트 EF BB BF 가 그것입니다.

이때 이 표시가 하는 일은 순서 알림이 아닙니다. 「이 파일은 UTF-8 이다」라는 꼬리표입니다. 인코딩을 따로 알려 줄 방법이 없을 때, 읽는 쪽은 짐작하는 대신 이 세 바이트를 봅니다.

이름은 바이트 순서 표시 그대로입니다. 하는 일만 다릅니다.

UTF-8 에는 이 표시를 붙이지 않는 쪽이 기본입니다. 순서 문제가 없어 얻는 것이 적습니다. 게다가 읽는 쪽이 이 세 바이트를 모르면 본문 첫 글자에 그대로 섞입니다.

읽는 쪽이 거치는 단계

읽는 쪽이 파일을 열면 갈림길을 둘 지납니다. 맨 앞에 표시가 있나가 첫째입니다. 그 표시를 떼어 냈나가 둘째입니다. 아래 그림이 그 둘을 따라갑니다.

flowchart TD
    A["파일을 연다"] --> B{"맨 앞에 표시가 있나"}
    B -->|있다| C["표시가 가리키는 대로 읽는다"]
    B -->|없다| D["인코딩을 짐작한다"]
    C --> E{"표시를 떼어 냈나"}
    E -->|떼었다| F["본문만 넘어간다"]
    E -->|안 떼었다| G["본문 첫 글자로 남는다"]

떼지 않았을 때 생기는 고장

이 문자는 폭이 없어서 화면에 흔적을 안 남깁니다. 첫 글자로 남아도 눈으로는 못 찾습니다. 그래서 문제는 사람 눈이 아니라 글자를 세거나 맞춰 보는 쪽에서 먼저 드러납니다.

  • 설정 파일의 첫 키 이름이 한 글자 길어져 못 알아봅니다
  • 두 문자열을 견주면 눈에는 똑같은데 다르다고 나옵니다
  • 셸 스크립트 첫 줄의 #! 앞에 세 바이트가 끼면 실행기가 그 줄을 못 알아봅니다
  • 표 형식 데이터의 첫 열 이름이 안 맞아 그 열을 못 찾습니다
  • 맨 앞 글자부터 숫자로 읽으려던 변환이 첫 글자에서 멈춥니다

그래서 텍스트를 받아 다루는 쪽은 첫 글자가 U+FEFF 인지 먼저 보고 떼어 냅니다.

맨 앞이 아닌 대목에 나온 같은 문자는 예전에 낱말이 갈라지지 않게 붙들어 두는 용도로도 쓰였습니다. 지금은 그 용도로 U+2060 을 따로 둡니다. U+FEFF 는 맨 앞의 표시로만 씁니다. 그래서 글 한가운데에서 이 문자를 만나면 대개 편집기나 복사 과정에서 섞여 들어온 것입니다.

형식마다 미리 정해 둔 규칙

기계끼리 주고받는 형식은 이 표시를 어떻게 다룰지 미리 정해 둡니다. JSON(JavaScript Object Notation, 자바스크립트 객체 표기법) 텍스트를 네트워크로 보낼 때는 이 표시를 붙이지 않습니다. 읽는 쪽은 앞에 붙어 있어도 오류로 보지 않고 무시해도 됩니다.

XML(Extensible Markup Language, 확장 가능 마크업 언어)은 반대로 이 표시를 인코딩을 밝히는 데 씁니다. 밝히는 길은 둘입니다. 이 표시를 붙이거나, 인코딩 선언(파일 첫 줄에 어떤 인코딩으로 적었는지 글로 적어 두는 것)을 적거나입니다. 둘 다 없으면 UTF-8 로 적힌 것으로 봅니다.

붙일 때와 붙이지 않을 때

파일을 새로 만들 때 이 표시를 붙일지는 인코딩과 쓰임새로 갈립니다. 읽을 때의 처신은 맨 아래 줄입니다.

이런 파일이면 붙이나
UTF-16 으로 주고받는 파일 붙입니다. 순서를 알릴 다른 방법이 없습니다
UTF-8 로 적는 보통 텍스트 안 붙입니다. 얻는 것이 없고 새어 들어갈 위험만 남습니다
기계가 파싱하는 교환 형식 그 형식이 정한 대로 따릅니다
남이 만든 파일을 읽을 때 붙어 있다고 보고 떼어 낼 준비를 합니다

관련 항목

이 표시를 쓰는 문자 인코딩

Unicode · UTF-8 · UTF-16 · UTF-32 · 문자 인코딩 · ASCII

바이트를 늘어놓는 순서를 다루는 개념

엔디언 · 네트워크 바이트 순서 · 직렬화 · 바이트 · 십육진수

글자를 번호로 다루는 유니코드 개념

코드 포인트 · 코드 유닛 · 대리 쌍 · 유니코드 정규화 · 폭 없는 문자

맨 앞 몇 바이트로 정체를 알리는 다른 표시

매직 넘버 · 파일 시그니처 · 헤더 · 미디어 타입 · Content-Type charset

이 표시를 다루는 방법을 정해 둔 텍스트 형식

JSON · XML · HTML · CSV · 텍스트 파일

표시를 못 떼서 나는 문제

모지바케 · 대체 문자 · 인코딩 추측 · 보이지 않는 문자 · 인코딩 불일치

다른 이름: BOM · Byte Order Mark · 바이트 순서 마크