헛소리

'.한국' 같은 국가별 퓨니코드 최상위 도메인 구경하기

프로필사진
fienestar
2023. 8. 14. 23:02

구경만 하고 싶으면, '분류 결과'를 검색하거나 스크롤을 내리자

 

몇개월 전, 카카오톡에 '서양.한국' 등을 입력하면 성인 사이트가 나와 이슈가 됐었다. 사실 이는 한글로 만든 도메인으로, a.com 과 같이 그저 url이라서 그런 것 이었는데, 이런 비-알파벳 도메인은 어떤걸 만들 수 있을까?

 

우리가 보통 도메인을 만들게 되면

.com으로 끝날지, .net으로 끝날지 등 도메인의 마지막 .을 기준으로 오른쪽에 있는 최상위 도메인(TLD, Top Level Domain)또한 골라야한다. 사실 앞부분은 유니코드 문자면 어떤 것이든 상관 없으므로, TLD 중 비 알파벳 도메인을 찾아보자

 

TLD의 목록은 https://data.iana.org/TLD/tlds-alpha-by-domain.txt 에서 확인할 수 있다.

여기서 한국을 검색하면 나오질 않는다. 혹시 tlds-alpha-by-domain이라서 비 알파벳 도메인은 없는걸까?

 

사실 도메인에서 비 알파벳이 존재하면 퓨니코드(punycode)라는 인코딩으로 변환되는데, 흔히 url에 %20 과 같이 몇몇 문자를 %로 표기하는것(url encode)과 비슷하게 보면 된다.

 

퓨니코드는 xn--... 라는 방식으로 표시된다. 자세한 스팩이 궁금하다면 RFC 3492, RFC 5891을 참조하고, 변환해보고 싶다면 punycoder.com 를 확인하자.

예를 들어, hello서양.한국의 표니코드 표현은 xn--hello-7r5vh2u.xn--3e0b707e 인데, '.'을 제외하면 전부 바뀐것을 볼 수 있다.

 

즉, 우리는 https://data.iana.org/TLD/tlds-alpha-by-domain.txt 에서 xn--으로 시작하는 tld를 확인하면 된다. 프로그래밍을 통해 필터링후 디코드 해보자. 필자는 node를 이용했다.

 

const { readFile, writeFile } = require("fs/promises");
const punycode = require("punycode");

async function main()
{
    const tlds_txt = (await readFile('./tlds-alpha-by-domain.txt')).toString();
    writeFile('./tlds-parsed.txt', tlds_txt.split('\n').filter(tld => tld.startsWith('XN--')).map(v => {
        return v + ': ' + punycode.toUnicode(v.toLowerCase());
    }).join('\n'));
}

main()

*curl -LOJ https://data.iana.org/TLD/tlds-alpha-by-domain.txt를 통해 간단하게 파일을 다운로드 받을 수 있지만, 프로그래밍으로 fetch해와도 된다.

 

XN--11B4C3D: कॉम
XN--1CK2E1B: セール
..

*전문은 글의 말미에 첨부하겠다

1465개중 퓨니코드로 된 것은 152개 존재한다.

 

이를 언어별로 구분할 수 없을까? 처음엔 papago의 언어 감지 기능을 떠올렸지만, 귀찮으니 chatgpt보고 분류하라고 하자.

*이 글의 범위는 아니지만, chatgpt를 이용해 무언갈 자동화하고 싶다면, json 등의 이미 존재하는 구체적인 스팩을 명시하고 구조에 맞지 않으면 retry하는 방식이 좋다.

*끊기면 이어서 말해달라고 하면 된다.

 

하지만 gpt가 내는 결과는 오류가 꽤 있으므로, gpt를 두번 돌려 diff를 따서 수작업하자. 'diff'라는 명령을 이용해도 좋고, diffchecker.com 이런 사이트를 이용해도 편리하다.

 

이제 이를 국가별로 나눠 json으로 저장해보자

const { readFile, writeFile } = require("fs/promises");
const punycode = require("punycode");

