Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 

(시리즈 글이 8개 있습니다.)
.NET Framework: 326. 유니코드와 한글 - 유니코드와 닷넷을 이용한 한글 처리
; https://www.sysnet.pe.kr/2/0/1294

.NET Framework: 411. 유니코드의 "compatibility character"가 뭘까요?
; https://www.sysnet.pe.kr/2/0/1607

.NET Framework: 429. C# - 유니코드 한글 문자열을 ks_c_5601-1987로 변환하는 방법
; https://www.sysnet.pe.kr/2/0/1657

개발 환경 구성: 230. 유니코드의 Surrogate Pair, Supplementary Characters가 뭘까요?
; https://www.sysnet.pe.kr/2/0/1710

.NET Framework: 450. 영문 윈도우에서 C# 콘솔 프로그램의 유니코드 출력 방법
; https://www.sysnet.pe.kr/2/0/1712

.NET Framework: 794. C# - 같은 모양, 다른 값의 한글 자음을 비교하는 호환 분해
; https://www.sysnet.pe.kr/2/0/11710

개발 환경 구성: 407. 유니코드와 한글 - "Hangul Compatibility Jamo"
; https://www.sysnet.pe.kr/2/0/11724

Windows: 176. Raymond Chen이 한글날에 밝히는 윈도우의 한글 자모 분리 현상
; https://www.sysnet.pe.kr/2/0/12369




Raymond Chen이 한글날에 밝히는 윈도우의 한글 자모 분리 현상

우리에게는 "레이몬드 첸의 윈도우 개발 282 스토리"라는 책의 저자로 알려진 Raymond Chen이 이번에는 한글날에 맞춰 윈도우의 한글 자모 분리 현상에 대한 뒷이야기를 남겼습니다.

A consequence of being the first to adopt a standard is that you may end up being the only one to adopt it: The sad story of Korean jamo
; https://devblogs.microsoft.com/oldnewthing/20201009-00/?p=104351

우선 이해를 돕기 위해, 한글 문자를 맥과 윈도우에서 표현하는 방법을 알아보겠습니다.

윈도우의 경우, 가령 '각'이라는 문자를 '각'을 나타내는 0xAC01 2바이트로 나타냅니다.

[윈도우]
 - U+AC01 '각'

반면 맥의 경우에는 '각'이라는 문자를 각각의 초성, 중성, 종성을 따로 분리해 표현을 하지만, 화면에 보여줄 때는 '각'이라고 합쳐서 보여줍니다.

[맥]
 - U+1100 'ᄀ'
 - U+1161 'ᅡ'
 - U+11A8 'ᆨ'

즉, 윈도우의 경우에는 '각'을 표현하기 위해 2바이트가 필요한 반면, 맥의 경우에는 6바이트가 필요(현실적으로는 UTF-8 인코딩을 하므로 윈도우는 3바이트, 맥은 9바이트)합니다. 이것을 유니코드의 정규화 관점에서 보면, 윈도우는 "NFC"를 따르고 맥의 경우에는 "NFD"를 따른다고 설명합니다.

문제는, ICU(Internationl Components for Unicode)도, iOS도, Android도 모두 U+1100, U+1161, U+11A8을 하나의 글자로 합쳐서 보여주는데, 왜 윈도우만 그것을 곧이곧대로 'ᄀ ᅡᆨ'으로 보여주냐는 것입니다. Raymond Chend은 이에 대해 '가장 먼저 표준을 도입하는 선발 주자로써 겪게 되는 아픔'의 한 사례라고 합니다. 실제로, 윈도우는 당시 한국의 산업 표준인 "KS X 1026"에 따라 NFC 방식이 되었다고 합니다.

Korean standard KS X 1026
; http://unicode.org/L2/L2008/08225-n3422.pdf

위의 문서에 "4. KS x 1026-1"을 보면,

  1. Modern Hangul Syllable Blocks - Only code positions of Wanseong (Precomposed) Hangul Syllable block (UAC00 ~ D7A3)
  2. Old Hangul Syllable Blocks - Only code positions of Johab Hangul Jamo block (U11xx)
  3. Two or more code positions of simple letters cannot be concatenated to represent a complex letter.
  4. A Wanseong Syllable block (UAC00 ~ UD7A3) and Johab Hangul letter(s) (U11xx) cannot be concatenated to represent another Hangul Syllable block. Ÿ Implementation algorithms for separating, searching, sorting and normalizing Hangul text syllables.

