문자열 방식
SBCS(Single Byte Character Set)
- SBCS(Single Byte Character Set)는 1바이트로 문자를 표현하는 문자 집합이다. ASCII 문자 집합을 기반으로 만들어졌다. SBCS는 주로 컴퓨터 시스템의 호환성 유지를 위해 사용된다.
- ASCII
7bit로 영문자, 숫자, 특수문자, 기호 등 128개 문자를 표현할 수 있다. 1bit는 Parity Bit로 통신 에러 검출을 위해 사용된다. - ANSI
8bit로 구성되어 있으며 256개의 문자를 표현할 수 있다. (ASCII의 확장판) ANSI의 앞 7bit는 ASCII와 동일하고, 뒤에 1bit를 이용하여 다른 언어의 문자를 표현한다.
새로 추가된 128개 문자(뒤에 1bit)로는 모든 언어의 문자를 표현할 수 없다. 그래서 생긴 개념이 CodePage이다.
MBCS(Multi Byte Character Set)
- MBCS(Multi Byte Character Set)는 한 문자를 표현하는 데 1바이트 이상을 사용한다. 문자당 여러 개의 바이트를 사용하기 때문에 다국어 문자 집합을 지원할 수 있다.
- 대부분 2바이트를 사용하기 때문에 DBCS(Double Byte Character Set)라고도 부른다. 이론상으로 MBCS는 3바이트 이상의 문자도 포함할 수 있다.
- MBCS는 SBCS보다 복잡하고 느리지만, 다국어를 처리할 수 있기 때문에 한국어(EUC-KR), 일본어(Shift-JIS), 중국어(GB2312)를 표현하기 위해 많이 사용된다.
- MBCS는 다양한 언어를 지원할 수 있지만, 문자열 처리에서 오류가 발생할 수 있다.
- 국가간의 호환이 되지 않는 방식이기에 다른 시스템으로 보내면 글자가 깨진다.
- 문자열의 길이를 계산할 때 한 문자가 1바이트 이상일 수 있기 때문에 문자열의 길이를 정확히 계산하기 어렵다.
- MBCS를 사용하는 경우 문자열 처리에 주의할 사항이 많기 때문에 프로그래밍 복잡성이 증가한다.
- 호환성 문제
- Microsoft Windows의 경우 유니코드를 지원하지 않았던 Windows 9x와의 호환성을 위해 여전히 MBCS를 기본 인코딩으로 사용한다.
- UTF-8이나 UTF-16에 BOM(바이트 순서 표식) 문자가 없으면 무조건 MBCS로 읽어들이는 프로그램들이 존재하기 때문에 Windows용 프로그램들은 UTF-8로 저장 시 BOM을 붙이는 경우가 많은데, 이는 BOM이 없는 UTF-8을 사용하는 타 운영체제에서 인코딩 오류를 일으키게 된다.
- UTF-8을 기본 인코딩으로 도입한 macOS나 2000년대 이후의 리눅스 등은 기본적으로 텍스트 파일을 단일 인코딩으로 읽어들이기 때문에 MBCS 형태로 작성된 텍스트 파일은 별도의 처리를 하지 않는 한 전부 ?로 보인다.
DBCS(Double Byte Character Set)
- DBCS(Double Byte Character Set)는 2바이트 이상의 다중 바이트 문자를 사용하는 문자 집합이다. SBCS와 MBCS의 한계를 극복하기 위해 나온 방식으로, 한글, 중국어, 일본어와 같은 문자열 처리에 사용된다.
- DBCS는 MBCS와 유사하지만, 한 문자를 표현하기 위해 2바이트 이상을 사용하며, 모든 문자가 같은 길이의 바이트를 사용하지 않는다. 문자당 사용하는 바이트 수가 고정되어 있지 않아 SBCS나 MBCS보다 복잡하고 느릴 수 있다.
- 이러한 문제점으로 인해 유니코드를 사용하는 것이 일반적이다.
WBCS(Wide Byte Character Set)
- WBCS(Wide Byte Character Set)는 한 문자를 표현하기 위해 2바이트를 사용하는 문자 집합이다. MBCS와 달리, 모든 문자가 같은 길이의 바이트를 사용하기 때문에 문자열 처리에서 발생할 수 있는 문제점을 해결할 수 있다.
- WBCS는 주로 유니코드(Unicode)를 기반으로 하며, 다양한 언어와 문자를 지원할 수 있다. 유니코드는 전 세계의 모든 문자를 표현하기 위한 국제 표준이며, WBCS는 유니코드를 사용하여 다국어 문자열을 처리하기 위한 방법 중 하나이다.
- WBCS는 여러 개의 바이트를 사용하기 때문에, SBCS보다는 더 복잡하고 느리지만, 다양한 언어와 문자를 지원할 수 있어 현대의 다국어 시스템에서 많이 사용된다. WBCS를 사용하면 한 문자당 사용하는 바이트 수가 고정되어 있기 때문에 문자열 처리가 더 간단해집니다.
- WBCS는 다국어를 처리하는 데에는 적합하지만, 바이트 수가 크기 때문에 메모리와 디스크 공간을 많이 사용한다. 다국어를 처리하지 않는 시스템에서는 SBCS나 MBCS를 사용하는 것이 더 효율적일 수 있다.
- 대표적인 WBCS로는 UTF-8, UTF-16 등이 있다. UTF-8은 8비트로 문자를 표현하고, UTF-16은 16비트로 문자를 표현한다. 또한 바이트 순서를 지정하는 방법에 따라서 Big-Endian과 Little-Endian으로 나뉜다.
유니코드 (Unicode)
- 전 세계의 모든 문자를 컴퓨터에서 일관되게 표현하고 다룰수 있도록 설계된 표준이다.
- 숫자와 글자, 키와 값이 1:1로 매핑된 형태의 코드로 전 세계의 모든 문자를 특정 숫자(키)와 1:1로 매핑한 것이다.
- UTF-8, UTF-16은 유니코드를 사용하는 인코딩 방식이다. 인코딩 방식은 유니코드표의 숫자(키)를 어떻게 표현하느냐에 따른 방식이다.
- UTF-8은 'A'를 0x41로 표현한다.
- UTF-16은 'A'를 0x0041로 표현한다.
- 'U+' 접두어가 붙어 있으면 유니코드 라는 의미이다.
윈도우에서의 문자열
CP949 / EUC-KR / UTF-8 이 혼합되어 사용됨.
C++로 컴파일을 하면 유니코드를 쓸지 멀티바이트를 쓸지 옵션으로 선택할 수 있음.
- 코드를 짤때 이 문자열 "" 방식이 중요함
- "" 멀티바이트, char
- L"" 유니코드, wchar
- _T("") 매크로, 옵션에 따라 멀티바이트/유니코드를 선택적으
- 파일 저장시 파일을 UTF-8 형식으로 저장할지 EUC-KR 형태로 저장할지 중요함.
2번 설정과 시스템에 언어에 따라 애플리케이션의 한글이 깨져보이는 현상이 있음.
웹페이지에서의 문자열
기본 타입 EUC-KR / UTF-8 (국내 웹페이지), header 에 meta 태그로 아래와 같이 정의
- <meta charset="euc-kr" />
- <meta charset="utf-8" />
- <meta http-equiv="Content-Type" content="text/html; charset=euc-kr" />
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
최근에는 UTF-8 로 통일되는 형태, 웹페이지와 통신하는 서버도 UTF8 형식으로 바꿈
MySql / MariaDB 에서의 문자열
위 이슈와 맞출려 서버 DB에 문자열 셋 영향이 있음
- mysql 기본 문자열은 latin1_swedish_ci = latin1 (cp1252 West European)
- 2000년대 초는 euckr_korean_ci = euckr (EUC-KR Korean): 2 바이트 고정
- 200년대 후반 utf8_general_ci = utf8 (UTF-8 Unicode): 3 바이트 가변
- 2010년 이후 utf8mb4_unicode_ci = utf8mb4 (UTF-8 Unicode): 4 바이트 고정
여전히 기본 문자열은 latin1 으로 세팅되기 때문에 DB를 생성하던지 테이블을 생성할때 utf8mb4 지정이 필요하다.
일렉트론(electron) 에서의 문자열
기본 타입 UTF-8
- 웹페이지가 대부분 utf-8 로 만들어지면서 문자열을 다른 문자열로 변환해야하는 이슈가 없어짐.
러스트(Rust) 에서의 문자열
기본 타입 UTF-8, 기본 문자열 타입
- String: 할당이 필요한 가변형으로 Vec<char> 구조체
- 할당해서 쓰므로 힙 영역에 할당되고 Vec 형태이므로 가변 형태로 상용 가능
- Vec 이므로 C++ 처럼 null 로 끝나지 않음.
- &Str: 고정문자 ("") 스텍영역에 저장
2번에 String 이 Vec 기반에 가변문자열이기 때문에 "" 문자를 넣기 위해서는 메모리 할당 혹은 문자열 변경이 필요하다.
- 기본 문자열은 UTF-8 3바이트(한글) 문자이기 때문에
-
- 다음과 같은 문자열은 메모리 상에 b 처럼 저장된다.
- 예) "c:\\users\\한글\\경로포함"
- "c:\\users\\\xed\x95\x9c\xea\xb8\x80\\\xea\xb2\xbd\xeb\xa1\x9c\xed\x8f\xac\xed\x95\xa8"
- 이 문자열을 10진수로 확인해보면 아래와 같다.
- 99 58 92 117 115 101 114 115 92 -19 -107 -100 -22 -72 -128 92 -22 -78 -67 -21 -95 -100 -19 -113 -84 -19 -107 -88
- 다음과 같은 문자열은 메모리 상에 b 처럼 저장된다.
- 네이티브 플랫폼에서 사용되는 문자열 타입
- OsString / &OsStr
- 이 문자열을 4번과 같이 출력해 보면
- 다음과 같은 문자열은 메모리 상에 b 처럼 저장된다.
- 예) "c:\\users\\한글\\경로포함"
- "c:\\users\\한글\\경로포함"
- 다음과 같은 문자열은 메모리 상에 b 처럼 저장된다.
일렉트론 / 러스트 와 C++ 코드간에 문자열 연동
- 일렉트론과 러스트는 기본적으로 UTF-8 문자열을 사용하기 때문에 특별한 이슈가 없다.
- 러스트와 C++ 코드간에 영문을 전달할때 특별한 이슈가 없다.
- C++ 코드에서 wchar (2바이트) 가 필요한 경우 utf-8 (3바이트) 문자열을 넘기면 인식할 수 없기에 변환이 필요하다.
- 위 러스트 문자열 중 OsString 가 2바이트 형태로 바뀌주나 이걸 wchar 형태로 내보낼 맴버를 찾지 못했다.
- 가이드 문서에는 아래와 같은 함수가 있다고 나오나 실제 빌드를 하면 없다고 나음
- fn into_os_str_bytes(self) -> Vec<u8>
- fn as_os_str_ptr(self) -> Vec<u8>
- 가이드 문서에는 아래와 같은 함수가 있다고 나오나 실제 빌드를 하면 없다고 나음
- 그래서 찾은 방법이 두 자지 모듈 인데
- encoding_rs 에 EUC_KR::encode 이용하여 2바이트 Vec 로 바꾼뒤 null 문자를 포함시키고 C++코드에서 wchar 로 바꾸
- 코드는 정상동작하나 C++코드에서 wchar 로 변경한 경우 C++코드에서 메모리 할당 및 해제가 필요해 번거러움
- widestring 에 U16CString 를 이용하여 변환 ptr (wchar) 바꾸기
- 테스트 결과 U16CString 에서 변환하면서 메모리를 할당하고 해제하기 때문에 사용하기 편함.
- encoding_rs 에 EUC_KR::encode 이용하여 2바이트 Vec 로 바꾼뒤 null 문자를 포함시키고 C++코드에서 wchar 로 바꾸
맥 OS 에서의 문자열
UTF8 은 조금 더 세부적으로 아래와 같이 표현된다. [출처]
정규화 방식 D (NFD) | 정준 분해 |
정규화 방식 C (NFC) | 정준 분해한 뒤에 다시 정준 결합 |
정규화 방식 KD (NFKD) | 호환 분해 |
정규화 방식 KC (NFKC) | 호환 분해한 뒤에 다시 정준 결합 |
NFD (Normalize Form D)
NFD는 모든 음절을 Canonical Decomposition(정준 분해)하여 한글 자모 코드를 이용하여 저장하는 방식이다. 즉, 각을 ㄱ + ㅏ + ㄱ 로 저장하는 방식이다. 이 방식은 현대 한글과 옛 한글을 동일한 방식으로 저장한다는 장점이 있지만 NFC 방식과 비교하여 텍스트의 크기가 커진다는 문제가 있다.
NFD는 macOS 시스템에서 주로 사용한다.
NFC (Normalize Form C)
NFC는 모든 음절을 Canonical Decomposition(정준 분해) 후 Canonical Composition(정준 결합) 하는 방식이다. 즉, 각을 각이라는 하나의 문자로 저장하는 방식이다. 이 방식을 사용하면 NFD 방식보다 텍스트의 사이즈는 작아지게 된다. 하지만, 옛 한글 자모의 결합으로 이루어진 한글 음절 코드가 없으므로 이 음절은 Canonical Composition 하지 못하므로 자소가 분리된 체로 저장하게 된다. 이로 인해, 현대 한글과 옛 한글이 다른 방식으로 저장되므로 텍스트를 처리할 때 유의해야 한다.
NFC는 많은 GNU/Linux 시스템, Windows에서 주로 사용한다.
NFKC, NFKD
NFKC와 NFKD는 또 다른 NFC, NFD 정규화 방식이다. 많은 사람들이 NFC와 NFD만 한글 유니코드를 처리하는데 쓰이고 NFKD/NFD, NFKC/NFC의 차이가 없다고 생각한다. 이는 한글 음절/자모 유니코드에서 호환분해 과정과 정준분해 과정이 동일하기 때문에 생기는 인식이다.
NFKC와 NFKD는 한글자모/한글음절 영역 이외의 한글 유니코드 영역을 처리할 때 유용하게 사용할 수 있다. 다음 표를 참고하면 각 유니코드 클자가 정규화 방식에 따라 어떻게 변하는 가를 확인할 수 있다.
'개발 > 기타' 카테고리의 다른 글
[macOS] 인텔 맥북 터보 부스터 끄기 (0) | 2024.10.15 |
---|---|
[공통] 폰트 (0) | 2024.10.10 |
Chromium Codec, Containers and File Extensions Support (0) | 2023.10.27 |
BananaPI (0) | 2023.10.27 |
CEF (Chromium Embedded Framework) (0) | 2023.10.27 |