2019.03.12 TIL
(TIL은 스스로 이해한 것을 바탕으로 정리한 것으로 오류가 있을 수 있습니다)
# 질문에 답하기.
- ASCII, Unicode, UTF-8에 대해 아는대로 상세히 이야기해라
character set
- 문자 집합(charater을 모아둔 것)
charater encoding
- 문자 인코딩 —> 부호화
- 문자 집합을 메모리에 저장, 통신하기 위해 부호화 하는 방식
code point
- 컴퓨터는 0,1 밖에 모르기 때문에 문자를 숫자화 해야한다.
- a = 97이라고 했을 때 97을 코드 포인트라고 한다.(문자에 맵핑 된 정수)
- 문자 하나에 정수 하나를 맵핑해 놓았다.
- ex) ASCII(아스키) table
- 0 부터 127까지 7비트를 사용하여 문자와 특수문자 등을 맵핑해놓음
- 실제 저장은 1byte로 저장한다.
UNICODE(통합 코드)
- 기존에 아스키코드를 확장하여 16비트로 문자 표현 —> 65,536개 문자 가능
- 추가적으로 2byte자리 테이블을 17개 만들어 놓았다.
- 현재 4개의 table이 이용되고 있다.
- 유니코드 기본 평면에서 가장 첫번째 0000 ~ 0FFF는 아스키이다
- U+0000 ~ U+007F —> 0000 0000 0111 1111 아스키를 첫 평면에 배치해놓았다.
- 한글은 어디 있나? U+AC00 ~ U+D7AF 파이썬에서 \uac00
hex(ord(“가”))
0xac00
hex(ord(“ㄱ”))
0x3131
유니코드 인코딩 방식
ASCII는 code point 그대로 컴퓨터에 저장된다.
unicode에서는’가’ u+ac00 이라는 code테이블를 ac00 —> 1010 1100 0000 0000을 그대로 메모리에 저장해 주면 정말 좋을 것 같다. 하지만 이렇게 되면 2번째 평면부터는 2바이트가 아니라 3바이트는 있어야 표현할 수 있다. 따라서 2byte + 4bit(17개 테이블을 나타내기 위한) 만 있으면 17개 다 표현할 수 있으나 저 4bit 떄문에 1byte가 더 필요하게 되고 3byte는 padding을 붙여 4byte를 관리해야 하게 된다. 이거 때문에 4byte를 쓰기에는 너무 아깝다.
특히 미국 입장에서는 “나는 평생 한글을 안 쓸 건데 1byte a,b,c등을 쓰기 위해서 4byte에 저장해야 한다고??”는 의문이 생길 수 있다. 그래서 나온 방법이 encoding 방식이다. unicode는 테이블로 존재하며 ‘가’라는 애는 ac00 이라는 codepoint로 저장된다. uxac00을 메모리에 저장할 때 utf - 8 / utf-16/utf-32와 같은 방법들이 있다. 인코딩 방식은 크게 3가지로 나눌 수 있다. UTF-8/ UTF-16/ UTF -32 (Universal Coded Character Set + Transformation Format – 8, 16, 32-bit)에서 8 , 16 , 32는 bit를 이야기하며 각각의 숫자 비트만큼 늘어가며 확장된다. 각각을 구분해서 볼 때는 아스키코드들을 어떻게 저장할 것인가에 따라서 UTF-8, UTF-16, UTF-32로 나눌 수 있다.
UTF-16
utf - 16은 ac00을 1010 1100 0000 0000을 2byte로 그대로 쏜다. 1차 테이블(bmp, 1차평면)에 있는 문자은 그 숫자를 그대로 사용하고 문제가 발생하기 시작하는 2차 table에 있는 문자는 그냥 4byte로 쏜다. 기존 인코딩인 ASCII와 호환이 되지 않는 문제가 있다.
UTF-16은 저장될 때 little endian 방식으로 저장된다.
AC00 —> 00AC
UTF-32
utf-32은 모든 숫자를 다 4byte로 쏜다. 이게 제일 간단하다. 모든 문자를 편하게 쓸 수 있다.
UTF-32 역시 저장될 때 little endian 방식으로 저장된다.
00 ac 00 00 으로 저장
UTF-8
UTF-8은 1byte 기반이다. ASCII에 속하는 애들은 모두 1byte로 보낸다. 따라서 가변길이 인코딩이라고 부르며 1byte단위로 확장하며 문자를 표현한다. but UTF-8로 한글을 보내면 3byte로 된다. 따라서 우리는 UTF-16에 비해 1byte를 손해보게 된다. 현재 아스키코드를 그대로 읽을 수 있는 UTF-8이 기본이 되었다. 또한 UTF-8은 littel indian, big indian의 문제가 없다.
UTF - 8 인코딩 방식
- 1110xxxx의 111은 나타내는 바이트 수를 나타낸다. (3바이트)
컴퓨터 사이언스 부트캠프 with 파이썬: 3.1 UTF-8 - 1
little endian , big endian
전 세계 사람들은 1423을 보면 1423이라고 순서대로 읽는다. 여기서 가장 중요한 것은 1이다. most significant digit이다.사람이 보기에 제일 중요한 것 부터 저장하는 것은 big endian이다. 최근에 intel이 만든 것은 little endian이다. 1423 을 3241로 저장한다.메모리 저장 할 때는 메모리 단위로 하므로 ac/00 —> 00/ac로 저장한다. 여기에서는 가장 뒤에 자리가 significant digit이다 network를 할 때 어떤 컴퓨터는 big인디언를 어떤 컴퓨터는 little인디언을 쓸텐데 어떻게 구분하는가? 따라서 network를 쏠 때는 big인디언으로 쓰기로 합의 하였다.
- to_byte()함수를 이용하여 빅 엔디언 방식일 떄의 바이트의 나열과 리틀 엔디언일 때의 바이트 나열을 확인 할 수 있다.
```python a = 0x01020304 #16진수 a #16909060 10진수 변환 a.to_byte(4, ‘big) #b’\x01\x02\x03\x04 a.to_byte(4, ‘little) #b’\x04\x03\x02\x01