Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 
(연관된 글이 1개 있습니다.)
(시리즈 글이 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




C# - 같은 모양, 다른 값의 한글 자음을 비교하는 호환 분해

다음과 같은 질문이 있군요. ^^

문자 질문입니다.
; https://www.sysnet.pe.kr/3/0/5065

위 질문에 링크된 글이 재미있습니다.

같은 모양, 다른 값의 한글 자음
; http://winplz.tistory.com/entry/%ED%95%9C%EA%B8%80-%EC%9E%90%EC%9D%8C-%EB%B9%84%EA%B5%90%EA%B0%99%EC%A7%80%EB%A7%8C-%EB%8B%A4%EB%A5%B8-%EC%9E%90%EC%9D%8C%EB%93%A4

위의 글은 iOS의 Objective C나 Swift 환경으로 설명하는 것 같은데, 닷넷 환경으로 질문을 다시 옮겨 보면 이렇습니다.

{
    string txt1 = "ㄱ";
    string txt2 = "각";

    String nfd = txt1.Normalize(System.Text.NormalizationForm.FormD);
    String nfc = txt2.Normalize(System.Text.NormalizationForm.FormD);

    Console.WriteLine(nfd + ": " + (int)nfd[0]);
    Console.WriteLine(nfc[0] + ": " + (int)nfc[0]);
}

/*
출력 결과:

ㄱ: 12593
ㄱ: 4352
*/

출력 결과가 상이한데, 처음의 'ㄱ'은 한글 자음을 나타내는 문자(유니코드 심벌 명은 "Hangul Letter Kiyeok")이고 두 번째 줄의 경우는 약간 '위 첨자' 식으로 상단에 살짝 떠 있는 초성에서의 'ㄱ'(유니코드 심벌 명은 "Hangul Choseong Kiyeok")을 나타냅니다. 따라서, 어찌 보면 당연히 달라야 하지만 '자음 입력에 따른 검색 엔진'을 구현하는 경우에는 이 결과가 그다지 바람직하지 않습니다.

재미있는 것은, 2개의 문자가 속한 "Unicode Group"입니다.

[그림: "Hangul Jamo"에 속한 "Hangul Letter Kiyeok"]
hangul_unicode_jamo_0.png

[그림: "Hangul Compatibility Jamo"에 속한 "Hangul Choseong Kiyeok"]
hangul_unicode_jamo_1.png

"Hangul Compatibility Jamo"의 wikipedia 설명을 보면,

Hangul Compatibility Jamo
; https://en.wikipedia.org/wiki/Hangul_Compatibility_Jamo

Hangul Compatibility Jamo is a Unicode block containing Hangul characters for compatibility with Korean Standard KS X 1001:1998.

"Hangul Compatibility Jamo" 영역의 문자들은 KS X 1001:1998 표준과 호환하는 글자를 포함한다고 합니다.

KS X 1001
; https://en.wikipedia.org/wiki/KS_X_1001

위의 문서를 보면, KS X 1001은 "KSC-5601"로 불렸던 한글 문자 셋의 새 이름인데, KSC-5601 문자 셋과의 호환을 위해 특별히 유니코드에서 별도로 "Hangul Compatibility Jamo" 그룹에 배치했다는 정도로 받아들이면 되겠습니다.




다시 문제로 돌아와서, 그러니까 텍스트 박스에 글자를 입력할 때 'ㄱ' 글자만을 입력한 경우 유니코드 상의 값은 12593(0x3131: 한글 호환 자모의 'ㄱ')인 반면 검색해야 할 문자열에 포함된 글자들은 초성으로써의 'ㄱ'이기 때문에 값의 비교를 할 수 없다는 것입니다.

당연히 이 문제를 해결하려면 '정규화'를 해야 하고, 정규화 시 글자의 분해를 '정준 분해'가 아닌 '호환 분해'를 하면 됩니다. 따라서 다음과 같이 코딩하는 것으로 해결할 수 있습니다.

{
    string txt1 = "ㄱ";
    string txt2 = "각";

    String nfd = txt1.Normalize(System.Text.NormalizationForm.FormKD);
    String nfc = txt2.Normalize(System.Text.NormalizationForm.FormKD);

    Console.WriteLine(nfd + ": " + (int)nfd[0]);
    Console.WriteLine(nfc[0] + ": " + (int)nfc[0]);
}

/*
출력 결과:

ㄱ: 4352
ㄱ: 4352
*/

보는 바와 같이 2개 모두 (단 자음으로서의 'ㄱ'이 아닌) '초성'으로서의 'ㄱ'으로 값을 비교할 수 있습니다. 자바의 경우에도 Normalizer.normalize 메서드를 지원하므로 Normalizer.Form.NFD 옵션으로 분해해 해결할 수 있습니다.




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

[연관 글]






[최초 등록일: ]
[최종 수정일: 10/5/2018]

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

비밀번호

댓글 작성자
 



2018-10-04 12시33분
[키모] 혹시 반대로 4352의 값을 12593으로 할려면 어떻게 해야하나요?string txt2 = "각"을
String nfc = txt2.Normalize(System.Text.NormalizationForm.FormD);을 했을경우 4352로
나오던데 혹시 반대로 할려면 어떻게 해야할까요?
[guest]
2018-10-04 01시04분
[정환] "각"을 초성 중성 종성으로 분리해서 유니코드로 캐스팅하면 되지 않을까요?
[guest]
2018-10-04 06시45분
[키모] 저 자체가 같은 유니코드인데 값이 다르다는 말씀이신거 같은거 같은데 캐스팅이랑은 다르지 않을까요?
[guest]
2018-10-05 10시43분
다음의 글을 참고하세요.

유니코드와 한글 - "Hangul Compatibility Jamo"
; http://www.sysnet.pe.kr/2/0/11724
정성태
2018-10-07 03시56분
[키모] 아 감사합니다 확인해보겠습니다. :)
[guest]

