logo

JEONGGON

    블로그
github
mode
목 차
down-arrow

블로그 개발 - URL 파싱

2024.06.01.

post-thumbnail

카테고리, 태그 등 URL의 데이터 파싱하기

앞서, 탭 기능을 구현하면서, 아래와 같이 URL 경로를 설정하였다.


URL
포스트별 /posts/
포스트 태그 /posts/?tag={태그}
카테고리별 /categories/
카테고리 /categories/?category={카테고리}

여기서 태그 검색 페이지와 카테고리 페이지로 이동 시, 경로 뒤에 ?키=값 형태의 Query String을 사용하기로 하였다.

그렇다면 URL의 Query String을 어떻게 가져올 수 있는지 알아보자


⛏️ URL에서 Query String 가져오기

1. query-string 라이브러리 설치

$ yarn add query-string

2. Props 받아오기

Query 정보는 Gatsby에서 페이지를 렌더링할 때, 자동으로 제공하는 location 객체 내의 search 프로퍼티에 들어있다. 이 정보를 props로 가져온다.

// Query 정보 props 전달하기 예시

// TypeScript를 활용하기에 타입 지정
type categoryPageProps = {
  location: {
    search: string
  }
}

// Gatsby가 전달한 location 객체에서 search 속성을 추출
const categoryPage: FC<categoryPageProps> = ({
                                               location: { search }
                                             }) => {
// ...

3. 파싱하기

queryString의 parse 함수는 쿼리 스트링을 파싱하여 ParsedQuery<string> 타입의 객체를 반환한다.

만약 URL이 /categories?page=1&category=git이라면, search?page=1&category=git가 된다.

최종적으로 queryString.parse(search) 함수는 쿼리 스트링을 파싱하여 { page: '1', category: 'git' }와 같은 객체를 반환한다.

// query string 라이브러리의 parse 이용 예제

// ...

const parsed: ParsedQuery<string> = queryString.parse(search)

// 해당 객체에 category 키의 값의 타입이 문자열이 아니거나 아예 category 키가 없는 경우, 빈문자열 반환, 그렇지 않으면 값을 반환
const selectedCategory: string = typeof parsed.category !== "string" || !parsed.category ? "" : parsed.category

// ...

4. 해당 정보로 포스트를 필터링하고 페이지 렌더링하기

// 필터링 및 렌더링 예시

// ...

// 선택된 카테고리에 해당하는 포스트들을 필터링
const selectedEdges = useMemo(() => (
  edges.filter(({ node: { frontmatter: { category } } }) => (
    category === selectedCategory
  ))
), [selectedCategory])

// 페이지를 렌더링
return (
  <BlogTemplate
    title={title}
    description={description}
    url={siteUrl}
    image={publicURL}
  >
    <CategoryWrapper>
      <CategoryItem
        category={selectedCategory}
        active={false}
        position={"sticky"}
      />
      <PostCards edges={selectedEdges} />
    </CategoryWrapper>
  </BlogTemplate>
)

5. Query String 예시 전체 코드

// 예시

import { FC, useMemo } from "react";
import BlogTemplate from "../templates/BlogTemplate";
import CategoryItem from "components/Blog/Category/CategoryItem";
import PostCards from "components/Blog/Post/PostCards";
import queryString, { ParsedQuery } from "query-string";

type categoryPageProps = {
  location: {
    search: string
  }
  data: {
    site: {
      siteMetadata: {
        title: string
        description: string
        siteUrl: string
      }
    }
    allMarkdownRemark: {
      edges: PostType[]
    }
    file: {
      publicURL: string
    }
  }
}

// 1. props로 search 가져오기
const categoryPage: FC<categoryPageProps> = ({
                                               location: { search },
                                               data: {
                                                 site: {
                                                   siteMetadata: { title, description, siteUrl }
                                                 },
                                                 allMarkdownRemark: { edges },
                                                 file: { publicURL }
                                               }
                                             }) => {

  // 2. parse 함수로 파싱 후, 객체 반환
  const parsed: ParsedQuery<string> = queryString.parse(search)

  // 3. 해당 객체에서 카테고리 값 가져오기
  const selectedCategory: string = typeof parsed.category !== "string" || !parsed.category ? "" : parsed.category

  // 4. 필터링하기
  const selectedEdges = useMemo(() => (
    edges.filter(({ node: { frontmatter: { category } } }) => (
      category === selectedCategory
    ))
  ), [selectedCategory])

  // 5. 페이지 렌더링
  return (
    <BlogTemplate
      title={title}
      description={description}
      url={siteUrl}
      image={publicURL}
    >
      <CategoryWrapper>
        <CategoryItem
          category={selectedCategory}
          active={false}
          position={"sticky"}
        />

        <PostCards edges={selectedEdges} />
      </CategoryWrapper>
    </BlogTemplate>
  );
};

export default categoryPage;



Sources

- JeonggonCho_Blog 템플릿 레포지토리

https://github.com/JeonggonCho/JeonggonCho_Blog

blogprojectgatsbyurlparse
profile

조정곤

주니어 프론트엔드 개발자

github
linkedin
instagram
email

< 이전글

블로그 개발 - Slug 적용하기

다음글 >

블로그 개발 - GraphQL 쿼리하기

Blog 포스트 (17)

down-arrow