사전 비트
개념

비트

gabury1고친 사람 github-actions[bot]

비트는 컴퓨터가 정보를 담고 나르는 가장 작은 단위입니다. 한 비트는 두 가지 중 어느 쪽인지를 하나 가려 줍니다. 그 두 가지를 0 과 1 로 적습니다. 컴퓨터 안의 모든 데이터는 비트를 여러 개 나란히 놓은 것입니다.

쉽고 빠른 이해

비트는 두 가지 중 어느 쪽인지를 하나 가려 주는 단위입니다. 전등이 켜졌는지 꺼졌는지를 적어 둔 쪽지 한 장이라고 보면 됩니다.

회로 속 전압은 늘 조금씩 흔들립니다. 두 상태만 가르면 웬만큼 흔들려도 어느 쪽인지 틀리지 않습니다. 그래서 모든 값을 두 상태의 나열로 바꿔 놓고 다룹니다.

쓰는 순서는 셋입니다.

  1. 담고 싶은 것을 예·아니오 물음 여러 개로 쪼갭니다
  2. 물음 하나를 비트 하나에 0 또는 1 로 적습니다
  3. 비트를 정해진 개수만큼 한 줄로 놓고 한 값으로 읽습니다

대가는 값 하나를 적는 데 비트가 여러 개 든다는 것입니다. 비트 여덟 개로 가릴 수 있는 것은 256 가지뿐입니다. 더 넓은 값을 담으려면 비트를 더 써야 합니다.

상세

스무고개는 예와 아니오로만 답합니다. 물음 하나에 답이 하나씩 쌓입니다. 답이 스무 개쯤 모이면 처음에 아무도 몰랐던 하나가 정해집니다. 비트는 그렇게 쌓이는 답 한 개입니다.

비트는 0 또는 1 중 하나를 담는 가장 작은 단위입니다. 참과 거짓을 담는 불리언 값 하나를 비트 하나로 담을 수 있습니다. 파일 소유자에게 쓰기 권한이 있는지 없는지를 적는 표시도 비트 하나입니다. 아래 예시의 S_IWUSR 가 그 비트입니다.

이름은 binary digit 을 줄인 것입니다. 0 과 1 두 숫자만 쓰는 자릿수 하나라는 뜻입니다. 릴레이나 플립플롭 회로처럼 안정된 상태가 둘인 장치 하나가 비트 하나를 담습니다.

비트를 나란히 놓아 만드는 수

비트 하나는 두 가지만 가립니다. 두 개를 나란히 놓으면 00 · 01 · 10 · 11 네 가지가 됩니다. 하나 늘 때마다 가짓수가 두 배가 됩니다.

flowchart TD
    S["비트 0 개"] --> A0["0"]
    S --> A1["1"]
    A0 --> B00["00"]
    A0 --> B01["01"]
    A1 --> B10["10"]
    A1 --> B11["11"]
    B00 --> C000["000"]
    B00 --> C001["001"]
    B01 --> C010["010"]
    B01 --> C011["011"]
    B10 --> C100["100"]
    B10 --> C101["101"]
    B11 --> C110["110"]
    B11 --> C111["111"]

그림은 비트 셋까지 펼친 것입니다. 맨 위 뿌리는 비트가 0 개일 때입니다. 한 단계 내려갈 때마다 비트가 하나 늘어납니다. 갈래도 둘씩 붙습니다. 비트가 셋인 맨 아래 단계에서 여덟 가지가 됩니다. 비트 N 개는 2 의 N 제곱 가지를 가립니다. 여덟 개면 256 가지입니다.

앞에서 말한 자릿수마다 값이 하나씩 정해져 있습니다. 그 값을 자릿값이라고 합니다. 오른쪽 끝 자릿값이 1 입니다. 왼쪽으로 갈수록 두 배씩 커집니다. 1 인 자릿수의 자릿값만 모두 더하면 그 수가 나옵니다.

여덟 비트로 적은 177 을 네 비트씩 두 덩이로 나눠 봅니다. 먼저 자릿값이 큰 위 네 비트입니다.

block-beta
columns 5
  z1["자릿값"] a["128"] b["64"] c["32"] d["16"]
  y1["비트"] e["1"] f["0"] g["1"] h["1"]

