개발자는 기록이 답이다

혼공 컴퓨터구조 + 운영체제 2. 데이터 본문

CS/운영체제

혼공 컴퓨터구조 + 운영체제 2. 데이터

slow-walker 2023. 12. 20. 18:22

 

컴퓨터가 이해하는 정보의 단위를 학습하고, 이진법, 십육진법을 통해 다양한 숫자를 표현하는 방법,

아스키 코드, 유니코드 등 컴퓨터가 이해할 수 있는 0과 1로 다양한 문자를 표현하는 방법에 대해서 알아본다


1. 0과 1을 "숫자"로 표현하는 방법

컴퓨터는 0과 1로 모든 정보를 표현하고 이해한다고 했는데, 3+4를 계산하는 연산은 어떻게 하는걸까?

 

정보단위

 

  • 0과 1을 나타내는 가장 작은 정보 단위를 비트(bit)라고 한다.
  • 비트는 전구에 빗대어 생각해보면 이해하기 쉽다.
  • 전구 한개로 꺼짐과 켜짐 두 가지 상태를 표현할 수 있듯이, 1비트0 또는 1 두가지 정보를 표현할 수 있다.
  • n개의 전구로 표현할 수 있는 상태는 2ⁿ가지 이다.
  • n비트는 2ⁿ가지 정보를 표현할수 있다.
  • 웹 브라우저, 워드 프로세서, 포토샵 등 우리가 실행하는 모든 프로그램은 수십, 수백만개 이상의 0과 1로 이루어져 있다.

 

단위 묶음
1바이트 (1byte) 8비트(bit) = 2팔(256)개의 정보 표현
1킬로바이트 (1kB) 1,000바이트 (1,000 byte)
1메가바이트 (1MB) 1,000킬로바이트 (1,000kB)
1기가바이트 (1GB) 1,000메가바이트 (1,000MB)
1테라바이트 (1TB) 1,000기가바이트(1,000GB)

 

※ 1kB를 1,024byte, 1MB를 1,024kB...이런식으로 표현하는 것은 잘못된 관습이다.

이전 단위를 1,024개 묶어 표현한 단위는 KiB, MiB, TiB이다.

 

이진법

 

  • 수학에서 0과 1만으로 모든 숫자를 표현하는 방법을 이진법(binary)라고 한다.
  • 십집법은 숫자를 셀때 9를 넘어가는 시점에 자리올림을 해서 10이 되서 0부터 9까지 10개의 숫자만으로 모든 수를 표현(십진수)
  • 이진법은 1을 넘어가는 시점에 자리 올림을 하여 0과 1, 2 개의 숫자만으로 모든 수를 표현(이진수)

이진수 8표기 

  • 수학적 표현 : 1000₍₂₎
  • 코드상 표현 : 0b1000
이진수의 음수 표현

 

2의 보수(two's complement)를 구해 이 값을 음수로  간주

  • 모든 0과 1을 뒤집고, 거기에 1을 더한 값

2의 보수란 ? 어떤 수를 그보다 큰 2ⁿ에서 뺀 값

e.g) 11₍₂₎의 2의 보수는 11₍₂₎보다 큰 2ⁿ, 즉 100₍₂₎에서 11₍₂₎을 뺀 01₍₂₎이 되는 것

e.g) 1011₍₂₎의 음수는 0101₍₂₎ / 0101₍₂₎의 음수는  1011₍₂₎

 

그렇다면 1011₍₂₎의 음수인 0101₍₂₎와 십진수 5를 양수로서 표기한 0101₍₂₎를 어떻게 구분할까?

실제로 이진수만 봐서는 구분하기 어렵기 때문에, 컴퓨터 내부에서 플래그를 사용한다.

 

이진수의 음수를 표현하기 위해 2의 보수를 취하는 방식은 널리 쓰이지만, 완벽하지 않다.

0의 음수는 10000₍₂₎이고,
2³의음수는 1000₍₂₎로 양수로 표현한 값과 같다.

첫번째의 경우, 자리 올림이 발생한 비트의 1을 버리고
두번째의 경우, 2ⁿ의 보수를 취하면 자기 자신이 되어버리는 문제를 본질적으로 해결하기 어렵다.
즉, n비트로는 -2ⁿ와 2ⁿ이라는 수를 동시에 표현할 수 없다.

 

십육진법

 

이진수만 사용하게 된다면 단점이 있다.

십진수 32를 이진수로 표현하면 100000₍₂₎와 같이 여섯 개의 자리숫가 필요한 것처럼 숫자의 길이가 너무 길어지는 현상이다.

