React Router_SPA

the Other Object·2023년 3월 29일
0

라우팅

- 라우팅 : 사용자가 요청한 URL에 따라 알맞은 페이지를 보여주는 것
- 웹 애플리케이션을 만들 때 프로젝트를 하나의 페이지로 구성할 수도 있고 여러 페이지로 구성할 수도 있다.
- 여러페이지로 구성된 웹 애플리케이션을 만들 때 페이지 별로 컴포넌트들을 분리해가면서 프로젝트를 관리하기 위해 필요함
- 리액트에서 라우트 시스템을 구축하기 위해 사용할 수 있는 선택지2
	(1) React Router 라이브러리 : 컴포넌트 기반으로 라우팅 시스템을 설정할 수 있다.
	(2) Next.js : 리액트프로젝트의 프레임워크. creat-react-app처럼 리액트 프로젝트 설정을 하는 기능, 라우팅 시스템, 최적화, 다국어시스템 지원, ssr 등 다양한 기능 제공, 파일경로 기반으로 작동함.
- 라우팅 관련 기능은 리액트 라이브러리에서 공식적으로 지원하는 것이 아니고 서드파티로 제공

싱글 페이지 애플리케이션

- 하나의 페이지로 이루어진 애플리케이션 (이전: 멀티 페이지 애플리케이션)
- MPA : 사용자가 다른 페이지로 이동할 때마다 새로운 html을 받아오고 페이지를 로딩 때마다 서버에서 css, js, 이미지 파일 등의 리소스를 전달받아 브라우저 화면에 보여줌. 각 페이지마다 다른 html파일을 만들어서 제공하거나, 데이터에 따라 유동적 html 생성해주는 템플릿 엔진 사용하기도 함
- 사용자 인터렉션이 많고 다양한 정보를 제공하는 모던 웹 애플리케이션은 이 방식이 적합하지 않다. 서버의 자원, 트래픽 문제
- 리액트 같은 라이브러리 사용해서 뷰 렌더링을 사용자의 브라우저가 담당하도록 하고 새로운 데이터 필요하면 서버 API 호출해서 필요 데이터만 새로 불러옴
- SPA : html을 한번만 받아와서 웹 애플리케이션 실행 시킨 후 이후에는 필요한 데이터만 받아와서 화면에 업데이트하는 것
- 기술적으로는 한 페이지만 존재하지만, 사용자 경험으로는 여러 페이지가 존재하는 것처럼 느껴진다.
- 리액트 라우터 같은 라우팅 시스템은 : 사용자 브라우저 주소창의 경로에 따라 알맞은 페이지를 보여주는데 링크를 눌러서 다른 페이지로 이동시 다른 페이지의 html을 새로 요청하는 것이 아니라 브라우저의 History API를 사용하여 브라우저의 주소창의 값만 변경하고 기존에 페이지에 띄웠던 웹 애플리케이션 유지하면서 라우팅 설정에 따라 또 다른 페이지를 보여줌

리액트라우터 적용 및 기본 사용

$ yarn create react-app 새로운프로젝트
$ cd 새로운프로젝트
$ yarn add react-router-dom

- 프로젝트에 리액트 라우터 적용할 때는 src/index.js 에서 react-router-dom에 내장되어 있는 `BrowserRouter` 라는 컴포넌트를 사용하여 감싸면 된다.
- 페이지 새로 불러오지 않아도 HTML5의 History API 사용하여 주소변경, 현재 주소경로에 관련 정보를 리액트 컴포넌트에서 사용할 수 있게 해준다.


//src/index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import {BrowserRouter} from 'react-router-dom';

ReactDOM.render(
  <BrowserRouter>
  	 <App />
  </BrowserRouter>
  document.getElementById('root')
);
  • 페이지 컴포넌트 만들기
    - 리액트라우터를 통해 여러 페이지로 구성된 웹 애플리케이션 만들기 위해 각 페이지에서 사용할 컴포넌트를 만들자.
    • 사용자가 웹사이트 처음 들어왔을 때 가장 먼저 보여지게 될 (1)Home 페이지 컴포넌트, 웹사이트 소개하는 (2)About 페이지 컴포넌트
    • src 디렉토리에 pages 경로를 만들고 그 안에 파일들 생성
