본문 바로가기

React

[React] 라우터 (useNavigate, Navigate, Link 등)

728x90

 

 

 


SPA ( Single Page Application ) :  하나의 페이지로 만들어진 어플리케이션

 

전통적 웹 어플리케이션 vs SPA

 

 

 

 

  SPA는 html파일을 브라우저 측에서 로드하고, 필요한 데이터는 API와 ajax통신을 이용해서 처리한다
  브라우저에서 사용자가 상호작용 하면 필요한 부분만 업데이트해서 처리한다
  멀티플랫폼 Android, IOS에 대응하여 웹뷰로 처리하는 목적으로도 사용된다

 

 

SPA의 단점

 

    1️⃣ 앱의 규모가 커지면, JS파일도 너무 커져서 로딩이 오래걸리게 된다

    2️⃣ 브라우저에서 렌더링이 완료되기 까지 비어있는 화면이 나오게 된다

    3️⃣ 규모가 큰 어플리케이션은 SSR(서버사이드 렌더링) 방식으로 처리한다 (웹팩 설정 필요)

 

 

라우팅이란?

   브라우저의 주소상태에 따라 다양한 화면을 보여주도록 처리하는 것을 의미한다

 

 

Why 왜 사용하는 거야?

    ✅ create-react-app로 프로젝트를 생성하게 되면 기본적으로  SPA에 CSR(클라이언트 렌더링)이다

    ✅ 하나의 페이지만 사용하게 된다

    ✅ SPA이지만 라우터를 활용해서 사용자로 하여금 여러 페이지가 존재하는 것처럼 느껴지게 할 수 있다

 


 👩‍💻라우터 설치하고 프로젝트 시작하기

 

1. 라우터를 적용할 프로젝트 생성

npm create react-app 프로젝트명

 

 

2. 라우터 설치

npm add react-router-dom

 

라우터를 설치하게 되면 다음과 같이 나오면 성공!

 

잘 설치되었는지 확인해볼까?

package.json파일에 들어가서 "react-dom"이 들어있는지 확인해보면 된다!

 

 

3. 프로젝트 시작

npm start

👩‍💻 라우터 적용하기

    1️⃣ 라우터를 사용할때는 index.js에서 App컴포넌트를 <BrowserRouter>로 감싸준다

    2️⃣ 페이지 컴포넌트 만들기

    3️⃣ App컴포넌트에서 <Routes>를 사용해서 분기하기

    4️⃣ 주소요청을 통해 확인하기

 

[ index.js ]

....
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>

);

 

 

[ App.js ]

 

   ✅ /요청은 Home컴포넌트가 나타남

   ✅ /user요청은 User컴포넌트가 나타남

   ✅ /info요청은 Info컴포넌트가 나타남

 

function App() {

  return (
    <Routes>
        <Route path='/' element={<Home/>}/>
        <Route path='/user' element={<User/>}/>
        <Route path='/info' element={<Info/>}/>
    </Routes>
  );
}

export default App;

 

< 정리본 >


 👩‍💻 Link를 이용해서 다른페이지로 이동하기

    ✅ link태그는 화면에서 a태그로 생성된다

    to 속성에는 연결할 요청주소를 작성한다

    어느 컴포넌트든 사용할 수 있다

 

//.....
return (
	<ul>
		<li><Link to='/user'>회원페이지</Link></li>
	</ul>
)

 


URL파라미터 or 쿼리스트링

   같은 컴포넌트라도 전달되는 데이터에 따라서 다른 내용을 보여줘야 하는 경우가 있는데, 대표적으로 상세페이지가 있다 

   이 때 URL주소의 매개변수를 전달할 수 있고, 컴포넌트는 그 값을 받아서 사용할 수 있다

 

1️⃣ 쿼리스트링

     쿼리스트링은 주소의 ? 뒤키 = 값 의 형태로 넘어가는 매개값이다

     별도의 라우터 설정은 하지 않아도 되고, 컴포넌트에서는 useLocation() 훅 or useSearchParams() 훅을 사용해서

     쿼리스트링을 받을 수 있다