async function main()
{
    const tlds = (await readFile('./with-country.txt')).toString().trim().split('\n').map(v => ({
        punycode: v.split(': ')[0],
        decoded: v.split(': ').slice(1).join(': ').split(' - ')[0],
        country: v.split(': ').slice(1).join(': ').split(' - ').slice(1).join(' - '),
    }));

    const countryToDomains = {};
    for(const tld of tlds){
        countryToDomains[tld.country] ??= [];
        countryToDomains[tld.country].push(tld.punycode + '|' + tld.decoded);
    }

    writeFile('./res.json', JSON.stringify(countryToDomains, null, 4));
}

main();

===

분류 결과

{
    "인도 (India)": [
        "XN--11B4C3D|कॉम",
        "XN--2SCRJ9C|ಭಾರತ",
        "XN--3HCRJ9C|ଭାରତ",
        "XN--45BR5CYL|ভাৰত",
        "XN--45BRJ9C|ভারত",
        "XN--FPCRJ9C3D|భారత్",
        "XN--GECRJ9C|ભારત",
        "XN--H2BREG3EVE|भारतम्",
        "XN--H2BRJ9C|भारत",
        "XN--H2BRJ9C8C|भारोत",
        "XN--I1B6B1A6A2E|संगठन",
        "XN--MGBBH1A71E|بھارت",
        "XN--RVC1E0AM3E|ഭാരതം",
        "XN--S9BRJ9C|ਭਾਰਤ",
        "XN--XKC2DL3A5EE0H|இந்தியா"
    ],
    "일본 (Japan)": [
        "XN--1CK2E1B|セール",
        "XN--BCK1B9A5DRE4C|ファッション",
        "XN--CCK2B3B|ストア",
        "XN--CCKWCXETD|アマゾン",
        "XN--ECKVDTC9D|ポイント",
        "XN--FCT429K|家電",
        "XN--GCKR3F0F|クラウド",
        "XN--GK3AT1E|通販",
        "XN--Q9JYB4C|みんな",
        "XN--TCKWE|コム",
        "XN--QCKA1PMC|グーグル"
    ],
    "중국 (China)": [
        "XN--1QQW23A|佛山",
        "XN--30RR7Y|慈善",
        "XN--3BST00M|集团",
        "XN--3DS443G|在线",
        "XN--3PXU8K|点看",
        "XN--45Q11C|八卦",
        "XN--55QW42G|公益",
        "XN--55QX5D|公司",
        "XN--5SU34J936BGSG|香格里拉",
        "XN--5TZM5G|网站",
        "XN--6FRZ82G|移动",
        "XN--6QQ986B3XL|我爱你",
        "XN--8Y0A063A|联通",
        "XN--9ET52U|时尚",
        "XN--9KRT00A|微博",
        "XN--CZR694B|商标",
        "XN--CZRS0T|商店",
        "XN--CZRU2D|商城",
        "XN--EFVY88H|新闻",
        "XN--FIQ228C5HS|中文网",
        "XN--FIQ64B|中信",
        "XN--FIQS8S|中国",
        "XN--FIQZ9S|中國",
        "XN--FJQ720A|娱乐",
        "XN--FLW351E|谷歌",
        "XN--G2XX48C|购物",
        "XN--HXT814E|网店",
        "XN--IMR513N|餐厅",
        "XN--IO0A7I|网络",
        "XN--JLQ480N2RG|亚马逊",
        "XN--JVR189M|食品",
        "XN--KCRX77D1X4A|飞利浦",
        "XN--KPUT3I|手机",
        "XN--MXTQ1M|政府",
        "XN--NQV7F|机构",
        "XN--NQV7FS00EMA|组织机构",
        "XN--NYQY26A|健康",
        "XN--OTU796D|招聘",
        "XN--PSSY2U|大拿",
        "XN--RHQV96G|世界",
        "XN--ROVU88B|書籍",
        "XN--SES554G|网址",
        "XN--UNUP4Y|游戏",
        "XN--VHQUV|企业",
        "XN--VUQ861B|信息",
        "XN--XHQ521B|广东",
        "XN--ZFR164B|政务"
    ],
    "대한민국 (South Korea)": [
        "XN--3E0B707E|한국",
        "XN--CG4BKI|삼성",
        "XN--T60B56A|닷넷",
        "XN--MK1BU44C|닷컴"
    ],
    "태국 (Thailand)": [
        "XN--42C2D9A|คอม",
        "XN--O3CW4H|ไทย"
    ],
    "이스라엘 (Israel)": [
        "XN--4DBRK0CE|ישראל",
        "XN--9DBQ2A|קום"
    ],
    "아랍 (United Arab Emirates)": [
        "XN--4GBRIM|موقع",
        "XN--MGBAAKC7DVF|اتصالات",
        "XN--MGBAAM7A8H|امارات",
        "XN--MGBCA7DZDO|ابوظبي",
        "XN--NGBRX|عرب"
    ],
    "방글라데시 (Bangladesh)": [
        "XN--54B7FTA0CC|বাংলা"
    ],
    "러시아 (Russia)": [
        "XN--80ADXHKS|москва",
        "XN--80AQECDR1A|католик",
        "XN--80ASEHDB|онлайн",
        "XN--80ASWG|сайт",
        "XN--C1AVG|орг",
        "XN--D1ACJ3B|дети",
        "XN--D1ALF|мкд",
        "XN--P1ACF|рус",
        "XN--P1AI|рф"
    ],
    "카자흐스탄 (Kazakhstan)": [
        "XN--80AO21A|қаз"
    ],
    "세르비아 (Serbia)": [
        "XN--90A3AC|срб"
    ],
    "불가리아 (Bulgaria)": [
        "XN--90AE|бг"
    ],
    "벨라루스 (Belarus)": [
        "XN--90AIS|бел"
    ],
    "싱가포르 (Singapore)": [
        "XN--B4W605FERD|淡马锡",
        "XN--CLCHC0EA0B2G2A9GCD|சிங்கப்பூர்",
        "XN--YFRO4I67O|新加坡"
    ],
    "힌디어 (Hindi)": [
        "XN--C2BR7G|नेट"
    ],
    "유럽연합 (European Union)": [
        "XN--E1A4C|ею"
    ],
    "이집트 (Egypt)": [
        "XN--FHBEI|كوم",
        "XN--WGBH1C|مصر"
    ],
    "스리랑카 (Sri Lanka)": [
        "XN--FZC2C9E2C|ලංකා",
        "XN--XKC2AL3HYE2A|இலங்கை"
    ],
    "홍콩 (Hong Kong)": [
        "XN--FZYS8D69UVGM|電訊盈科",
        "XN--J6W193G|香港",
        "XN--W4R85EL8FHU5DNRA|嘉里大酒店",
        "XN--W4RS40L|嘉里"
    ],
    "우크라이나 (Ukraine)": [
        "XN--J1AEF|ком",
        "XN--J1AMH|укр"
    ],
    "대만 (Taiwan)": [
        "XN--KPRW13D|台湾",
        "XN--KPRY57D|台灣"
    ],
    "몽골 (Mongolia)": [
        "XN--L1ACC|мон"
    ],
    "알제리 (Algeria)": [
        "XN--LGBBAT1AD8J|الجزائر"
    ],
    "오만 (Oman)": [
        "XN--MGB9AWBF|عمان"
    ],
    "사우디아라비아 (Saudi Arabia)": [
        "XN--MGBA3A3EJT|ارامكو",
        "XN--MGBA7C0BBN0A|العليان",
        "XN--MGBERP4A5D4AR|السعودية",
        "XN--NGBC5AZD|شبكة",
        "XN--NGBE9E0A|بيتك"
    ],
    "이란 (Iran)": [
        "XN--MGBA3A4F16A|ایران",
        "XN--MGBAB2BD|بازار",
        "XN--MGBT3DHD|همراه"
    ],
    "모리타니아 (Mauritania)": [
        "XN--MGBAH1A3HJKRD|موريتانيا"
    ],
    "파키스탄 (Pakistan)": [
        "XN--MGBAI9AZGQP6J|پاکستان",
        "XN--MGBGU82A|ڀارت"
    ],
    "요르단 (Jordan)": [
        "XN--MGBAYH7GPA|الاردن"
    ],
    "바레인 (Bahrain)": [
        "XN--MGBBH1A|بارت",
        "XN--MGBCPQ6GPA1A|البحرين"
    ],
    "모로코 (Morocco)": [
        "XN--MGBC0A9AZCG|المغرب"
    ],
    "교황청 (Vatican City)": [
        "XN--MGBI4ECEXP|كاثوليك",
        "XN--TIQ49XQYJ|天主教"
    ],
    "수단 (Sudan)": [
        "XN--MGBPL2FH|سودان"
    ],
    "이라크 (Iraq)": [
        "XN--MGBTX2B|عراق"
    ],
    "말레이시아 (Malaysia)": [
        "XN--MGBX4CD0AB|مليسيا"
    ],
    "마카오 (Macao)": [
        "XN--MIX891F|澳門"
    ],
    "조지아 (Georgia)": [
        "XN--NODE|გე"
    ],
    "시리아 (Syria)": [
        "XN--OGBPF8FL|سورية"
    ],
    "튀니지 (Tunisia)": [
        "XN--PGBS0DH|تونس"
    ],
    "라오스 (Laos)": [
        "XN--Q7CE6A|ລາວ"
    ],
    "그리스 (Greece)": [
        "XN--QXA6A|ευ",
        "XN--QXAM|ελ"
    ],
    "독일 (Germany)": [
        "XN--VERMGENSBERATER-CTB|vermögensberater",
        "XN--VERMGENSBERATUNG-PWB|vermögensberatung"
    ],
    "카타르 (Qatar)": [
        "XN--WGBL6A|قطر"
    ],
    "아르메니아 (Armenia)": [
        "XN--Y9A3AQ|հայ"
    ],
    "팔레스타인 (Palestine)": [
        "XN--YGBI2AMMX|فلسطين"
    ]
}

