사전 옥텟
개념

옥텟

gabury1고친 사람 github-actions[bot]

옥텟은 비트 여덟 개를 하나로 묶어 세는 단위입니다. 네트워크 프로토콜은 데이터의 길이를 이 단위로 적습니다. 오늘날의 바이트와 크기가 같지만, 여덟이라는 수가 이름 자체에 박혀 있는 점이 다릅니다.

쉽고 빠른 이해

옥텟은 「여덟 비트」를 한 낱말로 가리키는 셈 단위입니다. 인터넷 주소 하나를 네 옥텟이라고 부르는 것이 그 예입니다.

이 낱말이 없으면 「바이트」라고만 적게 됩니다. 바이트는 원래 기계마다 몇 비트인지 달랐습니다. 서로 다른 기계가 같은 문서를 읽고 각자 구현해야 하는 프로토콜에서는 그 차이를 그냥 둘 수 없었습니다.

쓰는 방법은 이렇습니다.

  1. 데이터를 앞에서부터 여덟 비트씩 끊어 옥텟으로 만듭니다
  2. 길이와 위치를 옥텟 개수로 셉니다
  3. 옥텟 하나를 0에서 255 사이의 수로 읽고, 16진수 두 글자로 적습니다

대가는 이름이 하나 더 는다는 것입니다. 바이트가 여덟 비트로 굳은 지금은 두 낱말이 같은 크기를 가리켜서, 처음 보면 왜 이름이 둘인지 헷갈립니다. 갈라 쓰는 기준은 하나입니다. 내 코드 안에서는 바이트라고 써도 됩니다. 여러 구현이 읽는 문서에는 옥텟이라고 적습니다.

상세

연필 한 다스는 열두 자루입니다. 「다스」라고 말하면 듣는 쪽이 열둘을 떠올립니다. 옥텟도 그런 셈 단위입니다.

옥텟(octet)은 비트 여덟 개를 하나로 묶은 것입니다. 비트는 0 또는 1 하나를 담는 가장 작은 단위입니다. 비트가 여덟 개 모이면 0과 1의 조합이 256가지 나옵니다. 음수를 쓰지 않는 수로 읽으면 0부터 255까지를 담습니다. 이름은 여덟을 뜻하는 말에서 왔습니다. 서로 다른 기계가 같은 크기를 읽게 하려고 쓰는 이름입니다.

먼저 바이트와 이름이 갈린 까닭을 봅니다.

바이트와 이름이 갈린 까닭

바이트는 원래 「기계가 글자 하나를 담는 데 쓰는 비트 묶음」이라는 뜻이었습니다. 그 크기는 기계를 만든 쪽이 정했습니다. 초기 컴퓨터 중에는 한 바이트가 여섯 비트인 것도, 아홉 비트인 것도 있었습니다.

한 기계 안에서만 도는 프로그램에는 이것이 문제가 아니었습니다. 문서에 「한 바이트」라고 적으면 그 기계의 바이트를 뜻했기 때문입니다.

프로토콜은 사정이 달랐습니다. 프로토콜은 서로 다른 기계가 무엇을 어떤 순서로 주고받을지 정해 둔 약속입니다. 한쪽이 여섯 비트짜리 바이트를 쓰고 다른 쪽이 여덟 비트짜리를 쓰면, 「길이 두 바이트」라는 한 문장이 양쪽에서 다른 크기가 됩니다.

flowchart TD
    D1["문서에 적힌 말 · 길이 두 바이트"] --> M1["여섯 비트 기계 · 12비트"]
    D1 --> M2["여덟 비트 기계 · 16비트"]
    D2["문서에 적힌 말 · 길이 두 옥텟"] --> M3["어느 기계든 · 16비트"]

위쪽 한 문장은 읽는 기계에 따라 두 크기로 갈립니다. 아래쪽 한 문장은 안 갈립니다. 프로토콜 문서는 아래쪽 낱말을 골랐습니다. 옥텟이라고 적으면 읽는 쪽이 어떤 기계를 쓰든 여덟 비트입니다.

지금은 거의 모든 기계가 한 바이트를 여덟 비트로 씁니다. 실무에서 두 낱말은 같은 크기를 가리킵니다. 그런데도 프로토콜이 옥텟을 계속 쓰는 것은, 크기가 기계의 관례가 아니라 문서 자신에 적혀 있어야 하기 때문입니다.

옥텟 하나를 읽는 법

옥텟 하나는 0에서 255 사이의 수입니다. 이 범위는 16진수 두 글자에 딱 들어맞습니다. 16진수는 0부터 9까지와 a부터 f까지 열여섯 글자로 수를 적는 방법입니다. 한 글자가 비트 넷을 맡습니다. 그래서 두 글자가 한 옥텟입니다.

