All'alba vincerò

At dawn, I will win!

React

[React] React Router 라이브러리(2) : 검색엔진최적화(SEO) 설정 / 네비게이션 상태 확인 / 다이내믹 세그먼트(Dynamic Segment) 설정

나디아 Nadia 2024. 8. 24. 11:06

📌 React Router 라이브러리

  • 프로덕션용으로 사용 가능한 싱글 페이지 앱을 구현(SPA)하기 위한 React Router 라이브러리
  • URL이 변경돼도 싱글페이지로 렌더링 하는 기능을 지원


 

☑️ 검색엔진최적화(SEO) 설정

⏩ react-helmet-async 활용

: React 애플리케이션에서 동적으로 HTML <head>를 관리할 수 있게 해주는 라이브러리

  • 리액트의 단점
    ➡︎  React는 하나의 index.html을 두고 있기 때문에 페이지 마다 페이지를 설명하는 메타태그를 설정하기 어렵다.
    ➡︎ SEO가 어렵다.
  • SEO(검색 엔진 최적화)와 소셜 미디어 공유를 위해 메타 태그, 타이틀, 링크 태그 등을 관리할 때 사용
  • 기존의 react-helmet 라이브러리를 비동기적으로 사용할 수 있도록 개선한 버전
  • 서버 사이드 렌더링(SSR)과 클라이언트 사이드 렌더링(CSR) 모두에서 사용할 수 있다.

 

설치

npm install react-helmet-async

 

 

1. HelmetProvider로 애플리케이션 또는 해당 컴포넌트를 감싼다.

  • HelmetProvider를 사용하여 App.js를 감싼다.
import router from '@/router';
import { RouterProvider } from 'react-router-dom';
import { HelmetProvider } from 'react-helmet-async';

function App() {
  return (
    <HelmetProvider>
      <RouterProvider router={router} />
    </HelmetProvider>
  );
}

export default App;

 

 

2. Helmet을 사용하여 HTML <head> 태그 내의 메타 데이터를 동적으로 설정한다.

  • Helmet을 사용하여 페이지의 HTML <head>를 변경한다.
    <title>, <meta/>, <link>, <style>, <script> 등을 관리한다.
    (순서를 지켜야 한다.)
import { AppDivider, AppLink } from '@/components';
import Counter from '@/miniApp/Counter';
import TaskManager from '@/miniApp/TaskManager/TaskManager';
import { Helmet } from 'react-helmet-async';

function HomePage() {
  return (
    <>
      <Helmet>
        <title>앱 글로벌 상태 관리 with Zustand</title>
        <meta
          name="description"
          content="Zustand를 사용하면 Context, useReducer, useState 없이 보다 효과적으로, 더 빠르게, 더 가볍게 상태를 관리할 수 있습니다."
        />
        <meta property="og:title" content="이듬(E.UID) 블렌디드 러닝" />
        <meta property="twitter:title" content="이듬(E.UID) 블렌디드 러닝" />
        <meta property="og:type" content="site" />
        <meta property="og:url" content="https://yamoo9.github.io/EUID" />
        <meta
          property="og:description"
          content="Front-End 개발자를 꿈꾸는 이들을 위한 블렌디드 러닝으로 개발에 필요한 모든 것!"
        />
        <meta
          property="og:image"
          content="https://yamoo9.github.io/EUID/og-image.jpg"
        />
        <meta property="og:site:author" content="야무(yamoo9)" />
      </Helmet>
      
      <section id="page">
        <div className="learn">
          <h1>앱 글로벌 상태 관리 with Zustand</h1>

          <p>
            <AppLink
              href="https://zustand.docs.pmnd.rs/getting-started/introduction"
              isExternal
            >
              Zustand
            </AppLink>{' '}
            라이브러리를 사용해 앱 또는 컴포넌트의 상태를 효과적으로 관리하는
            방법을 학습합니다.
          </p>

          <AppDivider />

          <h2 lang="en" className="uppercase">
            Counter
          </h2>

          <p>간단한 카운터 앱의 상태를 Zustand를 사용해 관리합니다.</p>

          <Counter />
          <AppDivider />

          <h2 lang="en" className="uppercase">
            Task Manager
          </h2>
          <p>
            태스크 매니저 앱의 상태를 컨텍스트 + 리듀서 대신, Zustand를
            사용하도록 변경해봅니다.
          </p>
          <TaskManager />
        </div>
      </section>
    </>
  );
}

export default HomePage;

react-helmet-async

 

 

 

 

Open Graph Protocols(OGP) 설정

