엔지니어링 기술

Vanilla JS로 구현하는 URL 파라미터 & 해시 관리 가이드

📅2026년 9월 19일
✍️꼬꼬마 (kkokkmakn)
1인 유니콘 AI-Native
⏱️8분

대표 이미지

여러분, 프레임워크의 화려한 마법에 속기 전에 우리가 먼저 마주해야 할 것은 결국 ‘데이터가 어떻게 흐르는가’라는 본질입니다. SPA(Single Page Application) 구조를 설계할 때 URL 파라미터와 해시 관리는 단순한 기능이 아니라, 사용자 경험을 결정짓는 핵심 State Management의 기초가 되죠. 제가 의료 영상 현장에서 정교한 데이터를 분류하며 얻은 통찰처럼, Vanilla JS로 이 메커니즘을 밑바닥부터 구현해보는 과정은 웹 개발의 기본기를 다지는 아주 단단한 훈련입니다. 복잡한 라이브러리 없이 순수 자바스크립트만으로 상태를 제어하는 이 여정에 함께 참여해 보실래요?

📑 목차

URL 파라미터와 해시의 개념 및 활용성

파라미터 vs 해시 비교

Query Strings (?id=123)의 역할

웹 페이지가 특정 데이터를 ‘기억’하게 만드는 첫 번째 단추는 바로 쿼리 스트링입니다. 단순히 ?id=123이라는 파라미터를 던지는 것은 단순한 데이터 전달를 넘어, 서버와 클라이언트 사이의 맥락(Context)을 공유하는 약속입니다. 저는 의료 영상 현장에서 환자 데이터를 식별할 때 특정 ID 값을 고정값으로 활용하듯, 웹에서도 쿼리 스트링을 통해 사용자 의도(Intent)를 파라미터화하여 페이지가 동적으로 반응하게 만듭니다. Vanilla JS로 URLSearchParams 객체를 활용하면 복잡한 정규식 없이도 특정 데이터를 추출해 UI를 즉각 업데이트할 수 있습니다.

