URL 정규화: utm 제거하고 표준 링크로

공유하려고 복사한 링크에 utm_source·fbclid·ref 같은 꼬리표가 잔뜩 붙어 있을 때, 이 도구는 정해진 규칙에 따라 그것들을 지우고 하나의 표준(canonical) URL로 정리해 줍니다. 핵심은 '무엇을 지우고 무엇을 남길지'가 코드에 고정돼 있다는 점입니다. 그래서 결과가 어떻게 나올지 미리 예측할 수 있습니다.
이 글은 그 규칙을 하나씩 뜯어보고, 결과 화면에 뜨는 '적용된 변경 사항' 목록을 어떻게 읽는지 설명합니다. '어떤 URL을 써야 하나'가 아니라 '어떻게 계산되고 결과를 어떻게 읽는가'에만 집중합니다.
요약 ① 제거되는 추적 파라미터는
utm_로 시작하는 모든 것 +fbclid·gclid·msclkid·yclid·affiliate·ref(정확히 일치)로 고정돼 있습니다. ② HTTPS 강제는 기본 꺼짐이라, 체크하지 않으면 http 링크는 http 그대로 남습니다. ③ 파라미터 정렬 항목은 남은 파라미터가 2개 이상일 때만 '적용된 변경 사항'에 표시됩니다.
링크 하나가 여러 주소로 보이는 문제
뉴스레터나 광고에서 클릭한 페이지의 주소를 복사해 메신저나 문서에 붙이면, ?utm_source=newsletter&utm_medium=email&fbclid=... 같은 긴 꼬리표가 그대로 따라옵니다. 정작 그 파라미터들은 클릭 출처를 추적하기 위한 것일 뿐, 페이지 내용과는 무관합니다.
문제는 이렇게 꼬리표가 다른 링크가 사람 눈에도, 기계 눈에도 서로 '다른 주소'처럼 보인다는 점입니다. 같은 글인데 ?utm_source=a가 붙은 주소와 아무것도 안 붙은 주소가 별개로 취급될 수 있습니다.
그래서 링크를 공유하거나 정리해 보관하기 전에, 추적용 파라미터를 떼고 남는 것을 일정한 순서로 맞춰 '표준형' 하나로 만드는 작업이 필요합니다. 이것이 URL 정규화입니다.
도구 없이 직접 정규화하는 방법
전부 손으로도 할 수 있습니다. 규칙만 알면 다음 순서를 따르면 됩니다.
- 프로토콜 확인 — 주소 앞에
http://나https://가 없으면http://를 붙여 시작합니다.example.com/foo는http://example.com/foo로 다룹니다. - 호스트 정리 —
://뒤 도메인 부분을 소문자로 바꾸고,:80(http)이나:443(https) 같은 기본 포트가 붙어 있으면 지웁니다.:8080같은 비기본 포트는 그대로 둡니다. - 경로 끝 슬래시 정리 — 경로가 있을 때 그 끝의 슬래시 하나를 뗍니다. 단 도메인 바로 뒤의 루트 슬래시(
example.com/)는 그대로 둡니다. - 추적 파라미터 제거 —
?뒤를&로 쪼갠 뒤, 키가utm_로 시작하거나fbclid·gclid·msclkid·yclid·affiliate·ref중 하나와 정확히 같은 항목을 삭제합니다. 나머지는 남깁니다. - 남은 파라미터 정렬 — 키 기준 알파벳순으로 정렬해 다시
&로 잇습니다.
브라우저 개발자 도구 콘솔에서 URL API를 쓰면 2·3단계를 파서가 자동으로 처리해 줍니다. 이 도구가 내부적으로 하는 것과 같은 방식입니다.
const u = new URL("https://example.com/blog/?utm_source=news&ref=xyz&b=2&a=1");
[...u.searchParams.keys()].forEach(k => {
if (/^utm_/.test(k) || ["fbclid","gclid","msclkid","yclid","affiliate","ref"].includes(k))
u.searchParams.delete(k);
});
u.searchParams.sort();
if (u.pathname !== "/") u.pathname = u.pathname.replace(/\/$/, "");
u.toString(); // => https://example.com/blog?a=1&b=2
이 절차로 나오는 결과는 아래 도구가 같은 입력에 대해 내놓는 결과와 정확히 일치합니다. 저희 도구로 확인하기.
브라우저 안에서만 동작하는 무료 도구로, 입력한 URL은 서버로 전송되지 않으며 가입도 필요 없습니다.