(3번과 4번은 차치하고) 현대 한글은 "Hangul Syllables"에 해당하는 AC00 ~ D7A3 범위의 완성형 코드를 쓰되, 옛한글(Old Hangul Syllable Blocks)은 "Hangul Jamo"에 해당하는 1100 ~ 11FF 범위의 조합형 코드로 쓴다고 언급이 됩니다. 즉, 일반적인 한글에 해당하는 '각'은 'ᄀ', 'ᅡ', 'ᆨ'로 따로 보관하지 않고 '각(U+AC01)'이라는 2바이트 완성형 한글을 쓰고, 옛 한글 - 예를 들어 '가ᇫ'이라는 글자는 맥에서처럼 "U+1100 U+1161 U+11EB"의 조합형으로 나타내라는 것입니다.

위키백과 문서를 보면 이에 대해 더 쉬운 설명을 포함하고 있는데요,

KS X 1026-1
; https://ko.wikipedia.org/wiki/KS_X_1026-1

위의 문서에 "금지된 조합"을 보면,

1) 조합형 한글 낱자 여러 개를 이용하여 겹낱자를 표현하지 않는다.
    예: ᄖ U+1116 (O),  U+1102 U+1107 (X)

2) 현대 한글 완성자는 반드시 한글 글자 마디(Hangul Syllables, U+AC00~U+D7AF) 영역의 문자로 표현해야 하며, 조합형 한글 낱자로 표현하지 않는다.
    예: 한 U+D55C (O), ᄒ ᅡ ᆫ U+1112 U+1161 U+11AB (X)

3) 옛한글 완성자를 표현할 때 한글 글자 마디 영역의 문자와 조합형 한글 낱자를 섞지 않는다.
    예: 가ᇫ U+1100 U+1161 U+11EB (O), 가ㅿ U+AC00 U+11EB (X)

두 번째 항목이 실제로 많이 볼 수 있는 맥의 표현으로 분명히 "KS X 1026-1" 표준 문서에는 그렇게 하지 말라고 명시하고 있습니다.

이런 설명과 함께, Raymond Chen은 윈도우가 잘못된 이유를 물을 것이 아니라, 오히려 다른 운영체제들의 잘못된 이유를 물어야 한다고 합니다. 즉, 아무도 지키지 않는 표준을 구현한 운영체제들 속에 단 하나의 표준을 구현한 운영체제가 잘못된 것처럼 보이게 된 것입니다.

어쨌든 결국, 이런 상황으로 인해 윈도우가 따르는 공식적인 표준인 NFC 방식과, 그 외의 운영체제들이 따르는 사실상의 표준인 NFD 방식으로 나뉘게 되었다고.




저 스스로가 개발자이다 보니, 사실 개인적인 관점에서 보면 만약 한글을 구현해야 했다면 NFD 방식을 따랐을 것입니다. 왜냐하면... ^^; 그것이 더 구현이 쉽습니다. 완성형 한글 속에서 옛 한글은 조합형으로 표현해야 하는 "KS X 1026-1" 표준보다는 무조건 조합형으로 구현하는 NFD 방식이 확실히 구현상 쉽다는 이점이 있습니다.

그나저나, 여기서 글을 맺으면 좀 아쉽고 Raymond Chen의 글에 달린 덧글에 보면 반박글이 재미있습니다. 즉, 맥과 같은 운영체제들이 구현한 방식이 표준이 아니라고 하는데 사실 유니코드 표준에 NFD 방식의 구현이 "UAX #29" 문서로 명확하게 나와 있다는 것입니다.

Unicode® Standard Annex #29
; http://unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries

(혹시... 저 현란한 문서 좀 정리해 주실 분 계실까요? ^^)

하지만 이에 대해서는 개인적으로 의문인 것이, 해당 문서의 초판 작성자가 "Authors Mark Davis (mark.davis@us.ibm.com)"으로 나오는데, 과연 저 문서를 작성할 때 한글 관련 부분에 대해 한국 측의 의견을 얼마나 잘 반영했느냐입니다. 혹시 이에 대한 이력을 아시는 한글 관련 전문가가 계시다면 덧글 부탁드리겠습니다. ^^




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]







[최초 등록일: ]
[최종 수정일: 10/21/2020]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 



2020-10-14 04시44분
'샾' 등 한글 표현 문제 해결을 위한 공공 정보시스템 한글 처리 가이드라인
; http://m.korea.kr/expertWeb/resources/files/data/document_file/2010/공공%20정보시스템%20한글%20처리%20가이드라인.pdf