그래서 데이터를 표현할때 이진법 외에 십육진법도 자주 사용된다.

  • 수가 15를 넘어가는 시점에 자리 올림을 하는 숫자 표현방식이다
  • 십진수 10, 11, 12, 13, 14, 15를 A, B, C, D, E, F로 표기한다.

 

십육진수 15 표기

  • 수학적 표현 : 15₍₁₆₎
  • 코드상 표현 : 0x15

십육진법을 사용하는 주된 이유? 이진수를 십육진수로, 십육진수를 이진수로 변환하기 쉽기 때문

 

십육진수를 이진수로 변환하기

 

  • 십육진수는 한 글자당 열여섯 종류(0~9, A~F)의 숫자를 표현할 수 있다.
  • 십육진수를 이루는 숫자 하나를 이진수로 표현하려면 몇 비트가 필요할까? 4비트가 필요하다! 2⁴ = 16

 

십육진수 한 글자를 4비트의 이진수로 간주하면 십육진수를 이진수로 간편하게 변환할 수 있다.

e.g) 1A2B₍₁₆₎

  • 각 1₍₁₆₎, A₍₁₆₎, 2₍₁₆₎, B₍₁₆₎을 이진수로 표현하면
  • 0001₍₂₎, 1010₍₂₎, 0010₍₂₎, 1011₍₂₎
  • 이 숫자를 그대로 이어 붙인 0001101000101011₍₂₎이 1A2B₍₁₆₎를 이진수로 표현한 값이다.
이진수를 십육진수로 변환하기

 

이진수를 네 개 씩 끊고, 끊어준 네 개의 숫자를 하나의 십육진수로 변환한 뒤 그대로 이어 붙인다.

e.g) 11010101₍₂₎

  • 각 네 개씩 끊으면 1101₍₂₎, 0101₍₂₎이고,
  • 이는 D₍₁₆₎과 5₍₁₆₎이므로
  • 그대로 이어붙인 D5₍₁₆₎이 11010101₍₂₎를 십육진수로 변환한 수이다.

 

※ 십육진수는 이진수와 같이 하드웨어와 밀접하게 맞닿아 있는 개발분야에서 많이 쓰인다고 한다.

 

2. 0과 1을 "문자"로 표현하는 방법

 

컴퓨터는 0과 1만 이해할 수 있다고 했는데, 지금 글을 작성하고 있는 텍스트와, 영어, 특수문자는 어떻게 이해하고 모니터에 출력하는걸까?

 

문자 집합과 인코딩

  • 문자 집합(Character set) : 컴퓨터가 인식하고 표현할 수 있는 문자의 모음
    • 문자 집합에 속해있지 않은 문자는 이해할 수 없다.
    • e.g) 문자집합이 {a, b, c, d, e}인 경우 컴퓨터는 이 다섯 개의 문자는 이해할 수 있고, f나 g와 같은 문자는 이해하지 못한다.
  • 문자 인코딩(Character encoding) : 문자 집합에 속한 문자여도, 해당 문자를 0과 1로 변환해야 비로서 컴퓨터가 이해할 수 있다
    • 인코딩 후 0과 1로 이루어진 결과값이 문자 코드가 된다
  • 문자 디코딩(Character decoding) :0과 1로 이루어진 문자 코드를 사람이 이해할 수 있는 문자로 변환

 

아스키 코드

  • 아스키(ASCII)는 초창기 문자 집합중 하나로, 영어 알파벳과 아라비아 숫자, 그리고 일부 특수문자를 포함한다.
  • 하나의 아스키 문자를 나타내기 위해 8비트(1바이트)를 사용하는데,
  • 8비트 중 1비트는 패리티 비트(parity bit)라고 불리는 오류 검출 비트이기 때문에 실질적으로 7비트가 사용된다.
  • 0부터 127까지 총 128개의 숫자 중 하나의 고유한 수에 일대일로 대응된다.
  • 한글을 표현할 수 없다. 한글 뿐만 아니라, 문자 집합 외의 문자. 특수문자도 표현할 수 없다
  • 근본적으로 아스키 문자 집합에 속한 문자들은 7비트로 표현하기에 128개보다 많은 문자를 표현하지 못한다.
  • 훗날 1비트를 추가한 확장 아스키가 등장하기도 했지만, 표현 가능한 문자의 수는 256개 뿐이다.

코드 포인트(code point)란? 문자 인코딩에서 '글자에 부여된 고유한 값'을 말한다. 가령 아스키 문자 A의 코드 포인트는 65이다. 

한국을 포함한 영어권 외 나라들은 자신들의 언어를 0과 1로 표현할 수 있는 고유한 문자 집합과 인코딩 방식이 필요했고,