윗줄이 자릿값입니다. 아랫줄이 실제 비트입니다. 1 인 자릿수의 자릿값은 128 · 32 · 16 입니다. 이어서 아래 네 비트입니다.

block-beta
columns 5
  z2["자릿값"] i["8"] j["4"] k["2"] l["1"]
  y2["비트"] m["0"] n["0"] o["0"] p["1"]

여기서 1 인 자릿수의 자릿값은 1 하나입니다. 두 덩이를 합쳐 128 + 32 + 16 + 1 을 더하면 177 입니다. 이렇게 여덟 개를 한 묶음으로 다루는 것이 바이트입니다.

비트 자리와 그 번호

비트 하나가 놓인 자릿수를 비트 자리라고 부릅니다. 한 수 안에서는 비트 자리마다 오른쪽 끝부터 0 번 · 1 번 하고 번호를 붙입니다. 앞의 177 에서 1 인 비트 자리는 7 번 · 5 번 · 4 번 · 0 번입니다.

번호가 있어야 "몇 번째 비트가 1 이냐"를 말로 주고받을 수 있습니다. 자릿값이 가장 큰 왼쪽 끝은 최상위 비트, 가장 작은 오른쪽 끝은 최하위 비트라고 부릅니다.

비트 자리를 골라 읽거나 바꾸는 계산을 비트 연산이라고 합니다. 값을 한 덩이로 다루는 사칙연산과 달리 비트 자리 하나하나를 건드립니다. 자주 쓰는 것은 둘입니다.

하나는 시프트입니다. 비트를 통째로 옆으로 밀어 비트 자리를 옮기는 연산입니다.

다른 하나는 비트 마스크입니다. 보고 싶은 비트 자리만 남기고 나머지를 지우는 연산입니다.

두 연산을 앞의 수 177 에 걸어 봅니다. 0b 는 이 수를 이진수로 적었다는 표시입니다. 밑줄은 눈으로 끊어 읽으라고 넣은 것입니다. >> 가 시프트, & 가 비트 마스크입니다.

x = 0b1011_0001      // 177 (십진)
x >> 4               // 1011 · 십진 11
x & 0b0000_1111      // 0001 · 십진 1

오른쪽으로 네 칸 밀면 아래 네 비트가 밀려 나갑니다. 위 네 비트만 남습니다. 네 비트씩 두 덩이로 끊어 연산 앞뒤를 맞대어 보면 이렇습니다.

block-beta
columns 3
  r0["x"] r1["1011"] r2["0001"]
  s0["x >> 4"] s1["0000"] s2["1011"]

비트 마스크는 같은 비트 자리끼리 짝지어 양쪽 모두 1 인 곳만 1 로 남깁니다. 둘 다 1 인 곳만 1 로 남기는 이 연산을 AND 라고 부릅니다. 위 네 비트 자리는 0 과 만나 지워집니다. 시프트와 반대로 아래 네 비트가 남습니다.

block-beta
columns 3
  t0["x"] t1["1011"] t2["0001"]
  u0["마스크"] u1["0000"] u2["1111"]
  v0["결과"] v1["0000"] v2["0001"]

시프트와 비트 마스크는 한 바이트 안에 서로 다른 값 둘을 나눠 담아 두고 꺼낼 때 씁니다.

배경

전압으로 값을 담는 회로를 생각해 봅니다. 전압을 열 단계로 쪼개 한 단계를 숫자 하나로 읽으면 한 칸에 열 가지를 담을 수 있습니다. 그런데 전압은 주변 온도가 오르거나 선이 길어지면 조금씩 흔들립니다. 단계 사이가 좁을수록 그 흔들림 하나에 값이 옆 단계로 넘어갑니다.

단계를 둘만 두면 사이가 가장 넓어집니다. 어지간히 흔들려도 어느 쪽인지 틀리지 않습니다. 그래서 값을 몇 번 옮겨 적어도 처음 값이 남습니다. 대가는 표현력입니다. 한 칸이 두 가지만 가리므로 큰 값은 칸 여러 개를 줄지어 적습니다.

두 상태짜리 칸을 고른 쪽이 값을 잃지 않으므로 컴퓨터 안의 값은 전부 그 칸의 나열로 다룹니다. 그 한 칸이 이진 숫자 한 자릿수입니다. 그것을 줄여 비트라고 부릅니다.

예시