: 웹 페이지가 소셜 미디어 플랫폼에서 어떻게 표시될지를 제어하는 메타데이터 표준

    • 웹 페이지의 콘텐츠를 소셜 미디어에서 공유할 때 제목, 이미지, 설명 등을 미리보기 카드 형식으로 표시할 수 있다.
    • 클릭률(CTR)을 높이고, 사용자 경험을 개선하며, 브랜드 인지도를 높이는 데 도움이 된다.
    • 일반적인 HTML <meta> 태그를 사용한다.

    • 속성
      • og:title
        : 공유되는 콘텐츠의 제목을 설정
      • og:description
        : 페이지에 대한 설명을 설정

        ➡︎ 이 설명은 소셜 미디어에서 링크를 공유할 때 미리보기 카드에 표시된다.
      • og:image
        : 콘텐츠를 대표하는 이미지 URL을 설정 

        ➡︎ 이 이미지는 소셜 미디어에서 링크를 공유할 때 미리보기 카드에 표시된다.
      • og:url
        : 페이지의 URL을 설정
        주로 정규화된 URL을 지정하는 데 사용된다.
      • og:type
        : 콘텐츠의 유형을 설정

        일반적인 웹 페이지는 website 또는 article을 사용한다.
      • og:site_name
        : 사이트의 이름을 설정

        ➡︎ 페이지를 공유할 때 사이트 이름이 함께 표시된다.
      • og:locale
        : 페이지의 언어 및 지역 설정을 지정
      • og:video
        : 페이지에 포함된 비디오의 URL을 지정
      • og:audio
        : 페이지에 포함된 오디오 파일의 URL을 지정
<meta property="og:title" content="My Awesome Page">
<meta property="og:description" content="This is a description of my awesome page">
<meta property="og:image" content="https://www.example.com/image.jpg">
<meta property="og:url" content="https://www.example.com/my-page">
<meta property="og:type" content="website">
<meta property="og:site_name" content="My Awesome Website">
<meta property="og:locale" content="en_US">
<meta property="og:video" content="https://www.example.com/video.mp4">
<meta property="og:audio" content="https://www.example.com/audio.mp3">

Open Graph Protocols

 


 

☑️ 프로그래밍 방식 페이지 링크 설정

useNavigate() 

: 컴포넌트 내에서 사용자를 다른 경로로 이동시키는 데 사용

 

  • 이동 방식
    • push
      : 새로운 경로로 이동하며, 이전 페이지는 히스토리에 남아 있다.
      - 뒤로 가기 버튼으로 이전 페이지로 돌아갈 수 있다⭕
    • replace
      : 새로운 경로로 이동하면서 현재 페이지를 히스토리에서 대체
      - 뒤로 가기 버튼으로 돌아갈 수 없다❌
  • 상태 전달
    : 경로 이동 시 상태(state)를 전달할 수 있고, 이를 통해 페이지 간 데이터 전달할 수 있다.

 

1. useNavigate() 훅 불러오기

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

 

 

2. useNavigate() 훅으로 navigate 함수 생성

  • useNavigate()를 호출하면 경로를 변경할 수 있는 navigate 함수를 반환한다.
const navigate = useNavigate();

 

 

3. navigate 함수를 사용하여 페이지 이동

navigate('/path'); // 기본적으로 'push' 방식

navigate('/path', { replace: true }); // 'replace' 방식

 

 

 

예제) 클릭 시 파일 이동 컴포넌트

import React from 'react';
import { useNavigate } from 'react-router-dom';

const MyComponent = () => {
  const navigate = useNavigate();

  const handleClick = () => {
    navigate('/about', { state: { fromHome: true } });
  };


  return (
    <div>
      <h1>Home Page</h1>
      <button onClick={handleClick}>Go to About Page</button>
    </div>
  );
};

export default MyComponent;

 

useNavigate()

 


 

☑️ 네비게이션 상태 확인

useNavigation() 훅

: 현재의 네비게이션 상태와 관련된 정보를 가져오는 데 사용

  • 특징
    • 네비게이션 상태 추적: 현재 네비게이션이 진행 중인지, 완료되었는지, 오류가 발생했는지 등의 상태를 알 수 있다.
    • 폼 데이터 처리: 폼 제출로 인해 발생한 네비게이션에서 제출된 데이터에 접근할 수 있다.
    • 네비게이션 응답 처리: 네비게이션 응답의 JSON 데이터나 텍스트 데이터를 처리할 수 있다.
  • React Router 6.4 이상에서 사용할 수 있다.

 

1. 불러오기

import { useNavigation } from "react-router-dom";

 

 

2. useNavigation 훅 호출

  • useNavigation 훅을 호출하여 네비게이션 상태를 가져온다.
  • 반환된 객체를 사용하여 현재 네비게이션 상태를 확인하고, 조건부 렌더링을 통해 UI를 업데이트할 수 있다.
const navigation = useNavigation();

 

 