"
유니코드에서 한글 표현의 경우 KS X 1026-1으로 표준화되어 있고, 기술표준원 산하 문자코드위원회에서 이를 권고하고 있다
"
정성태
2021-10-20 08시46분
정성태
2022-09-29 04시17분
제 글로 인해 이런 논쟁이 발생했군요. (아마도!)

맥의 한글 파일명 분리에 대한 오해
; https://www.clien.net/service/board/park/17595712

심지어, "'가장 먼저 표준을 도입하는 선발 주자로써 겪게 되는 아픔'의 한 사례"라고 제가 의역한 문장까지 그대로 자신의 문장인 것처럼 사용하는 덧글도 보이고.
정성태

1  2  3  4  5  6  7  8  9  10  11  12  [13]  14  15  ...
NoWriterDateCnt.TitleFile(s)
13298정성태3/27/20233680Windows: 236. Win32 - MessageBeep 소리가 안 들린다면?
13297정성태3/26/20234355Windows: 235. Win32 - Code Modal과 UI Modal
13296정성태3/25/20233693Windows: 234. IsDialogMessage와 협업하는 WM_GETDLGCODE Win32 메시지 [1]파일 다운로드1
13295정성태3/24/20233962Windows: 233. Win32 - modeless 대화창을 modal처럼 동작하게 만드는 방법파일 다운로드1
13294정성태3/22/20234135.NET Framework: 2105. LargeAddressAware 옵션이 적용된 닷넷 32비트 프로세스의 가용 메모리 - 두 번째
13293정성태3/22/20234200오류 유형: 853. dumpbin - warning LNK4048: Invalid format file; ignored
13292정성태3/21/20234329Windows: 232. C/C++ - 일반 창에도 사용 가능한 IsDialogMessage파일 다운로드1
13291정성태3/20/20234741.NET Framework: 2104. C# Windows Forms - WndProc 재정의와 IMessageFilter 사용 시의 차이점
13290정성태3/19/20234246.NET Framework: 2103. C# - 윈도우에서 기본 제공하는 FindText 대화창 사용법파일 다운로드1
13289정성태3/18/20233438Windows: 231. Win32 - 대화창 템플릿의 2진 리소스를 읽어들여 자식 윈도우를 생성하는 방법파일 다운로드1
13288정성태3/17/20233552Windows: 230. Win32 - 대화창의 DLU 단위를 pixel로 변경하는 방법파일 다운로드1
13287정성태3/16/20233707Windows: 229. Win32 - 대화창 템플릿의 2진 리소스를 읽어들여 윈도우를 직접 띄우는 방법파일 다운로드1
13286정성태3/15/20234164Windows: 228. Win32 - 리소스에 포함된 대화창 Template의 2진 코드 해석 방법
13285정성태3/14/20233757Windows: 227. Win32 C/C++ - Dialog Procedure를 재정의하는 방법파일 다운로드1
13284정성태3/13/20233955Windows: 226. Win32 C/C++ - Dialog에서 값을 반환하는 방법파일 다운로드1
13283정성태3/12/20233496오류 유형: 852. 파이썬 - TypeError: coercing to Unicode: need string or buffer, NoneType found
13282정성태3/12/20233820Linux: 58. WSL - nohup 옵션이 필요한 경우
13281정성태3/12/20233727Windows: 225. 윈도우 바탕화면의 아이콘들이 넓게 퍼지는 경우 [2]
13280정성태3/9/20234494개발 환경 구성: 670. WSL 2에서 호스팅 중인 TCP 서버를 외부에서 접근하는 방법
13279정성태3/9/20234043오류 유형: 851. 파이썬 ModuleNotFoundError: No module named '_cffi_backend'
13278정성태3/8/20234015개발 환경 구성: 669. WSL 2의 (init이 아닌) systemd 지원 [1]
13277정성태3/6/20234658개발 환경 구성: 668. 코드 사인용 인증서 신청 및 적용 방법(예: Digicert)
13276정성태3/5/20234336.NET Framework: 2102. C# 11 - ref struct/ref field를 위해 새롭게 도입된 scoped 예약어
13275정성태3/3/20234692.NET Framework: 2101. C# 11의 ref 필드 설명
13274정성태3/2/20234276.NET Framework: 2100. C# - ref 필드로 ref struct 타입을 허용하지 않는 이유
13273정성태2/28/20233973.NET Framework: 2099. C# - 관리 포인터로서의 ref 예약어 의미
1  2  3  4  5  6  7  8  9  10  11  12  [13]  14  15  ...