프론트엔드(Web)/React

React reducer,최적화, 페이지 라우팅

만능 엔터테이너 2024. 10. 3. 21:50
728x90
반응형
SMALL

useReducer

- 컴포넌트 내부에 새로운 State를 생성하는 React Hook, 모든 useState는 useReducer로 대체 가능

😎useState와의 차이점! : 상태 관리 코드를 컴포넌트 외부로 분리할 수 있음

useState와 useReducer의 차이점

// Exam.jsx
import { useReducer } from "react";

reducer : 변환기 -> 상태를 실제로 변화시키는 변환기 역할

function reducer(state, action) {
  console.log(state, action);
  
  return 값으로 상태를 변화하기에 따로 상태 변화 훅이 필요 없음!

   reducer문은 if문 보다 switch문으로 작성하는 것이 일반적
   
  switch (action.type) {
    case "Increase":
      return state + action.data;
    case "Decrease":
      return state + action.data;
    default: 
    return state; 2가지 경우가 아닐 경우 현재 상태 값 유지
  }
}

const Exam = () => {
  
  dispatch : 발송하다 -> 상태 변화가 있어야 한다는 사실을 알리는 함수
  const [state, dispatch] = useReducer(reducer, 0);

  const onClickPlus = () => {
    인수 : 상태가 어떻게 변화되길 원하는지 -> 인수를 담고 있는 객체 (액션객체)
    dispatch({
      type: "Increase",
      data: 1,
    });
  };
  const onClickMinus = () => {
    dispatch({
      type: "Decrease",
      data: -1,
    });
  };
  return (
    <>
      <h1>{state}</h1>
      <button onClick={onClickPlus}>+</button>
      <button onClick={onClickMinus}>-</button>
    </>
  );
};
export default Exam;

최적화 

- 웹 서비스의 성능을 개선하는 모든 행위를 일컫음, 아주 단순한 것부터 아주 어려운 방법까지 매우 다양

 

{ 일반적인 웹 서비스 최적화 방법 }

- 서버의 응답속도 개선
- 이미지, 폰트, 코드 파일 등의 정적 파일 로딩 개선
- 불필요한 네트워크 요청 줄임 ... 등

 

😎 { React App 내부의 최적화 방법 }  => 3가지 최적화 방법이 존재!

 

- 컴포넌트 내부의 불필요한 연산 방지

- 컴포넌트 내부의 불필요한 함수 재생성 방지

- 컴포넌트의 불필요한 리렌더링 방지

 

1) useMemo - 불필요한 연산 방지

: "메모이제이션" 기법을 기반으로 불필요한 연산을 최적화 하는 리액트 훅

메모이제이션이란? 

Memoization : 기억해두기, 메모해두기 라는 뜻 / 연산을 기억해 두고 동일한 연산 작업이 들어오면 기억해 둔 연산을 새롭게 연산 작업 없이 바로 제공하는 것

연산이 낭비가 됨 매번 새롭게 연산을 해야 됨
캐시에 저장해두어서 동일한 값이 들어오면 메모리에 저장해두고 불러오는 형식


페이지 라우팅 - 개

: 경로에 따라 알맞은 페이지를 렌더링 하는 과정 ex) /new -> new 페이지 렌더링

페이지 라우팅의 동작 과정

Multi Page Application (MPA) - 서버가 여러 개의 페이지를 가지고 있는 형태 (일반적 웹 브라우저 형태)

서버가 기존 페이지와 다른 페이지를 요청하면 브라우저는 기존 페이지를 삭제하고 새로운 페이지를 렌더링하는 과정에서 새로고침을 하게 되므로 속도가 느리다는 단점이 존재한다.

많은 서비스가 사용하는 전통적인 방식 / MPA 방식서버 사이드 렌더링엄연히 다름!

{ 서버 측에서 미리 렌더링 하여 브라우저에게 전달하는 것, 즉 서버 사이드 렌더링을 의미 }

MPA 방식의 단점으로 여러 명의 사용자가 접속 시 서버의 부하가 발생하는 단점이 존재

MPA(Multi Page Application) 방식은 페이지 이동이 매끄럽지 않고 비효율적이며 다수의 사용자가 접속 시, 서버의 부하가 심해진다는 단점이 존재한다!