이러한 이유로 한글 인코딩 방식인 EUC-KR이 나왔다.

 

EUC-KR

 

EUC-KR는 한글을 2바이트 크기로 인코딩할 수 있는 완성형 인코딩 방식이다.

알파벳을 쭉 이어쓰는 영어와 달리, 한글은 음절 하나하나가 초성, 중성, 종성의 조합으로 이루어져 있다(한글의 특수성).

한글 인코딩 방식

  • 완성형 방식 : 초성, 중성, 종성의 조합으로 이루어진 완성된 하나의 글자에 고유한 코드를 부여
  • 조합형 방식 : 초성을 위한 비트열, 중성을 위한 비트열, 종성을 위한 비트열을 할당하여 조합으로 하나의 글자 코드를 완성

 

한글 한 글자에 2바이트 코드가 부여된다.

EUC-KR로 인코딩된 한글 한 글자를 표현하려면 16비트가 필요하고, 16비트는 네 자리 십육진수로 표현할 수 있다.

즉, EUC-KR로 인코딩된 한글은 네 자리 십육진수로 나타낼 수 있다.

 

2,350개 정도의 한글 단어를 표현할 수 있지만, 모든 한글 조합을 표현할 수 있을 정도로 많은 양은 아니다.

그래서 문자 집합에 정의 되지 않은 '쀍','믜'와 같은 글자는 EUC-KR로 표현할 수 없다.

이 문제를 해결하기 위해 확장된 EUC-KR로서 마이크로소프트의 CP949(Code page 949)이 등장했지만, 부족하다.

 

 

유니코드와 UTF-8

 

언어별로 인코딩을 나라마다 해야 ㅎ나다면 다국어를 지원하는 프로그램을 만들 때,

각 나라 언어의 인코딩을 모두 알아야 하는 번거로움이 있다.

 

  • 유니코드는 여러 나라의 문자를 광범위하게 표현할 수 있는 통일된 문자 집합이다.
  • 아스키코드나 EUC-KR는 글자에 부여된 값을 그대로 인코딩 값으로 삼았는데,
  • 유니코드는 글자에 부여된 값 자체를 인코딩된 값으로 삼지 않고 이 값을 다양한 방법으로 인코딩한다.
  • UTF-8, UTF-16, UTF-32는 유니코드 문자에 부여된 값을 인코딩 하는 방식이다.

1바이트부터 4바이트까지의 인코딩 결과를 만들어낸다.

유니코드 문자에 부여된 값의 범위에 따라 인코딩 결과가 몇바이트인지 (1바이트~ 4바이트) 결정된다. 


 

🤔느낀점 

 

2장을 공부하면서 이전에 회사에서 다국어 지원해서 이메일이랑 문자 보낼때, 일부 일본어 한자때문에 인코딩이 제대로 안되던 때가 기억난다. 아마 그때 당시 AWS SES랑 SMS를 통해서 이메일과 문자를 보내던 방식이었는데, 문자같은경우에는 아예 발송조차 안됐다.

그래서 애꿎은 SMS만 계속 코드가 잘못됬나 수정해야되나 생각했었는데, 인코딩 문제가 있어서 에러가 났던것 같다.

 

그때 해결 방법도 UTF-8로 인코딩이 제대로 안되던 문자를 유니코드 이스케이프 시퀀스로 변경해서 해결했었기 때문이다.

그때 당시에는 제대로 모르는 상태로 해결되었는데, 지금은 코드 포인트가 무엇인지, 유니코드가 무엇인지 좀 알것 같다.

 

※ 이스케이프 시퀀스

  • 문자열 "\u" 다음에 16진수로 표현된 유니코드 코드 포인트가 이어지는 형태이다.
  • e.g) "\u30E1"은 유니코드 코드 포인트 U+30E1에 해당하는 문자를 나타낸다.
  • 이 코드 포인트는 일본어의 "メ" 문자를 나타낸다.
UTF-8은 유니코드의 일종이며, 유니코드를 나타내는 여러 인코딩 중 하나이고, 전 세계의 다양한 문자를 나타내기 위해 설계된 유니코드를 바이트 시퀀스로 표현하는 방법 중 하나이다.

유니코드 이스케이프 시퀀스는 주로 프로그래밍 언어나 데이터 포맷에서 유니코드 문자를 나타내는 데 사용된다
. 이는 유니코드 코드 포인트를 해당 문자에 대한 이스케이프된 문자열로 표현하는 방식입니다. 예를 들어, "\u0041"은 코드 포인트 U+0041에 해당하는 문자 'A'를 나타낸다.