Punycode / IDN 변환기

유니코드 텍스트를 ASCII Punycode(RFC 3492, xn-- 국제화 도메인 이름 뒤에 있는 인코딩)로 변환하거나 xn-- 레이블/도메인을 원래 문자로 디코딩합니다. 단일 레이블(예: 中文)이나 점으로 구분된 전체 도메인(예: 例え.jp)을 입력할 수 있으며, 비 ASCII 레이블은 각각 독립적으로 인코딩됩니다. 함께 보기: URL 인코더 | Ascii85 | Base32 / Base58.
모든 처리는 브라우저에서 로컬로 이루어지며 아무것도 업로드되지 않습니다.
Punycode를 처음 들어보셨나요? Punycode란 무엇인가 — 알기 쉬운 설명(예시, 오해, 실제로 걸리는 규칙 포함).
작동 방식: 비 ASCII 문자를 하나라도 포함하는 레이블(CJK, 악센트 라틴, 이모지 등)은 ASCII Punycode로 변환되어 xn-- 접두사가 붙습니다. 순수 ASCII 레이블(및 끝 점에서 나오는 빈 부분)은 변경 없이 통과합니다. 기본 ASCII 문자만으로 된 레이블은 절대 변하지 않습니다.
예시: 中文 → xn--fiq228c · 例え.jp → xn--r8jz45g.jp · bücher.de → xn--bcher-kva.de · 😂.com → xn--e28h.com
작동 방식: xn--로 시작하는 모든 레이블(대소문자 무관 접두사)은 유니코드로 디코딩되고, 다른 ASCII 레이블은 변경 없이 통과합니다. 인코딩된 부분(마지막 하이픈 뒤)의 대문자 A-Z는 모호하여 거부됩니다 — 소문자 A 레이블을 붙여넣으세요.
입력창에서 Ctrl+Enter를 누르면 현재 모드가 실행됩니다.
방향을 선택하고 실행하세요. 모든 처리는 브라우저 안에서 이루어집니다.
RFC 3492 Punycode 한눈에 보기:
Punycode는 부트스트링 인코딩입니다. 기본 ASCII 코드 포인트(문자, 숫자, 하이픈)를 먼저 복사한 뒤, 나머지 비 ASCII 코드 포인트를 하나씩 바이어스 적응형 가변 길이 기수 36 인코딩(숫자는 a-z 다음 0-9)으로 작은 정수 시퀀스에 삽입합니다. 도메인 이름에서는 인코딩된 각 레이블에 xn--가 붙어 브라우저와 DNS가 일반 레이블과 구별할 수 있습니다. 코드 포인트 -는 복사된 ASCII 부분과 인코딩된 부분의 구분자 역할을 합니다.

공개 벡터 — 中文 → xn--fiq228c, 例え → xn--r8jz45g, 中国 → xn--fiqs8s, bücher → xn--bcher-kva.
Punycode란 무엇인가?
한 문장으로: Punycode는 순수 영문자가 아닌 문자 — 중국어, 악센트 라틴, 키릴, 이모지 — 를 도메인 이름 시스템이 설계된 37문자(a-z, 0-9, -)만으로 표기하는 방법입니다. RFC 3492에 정의되어 있으며, 도메인 이름에서는 xn-- 접두사로 알아볼 수 있습니다: 中文는 xn--fiq228c가 됩니다.

따라서 Punycode는 언어도, 글꼴도, 국가 코드도 아닙니다 — 같은 이름의 두 철자 사이 번역입니다. 유니코드 철자를 U 레이블(中文.com, bücher.de)이라 하고, ASCII 철자를 A 레이블(xn--fiq228c.com, xn--bcher-kva.de)이라 부르며, 국제 이름을 DNS에 넣는 이 전체 아이디어를 IDN(국제화 도메인 이름) 또는 그 위에 세워진 규칙 집합인 IDNA라 합니다.

Punycode가 존재하는 이유는 DNS가 1980년대 초 의도적으로 아주 작은 알파벳을 중심으로 설계되었기 때문입니다. DNS를 통과해 존 파일, 리졸버 캐시, 로그 줄, TLS 인증서로 가는 호스트 이름은 순수 ASCII여야 합니다 — 전송 형식에는 그 외를 위한 필드가 아예 없습니다. Punycode는 탈출구입니다. ASCII가 아닌 이름이 ASCII인 것처럼 이동하게 하고, 수신 측이 원래 문자를 정확히 재구성하게 합니다. 중국어 도메인이 브라우저에서 작동하는 이유이자, 유니코드 철자를 보낼 수 없는 모든 곳에서 xn--가 보이는 유일한 문자열인 이유입니다.