앞 셋은 비트 하나, 또는 비트 몇 개에 뜻을 정해 값 안에 박아 둔 실물입니다. 운영체제의 파일 권한, 네트워크의 헤더, 네트워크의 주소에서 하나씩 봅니다. 넷째는 성격이 다릅니다. 값 안에 박힌 비트가 아니라 비트를 세어 적는 단위 기호를 봅니다.

파일 권한 비트

POSIX(Portable Operating System Interface) 운영체제는 파일마다 모드 값 st_mode 를 둡니다. 누가 읽고 쓰고 실행할 수 있는지가 이 값 안의 비트 하나씩입니다. 헤더 <sys/stat.h> 가 그 비트들을 상수로 정해 둡니다.

상수 8진 값 2진 (아홉 비트) 뜻
S_IRUSR 0400 100 000 000 소유자 읽기
S_IWUSR 0200 010 000 000 소유자 쓰기
S_IXUSR 0100 001 000 000 소유자 실행·탐색
S_IRWXU 0700 111 000 000 소유자 읽기·쓰기·실행·탐색
S_IRGRP 040 000 100 000 그룹 읽기
S_IROTH 04 000 000 100 그 밖 사용자 읽기

「실행·탐색」은 원문 execute/search 를 옮긴 것입니다. 비트 하나에 뜻이 둘 붙은 것이 아닙니다. 같은 비트를 보통 파일에서는 실행 권한으로 읽습니다. 디렉터리에서는 탐색 권한으로 읽습니다.

값은 C 언어의 8진 표기입니다. 0 으로 시작하는 수가 8진수입니다. 8진수는 한 자릿수가 0 부터 7 까지라 비트 셋으로 적힙니다. 8진 숫자 하나가 소유자 · 그룹 · 그 밖 사용자 중 한쪽의 비트 셋과 맞아떨어집니다.

상수는 하나씩 쓰거나 OR 로 합쳐서 open() 의 셋째 인자로 넘길 수 있습니다. OR 는 같은 비트 자리끼리 짝지어 어느 한쪽이라도 1 이면 1 을 남기는 비트 연산입니다. 0400 · 0200 · 0100 을 OR 로 합치면 0700, 곧 S_IRWXU 입니다.

TCP 헤더의 제어 비트

TCP(Transmission Control Protocol) 헤더에는 비트 하나짜리 칸이 줄지어 있습니다. 아래는 헤더에서 32 비트 한 줄을 16 비트씩 끊어 그린 것입니다. 칸 하나가 비트 자리 하나입니다.

번호를 세는 방향은 그림마다 다릅니다. 여기서는 이 32 비트 한 줄의 맨 앞 비트가 0 번입니다. 오른쪽으로 갈수록 번호가 커집니다. 헤더 그림은 32 비트씩 줄을 바꿔 가며 줄마다 0 번부터 다시 셉니다. 한 수 안의 비트 자리를 오른쪽 끝부터 0 번으로 세는 앞 절의 규칙과는 반대입니다. 세는 대상이 한 수의 자릿수가 아니라 헤더에 늘어선 칸이기 때문입니다.

---
config:
  packet:
    bitsPerRow: 16
---
packet-beta
0-3: "데이터 오프셋"
4-7: "예약"
8: "CWR"
9: "ECE"
10: "URG"
11: "ACK"
12: "PSH"
13: "RST"
14: "SYN"
15: "FIN"
16-31: "윈도"

데이터 오프셋은 비트 넷짜리 칸입니다. TCP 헤더가 32 비트 단위로 몇 개인지를 적습니다. 그 값으로 데이터가 어디서 시작하는지 알 수 있습니다.

예약 칸 넷은 앞으로 쓸 제어 비트로 남겨 둔 것입니다. 그 기능을 아직 구현하지 않은 쪽은 내보내는 세그먼트에서 이 칸을 0 으로 채워야 합니다(Must). 받은 세그먼트에서는 이 칸을 무시해야 합니다(Must).

그 뒤 여덟 칸이 제어 비트입니다. 플래그라고도 부릅니다. 한 칸이 한 비트입니다. 칸마다 뜻이 하나입니다.

비트 뜻
SYN 순서 번호를 맞춥니다 (Synchronize sequence numbers)
ACK 확인 번호 칸이 유효합니다 (Acknowledgment field is significant)
RST 연결을 리셋합니다 (Reset the connection)
FIN 보내는 쪽에 더 보낼 데이터가 없습니다 (No more data from sender)

