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

(시리즈 글이 12개 있습니다.)
.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

닷넷: 2307. C# - 윈도우에서 한글(및 유니코드)을 포함한 콘솔 프로그램을 컴파일 및 실행하는 방법
; https://www.sysnet.pe.kr/2/0/13794

개발 환경 구성: 731. 유니코드 - 출력 예시 및 폰트 찾기
; https://www.sysnet.pe.kr/2/0/13798

개발 환경 구성: 732. 모바일 웹 브라우저에서 유니코드 문자가 표시되지 않는 경우
; https://www.sysnet.pe.kr/2/0/13799

닷넷: 2310. .NET의 Rune 타입과 emoji 표현
; https://www.sysnet.pe.kr/2/0/13813




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

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

... 136  137  138  139  140  141  142  [143]  144  145  146  147  148  149  150  ...
NoWriterDateCnt.TitleFile(s)
1480정성태8/22/201337863개발 환경 구성: 194. 윈도우 서버의 80 포트에 대한 port forwarding 설정 방법파일 다운로드1
1479정성태8/14/201325193오류 유형: 183. IIS - 바인딩 추가 시 Object reference not set to an instance of an object 오류 [5]
1478정성태8/14/201328520오류 유형: 182. 윈도우 정품 활성화 오류 - 0x80070426
1477정성태8/14/201327379VC++: 71. codeplex의 Project Austin - 실감나게 책장 넘기는 표현
1476정성태8/13/201335841디버깅 기술: 55. Windbg - 윈도우 핸들 테이블 (2)
1475정성태8/12/201334947.NET Framework: 377. 프로세스가 종료된 후에도 소켓이 살아있다면?파일 다운로드1
1474정성태8/10/201331028오류 유형: 181. 윈도우 8 - WmiPrvSE.exe 프로세스가 CPU 소비하는 현상
1473정성태8/8/201327831VC++: 70. Win32 socket이 Thread-safe할까? [1]파일 다운로드1
1472정성태8/7/201326256.NET Framework: 376. .NET 2.0의 유니코드 관련 문자열 비교 오류
1471정성태8/7/201331012개발 환경 구성: 193. .aspx 확장자 대신 .html 확장자를 사용하는 방법
1470정성태8/6/201327023오류 유형: 180. DISM.exe 0xc1510111 실행 오류
1469정성태8/6/201324084.NET Framework: 375. System.Net.Sockets.Socket이 Thread-safe할까? [2]파일 다운로드1
1468정성태8/6/201322225오류 유형: 179. IIS - No connection could be made because the target machine actively refused it 127.0.0.1:80
1467정성태8/5/201325672Java: 16. IE에 로드된 Java Applet의 다운로드 위치를 확인하는 방법
1466정성태7/27/201331290.NET Framework: 374. C#과 비교한 C++ STL vector 성능 [7]파일 다운로드1
1465정성태7/18/201334574기타: 33. C:\Windows\Installer 폴더의 용량 줄이기 [3]
1464정성태7/15/201322843오류 유형: 178. Visual Studio 2012 Express - ImportCardinalityMismatchException
1463정성태7/15/201323519오류 유형: 177. [DBNETLIB][ConnectionOpen (Connect()).]SQL Server does not exist or access denied.
1462정성태7/5/201326802VC++: 69. geek스러운 C/C++ 퀴즈 문제 [2]
1461정성태6/27/201343354.NET Framework: 373. C# 문자열의 인코딩이란?
1460정성태6/17/201325222.NET Framework: 372. PerformanceCounter - Category does not exist. [1]
1459정성태6/15/201328851Windows: 74. 한글 키가 아닌 영문 키를 기본으로 선택하는 방법 [5]
1458정성태6/13/201329676.NET Framework: 371. CAS Lock 방식이 과연 성능에 얼마나 도움이 될까요? [1]파일 다운로드1
1457정성태6/13/201325883개발 환경 구성: 192. "Probabilistic Programming and Bayesian Methods for Hackers" 예제 코드 실행 방법
1456정성태6/5/201334543.NET Framework: 370. C# - WebKit .NET 사용 [2]파일 다운로드1
1455정성태6/1/201328329.NET Framework: 369. ThreadPool.QueueUserWorkItem의 실행 지연 [4]파일 다운로드1
... 136  137  138  139  140  141  142  [143]  144  145  146  147  148  149  150  ...