30초 Punycode
입력값 (U 레이블) DNS가 받는 것 (A 레이블) 의미
中文.comxn--fiq228c.com"중국어"를 뜻하는 중국어 단어
中国xn--fiqs8s중국어로 "중국"
例え.jpxn--r8jz45g.jp일본어 예시
bücher.dexn--bcher-kva.de독일어 bücher, "책"
münchen.dexn--mnchen-3ya.de뮌헨
😂.comxn--e28h.com이모지 레이블 — 인코딩상 유효, 대부분의 등록소에서는 비허용

기억할 만한 길이 비교: 中文은 2자이고 UTF-8로 6바이트지만 xn--fiq228c는 ASCII 11바이트입니다. Punycode는 보통 이름을 길게 만들 뿐 짧게 만들지 않습니다.

인코딩이 실제로 작동하는 방식

bücher를 예로 이 세 단계를 살펴보세요. 엔진은 부트스트링이라 불리고, 알고리즘 전체는 코드 몇십 줄에 불과합니다(이 페이지의 스크립트에서 읽을 수 있습니다).

  1. 순수 문자를 앞으로 복사. 기본 ASCII 문자는 원래 순서대로 복사되어 읽을 수 있게 유지됩니다: bücher → bcher. 무언가 복사되고 동시에 무언가 남았기 때문에 경계로 단일 -가 붙습니다: bcher-.
  2. 나머지를 기수 36 숫자로 기록. 남은 문자들은 코드 포인트 오름차순으로 처리되며, 각각은 a=0 … z=25, 0=26 … 9=35인 가변 길이 기수 36 숫자로 기록됩니다. bücher에서 남는 문자 ü는 숫자 kva가 됩니다.
  3. 접두사 붙이기. 인코딩된 부분을 복사된 부분 뒤에 붙이면 bcher-kva가 되고, 도메인 맥락에서는 xn--bcher-kva로 쓰입니다.

이것을 영리하게 만드는 트릭은 그 기수 36 숫자에 담긴 내용입니다. 문자 자체가 아니라 델타 — 문자가 이전에 인코딩된 코드 포인트에서 얼마나 먼지, 그리고 문자열 안에서 어디에 속하는지. 인코더는 코드 포인트를 오름차순으로 걸으며 각 숫자 나열은 위치와 거리를 기술합니다. 문자 하나마다 바이어스라 불리는 공유 숫자가 조정되어 다음 숫자가 가능한 한 적은 자릿수를 필요로 하게 됩니다.

위에서 직접 확인할 수 있는 두 가지 결과:

  • 비슷한 문자는 저렴. 거리만 저장되므로 같은 문자의 연속은 거의 공짜입니다. 中 30개는 xn--fiqaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(겨우 36바이트)로 인코딩됩니다. 잘 측정된, 서로 다르지만 근처에 있는 중국어 혼합은 유효한 63바이트 레이블 하나에 약 41자를 담고, 단일 반복 문자는 57자에 도달합니다.
  • 흩어진 문자는 비쌉니다. 이전 문자에서 먼 문자는 더 긴 델타 숫자가 필요합니다. 서로 다른 문자가 많은 중국어 텍스트는 보통 문자당 대략 2–3글자가 추가로 들어, 레이블 한도가 63바이트인데도 CJK 레이블은 대략 20–40자에서 공간이 바닥납니다.

디코딩은 같은 레시피를 거꾸로 돌리는 것입니다: ASCII 접두부를 복사하고, 숫자를 읽고, 델타를 코드 포인트로 되돌리고, 델타가 인코딩하는 위치에 각 새 문자를 삽입합니다. 부트스트링에는 소문자 숫자만 존재하므로 인코딩된 부분 안의 대문자는 추측 대신 거부됩니다 — DNS는 대소문자를 구분하지 않으므로 두 케이스를 모두 허용하면 두 가지 다른 철자가 모호해지기 때문입니다.

