Chapter 02

0과 1로 모든 것을

컴퓨터 안에는 글자도, 사진도, 노래도 없다. 오직 켜짐과 꺼짐, 즉 1과 0만 있다. 그런데 어떻게 카톡 메시지와 셀카와 음악이 그 안에 들어 있을까? 이 장에서는 세상의 모든 것을 0과 1로 바꾸는 약속들을 직접 스위치를 켜고 끄며 배운다.

왜 하필 0과 1일까

컴퓨터 속 정보는 결국 전선에 흐르는 전압이다. 전압이 높으면 1, 낮으면 0으로 읽는다. 그런데 왜 0부터 9까지 열 단계로 나눠 우리에게 익숙한 10진수를 쓰지 않았을까?

이유는 잡음이다. 실제 전압은 온도, 주변 전선의 간섭, 부품의 미세한 차이 때문에 늘 조금씩 흔들린다. 0~1 V 사이를 10칸으로 나누면 한 칸이 0.1 V뿐이라서, 조금만 흔들려도 3이 4로 잘못 읽힌다. 두 칸으로만 나누면 “대충 높은가, 낮은가”만 보면 되니 웬만큼 흔들려도 틀리지 않는다.

SIMULATOR

잡음 속에서 신호 읽기: 2단계 vs 10단계

전압을 몇 단계로 나눌까?
보낸 값 개수—
잘못 읽은 값—
오류율—
해볼 것: 잡음을 0.08 정도로 두고 2단계와 10단계를 비교해 보자. 같은 잡음인데 10단계는 오류가 쏟아진다. 회색 점선은 “이 위면 다음 값으로 읽는다”는 경계선이다.

이렇게 정보를 두 가지 상태로만 나타내는 최소 단위를 비트(bit, binary digit)라고 한다. 비트 하나는 “예/아니오”, “켜짐/꺼짐” 한 가지를 담는다. 정보가 더 필요하면 비트를 여러 개 늘어놓으면 된다.

전등 스위치 줄

방에 전등 스위치가 8개 나란히 있다고 하자. 각 스위치는 켜짐/꺼짐 둘뿐이지만 8개를 조합하면 2×2×…×2 = 2⁸ = 256가지 상태를 만들 수 있다. 친구와 “켜진 패턴마다 뜻을 정하자”고 약속하면 256가지 메시지를 주고받을 수 있다. 컴퓨터가 하는 일이 정확히 이것이다. 모든 것은 패턴과 약속이다.

2진수: 자리마다 두 배

우리가 쓰는 10진수에서 352는 3×100 + 5×10 + 2×1이다. 자리가 하나 왼쪽으로 갈 때마다 값이 10배가 된다. 2진수도 똑같은데, 자리마다 2배가 된다. 오른쪽부터 1, 2, 4, 8, 16, 32, 64, 128이다.

아래 8개의 스위치(비트)를 눌러 켜고 꺼 보자. 켜진 자리의 값을 모두 더하면 10진수가 된다. 8비트를 묶은 단위를 바이트(byte)라고 하며, 0부터 255까지 256가지 값을 나타낼 수 있다.

SIMULATOR

8비트 스위치 보드

0켜진 스위치가 없다
미션: 이 숫자를 만들어 보세요 →13
2진수00000000
10진수0
16진수0x00
해볼 것: 모든 스위치를 켜면 얼마일까? 맨 오른쪽 스위치(1의 자리)가 켜져 있으면 숫자는 항상 홀수다. 왜 그럴까?

10진수를 2진수로 바꾸기

반대 방향은 “큰 자리부터 채우기”로 하면 쉽다. 예를 들어 13을 바꿔 보자. 13 안에 8이 들어가니 8 자리를 켜고 나머지 5. 5 안에 4가 들어가니 4 자리를 켜고 나머지 1. 2는 안 들어가니 끄고, 1 자리를 켜면 끝. 결과는 1101이다. 돈을 큰 지폐부터 거슬러 주는 것과 같은 방식이다.

16진수: 사람을 위한 줄임말

2진수는 컴퓨터에게는 자연스럽지만 사람이 읽기엔 너무 길다. 11010110을 소리 내 읽어 보면 금방 헷갈린다. 그래서 프로그래머는 2진수 4자리를 한 글자로 줄인 16진수(hexadecimal)를 쓴다. 0~9 다음에 A(10), B(11), C(12), D(13), E(14), F(15)를 쓴다.

2진수 4자리10진수16진수2진수 4자리10진수16진수

그래서 1바이트(8비트)는 16진수 딱 두 글자가 된다. 1101 0110 → D6. 앞으로 메모리 주소나 색상 코드에서 0x3F, #FF8800 같은 표기를 보면 “16진수구나” 하면 된다(0x와 #는 16진수라는 표시다).