3. 속성 사용

  • navigation.state
    : 현재 네비게이션 상태
    : 'idle', 'loading', 'error'

  • navigation.location
    : 현재의 location 객체를 포함한다.
    ➡︎ URL 경로, 검색 쿼리, 해시 등을 포함한다.
    형식: { pathname: string, search: string, hash: string, state: any }

  • navigation.formData
    : 폼 제출로 인해 네비게이션이 발생한 경우, 제출된 폼의 데이터를 포함한다.
    형식: FormData 객체

  • navigation.json
    : 네비게이션 응답이 JSON 데이터를 포함할 때 사용
    ➡︎  JSON API와 상호작용할 때 유용하다.
    형식: Promise<any>

  • navigation.text
    : 네비게이션 응답이 텍스트 데이터를 포함할 때 사용됩니다.
    형식: Promise<string>

  • navigation.formAction
    : 현재 폼 제출의 액션 URL을 나타낸다.
    형식: string

  • navigation.formMethod
    : 현재 폼 제출의 메서드(POST, GET 등)를 나타낸다.
    형식: string
function SomeComponent() {
  const navigation = useNavigation();
  navigation.state;
  navigation.location;
  navigation.formData;
  navigation.json;
  navigation.text;
  navigation.formAction;
  navigation.formMethod;
  navigation.formEncType;
}

 

 

 

예제) 현재 네비게이션 상태를 추적, 이 상태를 기반으로 UI를 동적으로 업데이트

import { Outlet, useNavigation } from 'react-router-dom';
import { AppFooter, AppHeader, AppNav, AppSpinner } from '@/components';

function RootLayout() {
  const navigation = useNavigation();

  const isLoading = navigation.state === 'loading';

  return (
    <div className="h-screen bg-indigo-50/30 flex flex-col">
      <AppHeader />
      <AppNav />
      <main className="flex-1 m-4">
        {isLoading ? (
          <AppSpinner
            size={100}
            className="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2"
          />
        ) : (
          <Outlet />
        )}
      </main>
      <AppFooter />
    </div>
  );
}

export default RootLayout;

useNavigation()

 


 

☑️ 다이내믹 세그먼트(Dynamic Segment)  설정

: URL 경로의 일부를 동적으로 받아와 라우트를 매칭하는 방법

  • 주로 특정 리소스의 ID나 이름 등을 URL에 포함시켜 해당 리소스에 접근할 때 사용된다.
  • 라우트 정의 시 URL 경로에서 콜론(:)을 사용하여 다이내믹 세그먼트를 설정한다.
    이를 통해 다양한 리소스나 데이터를 동적으로 처리하는 애플리케이션을 쉽게 구현할 수 있다.

Dynamic Segments

 

 

 

 useParams()

: 현재 URL의 동적 세그먼트(Dynamic Segment)에 전달된 파라미터 값을 가져오는 데 사용

  • 이 훅을 사용하면 라우트 경로에 포함된 변수를 쉽게 접근하여 컴포넌트 내에서 활용할 수 있다.
  • 특징
    • URL 파라미터 접근
      : useParams()는 현재 URL에 매칭된 라우트의 파라미터 값을 객체 형태로 반환한다.
    • 동적 경로 처리
      : URL 경로에서 `:id`와 같은 동적 세그먼트를 정의하고, 해당 경로에 접근할 때 전달된 값을 읽어올 수 있다.
  • 사용 예시
    • 상세 페이지
      : 특정 리소스(ex. 특정 ID를 가진 블로그 글, 제품, 사용자 등)의 상세 페이지를 구현할 때,
      useParams()를 사용해 URL에서 해당 리소스의 ID를 가져와 필요한 데이터를 로드하고 표시한다.
    • 편집 페이지
      : 사용자가 특정 리소스를 편집할 수 있는 페이지를 만들 때, URL에서 리소스의 ID를 가져와 그 데이터를 불러오고 수정할 수 있게 한다.
    • 필터링 및 정렬된 리스트
      : URL에 필터 조건(ex. 카테고리, 태그)을 포함하여 해당 조건에 맞는 데이터를 필터링하거나 정렬된 리스트를 보여줄 때 사용한다.

 

1. 라우트 설정에서 다이내믹 세그먼트 정의

  • 라우트 설정에서 다이내믹 세그먼트를 정의한다.
    다이내믹 세그먼트 👉 URL 경로에서 콜론(:)으로 시작하는 부분
import { createBrowserRouter, RouterProvider } from 'react-router-dom';
import UserDetail from './components/UserDetail';

const router = createBrowserRouter([
  {
    path: '/users/:id', // :id(다이내믹 세그먼트) 설정
    element: <UserDetail />, // 해당 경로에 접근 시 UserDetail 컴포넌트 렌더링
  },
]);

function App() {
  return <RouterProvider router={router} />;
}

export default App;

 

 