실제로 만나게 되는 곳
  • 주소창에서. 브라우저는 中文.com 대신 xn--fiq228c.com을 표시할 수 있습니다. 같은 사이트입니다. 일부 브라우저는 이름이 문자 체계를 섞을 때 일부러 Punycode 형태를 보여주는데, 정확히 비슷하게 생긴 문자(키릴 а vs 라틴 a)가 URL에 숨을 수 없게 하기 위해서입니다.
  • DNS 자체에서. 존 파일, dig / nslookup / DNS-over-HTTPS 응답, 리졸버 로그에는 오직 xn-- 형태만 담깁니다. 순수 유니코드는 거부되거나 조용히 깨집니다.
  • TLS 인증서에서. 국제 도메인의 주체 대체 이름은 A 레이블로 저장됩니다(DNS:xn--fiq228c.com). 입력한 이름과 다르게 보이는 인증서는 불일치가 아니라 정상입니다.
  • 설정과 도구에서. 웹 서버의 server_name / 가상 호스트 항목, 쿠키 도메인, 호스팅·CDN 패널, 메일 도메인, 도메인에 묶인 API 키, 데이터베이스 키는 모두 A 레이블 형태가 더 안전합니다.
  • 테스트와 데이터 파이프라인에서. 일부 라이브러리는 유니코드를 리졸버에 그대로 넘겨 실패합니다. 먼저 Punycode로 변환하는 것이 표준 해결책입니다. 매핑이 정준(유니코드 레이블 하나가 정확히 하나의 A 레이블에 대응)이기 때문에 xn-- 형태는 로그와 검색의 안정적인 식별자이기도 합니다.
Punycode가 아닌 것

Punycode는 되돌릴 수 있는 표기법, 그 이상도 이하도 아닙니다. 암호화가 아니고 보안 기능도 아닙니다. 누구나 위의 도구로 디코딩할 수 있으므로 xn-- 레이블은 "인코딩되었다"는 것만 말할 뿐 소유자에 대해서는 아무것도 말하지 않습니다. 압축도 아닙니다 — 보통 텍스트를 길게 만듭니다(위의 6바이트 → 11바이트 예시처럼). 그리고 유니코드가 인터넷을 돌아다니는 다른 방식과 같은 것도 아닙니다. 그들은 문제의 다른 층을 해결합니다.

방식 무엇을 무엇으로 사용되는 곳 中文 →
Punycode (RFC 3492)유니코드 도메인 레이블을 ASCII 문자와 숫자로국제화 도메인 레이블 전용xn--fiq228c
UTF-8 (RFC 3629)코드 포인트를 바이트로모든 파일과 웹 요청E4 B8 AD E6 96 87 (6바이트)
퍼센트 인코딩 (RFC 3986)바이트를 %XX 이스케이프로URL 경로, 쿼리 문자열, 폼 본문%E4%B8%AD%E6%96%87
Base64 (RFC 4648)바이트를 ASCII 64문자로텍스트, JSON, 이메일, data URL 안의 바이너리5Lit5paH
HTML 엔티티코드 포인트를 이름 또는 숫자 참조로HTML 및 XML 소스中文
유니코드 이스케이프코드 포인트를 \uXXXX로소스 코드와 JSON 문자열 리터럴\u4e2d\u6587

실용적 결론: Punycode는 URL의 도메인 레이블에 적용되지 전체 URL에 적용되지 않습니다. 경로와 쿼리 문자열은 다른 문제이며 퍼센트 인코딩을 씁니다(URL 인코더 참고).

실제로 걸리는 한도와 규칙
  • 크기 한도는 Punycode가 아니라 DNS에서 옵니다. 레이블 하나는 최대 63바이트, 전체 이름은 최대 255바이트입니다(RFC 1034/1035). A 레이블은 순수 ASCII이므로 바이트 수가 문자 수와 같고, 비 ASCII 문자 하나가 그 예산의 일부를 씁니다 — 대략 Punycode 글자 1–4개당 예산 1자.
  • Punycode는 무엇이든 변환하고, 등록소는 일부만 허용합니다. IDNA 규칙이 그 위에 얹혀 어떤 코드 포인트가 등록 가능한지 제한합니다 — 대문자, 공백, ! 같은 문장부호, 국기는 실제 도메인에서는 허용되지 않습니다. 이 페이지는 RFC 3492 변환을 수행하므로 등록소가 거부할 텍스트도 기꺼이 인코딩합니다.
  • 하나의 문자 체계에 머무세요. IDNA는 비슷하게 보이는 문자 공격 때문에 단일 레이블 안에서 문자 체계 혼합을 권장하지 않습니다. 인코딩은 되지만 사용 불가능하거나, 사용 가능해도 브라우저가 차단 목록에 올릴 수 있습니다.
  • 이중 인코딩 금지. xn-- 뒤에 이미 인코딩된 텍스트가 오는 것은 무효이고, 순수 ASCII 레이블은 절대 변하지 않습니다 — 인코딩할 것이 없으므로 접두사도 붙지 않습니다.
  • 끝의 점은 괜찮습니다. 例え.jp.는 완전한 정규화 이름이며 끝의 빈 레이블이 유지됩니다. 중간의 빈 레이블은 유효한 호스트 이름이 아닙니다.