*누차 언급하지만, gpt에는 오류가 있을 수 있다.

 

한글 tld는 .삼성, .닷넷, .닷컴, .한국이 있음을 확인할 수 있다.

chatgpt의 XN--QCKA1PMC|グーグル 분류가 '국제' 길래 일본으로 수정 후 번역해봤는데, 우리가 아는 그 Google의 일본어 표기여서 독특했다

 

아까 생략했던 디코드된 데이터는 아래와 같다.

XN--11B4C3D: कॉम
XN--1CK2E1B: セール
XN--1QQW23A: 佛山
XN--2SCRJ9C: ಭಾರತ
XN--30RR7Y: 慈善
XN--3BST00M: 集团
XN--3DS443G: 在线
XN--3E0B707E: 한국
XN--3HCRJ9C: ଭାରତ
XN--3PXU8K: 点看
XN--42C2D9A: คอม
XN--45BR5CYL: ভাৰত
XN--45BRJ9C: ভারত
XN--45Q11C: 八卦
XN--4DBRK0CE: ישראל
XN--4GBRIM: موقع
XN--54B7FTA0CC: বাংলা
XN--55QW42G: 公益
XN--55QX5D: 公司
XN--5SU34J936BGSG: 香格里拉
XN--5TZM5G: 网站
XN--6FRZ82G: 移动
XN--6QQ986B3XL: 我爱你
XN--80ADXHKS: москва
XN--80AO21A: қаз
XN--80AQECDR1A: католик
XN--80ASEHDB: онлайн
XN--80ASWG: сайт
XN--8Y0A063A: 联通
XN--90A3AC: срб
XN--90AE: бг
XN--90AIS: бел
XN--9DBQ2A: קום
XN--9ET52U: 时尚
XN--9KRT00A: 微博
XN--B4W605FERD: 淡马锡
XN--BCK1B9A5DRE4C: ファッション
XN--C1AVG: орг
XN--C2BR7G: नेट
XN--CCK2B3B: ストア
XN--CCKWCXETD: アマゾン
XN--CG4BKI: 삼성
XN--CLCHC0EA0B2G2A9GCD: சிங்கப்பூர்
XN--CZR694B: 商标
XN--CZRS0T: 商店
XN--CZRU2D: 商城
XN--D1ACJ3B: дети
XN--D1ALF: мкд
XN--E1A4C: ею
XN--ECKVDTC9D: ポイント
XN--EFVY88H: 新闻
XN--FCT429K: 家電
XN--FHBEI: كوم
XN--FIQ228C5HS: 中文网
XN--FIQ64B: 中信
XN--FIQS8S: 中国
XN--FIQZ9S: 中國
XN--FJQ720A: 娱乐
XN--FLW351E: 谷歌
XN--FPCRJ9C3D: భారత్
XN--FZC2C9E2C: ලංකා
XN--FZYS8D69UVGM: 電訊盈科
XN--G2XX48C: 购物
XN--GCKR3F0F: クラウド
XN--GECRJ9C: ભારત
XN--GK3AT1E: 通販
XN--H2BREG3EVE: भारतम्
XN--H2BRJ9C: भारत
XN--H2BRJ9C8C: भारोत
XN--HXT814E: 网店
XN--I1B6B1A6A2E: संगठन
XN--IMR513N: 餐厅
XN--IO0A7I: 网络
XN--J1AEF: ком
XN--J1AMH: укр
XN--J6W193G: 香港
XN--JLQ480N2RG: 亚马逊
XN--JVR189M: 食品
XN--KCRX77D1X4A: 飞利浦
XN--KPRW13D: 台湾
XN--KPRY57D: 台灣
XN--KPUT3I: 手机
XN--L1ACC: мон
XN--LGBBAT1AD8J: الجزائر
XN--MGB9AWBF: عمان
XN--MGBA3A3EJT: ارامكو
XN--MGBA3A4F16A: ایران
XN--MGBA7C0BBN0A: العليان
XN--MGBAAKC7DVF: اتصالات
XN--MGBAAM7A8H: امارات
XN--MGBAB2BD: بازار
XN--MGBAH1A3HJKRD: موريتانيا
XN--MGBAI9AZGQP6J: پاکستان
XN--MGBAYH7GPA: الاردن
XN--MGBBH1A: بارت
XN--MGBBH1A71E: بھارت
XN--MGBC0A9AZCG: المغرب
XN--MGBCA7DZDO: ابوظبي
XN--MGBCPQ6GPA1A: البحرين
XN--MGBERP4A5D4AR: السعودية
XN--MGBGU82A: ڀارت
XN--MGBI4ECEXP: كاثوليك
XN--MGBPL2FH: سودان
XN--MGBT3DHD: همراه
XN--MGBTX2B: عراق
XN--MGBX4CD0AB: مليسيا
XN--MIX891F: 澳門
XN--MK1BU44C: 닷컴
XN--MXTQ1M: 政府
XN--NGBC5AZD: شبكة
XN--NGBE9E0A: بيتك
XN--NGBRX: عرب
XN--NODE: გე
XN--NQV7F: 机构
XN--NQV7FS00EMA: 组织机构
XN--NYQY26A: 健康
XN--O3CW4H: ไทย
XN--OGBPF8FL: سورية
XN--OTU796D: 招聘
XN--P1ACF: рус
XN--P1AI: рф
XN--PGBS0DH: تونس
XN--PSSY2U: 大拿
XN--Q7CE6A: ລາວ
XN--Q9JYB4C: みんな
XN--QCKA1PMC: グーグル
XN--QXA6A: ευ
XN--QXAM: ελ
XN--RHQV96G: 世界
XN--ROVU88B: 書籍
XN--RVC1E0AM3E: ഭാരതം
XN--S9BRJ9C: ਭਾਰਤ
XN--SES554G: 网址
XN--T60B56A: 닷넷
XN--TCKWE: コム
XN--TIQ49XQYJ: 天主教
XN--UNUP4Y: 游戏
XN--VERMGENSBERATER-CTB: vermögensberater
XN--VERMGENSBERATUNG-PWB: vermögensberatung
XN--VHQUV: 企业
XN--VUQ861B: 信息
XN--W4R85EL8FHU5DNRA: 嘉里大酒店
XN--W4RS40L: 嘉里
XN--WGBH1C: مصر
XN--WGBL6A: قطر
XN--XHQ521B: 广东
XN--XKC2AL3HYE2A: இலங்கை
XN--XKC2DL3A5EE0H: இந்தியா
XN--Y9A3AQ: հայ
XN--YFRO4I67O: 新加坡
XN--YGBI2AMMX: فلسطين
XN--ZFR164B: 政务

 

'헛소리' 카테고리의 다른 글

jekyll 테마 만들기  (0) 2023.08.19