그 덕분에 글자가 아닌 바이너리 데이터도 두 글자씩 끊어 적으면 옥텟 하나씩 읽힙니다. c0 00 02 01 은 옥텟 넷입니다. 아래에서 계속 쓸 주소 192.0.2.1 을 그렇게 적은 것입니다.

비트 넷을 묶은 이 단위에도 이름이 있습니다. 니블입니다. 16진수 한 글자가 니블 하나입니다. 니블 둘이 옥텟 하나입니다.

flowchart TD
    subgraph O["옥텟 하나 · 8비트 · c0"]
        N1["앞 4비트 · 1100 · 16진수 c"]
        N2["뒤 4비트 · 0000 · 16진수 0"]
    end

긴 비트 나열도 여덟 비트마다 끊어 읽습니다. 아래는 그 주소를 옥텟 넷으로 끊은 것입니다. IPv4(Internet Protocol version 4, 인터넷 프로토콜 4판)는 인터넷에서 기계를 가리키는 주소 체계 중 먼저 나온 판입니다. 주소 하나는 32비트입니다.

여덟 비트를 수로 읽으면 11000000 은 192 입니다. 옥텟 넷을 각각 그렇게 읽습니다.

flowchart TD
    W["32비트 주소 · 11000000 00000000 00000010 00000001"]
    W --> O1["첫째 옥텟 · 11000000 · 192"]
    W --> O2["둘째 옥텟 · 00000000 · 0"]
    W --> O3["셋째 옥텟 · 00000010 · 2"]
    W --> O4["넷째 옥텟 · 00000001 · 1"]

그림에서 볼 것은 끊는 지점이 언제나 여덟 비트마다라는 점입니다. 옥텟마다 십진수로 바꿔 점으로 이으면 192.0.2.1 이라는 낯익은 표기가 됩니다.

코드로 끊을 때는 비트를 옆으로 밀어낸 뒤, 가장 작은 값을 맡는 아래쪽 여덟 비트만 남깁니다. 아래는 그 주소를 담은 수 하나에서 옥텟 둘을 꺼내는 파이썬 코드입니다.

Python
addr = 0xC0000201      # 192.0.2.1
(addr >> 24) & 0xFF    # 192 · 첫째 옥텟
addr & 0xFF            # 1 · 넷째 옥텟

>> 는 비트를 오른쪽으로 밀어내는 연산입니다. & 0xFF 는 아래 여덟 비트만 남기고 나머지를 0으로 지우는 연산입니다. 둘을 이어 쓰면 원하는 옥텟 하나만 남습니다.

옥텟을 늘어놓는 차례

한 옥텟에 안 들어가는 큰 수는 옥텟 여러 개에 나눠 담습니다. 그러면 큰 자릿수를 앞에 둘지 뒤에 둘지를 정해야 합니다. 이 선택이 엔디언입니다.

기계마다 이 선택이 다릅니다. 네트워크로 수를 내보내는 프로토콜은 큰 쪽을 먼저 보내기로 정해 두었습니다. 받는 쪽은 그것을 자기 기계의 순서로 되돌려 읽습니다.

이 순서의 이름이 네트워크 바이트 순서입니다. 이름은 바이트지만 여기서 말하는 바이트는 옥텟입니다. 이 이름이 굳었을 때 바이트는 이미 여덟 비트였습니다.

flowchart TD
    N["수 하나 · 0xC0000201"]
    N --> B
    N --> L
    subgraph B["큰 쪽 먼저 · 네트워크 바이트 순서"]
        B1["c0"] --> B2["00"] --> B3["02"] --> B4["01"]
    end
    subgraph L["작은 쪽 먼저"]
        L1["01"] --> L2["02"] --> L3["00"] --> L4["c0"]
    end

화살표는 먼저 나가는 옥텟에서 나중에 나가는 옥텟으로 읽습니다. 같은 수 하나가 어느 쪽을 고르느냐에 따라 정반대 차례로 나갑니다.

옥텟 안에서 비트를 어떤 차례로 내보내는지는 다른 이야기입니다. 그쪽은 케이블로 신호를 내보내는 링크 계층이 정합니다. 이 절이 말한 차례는 옥텟과 옥텟 사이의 것입니다.

옥텟 문자열

뜻을 붙이지 않고 옥텟을 그냥 늘어놓은 것은 옥텟 문자열입니다. 이름에 문자열이 들어가지만 글자가 아닙니다. 암호 키나 해시 결과처럼 사람이 읽을 뜻이 없는 조각을 가리킬 때 씁니다.