글자를 숫자로: ASCII와 유니코드

컴퓨터에게 글자 ‘A’를 저장하라고 하면 무엇을 저장할까? 답은 약속된 번호다. 1960년대 미국에서 영어 알파벳, 숫자, 기호에 0~127번을 붙인 약속을 정했는데 이를 ASCII(아스키)라 한다. ‘A’는 65번, ‘a’는 97번, 숫자 ‘0’은 48번이다.

하지만 128칸으로는 한글, 한자, 아랍 문자, 이모지를 담을 수 없다. 그래서 전 세계 모든 문자에 고유 번호를 붙인 유니코드(Unicode)가 만들어졌다. ‘가’는 44032번(16진수 AC00), ‘😀’는 128512번이다. 유니코드 번호를 실제 바이트로 저장하는 방법 중 가장 널리 쓰이는 것이 UTF-8이다. 영어는 1바이트, 한글은 3바이트, 이모지는 4바이트를 쓴다.

SIMULATOR

글자 → 바이트 변환기 (UTF-8)

글자 수—
바이트 수—
비트 수—
해볼 것: 대문자 A와 소문자 a의 번호 차이는 32다. 2진수로 보면 딱 한 비트만 다르다. 한글 한 글자가 왜 3바이트인지도 확인해 보자.
글자가 깨지는 이유

옛날 문서를 열었을 때 “문잔 같은 이상한 글자가 보이는 경험이 있을 것이다. 저장할 때 쓴 약속(예: UTF-8)과 읽을 때 쓴 약속(예: 다른 인코딩)이 달라서, 같은 바이트를 다른 글자로 해석했기 때문이다. 바이트는 그대로인데 해석하는 약속이 어긋난 것이다.

색과 사진을 숫자로

화면을 돋보기로 아주 가까이 들여다보면 빨강(R), 초록(G), 파랑(B) 세 가지 작은 빛이 보인다. 세 빛의 세기를 조절해 섞으면 거의 모든 색을 만들 수 있다. 컴퓨터는 각 빛의 세기를 0~255(1바이트)로 저장한다. 그래서 색 하나는 3바이트, 즉 24비트이고 약 1677만 가지 색을 표현한다.

SIMULATOR

RGB 색 섞기

#FF8800
해볼 것: 세 값을 모두 255로 하면 흰색, 모두 0이면 검정이 된다. 물감은 섞을수록 어두워지지만 빛은 섞을수록 밝아진다. 빨강과 초록 빛을 섞으면 무슨 색일까?

사진은 이런 색 점을 바둑판처럼 촘촘히 늘어놓은 것이다. 점 하나를 픽셀(pixel, picture element)이라 한다. 1200만 화소 카메라는 가로 4000 × 세로 3000개의 픽셀을 저장하고, 각 픽셀이 3바이트이므로 압축하기 전 사진 한 장은 약 36 MB다. 아래 그림을 확대해 보면 사진의 정체가 숫자 표라는 것이 보인다.

SIMULATOR

그림 확대: 사진은 숫자 표다

픽셀 수—
필요한 저장 공간—
해볼 것: 해상도를 낮추면 계단 모양이 보인다. 해상도를 두 배로 올리면 저장 공간은 몇 배가 될까? (가로와 세로가 함께 늘어난다!)
압축

실제 사진 파일(JPEG)은 36 MB가 아니라 3~5 MB 정도다. 하늘처럼 비슷한 색이 이어지는 부분을 “이 색이 100칸 계속”처럼 요약하고, 사람 눈이 잘 못 느끼는 미세한 차이를 버려서 크기를 줄이기 때문이다. 동영상은 앞 장면과 달라진 부분만 저장해서 더 크게 줄인다.

소리를 숫자로

소리는 공기의 떨림이고, 마이크는 그 떨림을 매끄럽게 오르내리는 전압으로 바꾼다. 컴퓨터는 이 곡선을 아주 짧은 간격으로 재서(샘플링) 그 높이를 숫자로 적어 둔다. 1초에 몇 번 재는지를 샘플링 주파수, 높이를 몇 단계로 적는지를 비트 깊이라고 한다. CD 음질은 1초에 44,100번, 높이는 16비트(65,536단계)로 적는다.

SIMULATOR

샘플링과 양자화

회색 곡선은 원래 소리, 색 계단선은 숫자로 저장된 소리다. 해볼 것: 샘플링을 아주 듬성듬성 하거나 비트를 1~2로 줄이면 원래 소리와 얼마나 달라질까? 둘 다 늘리면 정확해지는 대신 숫자(용량)가 많아진다.

얼마나 큰가: 바이트의 단위