빠른 답변

"내 중국어 도메인이 주소창에 왜 xn--fiq228c.com으로 보이나요?"

브라우저가 A 레이블을 표시하기로 선택했기 때문입니다. 사이트는 동일합니다. 이 페이지의 디코딩 방향으로 유니코드 형태를 보거나, 유니코드 형태를 인코딩해 두 철자가 일치하는지 확인하세요.

"DNS 레코드, 인증서, 호스팅을 바꿔야 하나요?"

아니요. 기계가 이름을 읽는 모든 곳(DNS, 인증서, 설정)에서는 xn-- A 레이블을 유지하고, 사람이 읽는 곳에서만 유니코드 형태를 쓰세요.

"결과가 입력보다 왜 길어지나요?"

인코딩이 문자 자체가 아니라 기수 36 거리를 담기 때문이고, 36문자 알파벳은 커질 수 있는 숫자를 풀어 써야 합니다. 늘어나는 것은 버그가 아니라 예상된 동작입니다.

"디코딩이 왜 '대문자'라고 말하나요?"

부트스트링 숫자가 소문자로만 정의되어 있기 때문입니다(a-z, 0-9). 마지막 하이픈 뒤의 대문자 A-Z는 DNS의 대소문자 무관성을 고려하면 모호하므로, 조용히 추측하는 대신 보고됩니다.

"이메일 주소에서 @ 앞 부분에도 Punycode가 적용되나요?"

도메인 부분만 DNS 이름이며 Punycode가 될 수 있습니다. 로컬 부분은 DNS가 아니라 메일 시스템이 다루므로 이 인코딩은 적용되지 않습니다.

"서로 다른 두 유니코드 이름이 같은 A 레이블을 만들 수 있나요?"

아니요. 인코딩은 단사 함수입니다. 서로 다른 코드 포인트 시퀀스는 항상 서로 다른 부트스트링을 만들므로, xn--fiq228c를 디코딩하면 정확히 中文이 되고 다른 것이 나오지 않습니다. 충돌할 수 있는 것은 겉모습 — 비슷하게 생긴 다른 문자 — 이며, 이는 인코딩이 아니라 유니코드 레퍼토리의 성질입니다.

이 페이지가 따르는 표준
  • RFC 3492 — Punycode, 이 페이지에 구현된 부트스트링 인코딩. 위에 인용된 공개 벡터는 해당 문서의 샘플 문자열과 대조하여 검증했습니다.
  • RFC 5890, RFC 5891, RFC 5892와 유니코드 UTS #46 — IDNA2008과 브라우저 측 해석. 어떤 문자가 유효한지 레이블이 어떻게 정규화되며 문자 체계를 어떻게 섞을 수 있는지를 정하는 규칙입니다.
  • RFC 1034와 RFC 1035 — DNS에서 물려받은 63바이트 레이블과 255바이트 이름 한도.
  • RFC 3490과 RFC 3491 — 구세대 IDNA2003으로, IDNA2008이 대체했습니다. 오래된 소프트웨어에서 이름이 다르게 동작한다면 보통 이것이 이유입니다.

범위 참고: 이 도구는 RFC 3492 변환만 수행합니다. IDN 검증기가 아니며 도메인의 등록 규칙, 가격, 사용 가능 여부를 검사하지 않습니다 — 네트워크에 절대 접속하지 않으므로 이름이 존재하는지도 알려줄 수 없습니다.

위에서 시도해 보세요: 中文을 붙여넣고 텍스트 → Punycode 인코딩을 누르면 A 레이블을 볼 수 있고, xn--fiq228c를 붙여넣고 Punycode → 텍스트 디코딩을 누르면 문자가 돌아옵니다.