// src/pages/Home.js

const Home = () => {
  return (
    <div>
      <h1></h1>
      <p> 이 페이지는 가장 먼저 보여지는 화면입니다. </p>
    </div>
  )
}
// src/pages/About.js

const About = () => {
  return (
    <div>
      <h1> 페이지 소개 </h1>
      <p> 리액트라우터를 사용해보는 페이지입니다. </p>
    </div>
  );
};

export default About;


- 페이지로 사용할 이러한 컴포넌트들을 꼭 pages경로에 넣을 필요는 없다.
- 이것은 단순히, 페이지를 위한 컴포넌트들을 다른 파일들과 구분하기 위함이고, routes라는 이름을 써도 되고 그냥 src 경로에 바로 생성해도 문제가 되지는 않음.

Route 컴포넌트로 특정 경로에 원하는 컴포넌트 보여주기

  • 사용자의 브라우저 주소 경로에 따라 우리가 원하는 컴포넌트를 보여주려면 : Route 라는 컴포넌트를 통해 라우트설정을 해줘야 한다.
  • Route 컴포넌트는

    이렇게 사용하고, Route컴포넌트는 Routes컴포넌트 내부에서 사용되어야 한다.
// src/App.js

import {Route, Routes} from 'react-router-dom';
import About from './pages/About';
import Home from './pages/Home';

const App = () => {
  return (
    <Routes>
      <Route path="/" elements={<Home />} />
	  <Route path="/about" element={<About />} />
    </Routes>
  );
};

export default App;

Link컴포넌트

  • 웹페이지에서는 원래 링크를 보여줄 때 a태그를 사용하는데, 리액트라우터를 사용하는 프로젝트에서는 a태그를 바로 사용하면 안된다. 왜냐하면 a태그를 클릭하여 페이지를 이동할 때 브라우저에서는 페이지를 새로불러오기때문,
  • Link컴포넌트도 a태그를 사용하긴 하지만, 페이지를 새로 불러오는 것을 막고 History API를 통해 브라우저 주소의 경로만 바꾸는 기능이 있음
    	<Link to="경로"> 링크이름 </Link>
    이렇게 사용함
- Home페이지에서 About페이지로 이동할 수 있도록 Link 컴포넌트를 Home페이지컴포넌트에서 사용해보기,
  
// src/pages/Home.js
  
import {Link} from 'react-router-dom';

const Home = () => {
  return (
    <div>
      <h1></h1>
      <p> 가장먼저 보여지는 페이지입니다. </p>
      <Link to="/about"> 소개 </Link>
    </div>
  )
}

URL 파라미터와 쿼리스트링

  • URL 파라미터 예시 : /profile/ikjoonhee
  • 쿼리스트링 예시 : /articles?page=1&keyword=react
  • URL파라미터는, 주소의 경로에 유동적인 값을 넣는 형태이고,

  • 쿼리스트링은, 주소의 뒷부분에 ? 문자열 이후에 key=value 로 값을 정의하며 & 로 구분하는 형태이다.

  • URL파라미터는 주로, ID 또는 이름을 사용하여 특정 데이터를 조회할 때 사용,

  • 쿼리스트링(Querystring)은 키워드검색, 페이지네이션, 정렬방식 등 데이터조회에 필요한 옵션을 전달할 때 사용

1. URL파라미터

// src/pages/Profile.js

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

const data = {
  velopert: {name: 'kim', description: 'reactDev'},
  gildong: {name: 'lee', description: 'hongName'}
};

const Profile = () => {
  // URL파라미터는 useParams라는 Hook을 사용하여 객체 형태로 조회할 수 있다.
  // URL파라미터의 이름은, 라우트설정을 할 때 Route컴포넌트의 path props를 통해 설정한다.
  const params = useParams();
  const profile = data[params.username];
  
  return (
    <div>
      <h1> 사용자프로필 </h1>
      // 삼항연산자 {profile ? () : ()}
      {profile ? (
    	<div>
    	  <h2> {profile.name} </h2>
		  <p> {profile.description} </p>
    	</div>
  	  ) : (
    	<p> 존재하지 않는 프로필입니다.</p>
  	  )}
    </div>
  );
}

