유니코드 문자 검사기
텍스트를 코드 포인트로 분해해 이름, 범주, 블록, 인코딩을 표시. 보이지 않는 문자, 양방향 제어, 닮은꼴 문자도 감지합니다.
이 도구가 하는 일
아무 텍스트나 붙여넣으면 그것이 실제로 이루어진 개별 문자로 분해되어 돌아옵니다. 각각이 유니코드 이름, U+ 번호, 어떤 종류의 문자인지, 어느 문자 체계와 블록에 속하는지, UTF-8과 UTF-16에서 차지하는 바이트, 그리고 여섯 가지 다른 형식의 이스케이프 나열을 얻습니다.
대부분의 사람은 무언가가 맞지 않아 여기 옵니다. 문자열이 보기보다 길거나, 똑같이 표시되는 두 값이 같게 비교되기를 거부하거나, 맨 글자처럼 보이는 것 때문에 사용자 이름이 거부되었거나, 소스 코드 한 줄이 동작과 다르게 읽힙니다. 넷 다 같은 모양입니다: 화면이 보이지 않는 무언가를 하는 문자입니다.
문자, 코드 포인트, 자소
"문자"라는 말은 적어도 세 가지 다른 것을 뜻하고, 그것들을 뒤섞는 데서 대부분의 유니코드 혼란이 시작됩니다. 코드 포인트는 유니코드 표준의 값 하나로, U+0041이나 U+1F600으로 쓰입니다. 자소는 읽는 사람이 한 글자로 세는 것입니다. 둘은 흔히 같은 수가 아닙니다.
- 맨 "a"는 자소 1, 코드 포인트 1, UTF-16 단위 1 — 모두 일치합니다.
- U+00E9, 미리 합성된 e-악센트는 자소 1, 코드 포인트 1, UTF-16 단위 1입니다.
- U+0065 U+0301, e에 결합 악센트를 이은 같은 글자는 자소 1이지만 코드 포인트 2, UTF-16 단위 2입니다.
- U+1F600, 활짝 웃는 얼굴은 자소 1, 코드 포인트 1이지만 UTF-16 단위 2입니다 — BMP 위에 살아 JavaScript가 그것을 서로게이트 쌍으로 저장합니다.
- 가족 이모지는 자소 1, 코드 포인트 5, UTF-16 단위 8입니다: 두 개의 보이지 않는 결합자로 이어진 세 사람.
가족 이모지가 사람을 걸리는 경우입니다. 한 가지로 보이는데 JavaScript는 그 길이를 8로 보고하고, 5글자 데이터베이스 열은 그것을 담지 못합니다. 이 도구는 코드 포인트를 그것이 이루는 자소 아래에 묶어, 머릿속에서 맞춰야 하는 대신 두 읽기가 한꺼번에 보이게 합니다.
볼 수 없는 문자
놀랄 만큼 많은 유니코드 문자가 아무것도 그리지 않습니다. 주변 텍스트가 어떻게 동작할지 제어하려고 있고, 자국을 남기지 않으므로 아무도 눈치채지 못한 채 복사, 붙여넣기, 검토를 살아남습니다. 이것들이 그저 나열하지 않고 이 도구가 짚는 것입니다:
- 폭 없는 공백, 결합자, 비결합자(U+200B, U+200D, U+200C) — 폭도 자국도 없고, 닿는 모든 문자열 비교를 깨뜨립니다.
- 소프트 하이픈(U+00AD) — 단어가 어디서 끊길 수 있는지에 대한 제안으로, 끊길 때까지 보이지 않습니다.
- 줄바꿈 없는 공백(U+00A0) — 공백과 똑같아 보이고 다른 문자라, 설정 파일에서 그토록 오래 살아남습니다.
- 바이트 순서 표시(U+FEFF) — 흔히 파일 맨 앞에 남아, 거기서 첫 값의 보이지 않는 첫 문자가 됩니다.
- 양방향 제어와 재정의(U+202A~U+202E, U+2066~U+2069) — 주변 텍스트를 재배열합니다.
양방향 제어는 따로 언급할 만합니다. 히브리어와 아랍어가 라틴 텍스트와 올바르게 섞이도록 더해졌고, 그 일을 잘 해냅니다. 하지만 주석이나 문자열 리터럴 안에 놓인 재정의는 소스 코드 한 줄을 컴파일러가 읽는 순서와 완전히 다른 순서로 표시하게 할 수 있습니다 — 즉 검토자가 전혀 다른 것을 하는 코드를 승인할 수 있습니다. 그런 종류의 수법은 Trojan Source라 알려져 있고, 그래서 이 도구는 모든 양방향 제어를 다른 보이지 않는 문자와 따로 짚습니다.
닮은꼴 문자와 혼합 문자 체계
유니코드에는 ASCII 글자와 시각적으로 동일하면서 그것이 아닌 문자가 많습니다. 키릴 а, 그리스 ο, 라틴 a는 다른 코드 포인트를 차지하고 대부분의 폰트에서 같게 그려집니다. 그것들로 만든 도메인이나 사용자 이름은 옳아 보이면서 다른 곳을 가리킵니다.
모든 비ASCII 닮은꼴을 짚는 것은 쓸모없을 것입니다: 모든 러시아어, 그리스어, 히브리어 단어를 빨갛게 칠하고, 보통 텍스트에 반응하는 경고는 사람이 넘기기를 배우는 경고입니다. 그래서 여기 규칙은 유니코드 보안 표준이 쓰는 것입니다 — 단어는 그 안의 글자가 둘 이상의 문자 체계에서 올 때 의심스럽습니다:
- 모두 라틴 글자로 쓰인 "paypal.com": 할 말이 없습니다.
- 라틴 "ypal" 앞에 키릴 er과 a를 붙인 같은 단어: 한 단어, 두 문자 체계, 짚힙니다.
- 키릴로 된 러시아어 단어 전체: 한 문자 체계, 보통 텍스트, 짚히지 않습니다.
- Han, 히라가나, 가타카나를 함께 쓰는 일본어 문장: 세 용자, 한 문자 체계, 짚히지 않습니다.
그 마지막 경우가 규칙에 주의가 필요한 이유입니다. 일본어는 세 용자를 한꺼번에 써서 쓰이고 한국어는 둘을 섞으므로, 순진한 "둘 이상의 용자는 의심스럽다" 검사는 모든 일본어 문장을 공격이라 부를 것입니다. 정말로 한 문자 체계인 조합은 하나로 다뤄져, 경고를 의미 있게 유지합니다.
정규화, 또는 왜 동일한 두 문자열이 다른가
어떤 문자는 여러 방식으로 쓸 수 있습니다. 글자 é는 단일 코드 포인트 U+00E9이거나 쌍 U+0065 U+0301 — 맨 e에 결합 예음 악센트를 이은 것 — 중 하나입니다. 둘 다 똑같이 표시됩니다. 어느 쪽도 틀리지 않았습니다. 그것들은 같지 않습니다.
정규화는 하나의 철자를 고르는 과정이고, 네 형식이 있습니다. NFC는 될 수 있는 곳에서 합성하며 웹이 기본으로 가정하는 것이고, NFD는 대신 분해합니다. 두 K 형식은 더 나아가 호환 문자도 접습니다 — 전각 A가 맨 A가 되고, 합자 fi가 fi가 됩니다 — 이는 검색과 대조에 유용하고 저장에는 손실이 있습니다.
여기 패널은 붙여넣은 것의 네 형식 모두를 보이고 그중 어느 것이 입력과 다른지 표시합니다. 어느 것도 다르지 않으면 텍스트는 이미 정규화되어 있고 쫓던 어긋남은 다른 데 있습니다. 몇 개가 다르면 그것을 찾은 것입니다.
이름, 범주, 용자, 블록
할당된 모든 문자는 네 조각의 정체를 지니고, 그것들은 다른 물음에 답합니다. 이름은 문자 그 자체입니다. 일반 범주는 그것이 어떤 종류인지 — 소문자, 결합 문자, 통화 기호, 서식 제어 — 를 말합니다. 용자는 그것이 속한 문자 체계입니다. 블록은 그것이 할당된 코드 포인트의 범위로, 언어적이 아니라 조직상의 사실입니다.
블록과 용자는 헷갈리기 쉽고 흔히 어긋납니다. 라틴 글자는 적어도 여섯 개 블록에 살고, 한 블록이 여러 용자의 문자를 담을 수 있습니다. "이것이 무슨 알파벳인가"를 알고 싶으면 용자가 답이고, "이것이 표준의 어디에 사는가"를 알고 싶으면 블록입니다.
이름, 용자, 블록은 어느 언어에서든 여기서 일부러 영어로 표시됩니다. 그것들은 표준이 정하는 식별자이지 산문이 아니라 — U+200D는 세계 어디서나 ZERO WIDTH JOINER라 이름 붙고, 그것을 번역하면 검색할 수 없게 됩니다.
인코딩과 이스케이프
코드 포인트는 수이고, 인코딩이 골라져야 비로소 바이트가 됩니다. UTF-8은 1에서 4바이트를 쓰고 ASCII를 그대로 두어, 그래서 이겼습니다. UTF-16은 하나나 두 개의 16비트 단위를 쓰고, JavaScript 문자열이 이루어진 것입니다 — 그래서 .length가 단일 이모지에 2를 보고합니다.
U+0041 41 # UTF-8: 1바이트, ASCII와 같음 U+00E9 C3 A9 # UTF-8: 2바이트 U+20AC E2 82 AC # UTF-8: 3바이트 U+1F600 F0 9F 98 80 # UTF-8: 4바이트
여기 각 행은 문자를 JavaScript, JSON, HTML, CSS, URL, Python에서의 이스케이프로도 주어 복사할 수 있게 합니다. 그것들이 모두 같지는 않고, 그 차이는 BMP 위에서 중요합니다: JavaScript와 Python은 코드 포인트 이스케이프를 지녀 쓰고, JSON은 그것이 없어 이모지를 두 개의 서로게이트 반쪽으로 철자해야 합니다.
자주 묻는 질문
- 제 문자열이 보이는 글자 수보다 긴 이유는 무엇인가요?
- 보이지 않는 문자를 담았거나 여러 코드 포인트로 이루어진 자소를 담았거나 둘 중 하나입니다. 둘 다 여기 보입니다: 보이지 않는 문자는 짚히고, 여러 코드 포인트의 자소는 묶여 한 문자와 그것이 이루어진 여러 값이 보입니다.
- 두 문자열이 동일해 보이는데 같지 않습니다. 왜인가요?
- 대개 정규화입니다. 악센트 붙은 글자는 코드 포인트 하나이거나 글자에 결합 문자를 더한 것일 수 있고, 둘 다 같게 표시됩니다. 각 문자열을 여기 붙여넣어 코드 포인트 목록을 비교하거나, 어느 정규화 형식이 입력과 다른지 보세요.
- 폭 없는 공백이란 무엇이고 어떻게 제 텍스트에 들어왔나요?
- 폭도 자국도 없는 문자로, 줄바꿈 기회를 제안하는 데 쓰입니다. 대개 웹 페이지, 문서 편집기, 채팅 클라이언트에서 텍스트를 복사해 들어오고, 아무것도 표시되지 않으므로 무언가가 문자열을 비교해 실패할 때까지 모든 검토를 살아남습니다.
- 코드 포인트와 문자의 차이는 무엇인가요?
- 코드 포인트는 유니코드 값 하나입니다. 일상적 의미의 문자는 자소 — 읽는 사람이 하나로 세는 것 — 이고, 자소는 여러 코드 포인트일 수 있습니다. 가족 이모지는 다섯 코드 포인트와 한 자소입니다.
- 도구가 어떤 문자에 이름이 없다고 하는 이유는 무엇인가요?
- 네 가지 다른 이유가 있고, 어느 것인지 말합니다. 서로게이트와 사용자 영역 코드 포인트는 표준에 이름이 없고, 할당되지 않은 것은 이름 붙일 것이 없고, 좀처럼 살피지 않는 역사적 블록의 문자는 이 빌드가 지니지 않은 이름을 지닙니다 — 이름 표는 전부를 싣기보다 사람이 실제로 붙여넣는 블록을 지닙니다.
- 혼합 문자 체계 경고가 공격의 증거인가요?
- 아니요. 한 단어가 둘 이상의 문자 체계에서 글자를 끌어옴을 뜻하고, 그것은 위장된 이름이 지니는 모양이자 보통 텍스트가 이따금 하는 것이기도 합니다. 볼 이유이지 판정이 아닙니다.
- 제가 붙여넣은 것이 서버로 전송되나요?
- 아니요. 문자 데이터베이스는 페이지와 함께 내려받고 모든 것이 브라우저 안에서 돕니다. 입력한 내용이 업로드·기록되지 않고, 네트워크 연결 없이 동작합니다.