길이를 옥텟으로 재는 곳

헤더의 길이 필드가 대표입니다. 헤더는 패킷 앞에 붙어 그 패킷을 어떻게 다룰지 알려 주는 부분입니다. 패킷은 네트워크가 한 번에 나르는 데이터 묶음입니다.

필드는 헤더 안에서 한 가지 값을 맡는 칸입니다. 길이 필드는 대개 「이 뒤로 몇 옥텟이 더 있다」를 적습니다.

주소도 옥텟으로 셉니다. IPv4 주소는 네 옥텟입니다. IPv6(Internet Protocol version 6, 인터넷 프로토콜 6판) 주소는 열여섯 옥텟입니다. IPv6 는 주소가 모자라는 문제를 풀려고 나온 뒷판입니다.

한 번에 보낼 수 있는 크기도 옥텟으로 적습니다. MTU(Maximum Transmission Unit, 최대 전송 단위)는 한 구간이 쪼개지 않고 나를 수 있는 가장 큰 묶음입니다. 그 값은 옥텟 수로 말합니다.

글자도 옥텟으로 바뀌어 나갑니다. 문자 인코딩은 글자를 옥텟 나열로 옮기는 규칙입니다.

ASCII(American Standard Code for Information Interchange, 미국 정보 교환 표준 부호)는 글자 하나를 한 옥텟에 담습니다. UTF-8(Unicode Transformation Format, 8비트 단위의 유니코드 변환 형식)은 글자에 따라 한 옥텟에서 네 옥텟까지 씁니다. 이름 끝의 8 이 옥텟 하나를 기본 단위로 삼는다는 뜻입니다.

옥텟과 이웃한 단위

비트 묶음을 부르는 이름이 여럿입니다. 앞에서 본 니블은 비트 넷입니다. 워드는 기계가 한 번에 다루는 묶음입니다. 그 크기는 16비트·32비트·64비트처럼 기계가 정합니다.

이름 크기 크기가 고정인가
비트 1비트 고정
니블 4비트 고정
옥텟 8비트 고정
바이트 오늘날 8비트 기계가 정한다
워드 16 · 32 · 64비트 등 기계가 정한다

표에서 갈리는 축은 마지막 칸입니다. 크기가 문서에 적혀 있으면 고정입니다. 기계가 정하면 고정이 아닙니다.

옥텟이라고 쓰는 때

여러 기계가 같은 문서를 읽고 각자 구현해야 하면 옥텟이라고 적습니다. 프로토콜과 포맷 명세가 그런 문서입니다.

한 언어나 한 런타임 안에서만 도는 코드라면 바이트라고 써도 뜻이 갈리지 않습니다. 그 세계에서는 바이트가 이미 여덟 비트로 굳어 있기 때문입니다.

flowchart TD
    Q["여러 기계가 이 문서를 읽고 각자 구현하나"]
    Q -->|그렇다| A["옥텟이라고 적는다 · 프로토콜 · 포맷 명세"]
    Q -->|아니다| B["바이트라고 써도 된다 · 한 언어 · 한 런타임 안"]

읽을 때는 반대로 봅니다. 문서가 옥텟이라고 적었으면 여덟 비트로 읽으면 됩니다. 바이트라고 적었으면 그 문서가 어느 기계를 전제하는지 한 번 확인합니다.

관련 항목

옥텟을 이루거나 옥텟이 이루는 크기 단위

비트 · 바이트 · 니블 · 워드 · 비트열 · 옥텟 문자열

옥텟 여럿을 늘어놓는 차례를 정하는 규칙

엔디언 · 네트워크 바이트 순서 · 정렬 · 패딩 · 바이트 순서 표시

길이와 주소를 옥텟으로 재는 프로토콜

IP 주소 · IPv4 · IPv6 · MTU · 경로 MTU 탐색 · MSS · TCP · UDP

옥텟 묶음을 실어 나르는 메시지 부분

헤더 · 필드 · 페이로드 · 패킷 · 데이터그램 · 프레임 · 세그먼트

옥텟을 사람이 읽는 표기로 바꾸는 방법

16진수 · 헥사 덤프 · 점 십진 표기 · base64 · 비트 마스크

글자를 옥텟으로 옮기는 인코딩

문자 인코딩 · ASCII · UTF-8 · UTF-16 · 코드 유닛 · 코드 포인트

옥텟을 다루는 코드가 쓰는 연산

비트 연산 · 시프트 연산 · 바이너리 · 직렬화 · 바이트 배열

다른 이름: octet · 옥텟열 · octet string