본 포스팅은 인프런의 개발자를 위한 컴퓨터공학 1: 혼자 공부하는 컴퓨터구조 + 운영체제를 참조하여 작성한 글입니다.
컴퓨터가 이해하는 것은 오직 0과 1뿐이다. 그러면 컴퓨터는 어떻게 숫자 3과 숫자 7을 이해할 수 있을까? 그것에 대해 한번 알아보도록 하자.
먼저 정보의 단위부터 학습을 해보고 위의 궁금증을 해결해보도록 하겠다. 컴퓨터가 이해하는 가장 작은 정보의 단위를 비트라고 한다.
bit: 0과 1을 표현하는 가장 작은 정보의 단위로 0과 1 2가지 정보를 표현할 수 있다.
1비트는 총 2가지의 경우의 수가 존재한다. 그러면 2비트는 몇가지가 존재할까? 총 4가지가 존재한다. 그러면 3비트는 몇가지가 존재할까? 총 8가지 경우의 수가 존재한다. 즉 아래와 같은 규칙이 발생한다.
용량의 최소 단위는 보통 비트로 표현하지 않고 바이트로 표현한다. 비트는 표현의 최소단위이고 보통 용량을 이야기하면 바이트부터 시작한다.
1KB는 1024byte, 1MB는 1024KB... 이런식으로 표현하는 것은 잘못된 습관이다. 이전 단위를 1024개 묶어 표현하는 단위는 KB, MB, GB, TB가 아닌 KiB, MiB, GiB, TiB로 표현한다.
또한 중요한 정보 단위 중에 워드라는 단위도 존재한다. 워드란 CPU가 한번에 처리할 수 있는 데이터 크기를 말한다. 그리고 이런 워드 단위가 나옴에 따라 아래와 같은 용어도 같이 등장하기 시작했다.
2진법이란 0과 1로 수를 표현하는 방법을 말한다. 숫자가 1을 넘어가는 시점에 자리올림이 발생한다. 우리가 일상적으로 사용하는 진법은 숫자가 9가 넘어가면 자리올림이 발생하는 십진법이다. 또한 2진법을 표기할 때 아래와 같이 표기한다.
그러면 2진법을 이용하여 컴퓨터가 숫자를 받아들이는 것은 이해가 되었을 것이다. 그런데 음수는 어떻게 파악할까? 우리는 -라는 부호를 통해서 표현을 하지만 실제 컴퓨터는 -라는 부호는 알 수 없는 기호이기 때문이다. 이를 위해 컴퓨터는 2의 보수법을 통해 음수를 표현한다. 2의 보수법의 사전적 정의를 보면 아래와 같다.
어떤 수를 그보다 큰 2^n에서 뺀 값을 말한다.
하지만 해당 사전적 정의는 도통 이해가 되지 않는다. 그래서 사람들이 새로운 방법을 찾아냈는데 바로 아래와 같다.
모든 0과 1을 뒤집고 1을 더한다.
위와 같은 공식을 통하면 음수를 구할 수 있다. 그러면 또 다음과 같은 의문이 들 수도 있을 것이다.
-1011(2)을 표현하기 위한 음수으로서의 0101(2)과 십진수 5를 표현하기 위한 양수로서의 0101(2)은 똑같이 생겼는데 이진수만 보고 이게 음수인지 양수인지 어떻게 구분할까?
실제로 2진수만 봐서는 이게 음수인지 양수인지 구분하기 어렵다. 그래서 컴퓨터 내부에서 어떤 수를 다룰 때는 이 수가 양수인지 음수인지를 구분하기 위한 플래그를 사용한다. 즉, CPU 내부에 플래그 레지스터가 존재하는데 플래그 레지스터로 현재 값이 양수인지 음수인지를 표기하는 것이다.
하지만 2진법으로 숫자를 표현하면 자릿수가 너무 길어진다. 예를 들어 10진수 32를 2진수로 표현하면 100000(2)가 되는 것처럼 말이다. 그래서 컴퓨터의 데이터를 표현할 때 16진법도 많이 사용한다. 16진법은 수가 15를 넘어가는 시점에 자리올림이 발생한다.
16진법에서 숫자 10은 A로 숫자 15는 순서에 따라 F로 표현하니 유의바란다.
16진법의 표기법은 아래와 같으니 잘 알아두길 바란다.
그러면 이런 의문점이 들 수 있을 것이다. 하필 왜 16진법을 사용할까? 여러 이유가 존재하지만 컴퓨터가 2진법을 알아듣고 결국 해당 2진법으로 변환이 되어야 하는데 16진법은 2진법으로 변환하기 가장 쉽기 때문이다. 방법은 간단하다. 2진수 4자리를 10진수로 표현하여 바로 16진법으로 표기하면 되기 때문이다.
1A2B(16) = 0001 1010 0010 1011(2)
우리는 컴퓨터를 가지고 숫자놀이만 할려고 한 것은 아니다. 당연히 문자도 다룰 일이 생긴다. 그러면 컴퓨터는 문자를 어떻게 표현할까? 그것을 한번 알아보자.
0과 1로 문자를 표현하는 방법에 대해 알아보기 전에 우리가 반드시 알아야 하는 용어들이 존재한다.
먼저 문자 집합이다. 문자 집합이란, 컴퓨터가 이해할 수 있는 문자의 모음을 말한다. 물론 문자 집합에 속한 문자라고 해서 컴퓨터가 이해할 수 있는 것은 아니다. 당연히 문자를 0과 1로 변환하는 작업이 필요하다. 이것을 바로 인코딩이라고 한다. 인코딩이란, 코드화 과정을 말하며 문자를 0과 1로 이루어진 문자 코드로 변환하는 작업을 말한다. 인코딩의 반대 개념도 존재하는데 바로 디코딩이다. 디코딩이란 코드를 해석하는 과정으로 0과 1로 표현된 문자코드로 문자를 변환하는 과정을 말한다.
그럼 용어를 학습해보았으니 다양한 문자 집합과 인코딩 방법에 대해 알아보도록 하자.
아스키 코드란, 초창기 문자 집합 중 하나이다. 알파벳, 아라비아 숫자, 일부 특수문자 및 제어문자를 다룰 수 있는 문자집합이였다. 아스키 코드는 7bit로 하나의 문자를 표현하였다.
실재로는 하나의 아스키 문자를 나타내기 위해 8bit를 사용한다. 하지만 8bit중 1bit는 패리티 비트라고 불리는 오류 검출을 위해 사용되는 비트이기 때문에 실질적으로 문자 표현을 위해 사용되는 비트는 7bit이다.
아스키 코드의 특징으로는 아래와 같다.
특히 우리가 사용하는 한글은 아스키 코드로는 표현이 불가능했다. 즉, 언어별 인코딩 방식의 욕구가 생겼다.
코드 포인트: 문자에 부여된 값 = 인코딩된 값
한글 인코딩을 이해하려면 우선 한글의 특수성을 알아야 한다. 한글은 완성형 인코딩 방식과 조합형 인코딩 방식을 제공한다.
한글을 표현하는데 사용하는 대표적인 인코딩 방식으로는 EUC-KR이 존재한다. EUC-KR은 KS X 1001 KS X 1003 문자 집합 기반의 한글 인코딩 방식이다. 완성형 인코딩 방식을 사용하고 있으며 글자 하나 하나에 2byte 크기의 코드를 부여하고 있다. 그래서 총 2300여개의 한글 표현이 가능하였지만 여전히 모든 한글을 표현하기에는 부족하였다. '쀏', '뙠', '휔'같은 한글은 표현이 안되었다. 또한, 이렇게 언어별 인코딩을 국가마다 하게 되면 다국어를 지원하는 어플리케이션을 개발하는 개발자한테는 언어별 인코딩 방식을 모두 이해해야 한다.
그래서 사람들은 모든 언어, 특수문자까지 통일된 문자 집합을 사용하고 싶은 욕구가 생겼다. 즉, 통일된 문자 집합과 인코딩 방식을 원했었다.
그래서 등장한 것이 유니코드였다. 유니코드란, 통일된 문자 집합이며 한글, 영어, 화살표와 같은 특수문자 심지어 이모지까지 표현이 가능하였으며 현재 문자표현에 있어서 매우 중요한 위치를 서게 되었다. 그러면 유니코드의 인코딩은 어떻게 할까? 유니코드는 글자에 부여된 값 자체를 인코딩 값으로 삼지 않고 이 값을 다양한 방법으로 인코딩 할 수 있는데 이것을 유니코드 인코딩 방식이라 부른다.
유니코드 인코딩 방식에는 UTF-8, UTF-16, UTF-32가 존재하는데 가장 많이 이용하는 것이 UTF-8이다. UTF-8은 가변길이 인코딩 방식이다.
가변길이 인코딩 방식: 인코딩 결과가 1byte~4byte로 제 각각 다르다.
인코딩 결과에 따라 몇 byte가 될지는 유니코드 부여된 값에 따라 다르다. 보통은 아래의 규칙을 따른다고는 한다.