- 여기서는, data객체에 예시프로필 정보들을 key-value 형태로 담았고,
- Profile컴포넌트에서는 username URL파라미터를 통하여 프로필을 조회한 뒤에 true, false 결과값 보여지도록
// src/App.js

import {Route, Routes} from 'react-router-dom';
import About from './pages/About';
import Home from './pages/Home';
import Profile from './pages/Profile';

const App = () => {
  return (
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="/about" element={<About />} />
      <Route path="/profiles/:username" element={<Profile />} />
    </Routes>
  );
};

export default App;


- URL파라미터는, /profiles/:username 처럼 경로에 :를 사용하여 설정
- 만약, URL파라미터가 여러개면, /profiles/:username/:field 같은 형태로 설정할 수 있다.
  • Profile페이지로 이동할 수 있도록 Home 페이지에 Link를 더 만들기,
  • 링크가 여러개라서 ul태그를 사용하여 리스트로 보여주자,
// src/pages/Home.js
  
import {Link} from 'react-router-dom';

const Home = () => {
  return (
    <div>
      <h1></h1>
      <p> 가장먼저 보여지는 페이지입니다. </p>
      
      <ul>
        <li>
          <Link to="/about"> 소개 </Link>
        </li>
    
        <li>
          <Link to="/profiles/velopert"> velopert님의 프로필 </Link>
        </li>
    
        <li>
          <Link to="/about"> 소개 </Link>
        </li>
      </ul>
    </div>
  );
};

export default Home;

쿼리스트링

// src/pages/About.js

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

const About = () => {
  const location = useLocation();
  
  return (
    <div>
      <h1> 소개 </h1>
      <p> 리액트 라우터를 사용해보는 프로젝트입니다. </p>
      <p> 쿼리스트링: {location.search} </p>
    </div>
  );
};

export default About;

- useLocation 이라는 Hook : location 객체를 반환한다.
- 이 객체는 현재 사용자가 보고있는 페이지의 정보를 지니고 있다. 
	* pathname : 현재주소의 경로(쿼리스트링 제외)
	* search : 맨 앞의 ? 문자를 포함한 쿼리스트링 값
    * hash : 주소의 # 문자열 뒤의  (주로 History API가 지원되지 않는 구형 브라우저에서 클라이언트 라우팅을 사용할 때 쓰는 해시라우터에서 사용)
    * state : 페이지로 이동할 때 임의로 넣을 수 있는 상태 값
    * key : location 객체의 고유값, 초기에는 default 이며 페이지가 변경될때마다 고유의 값이 생성 됨.

useNavigate

  • Link컴포넌트를 사용하지 않고 다른 페이지로 이동해야하는 상황에 사용하는 Hook
// src/Layout.js

import {Outlet, useNavigate} from 'react-router-dom';

const Layout = () => {
  
  const navigate = useNavigate();
  
  const goBack = () => {
    navigate(-1);
    // 이전페이지로 이동
  };
  
  const goArticle = () => {
    navigate('/articles');
  };
  
  return (
    <div>
      <header style={{background: 'lightgray', padding: 16, fontSize: 24}}>
    	<button onClick={goBack}> 뒤로가기 </button>
    	<button onClick={goArticle}> 게시글 목록 </button>
      </header>
      <main>
    	<Outlet />
      </main>
    </div>
  )
}


// replace : 페이지 이동시 현재페이지를 페이지기록에 안남긴다.
const goArticles = () => {
  navigate('/articles', {replace: true});
};

콜백함수

- 파라미터 값이 주어지면 1초 뒤에 10을 더해서 반환하는 함수가 있다고 가정,
- 그리고 `해당 함수가 처리된 직후 어떠한 작업을 하고 싶다`면 콜백함수를 활용한다.

const increase = (number, callback) => {
  setTimeout(() => {
    const result = number + 10;
    if (callback) {
      callback(result);
    }
  }, 1000)
}

increase (0, result => {
  console.log(result);
});


- 1초에 걸쳐서 10, 20, 30, 40 과 같은 형태로 여러번 순차적으로 처리하고 싶다면 콜백함수를 중첩하여 구현한다.

0개의 댓글