해시(#section)를 통한 딥링크 구현

사용자가 클릭하는 순간, 페이지의 특정 위치로 ‘점프’하는 경험은 사용자 경험(UX)의 핵심입니다. 해시(#)는 URL의 경로를 변경하지 않으면서도 페이지 내부에 가상적인 이정표를 세우는 도구입니다. 딥링크(Deep Link)를 구현할 때 해시는 매우 강력한 무기가 됩니다. 예를 들어, 긴 기술 블로그 포스트에서 특정 섹션으로 바로 이동하는 링크를 만들 때 #header-01과 같은 해시를 활용하면, 사용자는 페이지 전체를 스크롤하지 않고도 원하는 정보에 즉각 도달합니다. 이는 1인 유니콘으로서 생산성을 극대화하는 핵심적인 내비게이션 전략입니다.

상태 동기화와 공유 가능한 URL의 중요성

단순히 화면을 바꾸는 것에 그치지 않고, 현재 페이지의 ‘상태(State)’를 URL에 동기화하는 것은 공유 경제 시대의 필수 요소입니다. 내가 보고 있는 필터링 결과나 스크롤 위치가 URL에 반영되지 않는다면, 친구에게 링크를 보냈을 때 상대방은 첫 페이지부터 다시 시작해야 하는 불편함을 겪게 됩니다. 쿼리 스트링과 해시를 조합하여 ‘공유 가능한 상태(Shareable State)’를 구축하는 것은 기술적 성숙도의 척도입니다. 12대의 노드가 유기적으로 연결되는 홈랩처럼, URL 파라미터는 사용자에게 내가 의도한 정확한 지점을 전달하는 고도로 정교한 통로가 됩니다.

Vanilla JS를 활용한 파라미터 추출 기술

URLSearchParams API 활용법

현장에서 방사선 영상 데이터를 처리할 때 정밀한 데이터 매칭이 중요하듯, 웹 페이지에서도 URL 파라미터는 정확하게 추출되어야 합니다. URLSearchParams 인터페이스는 복잡한 정규식 없이도 쿼리 스트링을 객체 형태로 변환해주는 강력한 도구입니다. 단순히 window.location.search를 파싱하는 수준을 넘어, 반복문이나 get() 메서드를 통해 특정 키값에 대응하는 데이터를 즉각적으로 추출할 수 있습니다. 저는 이 API를 활용해 12대의 Proxmox 노드에서 수집된 상태 데이터를 동적으로 매핑하며 시스템의 ‘데이터 고속도로’를 구축했습니다.

동적 데이터 로딩 및 필터링 예시

사용자가 특정 상품이나 콘텐츠를 클릭했을 때, 페이지 전체를 새로고침 하는 것은 낭비입니다. 대신 URL 파라미터를 활용해 필요한 데이터만 실시간으로 불러오는 ‘동적 로딩’이 핵심입니다. 예를 들어 ?category=home과 같은 파라미터가 입력될 때, 스크립트가 이를 감지하여 API 호출 경로를 결정하고 UI를 업데이트합니다. 이는 1인 유니콘으로서 운영 효율을 극대화하는 핵심 기술이며, 홈랩의 대시보드에 실시간 필터를 적용할 때 제가 즐겨 사용하는 방식입니다.

코드 스니펫: 파라미터 파싱 함수

실제 현장에서 바로 쓸 수 있는 Vanilla JS 기반의 파싱 함수를 공유합니다. 이 함수는 URL에서 searchhash를 분리하여 객체로 반환하며, 복잡한 로직을 최소화해 성능 최적화를 돕습니다.

/**
 * @param {string} url - 현재 페이지의 URL 또는 경로
 * @returns {Object} 파싱된 파라미터 객체
 */
function parseQueryParams(url) {
  const [path_part, query_part] = url.split('?');
  const params = new URLSearchParams(query_part);
  const result = {};

  // 파라미터를 순회하며 객체에 할당
  params.forEach((value, key) => {
    result[key] = value;
  });

  return result;
}

// 예시: 현재 URL에서 추출하여 대시보드 필터링에 적용
const currentUrl = window.location.href;
const params = parseQueryParams(currentUrl);
console.log('Extracted Params:', params);

해시(Hash)를 이용한 SPA 내비게이션

hashchange 이벤트 리스너 활용

현장에서 X-ray 영상 데이터를 처리할 때 데이터 유실을 방지하기 위해 체크섬을 확인하듯, 웹 페이지에서도 상태 변화를 놓치지 않기 위해 hashchange 이벤트를 활용합니다. URL의 # 뒤에 붙는 해시값은 현재 페이지의 ‘상태’를 정의하는 일종의 스냅샷입니다. window.addEventListener('hashchange', ...)를 통해 사용자가 클릭한 버튼이나 링크가 변경될 때마다 특정 함수를 실행하도록 설정하면, 복잡한 상태 관리 로직을 단순화할 수 있습니다. 특히 1인 유니콘으로서 시스템의 복잡도를 낮추는 것이 핵심이라면, 해시 기반 내비게이션은 SPA(Single Page Application)의 가장 기본적이면서도 강력한 기초가 됩니다.

페이지 리로드 없는 섹션 이동

사용자가 버튼을 누를 때마다 전체 페이지를 새로 고침 하는 것은 30년 경력의 숙련공이 매번 도구를 새로 조립하는 것과 같습니다. 비효율적이죠. Vanilla JS에서는 hashchange 발생 시 현재 URL에서 해시 파트만 추출하여 DOM 요소의 idclass에 매칭되는 섹션을 display: block으로 전환하거나, hidden 속성을 제어하는 방식으로 구현합니다. 이 과정에서 페이지 전체를 다시 로드하지 않기 때문에 사용자 경험(UX)이 비약적으로 개선됩니다. 12대의 Proxmox 노드에서 가동률을 유지하며 데이터를 처리하듯, 웹사이트는 단 한 번의 초기 로딩으로 모든 섹션을 미리 준비해두고 해시값에 따라 ‘스위칭’만 수행하는 구조를 택해야 합니다.

History API와 pushState의 원리

단순한 해시 변화를 넘어 더 정교한 경로 제어가 필요할 때는 History API가 등장합니다. pushState는 브라우저의 히스토리 스택에 새로운 상태를 쌓아 올리는 기술로, URL이 바뀌어도 페이지가 리로드되지 않도록 보장합니다. 제가 12개의 노드와 AI 에이전트 파이프라인을 연결할 때 각 경로(Path)를 동적으로 제어하듯, history.pushState()는 웹사이트의 경로를 동적으로 생성하며 ‘뒤로 가기’나 ‘앞으로 가기’ 버튼의 기능을 유지해줍니다. 해시 기반 방식이 단순한 상태 표시라면, History API는 구조적인 경로 이동을 가능하게 하는 핵심 엔진입니다. 이 원리를 이해하고 활용하면 1인 유니콘으로서 구축하는 서비스의 기술적 완성도가 한 단계 격상됩니다.

실무 적용 사례 및 최적화 팁

사용자 경험(UX) 개선을 위한 활용

단순히 URL이 변하는 것이 아니라, 사용자가 페이지를 이동할 때마다 브라우저의 ‘뒤로 가기’ 버튼이나 ‘공유하기’ 기능을 온전히 활용할 수 있도록 설계해야 합니다. 제가 12대의 Proxmox 노드에서 에이전트 파이프라인을 구축할 때도 URL에 상태값을 박는 방식을 택했습니다. 이를 통해 사용자가 특정 필터링 조건이나 페이지 번호를 링크로 복사했을 때, 클릭 한 번으로 정확한 스냅샷이 재현되는 ‘Deep Linking’ 경험을 제공할 수 있습니다.

SPA 아키텍처에서의 상태 관리

SPA(Single Page Application) 구조에서는 URL 파라미터와 해시(#)가 곧 애플리케이션의 현재 상태(State)를 정의하는 유일한 소스 트루스가 되어야 합니다. 저는 1인 유니콘 시스템을 구축하며 멀티 에이전트의 각 상태 값을 해시값에 매핑하여, 페이지 새로고침 시에도 데이터가 휘발되지 않도록 설계했습니다. history.pushStatepopstate 이벤트를 활용해 URL 변화를 감지하고, 이를 앱의 전역 상태와 동기화하는 것이 핵심입니다.

Vanilla JS 기반의 성능 최적화

프레임워크 없이 Vanilla JS로 이 기능을 구현할 때는 ‘이벤트 위임’과 ‘DOM 조작 최소화’가 핵심입니다. 매번 URL을 파싱하여 전체 페이지를 렌더링하는 대신, URLSearchParams API를 사용하여 필요한 값만 추출하고 특정 컴포넌트에만 업데이트를 전달해야 합니다. 12대의 서버 노드 가동률을 관리할 때처럼, 불필요한 리소스 소모를 줄이기 위해 변화가 감지된 파라미터만 선택적으로 반영하는 최적화 기법을 적용하십시오.

이 과정은 제가 의료 영상 현장에서 정밀도를 확보하던 경험과 닮아 있습니다. 데이터의 손실 없이 상태를 전달하는 것이 기술 블로그의 핵심입니다. 이 구조를 활용해 OSMU 부업의 기반을 다지는 Jamstack 아키텍처를 완성해 보세요.

자주 묻는 질문

Q1. Vanilla JS에서 URL 파라미터를 읽을 때 페이지가 새로고침되는 것을 방지하려면?

Vanilla JS에서 window.location.search를 직접 참조하여 파라미터를 읽으면 브라우저가 URL 변화를 감지해 페이지를 재로드할 수 있습니다. 이를 방지하려면 URLSearchParams 객체와 history.pushState 또는 replaceState API를 결합해야 합니다. 상태 변화를 유지하면서 파라미터를 추출할 때는 window.location.href를 문자열로 처리하거나, history.state를 활용해 데이터를 관리하면 페이지 새로고침 없이 깔끔하게 데이터를 처리할 수 있습니다.

Q2. 해시(#)와 쿼리 스트링(?) 중 어떤 상황에 무엇을 쓰는 것이 좋나요?

데이터의 성격과 목적에 따라 선택이 달라집니다. 단순히 페이지 이동이나 UI 상태 변화를 위한 ‘상태값’이라면 해시(#)가 적합합니다. URL을 덮어쓰지 않으면서도 가볍게 처리할 수 있죠. 반면, 검색 엔진 최적화(SEO)나 공유가 필요한 ‘데이터 전송’이 목적이라면 쿼리 스트링(?)을 써야 합니다. 특히 쿼리 스트링은 서버가 정보를 읽을 수 있어 정교한 필터링이나 페이지네이션 구현에 필수적입니다. 현장의 노하우로 보자면, “내부 상태는 해시, 외부 공유는 쿼리”라는 공식이 가장 깔끔한 설계 원칙입니다.

Q3. History API를 사용하여 URL을 변경할 때 주의해야 할 점은?

History API를 사용할 때는 pushStatereplaceState의 차이를 명확히 구분해야 합니다. 새로운 페이지로 이동할 때는 pushState를 사용하여 히스토리 스택을 쌓고, 현재 페이지 내에서의 상태 변경(필터링, 탭 전환 등)은 replaceState를 사용하여 URL이 중복되지 않도록 관리해야 합니다. 특히 모바일 환경에서는 뒤로 가기 버튼 클릭 시 의도치 않은 이전 상태가 반복되는 현상을 방지하기 위해 스택 관리에 유의해야 합니다.

Q4. SPA 구조에서 상태(State)를 URL에 동기화하는 가장 효율적인 방법은?

SPA 구조에서 상태(State)를 URL과 동기화할 때 가장 효율적인 방법은 ‘Single Source of Truth’ 원칙을 고수하며 URL을 유일한 소스로 활용하는 것입니다. UI 상태를 개별 변수로 관리하기보다 Query ParametersHash를 파싱하여 컴포넌트에 주입하는 방식을 택하세요. 특히 React나 Vue 환경이라면 useSearchParams와 같은 훅을 활용해 URL 변경 시 즉각적인 리렌더링을 유도하고, 복잡한 객체는 Base64 인코딩이나 정규화된 경로(Path)를 통해 구조화하는 것이 성능과 사용자 경험 측면에서 가장 최적화된 방식입니다.

마무리

Vanilla JS를 활용해 URL 파라미터와 해시를 제어하는 것은 웹 서비스의 ‘상태 관리’ 기초를 닦는 과정입니다. 복잡한 프레임워크에 의존하기 전, 순수 자바스크립트로 데이터 흐름을 파악하는 것이 기술적 근육을 키우는 핵심이죠. 이 가이드가 여러분의 홈랩 시스템에 정교한 상태 제어 로직을 심는 밑거름이 되길 바랍니다. 지금 바로 코드 스니펫을 복사해 여러분의 프로젝트에 적용해보세요. 더 깊은 Jamstack 아키텍처와 AI 에이전트 자동화 파이프라인 구축에 대한 이야기는 다음 포스트에서 이어집니다.

함께 읽으면 좋은 글

스폰서 링크 / ADVERTISEMENT