따라서, React.js는 페이지 이동이 빠르게 처리하기 어렵기에 이러한 방식을 따르지 않음! (CSR - 브라우저에서 직접 번들된 파일을 렌더링 하는 방식)

index. html : 브라우저에 제공하는 하나의 웹 페이지 Only 1개만 제공함!

JS Files :  App.jsx, main.jsx 등등 여러 개의 JSX 파일들 -> 제공할 때 번들(여러 개의 파일을 하나로 묶는 것)로 제공

결국, vite에 의해서 Bundle 되어 1개의 JAVASCRIPT 파일로 제공하는 것!

리액트의 클라이언트 사이드 렌더링, 번들된 JS 파일은 곧 React App을 가리킴!
MPA vs SPA 페이지 동작 원리


페이지 라우팅 - 라우팅 설정하기

https://reactrouter.com/en/main(리액트 라우터 공식 홈페이지)

// main,jsx
import { createRoot } from "react-dom/client";
import App from "./App.jsx";
import "./index.css";
import { BrowserRouter } from "react-router-dom";

createRoot(document.getElementById("root")).render(
  <BrowserRouter>
    <App />
  </BrowserRouter>
);

이렇게 App 컴포넌트를 BrowserRouter 컴포넌트로 감싸면 됨

 

<BrowserRouter> :  <BrowserRouter>깨끗한 URL을 사용하여 브라우저의 주소창에 현재 위치를 저장하고 브라우저의 내장된 기록 스택을 사용하여 탐색합니다.

https://reactrouter.com/en/main/router-components/browser-router#basename

<Routes> : Route 컴포넌트를 감싸는 역할

<Route> :

경로는 아마도 React Router 앱의 가장 중요한 부분일 것입니다. URL 세그먼트를 구성 요소, 데이터 로딩 및 데이터 변형에 결합합니다. 경로 중첩을 통해 복잡한 애플리케이션 레이아웃과 데이터 종속성이 간단하고 선언적이 됩니다.

- path

이 경로가 URL, 링크 href 또는 양식 작업과 일치하는지 확인하기 위해 URL과 일치시킬 경로 패턴입니다.

- element

경로가 URL과 일치할 때 렌더링할 React Element/Component입니다.

https://reactrouter.com/en/main/route/route

useNavigate() : useNavigate예를 들어 효과에서 프로그래밍 방식으로 탐색할 수 있는 함수를 반환합니다.

https://reactrouter.com/en/main/hooks/use-navigate#usenavigate

<Link> : 

<Link>사용자가 클릭하거나 탭하여 다른 페이지로 이동할 수 있게 해주는 요소입니다. 에서 react-router-doma는 링크하는 리소스를 가리키는 real을 사용하여 <Link>액세스 가능한 요소를 렌더링합니다 . 즉, 마우스 오른쪽 버튼을 클릭하는 것과 같은 작업이 예상대로 작동합니다. 를 사용하여 클라이언트 측 라우팅을 건너뛰고 브라우저가 정상적으로 전환을 처리하도록 할 수 있습니다(마치 처럼 ).<a>href<Link><Link reloadDocument><a href>

https://reactrouter.com/en/main/components/link#link

// App.jsx
import "./index.css";
import { Route, Routes } from "react-router-dom";
import Diary from "./pages/Diary";
import Home from "./pages/Home";
import New from "./pages/New";
import NotFound from "./pages/NotFound";
// 1. "/" : 모든 일기를 조회하는 Home 페이지
// 2. "/new" : 새로운 일기를 작성하는 New 페이지
// 3. "/diary" : 일기를 상세히 조회하는 Diary 페이지

const App = () => {
  return (
    <>
    😎{/* 여기서 div 태그가 모든 페이지에 렌더링 됨, 따라서 모든 페이지 렌더링 아닐 시에는 적절치 않음 */}
      <div>리액트 라우터</div>
     😎 {/* Routes 컴포넌트 위에 <></> 태그로 감싸고 작성한 내용은 Routes 컴포넌트 내부의 모든 페이지에 렌더링 됨! */}
     😎 {/* Routes 컴포넌트 내부에는 오직 Route 컴포넌트만 들어갈 수 있음!, 다른 거를 넣으면 오류가 발생 */}
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/new" element={<New />} />
        <Route path="/diary" element={<Diary />} />
      😎  {/* 여기서 위 3개 /,new,diary 페이지가 모두 아닐 시 *로 표시된 페이지가 렌더링됨 */}
        <Route path="/*" element={<NotFound />} />
      </Routes>
      ;
    </>
  );
};
export default App;
// NotFound.jsx
const NotFound = () => {
  return (
    <div>잘못된 페이지 입니다.</div>
  )
}
export default NotFound

