💡 URECA/🗒️ 스터디 노트

[URECA] Day58 React PROJ Shop URL

코딩하세현 2025. 4. 22. 15:22
728x90

URL

URL 객체는 웹 주소(URL)를 파싱하고 조작하기 위한 JavaScript의 내장 API

URL 객체를 사용하면 URL의 각 구성 요소(프로토콜, 호스트, 경로, 쿼리 매개변수 등)에 쉽게 접근하고 수정 가능

https://www.example.com:8080/path/to/page?name=value&search=test#section
└─┬─┘   └─────┬─────┘ └─┬──┘└─────┬─────┘└───────┬─────────────┘└──┬──┘
프로토콜     호스트     포트      경로        쿼리 매개변수    해시(프래그먼트)

 

URLSearchParams

URLSearchParams 객체는 URL의 쿼리 문자열(query string)을 쉽게 처리하기 위한 API

URL의 ? 뒤에 오는 부분(예: ?name=value&search=test)을 파싱하여 각 매개변수에 접근하고 조작 가능

 

URL 객체 사용 방법

// URL 객체 생성
const url = new URL('https://www.example.com:8080/path/to/page?name=value&search=test#section');

// URL 구성 요소에 접근
console.log(url.protocol);// 'https:'
console.log(url.hostname);// 'www.example.com'
console.log(url.host);// 'www.example.com:8080'
console.log(url.port);// '8080'
console.log(url.pathname);// '/path/to/page'
console.log(url.search);// '?name=value&search=test'
console.log(url.hash);// '#section'
console.log(url.origin);// 'https://www.example.com:8080'

 

URL 객체 수정하기

const url = new URL('https://www.example.com/cart');

// 경로 변경
url.pathname = '/products';

// 포트 추가
url.port = '3000';

// 쿼리 매개변수 추가
url.searchParams.append('category', 'books');

// 결과 확인
console.log(url.href);// 'https://www.example.com:3000/products?category=books'

상대 URL 처리

// 기본 URL을 기준으로 상대 URL 처리
const baseURL = new URL('https://www.example.com/products/');
const relativeURL = new URL('electronics', baseURL);

console.log(relativeURL.href);// 'https://www.example.com/products/electronics'

4. URLSearchParams 객체 사용 방법

기본 사용법

// 문자열로 URLSearchParams 생성
const params1 = new URLSearchParams('name=value&search=test');

// 객체로 URLSearchParams 생성
const params2 = new URLSearchParams({
  category: 'books',
  author: 'John Doe'
});

// URL 객체의 searchParams 속성을 통해 접근
const url = new URL('https://www.example.com/?page=1&limit=10');
const params3 = url.searchParams;

매개변수 다루기

const params = new URLSearchParams('category=books&price=20&inStock=true');

// 매개변수 값 가져오기
console.log(params.get('category'));// 'books'
console.log(params.get('price'));// '20'
console.log(params.has('inStock'));// true // 매개변수 존재 여부 확인
console.log(params.has('discount'));// false
params.append('author', 'Jane Doe'); // 매개변수 추가

// 매개변수 설정 (이미 존재하면 덮어씀)
params.set('price', '25');

// 매개변수 삭제
params.delete('inStock');

// 모든 매개변수 이름 가져오기
for (const key of params.keys()) {
  console.log(key);// 'category', 'price', 'author'
}

// 모든 매개변수 값 가져오기
for (const value of params.values()) {
  console.log(value);// 'books', '25', 'Jane Doe'
}

// 모든 매개변수 [이름, 값] 쌍 가져오기
for (const [key, value] of params.entries()) {
  console.log(`${key}: ${value}`);
}

// 문자열로 변환
console.log(params.toString());// 'category=books&price=25&author=Jane%20Doe'

/shop 페이지에 접근하기 위해

import { detailPageLoader, shopPageLoader } from './loaders/productsLoaders'

 

브라우저에서 /shop 접속

React Router가 해당 경로의 loader부터 실행

shopPageLoader가 실행

    const filteredRelatedProducts = relatedProducts.filter(p => p.id !== product.id)

    return { product, filteredRelatedProducts }
  } catch (err) {
    console.log('err----', err)
    throw new Response('상품 데이터를 가져오는 중 오류 발생', {
      status: err.status || 500,
    })
  }
}

export const shopPageLoader = async ({ request }) => {
  // console.log('productsLoaders.js:info', request.url)
  const url = new URL(request.url)
  const page = url.searchParams.get('_page') || 1
  const per_page = url.searchParams.get('_per_page') || 12
  const category = url.searchParams.get('category') || ''
  const sort = url.searchParams.get('_sort') || ''
  // const per_page = 12
  let queryString = `_page=${page}&_per_page=${per_page}`
  category ? (queryString += `&category=${category}`) : queryString
  sort ? (queryString += `&_sort=${sort}`) : queryString

  console.log('-----------------', queryString)

  try {
    const products = await getProductsData(queryString)
    console.log('productsLoaders.js:products ----- ', products)

    return { products, per_page }

 

처음 접속할 대 → URL에 아무 파라미터가 없어도 기본값으로 _page = 1, _per_page = 12

category와 sort가 없으면 전체 상품을 기본 정렬로 가져온다. 

 

카테고리 필터 작용

const handleCategoryFilter = category => {
  const params = new URLSearchParams(searchParams)
  params.set('_page', 1)
  params.set('_per_page', per_page)
  category ? params.set('category', category) : params.delete('category')
  navigate(`/shop/?${params}`)
}

 

  • 전체상품 버튼: category 파라미터를 삭제 ('' → 모든 상품)
  • 신상품 버튼: category=new → shopPageLoader에서 필터링됨
  • 인기상품 버튼: category=top → 동일하게 처리됨

정렬 작용 방법

const handleSort = sortOption => {
  const params = new URLSearchParams(searchParams)
  params.set('_page', 1)
  params.set('_sort', sortOption)
  navigate(`/shop/?${params}`)
}

 

 

  • 등록순 → _sort=id
  • 낮은 가격순 → _sort=price
  • 높은 가격순 → _sort=-price
  • 낮은 할인순 → _sort=discount
  • 높은 할인순 → _sort=-discount
더보기

[사용자: /shop 접속]
        ↓
[Router → shopPageLoader 실행]
        ↓
[queryString에 따라 상품 불러옴]
        ↓
[ShopPage → useLoaderData()로 받아서 상품 렌더링]
        ↓
[사용자가 필터/정렬 버튼 클릭]
        ↓
[navigate로 URL 변경 → loader 재실행 → 새로운 상품 렌더링]

 


 

 

1. 접근하자마자 12개의 콘텐츠가 나오게 - 카테고리 구분 없이 나오게

2. 신상품을 나오면 카테고리가 new인 상품만 가져오기

    인기상품은 카테고리가 top인 상품만 가져오기

    등록수는 _sort를 활용하기 (낮은 가격순)

 

더보기

오늘 하루 요약

😭

 

728x90