/ 경로 ? 키 = 값 & 키 = 값

 

 [ Link ]

//.....
return (
	<ul>
		<li><Link to='/user?id=aa123&key=1'>회원페이지(쿼리파람)</Link></li>
	</ul>
)

 

[ Component ] 

 ✅ useLocation( ) 훅

const location = useLocation( );   
 
 

 ✅ useSearchParams( ) 훅 : 배열을 반환!

const [객체, function] = useSearchParams() 

    첫 번째 요소는 쿼리파라미터를 조회하거나 수정하는 get, set이 담긴 객체

     두 번째 요소는 쿼리파라미터를 객체로 업데이트 하는 함수 반환

 

    const [obj, setObj] = useSearchParams();
    let id = obj.get("id"); //request.getParameter("키")
    let key = obj.get("key");

 


 

2. URL파라미터 ⭐⭐

     URL파라미터는 주소 뒤에 /경로/값/값 의 형태로 넘어가는 매개값이다

     라우터에 추가적인 설정이 필요하다 ( /주소:키 )

     컴포넌트에서는 useParams( ) 훅을 사용하여 URL파라미터를 받을 수 있다

 

[ Router ]

function App() {

  return (
    <Routes>
        .....
        <Route path='/info:num' element={<Info/>}/>
    </Routes>
  );
}

export default App;

 

[ Link ]

 

//.....
return (
	<ul>
		<li><Link to='/info/1'>1번 info</Link></li>
		<li><Link to='/info/2'>2번 info</Link></li>
		<li><Link to='/info/3'>3번 info</Link></li>
	</ul>
)

 

[ Component]

  ✅ useParams( ) 훅

 

     /param에는 link로 넘어온 키가 담겨 있다

   let param = useParams( );

 

 

< 정리본 >


👩‍💻 중첩라우터로 공통 부분 처리하기

     글페이지가 있고 글에 따른 상세화면이 있다고 가정해보면, 라우터의 설정은 다음과 같이 보여진다

 

<Routes>
	<Route path='/board' element={<Board/>}/>
	<Route path='/board/:num' element={<BoardContent/>}/>
</Routes>

 

    두 라우터가 다르기 때문에 각각 다른 화면이 보이게 된다

 


 

만약 Board 목록 페이지를 공통으로 사용하고 상세페이지를 서브로 보여주려고 한다면 중첩라우터를 활용할 수 있다

중첩라우터로 적용되면 부모컴포넌트에서 <Outlet> 컴포넌트를 활용해서 하위 라우터를 보여지게 할 수 있다

 

<Routes>
	<Route path='/board' element={<Board/>}> 👉 공통되는 부분 (부모 컴포넌트)
		<Route path=':num' element={<BoardContent/>}/>  👉 상세페이지는 서브 (하위 컴포넌트)
	</Route>
</Routes>

 

[ Board ]

const Board = () => {

    return (
        <div>
            <h3>게시글목록</h3>
            <ul>
                <li><Link to='/board/1' >글1</Link></li>
                <li><Link to='/board/2' >글2</Link></li>
                <li><Link to='/board/3' >글3</Link></li> 
             </ul>

            {/* Oulet컴포넌트가 사용된 자리에 중첩된 내용이 보여지게됩니다 */}
            <Outlet/>    👉 상세페이지가 보여짐
        </div>
    )
}

export default Board;

 

[ BoardContent ] 👉 < Outlet > 으로 보여지는 부분

const BoardContent = () => {

    let {num} = useParams()

    return (
        <div>
            <h3>글 상세페이지</h3>
            {num}번 글입니다      
        </div>
    )
}

export default BoardContent;

 

 

결과는 다음과 같이 나온다!

 

 < 정리본 > 


 

👩‍💻 헤더 태그 분리하기

