이번 문서의 목표: 이 문서를 다 읽으면 문자가 왜 숫자 코드로 저장되는지 설명하고, 주어진 비트열에 짝수·홀수 패리티 비트를 직접 계산해 붙이고, 해밍 코드의 코드워드 개념을 읽을 수 있다.
왜 문자도 숫자로 바꿔야 하는가
01편에서 배웠듯 컴퓨터는 0과 1만 저장하고 처리할 수 있다. 그런데 우리는 컴퓨터에 문자(‘A’, ‘가’, ’!’)를 입력하고 화면에 문자로 출력받는다. 이것이 가능한 이유는, 컴퓨터가 문자를 저장할 때 각 문자에 미리 정해진 고유한 숫자(코드)를 대응시켜 그 숫자를 2진수로 저장하기 때문이다. 화면에 문자를 표시할 때는 반대로 그 숫자를 다시 정해진 문자 모양(글꼴)으로 그려서 보여준다.
이렇게 “어떤 문자에 어떤 숫자를 대응시킬지” 정해 놓은 약속을 문자 인코딩(character encoding, 문자 부호화)이라고 한다. 전 세계가 이 약속을 통일하지 않으면, 한 컴퓨터에서 저장한 문서를 다른 컴퓨터가 열었을 때 완전히 다른 문자(깨진 글자, 흔히 “인코딩이 깨졌다”고 말하는 현상)로 표시된다.
쉽게 말하면: 문자 인코딩은 “이 숫자는 이 글자다”라고 정해 둔 전 세계 공통의 대응표다.
ASCII — 영문 중심의 초기 표준
ASCII(American Standard Code for Information Interchange, 미국 정보교환 표준 부호)는 1960년대에 만들어진 초창기 문자 인코딩 표준이다. ASCII는 7비트를 사용해 128가지()의 문자를 표현한다. 영어 대문자(AZ), 소문자(az), 숫자(0~9), 그리고 공백·줄바꿈 같은 제어 문자와 특수기호가 여기에 포함된다.
예를 들어 대문자 ‘A’는 ASCII 코드로 65(2진수로는 01000001)이고, 소문자 ‘a’는 97(2진수로는 01100001)이다. 대문자와 소문자의 코드 값이 정확히 32만큼 차이 나도록 설계되어 있어서, 이 규칙성 덕분에 옛날 프로그램에서는 산술 연산만으로 대소문자를 변환하기도 했다.
컴퓨터의 기본 저장 단위는 8비트(1바이트)인데 ASCII는 7비트만 쓰므로, 나머지 1비트가 남는다. 이 남는 비트는 초기에는 패리티 비트(parity bit, 뒤에서 자세히 다룬다)로 활용되었고, 이후에는 확장 ASCII처럼 추가 문자를 넣는 데 쓰이기도 했다.
유니코드 — 전 세계 문자를 담는 표준
ASCII의 가장 큰 한계는 영어 이외의 문자를 표현할 수 없다는 점이다. 한글, 한자, 아랍 문자, 이모지(emoji) 등은 128가지 안에 들어갈 수 없다. 이 문제를 해결하기 위해 만들어진 것이 유니코드(Unicode)다. 유니코드는 전 세계의 거의 모든 문자 체계에 고유한 번호(코드 포인트, code point)를 부여하는 것을 목표로 하는 표준으로, 현재 백만 개가 넘는 코드 포인트 공간을 갖고 있다.
유니코드는 “어떤 문자에 어떤 번호를 매길지”만 정의하고, 그 번호를 실제로 몇 바이트로, 어떤 규칙으로 저장할지는 별도의 인코딩 방식으로 정한다. 가장 널리 쓰이는 방식이 UTF-8(Unicode Transformation Format, 8비트 단위)로, 영어 문자는 1바이트로, 한글 같은 문자는 3바이트로 저장하는 식으로 문자마다 필요한 바이트 수를 가변적으로 쓰는 효율적인 방식이다. UTF-8은 ASCII와 하위 호환되도록 설계되어, 순수 영문 텍스트는 ASCII로 저장한 것과 완전히 동일한 바이트열을 갖는다는 특징이 있다.
쉽게 말하면: ASCII는 영어 전용 128자리 대응표이고, 유니코드는 전 세계 문자를 담기 위해 만든 훨씬 큰 대응표다. UTF-8은 그 유니코드 번호를 실제 바이트로 저장하는 대표적인 방법이다.
이 문자코드 개념은 08편(자료의 표현: 부동소수점·문자코드·오류검출)에서 시험 출제 포인트 중심으로 다시 정리한다. 여기서는 “문자도 결국 숫자이고, 그 숫자를 저장하는 약속이 여러 개 있다”는 감각을 잡아 두면 충분하다.
왜 오류검출이 필요한가
데이터를 저장하거나 다른 장치로 전송하는 과정에서, 전기적 잡음이나 하드웨어 결함 때문에 비트 하나가 원래 값과 다르게 바뀌는 사고가 일어날 수 있다. 예를 들어 01000001(문자 ‘A’)을 전송했는데 중간에 한 비트가 뒤집혀 01000011(문자 ‘C’)로 도착하면, 받는 쪽은 이것이 원래 무슨 문자였는지 전혀 알 방법이 없다. 이런 사고를 막으려면 데이터에 오류를 감지할 수 있는 여분의 정보를 추가로 붙여서 보내야 한다. 이것이 오류검출(error detection)의 기본 아이디어다.
가장 간단한 오류검출 방법이 패리티 비트(parity bit, 우리말로는 짝수/홀수 검사 비트)이고, 조금 더 발전된 방법이 해밍 코드(Hamming code)다.
패리티 비트 — 짝수 패리티와 홀수 패리티
패리티 비트는 원래 데이터 비트열에 1비트를 추가로 붙여서, 전체 비트열에서 1의 개수를 짝수 또는 홀수로 맞추는 방식이다. 어떤 기준으로 맞추느냐에 따라 두 가지로 나뉜다.
- 짝수 패리티(even parity): 패리티 비트를 포함한 전체 비트열에서 1의 개수가 짝수가 되도록 패리티 비트를 정한다.
- 홀수 패리티(odd parity): 패리티 비트를 포함한 전체 비트열에서 1의 개수가 홀수가 되도록 패리티 비트를 정한다.
짝수 패리티 계산 예제
데이터 비트열 1011001이 있다고 하자. 먼저 이 안에 1이 몇 개인지 센다. 1, 0, 1, 1, 0, 0, 1에서 1은 4개(첫째, 셋째, 넷째, 일곱째 자리)다.
짝수 패리티를 적용하려면 패리티 비트를 붙인 뒤에도 1의 개수가 짝수여야 한다. 이미 1이 4개(짝수)이므로, 패리티 비트는 0이 되어야 한다(0을 더해도 1의 개수는 그대로 4개, 짝수를 유지). 따라서 최종 전송 비트열은 1011001 + 패리티 비트 0 = 10110010이다.
이번엔 데이터 비트열 1100110을 보자. 1의 개수를 세면 1, 1, 0, 0, 1, 1, 0에서 4개다. 이 역시 짝수이므로 짝수 패리티 비트는 0이 되어 최종 비트열은 11001100이다.
이제 1의 개수가 홀수인 경우를 보자. 데이터 비트열 1010001은 1이 1, 0, 1, 0, 0, 0, 1에서 3개(홀수)다. 짝수 패리티를 만들려면 1개를 더 추가해 짝수(4개)로 만들어야 하므로, 패리티 비트는 1이 된다. 최종 비트열은 10100011이다.
홀수 패리티 계산 예제
같은 데이터 비트열 1011001(1이 4개, 짝수)에 홀수 패리티를 적용해 보자. 전체 1의 개수를 홀수로 만들어야 하므로, 패리티 비트는 1이 되어(4개+1=5개, 홀수) 최종 비트열은 10110011이다.
쉽게 말하면: 짝수 패리티는 “1의 개수를 짝수로 맞춰라”, 홀수 패리티는 “1의 개수를 홀수로 맞춰라”는 규칙이다. 데이터에 있는 1의 개수를 세고, 목표(짝수 또는 홀수)에 맞게 패리티 비트를 0 또는 1로 정하면 된다.
수신 측에서의 검사
받는 쪽은 도착한 전체 비트열(데이터+패리티)에서 1의 개수를 다시 세어, 약속된 규칙(짝수 또는 홀수)과 맞는지 확인한다. 예를 들어 짝수 패리티로 10110010을 보냈는데, 전송 중 한 비트가 뒤집혀 10111010으로 도착했다고 하자. 1의 개수를 세면 1,0,1,1,1,0,1,0에서 5개(홀수)다. 짝수 패리티 약속과 맞지 않으므로, 수신 측은 “전송 중 오류가 발생했다”는 것을 즉시 알 수 있다.
패리티 비트의 한계는 비트가 짝수 개(2개, 4개 등) 동시에 뒤집히면 1의 개수의 짝/홀 여부가 원래대로 돌아와 오류를 감지하지 못한다는 점, 그리고 오류가 있다는 것만 알 뿐 어느 자리가 틀렸는지는 알 수 없다는 점이다. 이 한계를 넘어서기 위해 만들어진 것이 해밍 코드다.
해밍 코드 — 오류 위치까지 찾아내는 개념 맛보기
해밍 코드(Hamming code)는 리처드 해밍(Richard Hamming)이 고안한 오류검출·정정 코드로, 패리티 비트를 한 개가 아니라 여러 개를 정해진 위치에 분산 배치해서, 오류가 발생했을 때 그 위치까지 계산해낼 수 있게 만든 방식이다.
해밍 코드가 만들어내는 전체 비트열을 코드워드(codeword)라고 부른다. 코드워드는 원래 데이터 비트와 여러 개의 패리티 비트가 정해진 규칙에 따라 섞여 있는 비트열이다. 해밍 코드에서 패리티 비트는 위치가 2의 거듭제곱인 자리(1번, 2번, 4번, 8번…자리)에 배치되고, 나머지 자리에 실제 데이터 비트가 들어간다.
각 패리티 비트는 전체 비트 중 자신을 포함해 특정 자리들만 검사하도록 설계된다. 예를 들어 1번 위치의 패리티 비트는 1, 3, 5, 7번처럼 이진수로 표현했을 때 1의 자리(가장 오른쪽 비트)가 1인 자리들을 검사하고, 2번 위치의 패리티 비트는 2, 3, 6, 7번처럼 2의 자리가 1인 위치들을 검사하는 식이다. 수신 측은 각 패리티 그룹이 맞는지 하나씩 확인해서, “몇 번 패리티 그룹에서 오류가 감지되었는가”를 조합하면 오류가 발생한 정확한 비트 위치를 이진수로 계산해낼 수 있다.
쉽게 말하면: 패리티 비트 하나는 “오류가 있다, 없다”만 알려주지만, 해밍 코드는 패리티 비트 여러 개를 겹치게 배치해서 “몇 번째 비트가 틀렸다”까지 콕 집어낼 수 있게 만든 것이다.
이 문서에서는 해밍 코드의 개념(코드워드, 여러 패리티 비트의 분산 배치, 오류 위치 계산이 가능하다는 원리)만 맛보기로 다루며, 코드워드를 실제로 비트 단위까지 구성하고 계산하는 절차는 08편(자료의 표현: 부동소수점·문자코드·오류검출)에서 출제 포인트 중심으로 더 깊이 다룬다.
코드워드 읽는 법
시험 문제에서 코드워드가 주어지고 “이 코드워드에 오류가 있는가”를 묻는 유형이 나올 수 있다. 이때는 다음 순서로 접근한다.
1단계: 코드 방식 확인
문제에서 짝수 패리티인지 홀수 패리티인지, 아니면 해밍 코드인지 먼저 확인한다. 방식에 따라 검사 규칙이 다르다.
2단계: 1의 개수 세기 (패리티인 경우)
코드워드 전체(데이터+패리티 비트)에서 1이 몇 개인지 정확히 센다.
3단계: 규칙과 대조
짝수 패리티라면 1의 개수가 짝수인지, 홀수 패리티라면 홀수인지 확인한다. 규칙과 맞지 않으면 오류가 발생한 것이다.
4단계: 해밍 코드는 그룹별로 반복
해밍 코드라면 2단계·3단계를 각 패리티 그룹(1번 그룹, 2번 그룹, 4번 그룹…)마다 반복하고, 오류가 감지된 그룹 번호를 모두 더해 오류 비트의 위치를 구한다.
자주 틀리는 점
- 짝수 패리티와 홀수 패리티를 반대로 적용하는 실수: 짝수 패리티는 “짝수를 만든다”, 홀수 패리티는 “홀수를 만든다”는 목표만 정확히 기억하면 헷갈리지 않는다.
- 패리티 비트 자신을 1의 개수 세기에서 빠뜨리는 실수: 수신 측 검사에서는 패리티 비트까지 포함한 전체 비트열의 1의 개수를 세야 한다.
- 패리티 비트가 모든 오류를 잡아준다고 오해하는 실수: 패리티 비트 1개는 비트가 짝수 개 동시에 뒤집히는 경우를 감지하지 못하고, 오류 위치도 알려주지 않는다.
- ASCII가 한글도 표현할 수 있다고 오해하는 실수: ASCII는 7비트, 128가지 조합으로 영문과 기본 기호만 표현하며 한글 같은 비영문 문자는 유니코드 계열 인코딩이 필요하다.
핵심 정리
- 문자는 인코딩 규칙에 따라 고유한 숫자로 바뀌어 2진수로 저장된다. ASCII는 7비트 영문 전용, 유니코드는 전 세계 문자를 포괄하는 표준이며 UTF-8이 대표적인 인코딩 방식이다.
- 짝수 패리티는 전체 1의 개수를 짝수로, 홀수 패리티는 홀수로 맞추도록 패리티 비트를 정한다.
- 패리티 비트는 오류 유무만 알려주고 위치는 알려주지 못하며, 짝수 개의 비트가 동시에 틀리면 감지하지 못하는 한계가 있다.
- 해밍 코드는 여러 개의 패리티 비트를 겹치게 배치한 코드워드로, 오류가 발생한 정확한 비트 위치까지 계산할 수 있다.
마무리 복습
참고 자료
- NIST — 이진 표현과 오류검출 개념의 신뢰할 수 있는 표준화 기관 참고 자료.
- 국가평생교육진흥원 독학학위제 — 독학사 시험 안내 및 평가영역 공식 자료.