URL 파라미터 정리하기: JavaScript와 React에서

2025. 12. 30. 22:08·개발/개발 아카이브

 

오늘은 URL 파라미터를 정리해보려고 합니다.

URL 파라미터에 대해 간략한 설명과 JS에서 운영하는법, react에서 react-router의 hook들을 사용한 방법들을 소개해보려고합니다.

 

바쁘신 분들은 맨 밑으로 내려가셔서 5. 읏차차 최종정리 (요약) 섹션만 확인해주세요!

 

 

1. URL 파라미터의 종류

URL에는 두 가지 파라미터가 있습니다.

https://example.com/product/123?category=react&page=1
                      ↑         ↑
                 경로 파라미터  쿼리 파라미터

 

 

경로 파라미터 (Path Parameter)

  • URL 경로의 일부: /product/123, /user/kim
  • 필수 값, URL 구조의 핵심입니다.
  • 용도: 특정 리소스 식별 (상품 ID, 사용자 ID)

 

쿼리 파라미터 (Query Parameter)

  • ? 뒤에 key=value 형태: ?page=1&sort=latest
  • 선택 값, 필터링/정렬/페이지네이션에 주로 사용됩니다.
  • 용도: 검색, 필터, 정렬 조건

 

언제 무엇을 쓸까요?

파라미터 예시 사용 시점
경로 /product/123 특정 상품 상세 페이지
쿼리 /products?category=react 상품 목록 필터링
둘 다 /product/123?tab=review 상품 상세의 리뷰 탭

 

 

 

2.  Vanilla JavaScript로 파라미터 조작하기

 

 

 

자 그럼 이제 파라미터를 읽어보고 만져볼까요?

먼저 기본 자바스크립트에서 파라미터 조작하는 방법을 알아보겠습니다.

 

경로 파라미터 읽기

window.location.pathname을 사용하여 경로 파라미터를 확인할 수 있습니다.

// URL: https://example.com/product/123

// 경로 전체
console.log(window.location.pathname); // "/product/123"

// 특정 부분 추출
const id = window.location.pathname.split('/')[2]; // "123"

 

쿼리 파라미터 읽기/쓰기

URLSearchParams를 이용해 쿼리 파라미터를 관리할 수 있습니다.

// URL: https://example.com/products?page=1&category=react

// 1. 읽기
const params = new URLSearchParams(window.location.search);
console.log(params.get('page')); // "1"
console.log(params.get('category')); // "react"

// 2. 추가/수정
params.set('page', '2');
params.set('sort', 'latest');

// 3. 삭제
params.delete('category');

// 4. URL 업데이트 (새로고침 없이)
const newUrl = `${window.location.pathname}?${params.toString()}`;
window.history.pushState({}, '', newUrl);

// 결과: https://example.com/products?page=2&sort=latest

 

주의사항 : 

  • pushState (히스토리 추가)
    • 뒤로가기 스택에 쌓입니다.
    • 이동한 모든 페이지로 뒤로가기가 가능합니다.
  • replaceState (히스토리 교체)
    • 뒤로가기 시 replaceState 사용 이전 페이지로 이동합니다. (히스토리가 교체됩니다)
    • 교체된 URL들은 히스토리에서 사라집니다.
  • 새로고침 없이 URL만 변경되므로 상태 업데이트는 수동 처리가 필요합니다.

 

 

 

3. React에서 파라미터 조작하기

 

 

이번엔 리액트에서 파라미터와 관련된 훅들을 살펴보겠습니다.

주로 react router에서 제공하는 hook들을 사용해서 편하게 구현합니다.

 

물론 React Router 없이 useEffect와 window.location으로 직접 구현할 수도 있겠지만, 우리는 시간이 없습니다.

빨리 잘만들어진거 써서 일해야죠!

 

3-1. useParams - 경로 파라미터 읽기

단순히 경로 파라미터의 값을 가져와야 할 때 사용합니다.

import { useParams } from 'react-router-dom';

// 라우트 설정
<Route path="/product/:id" element={<ProductDetail />} />
<Route path="/user/:userId/post/:postId" element={<Post />} />

// 컴포넌트
export const ProductDetail = () => {
  const { id } = useParams();
  
  console.log(id); // URL이 /product/123이면 "123"
  
  return <div>상품 ID: {id}</div>;
}

export const Post = () => {
  const { userId, postId } = useParams();
  
  return (
    <div>
      사용자: {userId}, 게시글: {postId}
    </div>
  );
}

 

주의사항 :

  • 경로 파라미터 전용, 쿼리 파라미터(?key=value)는 읽을 수 없습니다.
  • 라우트 설정에서 :파라미터명 으로 정의가 필요합니다.

 

3-2. useSearchParams - 쿼리 파라미터 읽기/쓰기

쿼리 파라미터를 읽고 쓸 때 사용합니다.

import { useSearchParams } from 'react-router-dom';