2. useParams()로 파라미터 값 가져오기

  • 다이내믹 세그먼트로 전달된 파라미터 값을 가져오려면,
    해당 라우트로 렌더링되는 컴포넌트에서 useParams() 훅을 사용한다.
  • ID를 기반으로 데이터를 가져오거나 렌더링할 수 있다.
import { useParams } from 'react-router-dom';

function UserDetail() {
  const { id } = useParams(); // URL의 :id 값에 접근

  return (
    <div>
      <h1>User Detail</h1>
      
      {/* 가져온 id 값을 표시 */}
      {/* ID를 기반으로 데이터를 가져오거나 렌더링할 수 있음 */}
      <p>User ID: {id}</p> 
    </div>
  );
}

export default UserDetail;

useParams()

 

 

 

 

 useSearchParams() 훅

: URL의 쿼리 파라미터(query parameters)에 접근하여 읽고 수정할 수 있게 해준다.

  • 쿼리 파라미터(query parameters) : URL의 ? 뒤에 오는 키-값 쌍
  • 페이지의 상태를 관리하거나 데이터를 필터링할 때 유용하다.

  •  useSearchParams() 훅은 두 가지 값을 반환한다.
    • searchParams: URLSearchParams 객체, 현재 URL의 쿼리 파라미터를 관리
    • setSearchParams: 쿼리 파라미터를 수정할 수 있는 함수
  • 특징
    • 쿼리 파라미터 접근
      : URL의 쿼리 문자열을 읽어서 현재 상태를 컴포넌트에서 쉽게 사용할 수 있다.
    • 쿼리 파라미터 수정
      : 쿼리 파라미터를 업데이트하여 URL을 변경할 수 있고, 페이지의 상태를 동적으로 조절할 수 있다.
  • 사용 예시
    • 검색 기능
      : 사용자가 입력한 검색어를 쿼리 파라미터로 전달하여 검색 결과를 필터링한다.
    • 필터링 및 정렬
      : URL 쿼리 파라미터를 사용하여 리스트를 필터링하거나 정렬 기준을 지정한다.
    • 페이지 상태 유지
      : 페이지 이동 시 상태를 유지하고자 할 때, 페이지 네비게이션 시 현재 페이지 번호를 쿼리 파라미터로 관리한다.
  • 속성
    • get(name): 쿼리 파라미터의 값을 가져온다.
    • getAll(name): 모든 값을 배열로 가져온다.
    • has(name): 쿼리 파라미터의 존재 여부를 확인한다.
    • set(name, value): 값을 설정하거나 업데이트한다.
    • append(name, value): 값을 추가한다.
    • delete(name): 쿼리 파라미터를 삭제한다.
    • toString(): 쿼리 문자열을 반환한다.
    • entries(), keys(), values(): 각각 키-값 쌍, 키, 값을 반복 가능한 객체로 반환한다.

 

1. 불러오기

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

 

 

2. useSearchParams() 호출 후 배열로 받기

const [searchParams] = useSearchParams();

 

 

3. 현재 'query' 값 가져오기

const query = searchParams.get('query');

 

 

 

예제 1) 쿼리 파라미터 읽기

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

function SearchPage() {
  const [searchParams] = useSearchParams(); // 현재 URL의 쿼리 파라미터를 가져옵니다
  const query = searchParams.get('query'); // 'query' 파라미터의 값을 가져옵니다

  return (
    <div>
      <h1>Search Page</h1>
      <p>Current query: {query || 'No query specified'}</p>
    </div>
  );
}

export default SearchPage;

 

 

예제 2) 쿼리 파라미터 수정하기

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

function SearchPage() {
  const [searchParams, setSearchParams] = useSearchParams(); // 현재 쿼리 파라미터를 가져오고 업데이트하는 함수

  const query = searchParams.get('query') || '';

  const handleSearchChange = (event) => {
    const newQuery = event.target.value;
    setSearchParams({ query: newQuery }); // 쿼리 파라미터를 업데이트합니다
  };

  return (
    <div>
      <h1>Search Page</h1>
      <input
        type="text"
        value={query}
        onChange={handleSearchChange}
        placeholder="Enter search query"
      />
      <p>Current query: {query}</p>
    </div>
  );
}

export default SearchPage;

useSearchParams()

 

 


 

 

GitHub - staylor/react-helmet-async: Thread-safe Helmet for React 16+ and friends

Thread-safe Helmet for React 16+ and friends. Contribute to staylor/react-helmet-async development by creating an account on GitHub.

github.com

 

 

[React] SEO를 위한 react-helmet-async, react-snap

SEO를 위한 react-helmet-async, react-snap

velog.io

 

 

React Router | Notion

클라이언트 사이드 라우팅(CSR) 라이브러리

euid.notion.site