라우터의 부가적인 기능

 

 1️⃣ NavLink 컴포넌트

       링크에서 사용하는 경로가 라우터의 경로와 일치하면 특정스타일을 적용 (활성화기능)

 

 2️⃣ useNavigate( ) 훅 vs Navigate 컴포넌트

 

       ✅ useNavigate( ) 훅

               - JS의 history 객체를 대신

               - 이벤트에서 사용

 

       ✅ Navigate 컴포넌트 

               - 리다이렉트 기능  

               - 렌더링시에 사용

 


 

NavLink컴포넌트 

  NavLink는 링크의 경로가 라우터의 경로와 일치하면 특정스타일을 적용해준다 ( style속성을 제공 )
  style속성에는 실행시킬 함수를 작성한다
  이 함수에 매개변수로 { isActive : boolean } 객체를 넣어주는데, 활성화 여부를 표시가 가능하다
  사용은 반드시 { isActive }변수로 구조분해할당

 

[ Board ]

const Board = () => {
	 const myStyle = {color: "red", backgroundColor: "yellow"}
    return (
        <div>
            <h3>게시글목록</h3>
            <ul>
                {/* 
                <li><Link to='/board/1' >글1</Link></li>
                <li><Link to='/board/2' >글2</Link></li>
                <li><Link to='/board/3' >글3</Link></li> 
                */}
                <li><NavLink to='/board/1' style={
                    ({isActive}) => {
                    return isActive ? myStyle : undefined  
                    }
                }>글1</NavLink></li>
                <li><NavLink to='/board/2' style={({isActive}) => (isActive ? myStyle : undefined  )}>글2</NavLink></li>
                <li><NavLink to='/board/3' style={({isActive}) => (isActive ? myStyle : undefined  )}>글3</NavLink></li> 
            
             </ul>

            {/* Oulet컴포넌트가 사용된 자리에 중첩된 내용이 보여지게됩니다 */}
            <Outlet/>
        </div>
    )
}

export default Board;

 

 

< 정리본 >

 


 

useNavigate( ) 훅

   let navigator = useNavigate( );

 

 1️⃣ useNavigate훅은 특정 event가 발생할 때,  url을 조작할 수 있는 함수를 제공한다

 

import { Fragment } from "react";
import { NavLink, Outlet, useNavigate } from "react-router-dom";

const Header = () => {
    //useNavigate() 훅
    let nav = useNavigate();

    const goHome = () => {
        nav('/내가원하는 주소') 
    }
    return (
    	<button onClick={goHome}>이동</button>
    )

}
export default Header;

 

 

 

 

  2️⃣ react v6 에서 useHistory 가 변화한 것 ( JS의 history객체를 대신 함 )

 

  ...
  let nav = useNavigate();
  
  return(
      <>
          <button onClick={() => nav(-1)}>   // history.go(-1)
            Go back
          </button>
          <button onClick={() => nav(1)}>    // history.go(1)
            Go forward
          </button>
      <>
  )

 


 

Navigate 컴포넌트

    - <Navigate> 컴포넌트는 렌더링 될 때 현재 위치를 변경한다

    - useNavigate( ) 훅과 비슷해 보이지만, useNavigate( ) 훅은 렌더링 과정에 사용할 수 없다

 

const MyPage = () => {
    /*
    렌더링 과정에 nav를 쓰지말라는 경고 후 작동이 안됩니다.
    let nav = useNavigate()
    let loginYN = false;
    if(!loginYN) {
        nav('/');
    }
    */
	
    //Navigate컴포넌트
    let loginYN = false;
    if(!loginYN) {
        return <Navigate to='/' replace={true}/>
    }

    return (
        <div>
            여기는 권한있는 사람만 들어옴
        </div>
    )

}
export default MyPage;

 

< 정리본 >


 

https://onev.tistory.com/81

 

[React] 라우터 총정리본 (이것만 보면 반은 먹고 들어간다! )

 

onev.tistory.com