export const ProductList = () => {
  const [searchParams, setSearchParams] = useSearchParams();
  
  // 읽기
  const page = searchParams.get('page') || '1';
  const category = searchParams.get('category') || 'all';
  const sort = searchParams.get('sort');
  
  // 쓰기 - 방법 1: 객체로 전달 (기존 파라미터 모두 교체)
  const handlePageChange = (newPage) => {
    setSearchParams({ page: newPage, category });
  };
  
  // 쓰기 - 방법 2: 함수형 업데이트 (특정 파라미터만 수정)
  const handleCategoryChange = (newCategory) => {
    setSearchParams(prev => {
      prev.set('category', newCategory);
      prev.set('page', '1'); // 카테고리 변경 시 페이지 초기화
      return prev;
    });
  };
  
  // 삭제
  const handleDeleteSort = () => {
    setSearchParams(prev => {
      prev.delete('sort');
      return prev;
    });
  };
  
  // 전체 초기화
  const handleReset = () => {
    setSearchParams({});
  };
  
  return (
    <div>
      <p>페이지: {page}, 카테고리: {category}</p>
      <button onClick={() => handlePageChange('2')}>2페이지</button>
      <button onClick={() => handleCategoryChange('react')}>React 카테고리</button>
      <button onClick={handleReset}>초기화</button>
    </div>
  );
}

 

주의사항 :

  • 객체로 전달 시 기존 파라미터가 모두 교체됩니다.
  • 특정 파라미터만 수정하려면 함수형 업데이트를 사용하면 됩니다.
  • 페이지 전환 없이 같은 페이지에서 쿼리만 변경됩니다.

 

 

4. React 네비게이션 방식

 

 

이번엔 페이지 이동시에 파라미터를 어떻게 관리할지 알아보겠습니다.

React Router는 두 가지 방식으로 페이지 이동을 제공합니다.

 

4-1. 선언적 네비게이션 (Link)

링크를 사용해서 바로 파라미터와 함께 넘어갈 수 있습니다.

import { Link } from 'react-router-dom';

export const Navigation = () => {
  return (
    <nav>
      {/* 경로 파라미터 */}
      <Link to="/product/123">상품 123</Link>
      
      {/* 쿼리 파라미터 */}
      <Link to="/products?category=react&page=1">React 카테고리</Link>
      
      {/* 둘 다 사용 */}
      <Link to="/product/123?tab=review">상품 리뷰</Link>
    </nav>
  );
}

 

특징 :

  • JSX에 직접 작성해야합니다.
  • 사용자가 클릭해야 이동이 가능합니다.
  • 접근성이 자동 처리됩니다. (키보드, 스크린 리더)
  • 브라우저 우클릭 메뉴 사용이 가능합니다. (새 탭에서 열기, 새 창에서 열기, 링크 복사 등) 

 

4-2. 프로그래밍 방식 네비게이션 (useNavigate)

useNavigate를 사용하면 코드로 페이지 이동을 제어할 수 있습니다.

import { useNavigate, useSearchParams } from "react-router-dom";

export const Examples = () => {
  const navigate = useNavigate();
  const [searchParams, setSearchParams] = useSearchParams();

  // 예시 1: 경로 파라미터와 함께 이동
  const goToProduct = (productId: number) => {
    navigate(`/product/${productId}`);
  };

  // 예시 2: 쿼리 파라미터와 함께 이동
  const goToSearch = (keyword: string) => {
    navigate(`/search?q=${keyword}&page=1`);
  };

  // 예시 3: 객체 형태로 전달 (권장)
  const goToFilteredList = (category: string, sort: string) => {
    navigate({
      pathname: "/products",
      search: `?category=${category}&sort=${sort}`,
    });
  };

  // 예시 4: 경로 + 쿼리 파라미터 모두 사용
  const goToProductTab = (id: number, tab: string) => {
    navigate(`/product/${id}?tab=${tab}`);
  };

  // 예시 5: 기존 쿼리 파라미터 유지하며 추가
  const addSortParam = (sortType: string) => {
  	// 같은 페이지에서 쿼리만 변경할 때는 setSearchParams 사용
    setSearchParams(prev => {
      prev.set("sort", sortType);
      return prev;
    });
  };

  // 예시 6: 조건부 이동
  const handleSubmit = async (data: any) => {
    // API 호출 예시 (실제로는 구현 필요)
    const result = { success: true, id: 123 };
    
    if (result.success) {
      navigate(`/success?id=${result.id}`);
    } else {
      navigate("/error");
    }
  };

  // 예시 7: 히스토리에 남지 않고 이동 (replace)
  const redirectToHome = () => {
    navigate("/home", { replace: true });
  };

  return (
    <div>
      <button onClick={() => goToProduct(123)}>상품 보기</button>
      <button onClick={() => goToSearch("react")}>검색</button>
      <button onClick={() => goToFilteredList("react", "latest")}>
        필터 목록
      </button>
      <button onClick={() => goToProductTab(123, "review")}>
        상품 리뷰탭
      </button>
      <button onClick={() => addSortParam("latest")}>최신순 정렬</button>
      <button onClick={() => handleSubmit({})}>제출</button>
      <button onClick={redirectToHome}>홈으로 (replace)</button>
    </div>
  );
};

 

