블로그 목록
frontend

URL.parse()로 안전하게 URL 파싱하기 — new URL() try/catch 그만

폼에서 사용자가 입력한 URL을 다룰 때마다 걸리는 게 있다. new URL()은 문자열이 조금만 이상해도 그냥 예외를 던진다.

new URL('https://example.com'); // OK
new URL('어쩌고');              // Uncaught TypeError: Invalid URL

사용자가 주소창에 뭘 칠지 모르는데, 입력 하나 잘못 들어왔다고 코드가 통째로 죽으면 곤란하다. 그래서 다들 이렇게 감싸서 썼다.

function parseUrl(input) {
  try {
    return new URL(input);
  } catch {
    return null;
  }
}

동작은 하는데, URL 하나 검증하자고 매번 try/catch를 두르는 게 영 거슬린다. 특히 .map() 안에서 여러 개를 처리할 때는 더 지저분해진다.

이제 URL.parse()가 있다

예외를 던지는 대신 실패하면 null을 돌려주는 정적 메서드 URL.parse()가 들어왔다. 인자는 new URL()과 똑같다.

URL.parse('https://example.com'); // URL { ... }
URL.parse('어쩌고');              // null  ← 안 던진다

이제 위의 헬퍼가 통째로 사라진다.

const url = URL.parse(input);
if (!url) {
  setError('올바른 URL이 아닙니다');
  return;
}
console.log(url.hostname); // 바로 파싱된 걸 쓴다

상대 경로를 쓸 때 넣던 두 번째 base 인자도 그대로 동작한다.

URL.parse('/path', 'https://example.com');
// URL { href: 'https://example.com/path', ... }

검증만 할 거면 canParse()

유효한지 참/거짓만 보고 싶다면 짝으로 들어온 URL.canParse()가 더 깔끔하다. URL 객체를 안 만드니까 가볍다.

const urls = ['https://a.com', 'nope', 'https://b.com'];
const valid = urls.filter((u) => URL.canParse(u));
// ['https://a.com', 'https://b.com']

입력란 옆에 실시간으로 "유효한 주소" 표시 붙일 때 딱 좋다.

정리

  • 사용자 입력처럼 깨질 수 있는 URL은 new URL() + try/catch 대신 URL.parse()로 받고 null 체크 한 줄로 끝내라.
  • 통과 여부만 필요하면 URL.canParse()를 써라. 객체를 안 만들어서 더 가볍다.
  • 2026년 기준 최신 Chrome·Firefox·Safari와 Node에는 모두 들어와 Baseline이 됐지만, 구형 환경이 섞여 있으면 지원 여부를 먼저 확인하고 없으면 위의 try/catch 헬퍼를 폴백으로 두면 된다.

URL 유효성 검사 하나 하자고 예외를 잡아 삼키던 코드가 없어지니, 입력 처리 흐름이 훨씬 읽기 편해진다.