나머지 넷도 각각 비트 하나짜리 칸입니다. CWR(Congestion Window Reduced) · ECE(ECN-Echo, ECN 은 Explicit Congestion Notification) · URG(Urgent pointer field is significant) · PSH(Push function) 입니다.

맨 오른쪽 윈도 칸은 비트 하나짜리가 아닙니다. 16 비트를 한 값으로 쓰는 칸입니다. 이 절에서 볼 것은 그 앞의 비트 하나짜리 칸들입니다.

IPv4 주소와 프리픽스 길이

IPv4(Internet Protocol version 4) 주소는 길이가 옥텟 넷, 곧 32 비트로 고정돼 있습니다. 옥텟은 8 비트 한 묶음입니다.

CIDR(Classless Inter-Domain Routing) 표기는 주소 뒤에 / 와 0 부터 32 사이의 수를 붙입니다. 그 수가 프리픽스 길이입니다. 주소 맨 앞부터 몇 비트가 네트워크 번호인지를 셉니다.

192.168.99.0/24     최상위 24 비트가 네트워크 번호 · 블록 하나에 주소 256 개
172.16.0.0/16       마스크 255.255.0.0 · 블록 하나에 주소 65536 개

프리픽스 하나가 거느리는 주소 묶음을 블록이라고 부릅니다. /24 의 마스크는 최상위 24 비트가 1 이고 최하위 8 비트가 0 인 32 비트 값입니다. 이 마스크로 주소에서 네트워크 부분을 뽑아냅니다. 남는 8 비트가 가리는 가짓수가 256 이라 블록 하나에 주소가 256 개입니다.

위 둘째 보기의 마스크 255.255.0.0 에서 255 는 비트 여덟 개가 모두 1 인 옥텟입니다. 앞 두 옥텟이 1 로 채워져 최상위 16 비트가 네트워크 번호입니다. 남는 16 비트가 가리는 가짓수는 65536 입니다.

프리픽스 길이가 쓰이기 전에는 주소 맨 앞 비트 몇 개로 주소의 종류를 갈랐습니다. 그 종류에 class a · class b · class c 라는 이름을 붙였습니다. class a 는 최상위 비트가 0 인 주소였습니다. 그 다음 7 비트가 네트워크 번호였습니다.

단위 기호 bit 와 B

비트와 바이트는 단위 기호가 다릅니다. 비트는 bit, 바이트는 B 로 적습니다.

1 B      = 2^3 bit   = 8 bit
1 kbit   = 10^3 bit  = 1000 bit
1 Kibit  = 2^10 bit  = 1024 bit

k(킬로) 같은 국제단위계 접두어는 10 의 거듭제곱만 가리킵니다. 그래서 1 kbit 는 1000 비트입니다. 2 의 거듭제곱인 1024 를 가리키려면 Ki(키비) 같은 이진 접두어를 따로 씁니다.

통신 속도는 초당 비트 수, bit/s 로 셉니다. 근거리 네트워크 설계자 가운데는 megabit per second 를 1 048 576 bit/s 의 뜻으로 쓴 사람도 있었습니다. 통신 엔지니어는 모두 10^6 bit/s 의 뜻으로 씁니다. 그러니 Mbit/s 는 10^6 bit/s 로 읽으면 됩니다. 바이트로 적은 파일 크기와 견주려면 이 초당 비트 수를 8 로 나눕니다.

경계

저장 공간 1 비트에는 정보도 1 비트가 들어 있을까요? 늘 그렇지는 않습니다. 많아야 1 비트입니다. 두 값이 똑같이 그럴듯할 때만 꼭 1 비트입니다.

비트는 정보의 양을 재는 단위로도 씁니다. 결과가 여럿인 일에서 어느 결과가 나왔는지 알게 될 때 얻는 양을 잽니다. 결과가 둘이고 둘이 똑같이 그럴듯할 때 그 양이 1 비트입니다. 동전 한 번 던진 앞뒤가 그렇습니다.

이렇게 잰 정보의 양을 엔트로피라고 부릅니다. 기호로는 H 로 적습니다. 결과가 둘인 일에서 H 는 두 결과의 확률 p 와 1 − p 로 정해집니다. 로그의 밑을 2 로 잡으면 단위가 비트가 됩니다.