특징 :

  • JavaScript 코드로 제어할 수 있습니다.
  • 조건부 이동이 가능합니다.
  • API 호출, 폼 제출 등 로직 실행 후 이동등에 주로 사용합니다.

 

주의사항 :

  • replace: true 옵션 시 현재 페이지가 히스토리에서 교체되어, 뒤로가기 시 해당 페이지를 건너뜁니다. 주로 다음과 같은 상황에서 사용합니다.
    • 로그인 후 대시보드 이동 시 (뒤로가기로 로그인 페이지 복귀 방지)
    • 결제 완료 페이지 (뒤로가기 방지)
    • 폼 제출 후 (중복 제출 방지)
// 히스토리 상태
홈페이지
  ↓ 링크 클릭
로그인 페이지
  ↓ 로그인 성공 후 navigate("/dashboard", { replace: true })
대시보드 (현재)

// 뒤로가기 누르면?
대시보드 → 홈페이지 (로그인 페이지 건너뜀)
  • 한글/특수문자는 encodeURIComponent 사용이 필요합니다. 설명한 부분 중 녀석만 자동 인코딩이 안됩니다.
navigate(`/search?q=${encodeURIComponent(keyword)}`);
  • 쿼리 스트링 직접 조합 시 조금 복잡해질 수 있어, 객체 방식으로 진행하는 것을 강추드리옵니다.

 

4-3. 언제 무엇을 쓸까요?

상황 방식 예시
네비게이션 메뉴 Link 헤더, 사이드바 링크
목록 아이템 클릭 Link 상품 카드, 게시글 제목
폼 제출 후 이동 useNavigate 로그인, 회원가입, 글 작성
API 성공/실패 분기 useNavigate 결제 완료/실패 페이지
조건부 리다이렉트 useNavigate 권한 없을 시 로그인 페이지
타이머 후 자동 이동 useNavigate 3초 후 메인으로

 

 

5. 읏차차 최종 정리 (요약)

 

바로 요약으로 내려오신 분들 반갑습니다.

 

파라미터 타입별 Hook

파라미터 Hook 읽기 쓰기 페이지전환
경로 파라미터용 useParams 됨 안됨 안됨
쿼리 파라미터용 useSearchParams 됨 됨 안됨
둘 다 가능 useNavigate 안됨 됨 됨

 

네비게이션 방식

방식 도구 사용 시점
선언적 <Link> 사용자 클릭하는 링크
프로그래밍 방식 useNavigate() 코드 실행 후 자동 이동

 

선택 추천 가이드

쿼리 파라미터 조작 시?

  • 같은 페이지에서만 변경 → useSearchParams
  • 다른 페이지로 이동하며 전달 → useNavigate

네비게이션 방식?

  • 단순 링크 → <Link>
  • 조건부 이동/API 후 이동 → useNavigate

경로 파라미터 관련?

  • 읽기만 → useParams
  • 다른 ID로 이동 → useNavigate

 

 

'개발 > 개발 아카이브' 카테고리의 다른 글

동기화 안 되는 main-develop, PR Cherry-pick 전략으로 배포 프로세스 개선해보기  (1) 2025.10.18
디바운스(debounce)와 쓰로틀(throtte) 그리고 디바운스 적용기  (4) 2025.08.08
JavaScript 소수점 시리즈 - ceil, round, floor, trunc  (1) 2025.08.07
웹 스토리지 (로컬 스토리지 / 세션 스토리지) 개념과 조작법 그리고 사용하기 좋은 상황에 대하여  (0) 2025.07.16
간단하게 예제로 알아보는 코드의 자유도  (0) 2025.02.13
'개발/개발 아카이브' 카테고리의 다른 글
  • 동기화 안 되는 main-develop, PR Cherry-pick 전략으로 배포 프로세스 개선해보기
  • 디바운스(debounce)와 쓰로틀(throtte) 그리고 디바운스 적용기
  • JavaScript 소수점 시리즈 - ceil, round, floor, trunc
  • 웹 스토리지 (로컬 스토리지 / 세션 스토리지) 개념과 조작법 그리고 사용하기 좋은 상황에 대하여
dev-oil
dev-oil
개발 그리고 관련한 생각들
  • dev-oil
    dev-oil의 개발 블로그
    dev-oil
  • 전체
    오늘
    어제
    • 분류 전체보기 (14)
      • 개발 (13)
        • 개발 일지 (3)
        • 개발 아카이브 (6)
        • 키워드 (3)
        • 후기 (1)
      • 자유 (1)
        • 회고 (0)
        • 그냥 (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • github
  • 공지사항

  • 인기 글

  • 태그

    github
    참석 후기
    자유도
    git
    URL파라미터
    키워드
    TypeScript
    react
    Programming
    error
    개발생각
    JavaScript
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
dev-oil
URL 파라미터 정리하기: JavaScript와 React에서
상단으로

티스토리툴바