... 61  62  63  64  65  66  67  68  69  70  71  72  73  74  [75]  ...
NoWriterDateCnt.TitleFile(s)
11770정성태11/5/201819939Graphics: 27. .NET으로 구현하는 OpenGL (1) - OpenGL.Net 라이브러리 [3]파일 다운로드1
11769정성태11/5/201811743오류 유형: 501. 프로젝트 msbuild Publish 후 connectionStrings의 문자열이 $(ReplacableToken_...)로 바뀌는 문제
11768정성태11/2/201811646.NET Framework: 801. SOIL(Simple OpenGL Image Library) - Native DLL 및 .NET DLL 제공
11767정성태11/1/201813128사물인터넷: 55. New NodeMcu v3(ESP8266)의 IR LED (적외선 송신) 제어파일 다운로드1
11766정성태10/31/201814503사물인터넷: 54. 아두이노 환경에서의 JSON 파서(ArduinoJson) 사용법
11765정성태10/26/201812142개발 환경 구성: 420. Visual Studio Code - Arduino Board Manager를 이용한 사용자 정의 보드 선택
11764정성태10/26/201815765개발 환경 구성: 419. MIT 라이선스로 무료 공개된 Detours API 후킹 라이브러리 [2]
11763정성태10/25/201813725사물인터넷: 53. New NodeMcu v3(ESP8266)의 https 통신
11762정성태10/25/201814453사물인터넷: 52. New NodeMCU v3(ESP8266)의 http 통신파일 다운로드1
11761정성태10/25/201814116Graphics: 26. 임의 축을 기반으로 3D 벡터 회전파일 다운로드1
11760정성태10/24/201810578개발 환경 구성: 418. Azure - Runbook 내에서 또 다른 Runbook 스크립트를 실행
11759정성태10/24/201811321개발 환경 구성: 417. Azure - Runbook에서 사용할 수 있는 다양한 메서드를 위한 부가 Module 추가
11758정성태10/23/201813396.NET Framework: 800. C# - Azure REST API 사용을 위한 인증 획득 [3]파일 다운로드1
11757정성태10/19/201810855개발 환경 구성: 416. Visual Studio 2017을 이용한 아두이노 프로그램 개발(및 디버깅)
11756정성태10/19/201813166오류 유형: 500. Visual Studio Code의 아두이노 프로그램 개발 시 인텔리센스가 안 된다면?
11755정성태10/19/201814786오류 유형: 499. Visual Studio Code extension for Arduino - #include errors detected. [1]
11754정성태10/19/201811634개발 환경 구성: 415. Visual Studio Code를 이용한 아두이노 프로그램 개발 - 새 프로젝트
11753정성태10/19/201819112개발 환경 구성: 414. Visual Studio Code를 이용한 아두이노 프로그램 개발
11752정성태10/18/201811362오류 유형: 498. SQL 서버 - Database source is not a supported version of SQL Server
11751정성태10/18/201811476오류 유형: 497. Visual Studio 실행 시 그래픽이 투명해진다거나, 깨진다면?
11750정성태10/18/201810261오류 유형: 496. 비주얼 스튜디오 - One or more projects in the solution were not loaded correctly.
11749정성태10/18/201811706개발 환경 구성: 413. 비주얼 스튜디오에서 작성한 프로그램을 빌드하는 가장 쉬운 방법
11748정성태10/18/201812628개발 환경 구성: 412. Arduino IDE를 Store App으로 설치한 경우 컴파일만 되고 배포가 안 되는 문제
11747정성태10/17/201812775.NET Framework: 799. C# - DLL에도 EXE처럼 Main 메서드를 넣어 실행할 수 있도록 만드는 방법파일 다운로드1
11746정성태10/15/201812048개발 환경 구성: 411. Bitvise SSH Client의 인증서 모드에서 자동 로그인 방법파일 다운로드1
11745정성태10/15/201810605오류 유형: 495. TFS 파일/폴더 삭제 - The item [...] could not be found in your workspace, or you do not have permission to access it.
... 61  62  63  64  65  66  67  68  69  70  71  72  73  74  [75]  ...