• Router

    2022. 9. 13.

    by. JJo 😊

    📌 라우팅이란?

    사용자가 요청한 URL에 따라 알맞은 페이지를 보여주는 것을 의미한다.

    리액트에서 라우터 사용하는 방법

    ✅ 리액트 라우터 라이브러리 : 리액트에서 가장 오래됐고 가장 많이 사용하는 라이브러리이다. 컴포넌트 기반으로 라우팅 시스템을 설정할 수 있다.

    ✅ Next.js : 리액트 프로젝트의 프레임워크이다. 라우팅 시스템 뿐만 아니라 다국어 시스템 지원, 서버 사이드 렌더링 등 다양한 기능을 제공한다. 파일 경로 기반으로 작동한다. 리액트 라우터의 대안으로 많이 사용되고 있다.

    📌SPA의 개념

    싱글 페이지 애플리케이션이란 하나의 페이지로 이루어진 애플리케이션이라는 의미이다. 기존의 멀티 페이지 애플리케이션과는 반대로 웹 애플리케이션을 브라우저에 불러와 실행시킨 후, 사용자의 인터랙션이 발생하면 필요한 부분만 업데이트를 한다. 새로운 데이터가 필요하면 서버 API를 호출하여 필요한 데이터만 새로 불러온다.

    이렇게 html은 한번만 불러오고, 이후에는 필요한 데이터만 받아와서 화면에 업데이트 하는 방식이 SPA이다. 리액트 라우터 시스템은 브라우저의 History API를 사용하여 브라우저의 주소창의 값만 변경하고 기존 페이지에 띄웠던 웹 애플리케이션을 그대로 유지하면서 또 다른 페이지를 보여주게 된다.

    📌SPA 라우팅 과정

    1️⃣ 브라우저에서 최초에 ‘/’ 경로로 요청을 하면

    2️⃣ React Wep App을 내려준다.

    3️⃣ 내려받은 React App에서 ‘/’경로에 맞는 컴포넌트를 보여준다.

    4️⃣ React App에서 다른 페이지로 이동하는 동작을 수행하면,

    5️⃣ 새로운 경로에 맞는 컴포넌트를 보여준다.

    리액트 라우터를 사용해보자!

    (참고로 리액트 라우터가 6버전으로 메이저 업데이트가 되었기에 이전 버전과 문법 차이가 있다..!)

    npm install react-router-dom@6

    https://v5.reactrouter.com/web/guides/quick-start

     

    Docs Home

    Wanna dive deep? Level up your understanding of React Router with the concepts, vocabulary, and design principles of React Router and routing in general. A must read for would-be contributors.

    reactrouter.com

    https://reactrouter.com/en/main/getting-started/overview

     

    Quick Start

    Quick Start Overview If you're familiar with the JavaScript ecosystem, React, and React Router, this serves as a quick overview of React Router v6 with lots of code and minimal explanations. For a complete introduction to React Router, do the Tutorial For

    reactrouter.com

    라우터 적용하기

    프로젝트에 라우터를 적용하려면 react-router-dom에 내장되어 있는 BrowserRouter 컴포넌트를 사용하여 감싸야 한다. 이 컴포넌트는 History API를 사용하여 페이지를 새로 불러오지 않고 주소를 변경하고 관련된 정보를 사용할 수 있도록 해 준다.

    //index.js
    import {BrowserRouter} from 'react-router-dom';
    
    <BrowserRouter>
    	<App />
    </BrowserRouter>

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

    브라우저 경로에 따라 원하는 컴포넌트를 보여주려면 Route라는 컴포넌트로 라우터 설정을 해야한다. 그리고Route 컴포넌트는 Routes 컴포넌트 내부에서 사용해야 한다.

    <Route path='주소 규칙' element={보여줄 컴포넌트 jsx} />
    //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='/' element={<Home />} />
    			<Route path='/about' element={<About />} />
    		</Routes>
    	)
    }

    다른 페이지로 이동하는 링크 만들기

    웹 페이지에서 링크를 보여줄 때, a를 사용한다. 하지만 리액트에서는 a를 바로 사용하면 안된다. a를 클릭하여 페이지를 이동하게 되면 브라우저에서는 페이지를 새로 불러오게 되기 때문이다.

    그래서 리액트에서는 a대신 Link컴포넌트를 사하여 구현한다. Link컴포넌트 역시 a를 사용하지만 History API를 통해 브라우저 주소의 경로만 바꾸는 기능이 내장되어 있다.

    <Link to='경로'>링크 이름</Link>
    //App.js
    import { Link } from 'react-router-dom';
    
    const App = () => {
    	return (
    		<Link to='/about'>소개</Link>
    	)
    }

    📌Dynamic 라우팅

    URL 파라미터

    URL 파라미터는 주소의 경로에 유동적인 값을 넣는 형태이다. 주로 ID값 또는 이름을 사용하여 특정 데이터를 조회할 때 사용한다.

    <Route path='/about/:id' element={<About />} />

    URL 파라미터는 경로에 : 를 사용하여 설정한다. 만약 URL 파라미터가 여러 개인 경우에는 /about/:id/:id2와 같은 형태로 설정할 수 있다.

    //About.js
    import { useParams } from 'react-router-dom';
    
    const data = {
    	eunhye: {
    		name: '조으네'
    	}
    }
    
    const About = () => {
    	const params = useParams();
    	const profile = data[params.username];
    	return (
    		<Link to='/about/profile'>프로필</Link>
    	)
    }

    URL 파라미터는 useParams라는 Hook을 사용하여 객체 형태로 조회할 수 있다. URL 파라미터의 이름은 라우트 설정을 할 때 Route 컨포넌트의 path props를 통해 설정한다.

    쿼리스트링

    쿼리스트링은 주소의 뒷부분에 ? 문자열 이후 key = value형태로 값을 정의하여 &로 구분하는 형태이다. 주로 키워드 검색, 페이지네이션, 정렬 방식 등 데이터 조회에 필요한 옵션을 조회할 때 사용한다. 쿼리스트링을 사용할 때는 URL파라미터와 달리 Route 컴포넌트에서 별도로 설정해야 하는 것은 없다.

     

    URLSearchParams

    URLSearchParams는 브라우저 내장 객체로 URL의 Query문자열을 다루는 메소드이다. 쿼리 문자열을 다루기 위해서는 이와 같은 메서드를 이용할 수 있다.

    //About.js
    
    const About = (props) => {
    	const searchParams = props.location.search; //Route에서 props를 통해 쿼리 정보를 넣어주고 이를 참조할 수 있다.
    	const obj = new URLSearchParams(searchParams);
    	obj.get('name') // new URLSearchParams를 담은 obj에서 .get()메소드를 통해 쿼리 문자열을 꺼내 사용한다.
    
    	return (
    		<div>About 페이지입니다.</div>
    	)
    }

    https://developer.mozilla.org/ko/docs/Web/API/URLSearchParams

     

    URLSearchParams - Web API | MDN

    URLSearchParams 인터페이스는 URL의 쿼리 문자열을 대상으로 작업할 수 있는 유틸리티 메서드를 정의합니다.

    developer.mozilla.org

    💥단점

    URLSearchParams를 사용할 때 몇가지 단점이 있다.

    ✅ URLSearchParams의 메소드를 다 기억을 하고 사용해야 한다.

    ✅ IE에서는 아예 지원이 안된다.

     

    그래서 다른 라이브러리의 도움을 받아서 쿼리스트링을 다루는 방법이 있다.

    query-string

    $ npm install query-string

    https://github.com/sindresorhus/query-string#readme

     

    GitHub - sindresorhus/query-string: Parse and stringify URL query strings

    Parse and stringify URL query strings. Contribute to sindresorhus/query-string development by creating an account on GitHub.

    github.com

    //About.js
    import queryString from 'query-string';
    
    const About = (props) => {
    	const searchParams = props.location.search;
    	//const obj = new URLSearchParams(searchParams);
    	//obj.get('name') <- new URLSearchParams를 담은 obj에서 .get()메소드를 통해 쿼리 문자열을 꺼내 사용한다.
    	const query = queryString.parse(searchParams);
    	console.log(query) // {key: value} 객체 형태로 출력된다.
    	return (
    		<div>About 페이지입니다.</div>
    	)
    }

    Hook 사용하기

    useLocation

    useLocation은 location 객체를 반환한다. 이 객체에는 현재 사용자가 보고 있는 페이지의 정보를 가지고 있다.

    //About.js
    import { useLocation } from 'react-router-dom';
    
    const About = () => {
    	const location = useLocation();
    	
    	return (
    		<div>
    			About 페이지입니다.
    			<p>쿼리스트링 : {location.search}</p>
    		</div>
    	)
    }
      • pathname : 현재 주소의 경로 (쿼리스트링 제외)
      • search : 맨 앞의 ? 문자를 포함한 쿼리스트링 값
      • hash : 주소의 # 문자열 뒤의 값 (주로 History API가 지원되지 않는 구형 브라우저에서 클라이언트 라우팅을 사용할 때 쓰는 해시 라우터에서 사용)
      • state : 페이지로 이동할 때 임의로 넣을 수 있는 상태 값
      • key : location 객체의 고유값, 초기에는 default이며, 페이지가 변경될 때마다 고유의 값이 생성됨

    위의 값들 중에 가장 많이 사용될 값은 search의 쿼리스트링 값이다. 근데 이 쿼리스트링 값에는 앞의 ? 문자도 같이 출력이 된다. 그러므로 ? 문자열을 분리한 뒤 key와 value를 파싱하는 작업을 해야 한다. 이 작업은 보통 npm의 qs 또는 querystring 패키지를 설치하여 처리할 수 있다. 하지만 이 과정도 역시 번거로울 수 있다. 다행히 리액트 라우터에서는 v6부터 useSearchParams라는 Hook을 통해 쿼리스트링을 쉽게 다룰 수 있게 되었다.

    useSearchParams

    //About.js
    import { useSearchParams } from 'react-router-dom';
    
    const About = () => {
    	const [searchParams, setSearchParams] = useSearchParams();
    	const key = searchParams.get('key');
    
    	const onToggleKey = () => {
    		setSearchParams({key : key === 'true' ? false : true})
    	}
    	
    	return (
    		<div>
    			About 페이지입니다.
    			<button onClick={onToggleKey}>Toggle Kay</button>
    		</div>
    	)
    }

    useSearchParams 는 배열 타입의 값을 반환한다. 첫 번째 원소는 쿼리파라미터를 조회하거나 수정하는 메서드들이 담긴 객체를 반환한다.

    get 메서드를 통해 특정 쿼리파라미터를 조회할 수 있고, set 메서드를 통해 특정 쿼리파라미터를 업데이트할 수 있다. 만약 쿼리파라미터가 존재하지 않으면 null로 조회된다. useSearchParams 의 두 번째 원소는 쿼리파라미터를 객체 형태로 업데이트할 수 있는 함수를 반환한다.

    이때 주의할 점은 쿼리파라미터를 조회할 때 값은 무조건 문자열 타입이다. true또는 false 값을 넣으면 ‘true’와 같이 따옴표로 감싸서 비교해야 하고, 숫자를 다룰 경우 parseInt를 사용하여 숫자 타입으로 변환해야 한다.

    🖐Switch

    (라우트 5버전에서만 사용되며 6버전에서는 사라진 문법이다!)

    //App.js
    import { BrowserRouter, Route, Switch } from 'react-router-dom';
    import About from './pages/About';
    import Home from './pages/Home';
    
    const App = () => {
    	return (
    		<BrowserRouter>
    			<Switch>
    				<Route path='/about/:id' component={About} />
    				<Route path='/about/' component={About} />
    				<Route path='/' exact component={Home} />
    				<Route component={NotFound} />
    			</Switch>
    		</BrowserRouter>
    	)
    }

    📌 중첩된 라우트

    //App.js
    import { Route, Routes } from 'react-router-dom';
    import Article from './pages/Article';
    import Articles from './pages/Articles';
    
    const App = () => {
    	return (
    		<Routes>
    			<Route path='/articles' element={<Articles />}>
    				<Route path=':id' element={<Article />} />
    			</Route>
    		</Routes>
    	)
    }

    Route 안에 Route가 들어가는 중첩 형태이다. 이때 하위 Route를 감싸고 있는 Route 컴포넌트에 리액트 라우터에서 제공하는 Outlet이라는 컴포넌트를 사용해줘야 한다.

    //Articles.js
    import { Link , Outlet } from 'react-router-dom';
    
    const Articles = () => {
    	return (
    		<div>
    			<Outlet />
    			<ul>
    				<li>
    					<Link to='/articles/1' />
    				</li>
    				<li>
    					<Link to='/articles/2' />
    				</li>
    			</ul>
    		</div>
    	)
    }

    위 코드에서 Outlet이라는 컴포넌트가 사용된 자리에 중첩된 라우트가 보여지게 된다.

    이러한 기능을 이용하여 공통적으로 보여줘야 하는 레이아웃이 있을 때 유용하게 사용할 수 있다.

    📌 리액트 라우터 부가기능

    useNavigate

    useNavigate는 Link 컴포넌트를 사용하지 않고 다른 페이지로 이동할 때 사용하는 Hook이다.

    // Layout.js
    import { Outlet, useNavigate } from 'react-router-dom';
    
    const Layout = () => {
    	const navigate = useNavigate();
    
    	const goBack = () => {
    		navigate(-1); //이전 페이지로 이동
    	}
    
    	const goHome = () => {
    		navigate('/home'); // home 경로로 이동
    	}
    
    	return (
    		<div>
    			<button onClick={goBack}>뒤로가기</button>
    			<button onClick={goHome}>홈으로 이동</button>
    		</div>
    	)
    }

    위 코드에서 navigate함수를 사용할 때 파라미터가 숫자 타입이면 앞으로 이동하거나 뒤로 이동한다. navigate(-1)을 하면 뒤로 한 번 이동하고, navigate(-2)를 하면 뒤로 두 번 이동한다. 반대로 navigate(1)은 앞으로 한 번 이동한다.

    다른 페이지로 이동할 때,replace 라는 옵션을 사용하면 페이지를 이동할 때 현재 페이지를 페이지 기록에 남기지 않는다. 이 때는 자신의 메인 페이지 ("/")로 돌아오게 된다.

    const goHome = () => {
    	navigate('/home', {replace: true}); // home 경로로 이동
    }

    페이지 이동 시, 파라미터 전달 방법

    navigate() 함수의 첫 번째 인자에 이동할 경로, 두 번째 인자의 state 속성에 파라미터를 넣어준다.

    navigate( '/이동경로', { state: { key: value, key: value, ... } } )

    이동한 페이지에서,  파라미터 취득 방법

    • useLocation() 훅으로 location을 취득한다.
    • locaiton.state 로 전달 받은 파라미터를 취득할 수 있다.
    let location = useLocation();
    let key = location.state.key

    https://curryyou.tistory.com/477

     

    [React] Router v6: useNavigate() 파라미터 전달&취득 방법 - useLocation()

    # useNavigate() 파라미터 전달, useLocation() 파라미터 수신 방법 react-router-dom v6 에서 1. useNavigate() 로 페이지를 이동하면서 파라미터를 전달하는 방법 2. useLocation() 으로 파라미터를 취득하는 방..

    curryyou.tistory.com

    NavLink

    NavLink 컴포넌트는 링크에서 사용하는 경로가 현재 라우트의 경로와 일치하는 경우 특정 스타일 또는 css 클래스를 적용하는 컴포넌트이다. 이 컴포넌트의 style과 className은 {isActive : boolean} 을 파라미터로 전달받는 함수 타입의 값을 전달한다.

    const activeStyle = {
    	color: 'green',
    	fontSize: 20
    }
    
    <NavLink to="/about" style={({isActive}) => isActive ? activeStyle : undefined} >
    
    <NavLink className={({isActive}) => isActive ? 'active' : undefined} >

    Navigate 컴포넌트

    Navigate 컴포넌트는 컴포넌트를 화면에 보여주는 순간 다른 페이지로 이동하고 싶을 때 사용한다. 즉, 페이지를 리다이렉트할 때 사용한다.

    (ex. 사용자의 로그인이 필요한 페이지인데, 로그인을 안 한 상태라면 로그인 페이지로 이동해야 하는 경우)

    //MyPage.js
    import { Navigate } from 'react-router-dom';
    
    const MyPage = () => {
    	const isLoggedIn = false;
    	if(!isLoggedIn) {
    		return <Navigate to='/login' replace={true} />
    	}
    }

    📌Not Found

    Not Found 페이지는 사전에 정의되지 않은 경로에 진입했을 때 보여주는 페이지이다.

    //App.js
    import { Route, Routes } from 'react-router-dom';
    import Home from './pages/Home';
    import Article from './pages/Article';
    import Articles from './pages/Articles';
    import NotFound from './pages/NotFound';
    
    const App = () => {
    	return (
    		<Routes>
    			<Route index element={<Home />} />
    			<Route path='/articles' element={<Articles />}>
    				<Route path=':id' element={<Article />} />
    			</Route>
    			<Route path='*' element={<NotFound />} />
    		</Routes>
    	)
    }

    *는 wildcard문자로 아무 텍스트나 매칭한다는 뜻이다. 이 라우트 엘리먼트의 상단에 위치하는 라우트 규칙들을 모두 확인하고 일치하는 라우트가 없다면 이 라우트가 화면에 나타나게 된다.

    <Route index element={<Home />} />

    위 코드에서 index는 path='/ '와 동일한 역할을 한다.

    728x90

    'React' 카테고리의 다른 글

    React project 복사하기  (0) 2022.11.10
    useEffect에서 async/await 사용하기  (0) 2022.09.29
    불변성 지키기  (0) 2022.09.20
    propTypes  (0) 2022.09.04
    React 설치하기  (0) 2022.08.28

    댓글