'적용된 변경 사항'을 읽을 때 헷갈리는 것들
가장 많이 오해하는 부분은 '추적기'로 간주되는 파라미터의 범위입니다. utm_는 시작만 맞으면 뭐든 지워지는 접두어 방식이고, 나머지는 이름이 통째로 일치해야만 지워지는 정확일치 방식입니다. 게다가 매칭은 대소문자를 구분합니다.
| 파라미터 예시 | 결과 | 이유 |
|---|---|---|
utm_source, utm_id | 제거 | utm_로 시작 |
ref | 제거 | 정확히 'ref' |
referrer, referral, ref_src | 유지 | 'ref'와 완전히 같지 않음 |
affiliate | 제거 | 정확히 'affiliate' |
affiliate_id | 유지 | 'affiliate'와 다름 |
UTM_Source, Ref | 유지 | 대소문자까지 같아야 함 |
이 밖에도 결과를 읽을 때 자주 헷갈리는 지점이 몇 가지 더 있습니다.
- HTTPS 강제 옵션은 기본으로 꺼져 있습니다. 그래서
http://로 시작하는 주소를 넣어도 체크박스를 켜지 않으면 결과는http://그대로입니다. 프로토콜이 없어 자동으로 붙는 것도http://입니다. https로 바꾸려면 그 옵션을 직접 켜야 합니다. - 파라미터 정렬 항목은 남은 파라미터가 2개 이상일 때만 목록에 뜹니다. 추적기를 걷어낸 뒤 파라미터가 하나만 남으면 정렬할 대상이 없으므로 표시되지 않고, 원래부터 알파벳순이면 바뀔 게 없어 표시되지 않습니다.
- 호스트명 소문자화와 기본 포트(80/443) 제거는 결과에 항상 반영되지만 변경 목록에는 잘 나타나지 않습니다. 브라우저의 URL 파서가 주소를 읽는 단계에서 이미 호스트를 소문자로 바꾸고 기본 포트를 떼기 때문입니다. 그래서 대문자 도메인이나
:443을 넣어도 결과 URL은 이미 정리돼 있고, 목록에는 굳이 표시되지 않는 것입니다. - 끝 슬래시는 경로가 있을 때 그 끝의 슬래시 하나만 제거합니다.
example.com/처럼 도메인 뒤 루트 슬래시만 있는 경우는 건드리지 않습니다.
정리
핵심만 추리면 이렇습니다.
- 지워지는 추적기는
utm_접두어 +fbclid·gclid·msclkid·yclid·affiliate·ref정확일치로 고정돼 있고, 대소문자까지 같아야 합니다. referrer·ref_src·affiliate_id처럼 이름이 조금이라도 다르면 남습니다.- HTTPS 강제는 기본 꺼짐이라, 켜지 않으면 http 링크는 http로 남습니다.
- 파라미터 정렬 문구는 남은 파라미터가 2개 이상이고 순서가 바뀔 때만 표시됩니다.
- 호스트 소문자화와 기본 포트 제거는 결과엔 늘 반영되지만, 파서가 먼저 처리하므로 변경 목록엔 잘 안 뜹니다.
이 규칙들만 알면 결과 URL과 '적용된 변경 사항' 목록이 왜 그렇게 나왔는지 그 자리에서 설명할 수 있습니다.
브라우저 안에서만 동작하는 무료 도구로, 입력한 URL은 서버로 전송되지 않으며 가입도 필요 없습니다.
자주 묻는 질문
ref는 지워지는데 referrer는 왜 남나요?
ref는 정확일치 목록에 들어 있어 이름이 딱 ref일 때만 제거됩니다. referrer·referral·ref_src는 글자가 더 붙어 있어 ref와 완전히 같지 않으므로 그대로 남습니다. 매칭은 대소문자도 구분하기 때문에 Ref(대문자 R)도 남습니다. 접두어 방식으로 지워지는 건 utm_뿐입니다.
http 주소를 넣었는데 https로 안 바뀝니다.
HTTPS 강제 옵션이 기본으로 꺼져 있기 때문입니다. 이 옵션을 켰을 때만 http: 프로토콜이 https:로 바뀝니다. 프로토콜이 없는 주소에 자동으로 붙는 것도 http://이므로, https 결과를 원하면 옵션을 직접 켜 주세요.
파라미터가 하나뿐인데 '정렬' 문구가 안 뜹니다.
정렬 항목은 남은 파라미터가 2개 이상일 때만 '적용된 변경 사항'에 표시됩니다. 하나만 남으면 정렬할 대상이 없고, 여러 개라도 이미 알파벳순이면 바뀔 게 없어 표시되지 않습니다. 이때도 결과 URL 자체는 정상적으로 만들어집니다.
입력한 URL이 서버로 전송되나요?
아니요. 모든 정규화 처리는 브라우저 안 자바스크립트로만 이뤄지며, 입력한 URL은 외부로 전송되지 않습니다. 형식이 올바르지 않은 주소를 넣으면 결과 대신 오류 메시지가 표시됩니다.