데이터의 크기는 바이트로 잰다. 1,000배씩 커질 때마다 이름이 바뀐다(엄밀히는 1,024배로 세기도 하지만 감각을 잡는 데는 1,000배로 충분하다).

1 B영어 글자 1개
1 KB천 바이트 · 짧은 문자 메시지 몇 통
1 MB백만 바이트 · 사진 한 장의 3분의 1, 3분짜리 노래 4분의 1
1 GB10억 바이트 · 고화질 영화 몇 분의 1편
1 TB1조 바이트 · 사진 약 30만 장
비트(b)와 바이트(B)를 헷갈리지 말자

인터넷 속도는 보통 비트 단위로 말한다. “1 Gbps 인터넷”은 1초에 10억 비트, 즉 약 125 MB를 보낸다는 뜻이다. 그래서 1 GB 파일은 이론상 8초 걸린다. 소문자 b는 비트, 대문자 B는 바이트다.

숫자가 넘치면: 오버플로

8비트로는 255까지밖에 못 센다. 255(11111111)에 1을 더하면 어떻게 될까? 자리올림이 9번째 자리로 넘어가는데 그 자리가 없으니 버려지고, 남는 것은 00000000, 즉 0이다. 옛날 자동차 주행거리계가 99999 km 다음에 00000으로 돌아가는 것과 같다. 이를 오버플로(overflow)라 한다.

실제로 이런 일이 문제를 일으킨 적이 많다. 1990년대 게임에서 점수가 일정 값을 넘으면 0이나 음수가 되는 버그가 유명하고, 2038년에는 1970년부터 초를 32비트로 세는 일부 오래된 시스템의 시계가 넘쳐 버리는 “2038년 문제”가 예정되어 있다. 그래서 요즘 컴퓨터는 숫자 하나에 보통 64비트(약 1844경까지)를 쓴다.

음수는 어떻게 저장할까?

8비트에서 맨 앞 비트를 “음수 표시”로 쓰기로 약속하면 −128~127을 나타낼 수 있다. 실제 컴퓨터는 2의 보수라는 영리한 방법을 써서, −1을 11111111로 적는다. 이렇게 하면 −1 + 1을 그냥 2진수 덧셈으로 해도 자리올림이 버려지며 정확히 0이 나온다. 뺄셈을 따로 만들 필요 없이 덧셈 회로 하나로 해결된다.

핵심 정리

  1. 컴퓨터는 잡음에 강하도록 전압을 높음(1)/낮음(0) 두 단계로만 읽는다. 이 최소 단위가 비트다.
  2. 2진수는 자리마다 2배(1, 2, 4, 8, …)가 된다. 8비트 = 1바이트 = 0~255.
  3. 16진수는 2진수 4자리를 한 글자로 줄인 표기다. 1바이트 = 16진수 두 글자.
  4. 글자는 약속된 번호(ASCII, 유니코드)로, 색은 RGB 세 숫자로, 사진은 픽셀 숫자의 표로, 소리는 일정 간격으로 잰 높이의 목록으로 저장된다.
  5. 모든 데이터는 패턴과 약속이다. 같은 바이트라도 어떤 약속으로 해석하느냐에 따라 글자도, 색도, 명령어도 된다.
  6. 정해진 비트 수를 넘으면 숫자가 넘쳐(오버플로) 0으로 돌아간다.

확인 퀴즈

2진수 1010은 10진수로 얼마인가?

8 + 0 + 2 + 0 = 10. 오른쪽부터 1, 2, 4, 8 자리다.

컴퓨터가 10진수 대신 2진수를 쓰는 가장 큰 이유는?

두 단계 사이의 간격이 넓으면 전압이 흔들려도 0과 1을 혼동하지 않는다. 오히려 2진수는 같은 수를 나타내는 데 자리가 더 많이 필요하다.

색상 코드 #00FF00은 어떤 색일까?

R=00(0), G=FF(255), B=00(0). 초록 빛만 최대로 켠 색이다.

UTF-8에서 “한글”이라는 두 글자는 몇 바이트일까?

UTF-8에서 한글 한 글자는 3바이트이므로 두 글자는 6바이트다. 위 변환기에서 직접 확인해 보자.

8비트 숫자 255에 1을 더하면 어떻게 되는가?

9번째 자리로 넘어간 자리올림은 저장할 곳이 없어 버려진다. 주행거리계가 99999 다음 00000이 되는 것과 같다.

“500 Mbps 인터넷”으로 1 GB 파일을 받는 데 이론상 걸리는 시간은?

500 Mbps = 초당 5억 비트 = 초당 62.5 MB. 1 GB(1000 MB) ÷ 62.5 = 16초. b(비트)와 B(바이트)는 8배 차이다.