H = −( p · log₂ p  +  (1 − p) · log₂ (1 − p) )

p = 1/2   →  H = 1 비트      두 결과가 똑같이 그럴듯하다
p = 1     →  H = 0 비트      결과를 이미 안다

이 식을 p 를 0 에서 1 까지 옮겨 가며 그려 보면 이렇습니다.

xychart-beta
    x-axis "p" ["0", "0.1", "0.2", "0.3", "0.4", "0.5", "0.6", "0.7", "0.8", "0.9", "1"]
    y-axis "H (비트)" 0 --> 1
    line [0, 0.47, 0.72, 0.88, 0.97, 1, 0.97, 0.88, 0.72, 0.47, 0]

H 는 두 확률이 같을 때 가장 큽니다. 꼭대기가 1 비트입니다. 결과가 확실할 때만 0 입니다. 그 사이에서는 0 과 1 사이의 값입니다. 저장 공간 한 비트에 거의 늘 1 이 들어 있다면, 그 비트가 지고 있는 정보는 1 비트보다 적습니다.

가르는 선은 무엇을 재느냐입니다. 저장 공간의 비트는 그릇이 몇 자릿수냐를 셉니다. 정보량의 비트는 그 안에 든 내용의 양을 잽니다. 상태가 둘인 장치 N 개가 담는 정보는 N 비트를 넘지 못합니다. 값이 한쪽으로 쏠릴수록 그보다 적어집니다.

여담

binary digit 을 bit 로 줄여 부르자고 한 사람은 정보 이론을 세운 클로드 섀넌이 아니라 존 튜키(John W. Tukey)입니다. 섀넌은 1948 년 논문 「A Mathematical Theory of Communication」에서 정보량을 재는 로그의 밑을 2 로 잡으면 그 단위를 binary digits, 줄여서 bits 라 부를 수 있다고 적었습니다. 그리고 바로 그 문장에서 이 낱말을 J. W. Tukey 가 제안했다고 밝혔습니다. 같은 문단에는 밑을 10 으로 잡으면 decimal digits 라 부를 수 있다는 말도 있습니다. 미국 철학회 (American Philosophical Society)는 튜키가 1947 년에 쓴 벨 연구소 메모를 「bit」라는 낱말이 처음 쓰인 메모로 소장하고 있다고 소개합니다.

관련 항목

비트가 모여 이루는 크기 단위

바이트 · 니블 · 옥텟 · 워드 · 비트열 · 킬로바이트 · 키비바이트 · 이진 접두어 · 캐시 라인

비트 자리를 직접 다루는 연산

비트 연산 · 비트 마스크 · 시프트 · 마스킹 · 비트 필드 · 플래그 · 비트맵

비트를 사람이 읽는 표기로 바꾸는 방법

이진수 · 8진수 · 16진수 · 헥사 덤프 · base64 · 자릿값

비트를 늘어놓는 차례를 정하는 규칙

엔디언 · 비트 순서 · 최상위 비트 · 최하위 비트 · 네트워크 바이트 순서 · 정렬

비트 하나하나에 뜻을 정해 둔 필드

파일 권한 · st_mode · TCP 플래그 · TCP · 프리픽스 길이 · 서브넷 마스크 · CIDR · IPv4

비트가 뒤집혔는지 확인하는 수단

패리티 비트 · 체크섬 · 해밍 거리 · 오류 정정 부호 · 순환 중복 검사

비트 수로 값의 범위가 정해지는 자료형

정수 · 부동소수점 · 불리언 · 부호 비트 · 2의 보수 · 오버플로

전송 속도를 비트로 재는 지표

비트레이트 · 대역폭 · 처리량 · 보율 · 초당 비트

비트를 물리로 담거나 실어 나르는 장치

메모리 · 레지스터 · 디스크 · 플립플롭 · 릴레이 · 논리 게이트 · 트랜지스터 · 변조

정보의 양으로 비트를 세는 이론

엔트로피 · 정보량 · 압축 · 정보 이론 · 허프만 부호 · 무손실 압축

비트 단위를 실어 나르는 통신 계층

프레임 · 패킷 · 물리 계층 · 신호 · 직렬 통신

다른 이름: bit · binary digit · 이진 숫자