페이지 라우팅 - 페이지 이동

// App.jsx
import "./index.css";
import { Route, Routes, Link, useNavigate } from "react-router-dom";
import Diary from "./pages/Diary";
import Home from "./pages/Home";
import New from "./pages/New";
import NotFound from "./pages/NotFound";
// 1. "/" : 모든 일기를 조회하는 Home 페이지
// 2. "/new" : 새로운 일기를 작성하는 New 페이지
// 3. "/diary" : 일기를 상세히 조회하는 Diary 페이지

const App = () => {
  const nav = useNavigate();

  const onClickButton = () => {
    { /* 여기서 useNavigate함수인 nav ()에 인수로 이동하고자 하는 페이지 경로를 적으면 됨! 
    특정조건에 따른 페이지 이동 시 -> useNavigate() 그냥 페이지 이동 시 -> Link */ }
    nav("/new");
  };
  return (
    <>
      {/* 여기서 div 태그가 모든 페이지에 렌더링 됨, 따라서 모든 페이지 렌더링 아닐 시에는 적절치 않음 */}
      <div>
        {/* 페이지 이동시 새로고침 되지 않고 빠르게 렌더링 됨 
        여기서 <a></a> 태그로 페이지를 이동하면 클라이언트 사이드 렌더링 방식으로 제공되지 않기에 페이지 이동이 되질 않음!*/}
        <Link to={"/"}>Home</Link>
        <Link to={"/new"}>New</Link>
        <Link to={"/diary"}>Diary</Link>
      </div>
      <button onClick={onClickButton}>New 페이지로 이동</button>
      {/* Routes 컴포넌트 위에 <></> 태그로 감싸고 작성한 내용은 Routes 컴포넌트 내부의 모든 페이지에 렌더링 됨! */}
      {/* Routes 컴포넌트 내부에는 오직 Route 컴포넌트만 들어갈 수 있음!, 다른 거를 넣으면 오류가 발생 */}
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/new" element={<New />} />
        <Route path="/diary" element={<Diary />} />
        {/* 여기서 위 3개 /,new,diary 페이지가 모두 아닐 시 *로 표시된 페이지가 렌더링됨 */}
        <Route path="/*" element={<NotFound />} />
      </Routes>
      ;
    </>
  );
};
export default App;

페이지 라우팅 - 동적 경로

동적 경로란? 동적인 데이터를 포함하는 경로

URL Parmaeter 방식

useParams :

후크 는 useParams현재 URL에서 <Route path>.에 의해 매치된 동적 매개변수의 키/값 쌍의 객체를 반환합니다. 자식 경로는 부모 경로에서 모든 매개변수를 상속합니다.

https://reactrouter.com/en/main/hooks/use-params#useparams

// Diary.jsx
import { useParams } from "react-router-dom";

const Diary = () => {
  const params = useParams();
  console.log(params);
  return <div>{params.id}번 일기입니다~</div>;
};
export default Diary;

Query String 방식

userSearchParams : 후크 useSearchParams는 현재 위치의 URL에서 쿼리 문자열을 읽고 수정하는 데 사용됩니다. React의 자체 useState후크 와 마찬가지로 useSearchParams두 값의 배열을 반환합니다. 현재 위치의 검색 매개변수 와 이를 업데이트하는 데 사용할 수 있는 함수입니다. React의 useState후크  마찬가지로 함수형 업데이트setSearchParams 도 지원합니다 . 따라서 a를 가져와 업데이트된 버전을 반환하는 함수를 제공할 수 있습니다 .

https://reactrouter.com/en/main/hooks/use-search-params

// Home.jsx
import { useSearchParams } from "react-router-dom";

const Home = () => {
  const [params, setParams] = useSearchParams();
  console.log(params.get("value"))
  return <div>Home</div>;
};
export default Home;

 

728x90
반응형
LIST