SheepDev

인코딩·문자셋

같아 보이는 글자가 서로 다른 이유는?

사용할 도구

같아 보이는 글자도 코드 포인트 열은 다를 수 있습니다. 검색·중복 판정이 눈과 다르면 반복 입력보다 내부를 보는 편이 빠릅니다. Unicode 정보·정규화를 함께 써 실제 차이를 찾습니다.

비슷해 보이는 것을 모두 합치면 안 됩니다. 이름·상품명·수식·ID는 차이를 보존해야 할 수 있습니다. 정규화는 맞춤법 교정도 만능 위험 문자 필터도 아닙니다. 동일시할 범위를 정할 근거로 쓰세요.

é를 두 방식으로 만들기

각 행을 따로 검사
é
é

첫 줄은 U+00E9, 둘째는 U+0065 뒤 U+0301입니다. 보통 é로 보이지만 코드 포인트는 1대2입니다. 줄바꿈을 포함하지 않도록 따로 검사하세요. 글꼴을 바꿔도 내부 열은 바뀌지 않습니다.

둘째 문자열을 정규화하면 NFC는 é로 합성하고 NFD는 e+악센트로 분해합니다. 비교할 정해진 형태를 만듭니다. NFC 결과에 다시 NFC를 해도 안 바뀌는지 시험하세요. 전후 코드 포인트·UTF-8 바이트로 변화를 설명할 수 있습니다.

전각 A와 동그라미 ①는 다른 판단이 필요

호환 문자 실험
A①

NFC는 그대로, NFKC는 A1입니다. 호환 정규화는 검색에 도움되지만 동그라미·전각 차이를 잃습니다. 정규화 검색 키와 표시용 원문을 따로 보관해야 할 수 있습니다.

NFKD도 호환 변환을 하지만 분해형입니다. 네 결과 중 가장 짧은 것을 정답으로 고르지 마세요. 시스템이 같은 형식을 쓰고 없애는 차이를 허용해야 합니다. 나중에 정책을 바꾸면 기존 ID·검색에도 영향이 있습니다.

정규화가 보이지 않는 문자를 지우지는 않습니다

둘째 줄 a와 b 사이에 U+200B가 있습니다
ab
a​b

검사하면 a·b 사이 U+200B를 찾습니다. 폭이 없어도 코드 포인트입니다. NFC·NFKC 모두 ab로 바꾸지 않습니다. 정규화는 보이지 않는 문자를 모두 청소하지 않으며 허용 문자 정책은 별개입니다.

분류는 공백·결합·제어/서식 문자를 찾는 단서이지 전체 문자명 사전이나 안전 판정이 아닙니다. 폭 없는 문자도 언어·렌더링 역할이 있으므로 보이지 않으면 악의적·불필요하다고 단정하지 마세요. 정상 지원 예도 시험하세요.

비슷한 a도 다른 문자 체계일 수 있습니다

라틴 a와 키릴 а
a
а

첫째 U+0061·둘째 U+0430은 글꼴에 따라 비슷하지만 다른 문자 체계이며 NFKC로 합쳐지지 않습니다. 정규화됐다고 사칭용 유사 문자가 사라진 것은 아닙니다. URL·계정 안전은 별도 확인이 필요합니다.

반대로 자체 표로 유사 문자를 모두 바꾸면 다른 언어의 정상 이름을 망칠 수 있습니다. 검색 후보용 느슨한 비교와 로그인·권한 ID 비교는 같은 기준일 필요가 없습니다. 차이를 확인한 뒤 서비스 목적에 맞게 결정하세요.

변경 위치는 편집 이력이 아닙니다

변경 위치는 코드 포인트 배열의 같은 인덱스를 비교합니다. 한 글자가 분해되면 뒷부분도 밀려 여러 차이가 표시됩니다. 편집 횟수·오타 수가 아니므로 전후 전체 열과 문맥을 보세요.

UTF-16 위치와 코드 포인트 위치는 특히 앞에 이모지가 있으면 달라집니다. JavaScript 문자열 오프셋과 코드 포인트 수는 다른 기준입니다. 오류 위치를 맞출 때 단위와 0·1 시작 여부를 통일하세요.

원인을 좁힌 뒤 변환 정책 정하기

원본을 남기고 다른 코드 포인트를 찾은 뒤 NFC로 맞는지·호환 변환이 필요한지·정규화로 안 변하는지 나누세요. 변환 가능한 입력과 원본 유지 대상을 정하고 NFKC를 만능 수리로 쓰지 마세요.

보이는 예와 코드 포인트 열을 함께 기록하세요. 조합·분해 é, 전각 A, 폭 없는 문자, 다른 문자 체계 a를 테스트로 남겨 같아야 할 것과 달라야 할 것을 함께 검증합니다. 한 실패를 고치면서 별개 입력을 합치지 않아야 안정적입니다.

검색에서 같게 보는 것과 원문 수정은 다릅니다

상품 검색에서는 비교용 문자열만 정규화해 전각 A로 ASCII A를 찾게 할 수 있으며 공식 상품명까지 바꿀 필요는 없습니다. 원래 표기와 검색 표기를 분리하면 찾기 쉬우면서 데이터도 보존합니다. NFC와 NFKC 비교는 어떤 차이를 같게 볼지 정하는 과정이지 많이 바꾸거나 적게 바꾸는 쪽이 무조건 좋다는 뜻이 아닙니다.

사용자 ID, 서명 대상 문자열, 비밀번호처럼 일치 규칙이 정해진 데이터에 나중에 정규화를 추가하면 호환성이 바뀔 수 있습니다. 비슷하게 보인다고 저장 데이터를 고쳐도 되는 것은 아닙니다. 코드 포인트를 확인하고 정규화별 변화를 본 뒤 대상 시스템의 비교 규칙과 대조하세요. 원인 발견과 데이터 변경 허용은 별개의 판단입니다.

합성형과 분해형 é, 전각과 ASCII A, 제로 폭 문자 삽입을 각각 작은 사례로 만드세요. 원인을 섞으면 어느 변환이 도움이 됐는지 알기 어렵습니다. 외형뿐 아니라 코드 포인트와 UTF-8 크기도 확인하세요. 비슷해 보이는 모든 문자를 같게 만들기보다 필요한 동등성 범위를 좁게 정해야 잘못된 일치를 피할 수 있습니다.

참고 자료

사용할 도구

가이드 →