URL 단축의 구조와 로컬 단축기의 용도
먼저 분명히 해 둘 점이 있습니다. 이 도구는 호스팅되는 단축 URL 서비스가 아닙니다. 발급된 짧은 코드는 이 브라우저의 localStorage에만 저장되므로 다른 기기나 브라우저에서는 열리지 않습니다. 서버 없이 개인적인 링크 목록을 관리하거나, 단축 URL이 실제로 어떻게 동작하는지 이해하려는 용도에 맞습니다. 공유가 목적이라면 실제 리다이렉트 서비스가 필요합니다.
일반적인 단축 URL 서비스가 하는 일
단축 서비스의 핵심은 짧은 코드와 원본 URL을 짝지어 저장하는 것뿐입니다. 사용자가 짧은 URL을 방문하면 서버가 코드로 원본을 조회하고 HTTP 리다이렉트로 보냅니다. 마법은 없고, 필수 요소는 도메인과 그 매핑을 보관할 저장소입니다.
여기서 리다이렉트 상태 코드 선택이 실무적인 차이를 만듭니다. 301(영구)은 브라우저가 캐싱하므로 다음 방문에서 서버를 거치지 않아 빠르지만, 목적지를 바꿔도 이미 캐싱한 브라우저는 예전 주소로 갑니다. 302(임시)는 매번 서버를 거치므로 목적지 변경이 즉시 반영되고 클릭 통계도 정확하게 집계됩니다. 대부분의 단축 서비스가 302를 쓰는 이유입니다.
// GET /aB3xY const original = await db.get(code); // 코드로 원본 조회 if (!original) return res.status(404); await db.incrementClicks(code); // 통계 res.redirect(302, original); // 임시 리다이렉트
사용 방법
- 단축할 URL을 입력하면 짧은 코드가 발급되고 목록에 저장됩니다.
- 목록에서 원본 URL과 코드의 대응을 확인하고 필요할 때 복사합니다.
- 다른 기기에서도 열 수 있는 링크가 필요하면 base64 토큰 링크를 사용하세요. 원본 URL이 링크 안에 인코딩되어 있으므로 저장소 없이 동작합니다.
- 브라우저 데이터를 지우면 목록이 함께 사라지므로, 중요한 목록은 별도로 내보내 보관하세요.
짧은 코드는 어떻게 만드는가
코드 생성 방식은 크게 두 가지입니다. 순번을 62진수(0-9, a-z, A-Z)로 변환하는 방식은 코드가 짧고 충돌이 없지만, 순차적이라 남의 링크를 쉽게 추측해 순회할 수 있습니다. 무작위 문자열을 생성하는 방식은 추측이 어렵지만 충돌 확인이 필요합니다.
길이 선택은 필요한 개수에 달려 있습니다. 62진수 6자리는 약 568억 가지, 7자리는 약 3.5조 가지입니다. 다만 무작위 생성에서는 생일 문제 때문에 전체 공간의 제곱근 수준에 도달하면 충돌이 흔해지므로, 여유 있게 잡고 삽입 시 유일성 제약으로 재시도하는 구조가 안전합니다.
실무에서 놓치기 쉬운 것이 혼동되는 문자입니다. 0과 O, 1과 l과 I는 사람이 옮겨 적을 때 틀리기 쉬우므로, 인쇄물에 쓸 코드라면 이런 문자를 제외한 알파벳을 쓰는 것이 좋습니다. Crockford Base32가 이 목적으로 설계된 인코딩입니다.
단축 URL의 위험과 한계
- 목적지를 알 수 없음: 사용자는 클릭 전에 어디로 가는지 확인할 수 없어 피싱에 이용됩니다. 신뢰할 수 없는 단축 링크는 미리보기 기능(일부 서비스가 +를 붙이면 목적지를 보여 줍니다)으로 확인하세요.
- 링크 로트: 단축 서비스가 문을 닫으면 그 서비스로 만든 모든 링크가 한꺼번에 죽습니다. 실제로 여러 서비스가 종료되며 수많은 링크가 사라졌습니다. 논문이나 장기 보관 문서에는 원본 URL이나 DOI를 쓰는 것이 안전합니다.
- 짧은 코드의 열거 가능성: 순차 코드나 지나치게 짧은 코드는 무작위로 접근해 남의 링크를 수집할 수 있습니다. 비공개 문서 공유 링크를 단축하면 노출 위험이 커집니다.
- 추적: 대부분의 서비스가 클릭 시각, 참조 페이지, 대략적 위치를 수집합니다. 프라이버시가 중요한 맥락에서는 고려해야 합니다.
- SEO: 리다이렉트를 거치는 링크는 검색엔진 관점에서 직접 링크와 다르게 취급될 수 있습니다. 마케팅 목적이라면 자체 도메인의 단축 경로를 쓰는 편이 낫습니다.
자체 단축기를 만든다면
직접 운영하는 것은 생각보다 간단하고, 도메인 신뢰도를 유지할 수 있어 마케팅 링크에 특히 유리합니다. 짧은 도메인을 하나 등록하고 키-값 저장소를 붙이면 됩니다.
- 저장소: 조회가 압도적으로 많고 쓰기는 드물므로 KV 스토어(Redis, Cloudflare KV, DynamoDB)가 잘 맞습니다.
- 엣지 실행: 리다이렉트는 로직이 거의 없으므로 엣지 함수에서 처리하면 전 세계에서 지연이 낮습니다.
- 오픈 리다이렉트 방지: 단축 대상 URL을 검증하지 않으면 당신의 도메인이 피싱 경유지로 쓰입니다. 스킴을 http·https로 제한하고, 가능하면 등록 시 인증을 요구하세요.
- 만료: 필요 없어진 링크가 영구히 사는 것을 막으려면 TTL을 설정할 수 있게 하세요.
- 예약어 처리: /api, /admin 같은 경로와 코드 공간이 겹치지 않게 막아야 합니다.
이런 작업에 씁니다
- 개인적으로 자주 여는 긴 URL 목록을 브라우저에 정리
- 단축 URL의 동작 원리를 실제로 확인하며 학습
- 긴 URL을 base64 토큰 링크로 만들어 저장소 없이 전달
- 단축 코드 길이와 충돌 가능성을 직접 실험
자주 묻는 질문
- 발급한 짧은 링크를 다른 사람에게 보낼 수 있나요?
- 짧은 코드 자체는 보낼 수 없습니다. 이 도구는 서버 없이 브라우저 localStorage에만 매핑을 저장하므로, 다른 사람의 브라우저에는 그 코드에 해당하는 원본이 없습니다. 공유가 필요하면 base64 토큰 링크를 쓰거나 실제 단축 서비스를 이용하세요.
- base64 토큰 링크는 어떻게 동작하나요?
- 원본 URL을 base64로 인코딩해 링크 안에 그대로 담는 방식입니다. 저장소가 필요 없어 어디서든 열리지만, URL이 인코딩되어 있을 뿐 감춰진 것은 아니므로 누구나 디코딩할 수 있습니다. 그리고 원본이 길면 토큰 링크가 원본보다 길어질 수 있어 '단축' 효과는 없습니다.
- 입력한 URL이 외부로 전송되나요?
- 전송되지 않습니다. 브라우저 localStorage에만 저장됩니다. 단, base64 토큰 링크를 만들어 공유하면 그 링크를 받은 사람은 원본 URL을 볼 수 있습니다. 민감한 URL을 토큰 링크로 배포할 때는 이 점을 고려하세요.
- 브라우저를 바꾸면 목록이 사라지나요?
- 사라집니다. localStorage는 브라우저와 도메인 단위로 격리되어 있어 다른 브라우저, 다른 기기, 시크릿 모드에서는 접근할 수 없습니다. 시크릿 모드에서는 세션이 끝나면 삭제되고, 브라우저 데이터 삭제나 사이트 데이터 정리로도 지워집니다.
- 저장할 수 있는 개수에 제한이 있나요?
- localStorage의 용량 제한을 받습니다. 브라우저마다 다르지만 도메인당 5~10MB 정도이고, URL 하나가 수십에서 수백 바이트이므로 실용적으로는 수만 개까지 저장할 수 있습니다. 용량이 차면 저장이 실패하므로 주기적으로 정리하는 편이 좋습니다.
- 짧은 코드가 중복될 수 있나요?
- 이 도구는 저장 시 기존 코드와 겹치지 않도록 처리합니다. 다만 저장소가 브라우저마다 독립적이므로, 서로 다른 브라우저에서 같은 코드가 서로 다른 URL을 가리키는 상황은 얼마든지 생길 수 있습니다. 코드가 전역적으로 유일하다는 보장이 필요하면 중앙 저장소가 있는 서비스가 필요합니다.
💡 참고: 이 도구로 만든 목록은 브라우저 데이터와 함께 사라질 수 있습니다. 오래 보관해야 하는 링크 모음이라면 북마크나 별도 문서에 옮겨 두세요.