[wecode 4일차] Router

박요진·2023년 8월 31일
0

⭐️ 정리

  1. Link 컴포넌트
  • 클릭 시 바로 페이지를 이동하기 때문에, 조건 없이 페이지를 이동할 때 적합합니다.
  • Nav Bar의 메뉴 혹은 Aside Menu 등 바로 페이지를 이동하는 경우 사용하는 것이 좋습니다.
  1. useNavigate hook
  • 조건에 따라 페이지를 전환 해야할 때 사용하기 적합합니다.
  • 로그인 버튼 클릭 시 백엔드 API 로 데이터를 전송하는 작업을 하거나, 인증 혹은 인가가 필요한 경우, 혹은 로그인 작업 이후 응답 메세지에 따른 분기 처리를 해야 하는 상황일 때, useNavigate를 사용하는 것이 좋습니다.

개요

  • SAP가 무엇인지 알아보고, 웹에서 화면을 전환하는 Routing, 스타일링을 편하게 할 수 있는 CSS 전처리기에 대해서 배워봅시다.

학습 목표

  1. SPA 가 무엇인지 설명할 수 있다.
  2. react-router-dom을 이용해 Router Component를 구현할 수 있다.
  3. react-router-dom을 이용해 Routing을 하는 방법 2가지와 차이점에 대해 설명할 수 있다.
  4. <Link> Component 와 <a> tag 의 차이점에 대해 설명할 수 있다.
  5. css 전처리기의 역할에 대해 설명할 수 있다.
  6. sass에서 제공하는 문법을 이용하여 css파일을 scss파일로 변환할 수 있다.

1. Routing

  • 라우팅(Routing)과 관련된 용어를 정리하자면 Route는 경로, Routing은 경로를 찾는 행위 라는 의미를 가지고 있는데, Router는 Routing을 해주는 '도구' 라고 할 수 있습니다.
  • 기존의 웹페이지에서는 html에 a 태그를 통해 링크를 걸고, 화면에서 해당 링크를 클릭했을 때 다른 html 페이지로 이동하는 방식으로 라우팅 했습니다. 하지만 React에서는 다른 방식으로 라우팅을 구현해야 합니다.
  • 우선 React(리액트)는 Framework가 아닌 Library이기 때문에 라우팅 기능이 내장되어있지 않습니다. 그래서 별도의 Library를 설치해서 라우팅을 구현해야 하고, CRA를 통해서 만들 웹 애플리케이션은 SPA이기 때문에 기존의 라우팅 방식과는 다르게 라우팅을 구현해야 합니다.

2. SPA

  • SPA (Single Page Application) 는 페이지가 하나인 웹 애플리케이션입니다. 여기서 ‘페이지’란 html 파일을 뜻하기 때문에, SPA는 html이 하나인 웹 애플리케이션을 의미합니다. 상반되는 개념으로는 html 파일이 여러 개인 MPA (Multi Page Application)가 있습니다.
  • MPA는 html 파일이 여러 개라서 다른 페이지를 보여 주고 싶을 때, 해당 html 파일을 연결해 보여주는 형태로 페이지를 이동하는 기능을 구현할 수 있었습니다. 하지만 SPA는 html 파일이 하나이기 때문에 하나의 html에서 경로(url)에 따라서 다른 UI를 보여주는 라우팅 기능이 필요하게 된 것입니다.

3. React-Router

3-1. react-router-dom 설치

  • react-router-dom 은 React에서의 라우팅을 위해 가장 많이 사용되는 라이브러리 입니다.
$ npm install react-router-dom
  • 라이브러리 설치 방법은 위와 같습니다.
  • 터미널에서 프로젝트 폴더로 이동한 뒤, 위와 같은 명령어를 작성하면 설치가 가능합니다.
// package.json

{
  "name": "react-project",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^4.2.4",
    "@testing-library/react": "^9.3.2",
    "@testing-library/user-event": "^7.1.2",
		"react": "^18.0.0",
		"react-dom": "^18.0.0",
    "react-router-dom": "^6.3.0",
    "react-scripts": "3.4.3"
  }
}
  • 설치가 완료되었다면, 위처럼 package.jsondependencies 항목에서 해당 패키지 명과 버전이 잘 추가되었는지 반드시 확인해 줍니다.

3-2. Router 컴포넌트

3-2-1. Router 컴포넌트를 만드는 이유

  • CRA를 통해 프로젝트를 만들고 npm start를 터미널에 입력하면, 최초 화면에서 App 컴포넌트의 내용을 볼 수 있게 됩니다.
  • 하지만 지금은 아무리 url을 변경해도 똑같은 화면만 보이게 됩니다.
  • 그래서 라우팅 기능을 구현하고 관리하기 위해서 Router 컴포넌트를 만들어줘야 합니다.

3-2-2. Router.js 파일 위치

- Router.js 파일은 `src` 폴더 안 `index.js` 와 같은 위치에 생성하고, App.js와 App.css 파일은 제거해줍니다.

3-2-3. Router 컴포넌트 구현하기

// Router.js

import React from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
  • 라우팅을 구현하기 위해 설치했던 react-router-dom 패키지에는 여러 컴포넌트가 포함되어 있고, 이 중에서 Router 컴포넌트를 구현하기 위해서는 BrowserRouter, Routes, Route 컴포넌트를 import 해야 합니다.
// Router.js

import React from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';

const Router = () => {
	return (
		<BrowserRouter>                                        // 1
      <Routes>                                             // 2
        <Route path='/' element={<Components />} />        // 3
      </Routes>
    </BrowserRouter>
	);
};

export default Router;
  • import 한 3개의 컴포넌트를 이용해서 Router 컴포넌트를 구현해보겠습니다.
    1. BrowserRouter 컴포넌트로 전체를 감싸줍니다.
    2. BrowserRouter 컴포넌트의 자식 요소로 Routes 컴포넌트를 넣어줍니다.
    3. Routes 컴포넌트의 자식 요소로 Route 컴포넌트를 넣어줍니다.

  • Router 컴포넌트를 구성하는 각각의 컴포넌트들은 어떤 역할을 하는 지 알아봅시다.
    1. BrowserRouter : 주소 변경에 대해 다양한 편의 기능을 제공해주는 컴포넌트. 대표적인 기능으로는 페이지가 새로고침 되지 않ㅎ아도 주소 변경이 가능하게 하는 기능이 있습니다.

    	2. Routes : 여러 Route를 감싸서 그 중 규칙이 일치하는 라우트 단 하나만을 렌더링 시켜주는 역할을 합니다.
       
    	3. Route : 형식을 보면 html 에서 사용한 태그의 형식과 유사합니다. 
    	   예를 들어 input 태그에서 type 속성을 사용했던 것처럼 `Route` 컴포넌트에서는 path와 element 속성을 사용하고 있습니다. 
       
    	   - `path` : 경로를 속성하는 속성
    	   - `element` : path 속성에서 설정한 경로로 이동 했을 때, 어떤 컴포넌트를 보여줄 지 결정하는 속성 (화면에 그려지는 UI를 담은 컴포넌트)
// Router.js

import React from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import Login from './pages/Login/Login';                     ⌉
import Signup from './pages/Signup/Signup';                  ⎮ // 1
import Main from './pages/Main/Main';                        ⌋

const Router = () => {
	return (
		<BrowserRouter>
      <Routes>
        <Route path='/' element={<Login />} />               ⌉
        <Route path='/signup' element={<Signup />} />        ⎮ // 2
        <Route path='/main' element={<Main />} />            ⌋
      </Routes>
    </BrowserRouter>
	);
};

export default Router;
  1. Route 컴포넌트의 path 속성에 따라 화면에 그려줄 UI를 담은 컴포넌트를 import 합니다.

  2. Route 컴포넌트의 path 속성을 설정해 주고, 설정한 경로(url) 로 이동했을 때, 화면에 그려질 UI를 담은 컴포넌트를 element 속성에 설정합니다.

    • http://localhost:3000 이라는 주소를 기준으로 했을 때, url이 http://localhost:3000 이라면 Login 컴포넌트를 내용에 화면을 그려주고, url이 http://localhost:3000/signup 일 때는 Signup 컴포넌트의 내용을 화면에 그려주게 됩니다.
    • / 는 디폴트 값으로 경로가 지정되지 않은 경우와 같기 때문에, url에서 아무런 경로를 지정해주지 않은 경우에는 Route 컴포넌트의 path 속성에서 / 을 찾아 일치하는 element의 컴포넌트를 그려주기 때문입니다.

3-2-4. Router 컴포넌트 활용

  • Router 컴포넌트도 하나의 컴포넌트이기 때문에 render가 되면 url에 따라서 보여줄 내용물만 찾아서 화면에 그려주게 됩니다.
  • 그렇다면 경로에 상관없이 모든 화면에서 표시되어야 하는 컴포넌트는 어떻게 하면 좋을지 알아봅시다.
// Router.js

import React from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import Nav from './components/Nav/Nav';
import Footer from './components/Footer/Footer';
import Login from './pages/Login/Login';                    
import Signup from './pages/Signup/Signup';                  
import Main from './pages/Main/Main';                       

const Router = () => {
	return (
		<BrowserRouter>
			<Nav />                                           // nav 컴포넌트
      <Routes>
        <Route path='/' element={<Login />} />               
        <Route path='/signup' element={<Signup />} />        
        <Route path='/main' element={<Main />} />            
      </Routes>
			<Footer />                                        // footer 컴포넌트
    </BrowserRouter>
	);
};

export default Router;
  • Routes 컴포넌트는 여러 Route를 감싸서 그 중 규칙이 일치하는 라우트 단 하나만을 렌더링 시켜줍니다.
  • 경로에 상관없이 보여주고 싶은 컴포넌트가 있다면, 위와 같이 규칙에 포함되지 않도록 Routes 컴포넌트의 밖에 위치 시켜봅시다.
  • 이렇게 구현하게 되면 결과적으로 NavFooter 컴포넌트는 특정 경로에 따라 보여지는 것이 아니라 어떤 경로가 오더라도 항상 화면에 보여지게 됩니다.

3-3. index.js 수정하기

// index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import Router from './Router';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Router />);
  • Router 컴포넌트를 구현했지만, Router 컴포넌트를 화면에 그려주기 위한 마지막 단계 입니다.
  • 바로 index.js에서 App 컴포넌트가 있는 위치에 Router 컴포넌트를 대체해주는 것입니다.
  • 이후 잘 적용이 되었는지 확인해보려면, npm start 를 통해 화면을 띄우고 Router 컴포넌트에서 설정해 주었던 path 값을 직접 url에 입력해서 UI가 변경되는 것을 확인하면 됩니다.

3-4. Router 이동하기

  • 지금까지 우리는 페이지 이동을 위한 Router 컴포넌트를 구성하고, 그것을 확인하기 위해 매번 직접 url 값을 수정해주어야 했습니다.
  • 만약 다른 웹 페이지들처럼 특정 동작을 통해 라우팅을 구현하려면 어떻게 해야하는건지 알아봅시다.
// Login.js

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

const Login = () => {
  return <Link to='/signup'>회원가입</Link>;
};

export default Login;
  • react-router-dom 에서 제공하는 컴포넌트 중 Link 컴포넌트를 이용해 라우팅 기능을 구현할 수 있습니다.
  • Router에서 여러 컴포넌트를 import 해서 사용했던 것과 마찬가지로, react-router-dom 으로부터 Link 컴포넌트를 import해서 JSX 내부의 원하는 곳에 사용할 수 있습니다.
  • Link 컴포넌트의 형식을 보면 to 라는 속성에 /signup 이라는 경로가 적혀 있습니다.
  • 이를 통해 화면에서 회원가입이라는 글을 클릭하게 되면 /signup 이라는 경로로 이동하게 되고, Route 컴포넌트의 path 값 중 일치하는 경로를 찾아 해당 컴포넌트를 화면에 그려주게 됩니다.

[React] Link vs a
1. a 태그 : 페이지 이동 시 서버로부터 매번 새로운 페이지를 요청해서 받아 오게 됩니다.
그렇다면 현재 화면에서 몇 가지가 랜더링 되어야 하는 작업에서도 전체 화면을 매번 다시 렌더링 하기 때문에 비효율적으로 동작하게 됩니다.

  1. Link 컴포넌트 : 변환된 a 태그는 실제 서버에 요청하지 않고 url만 변경합니다.
  2. 그렇다고 a태그를 아예 사용하지 않는 것 은 아닙니다. 예를 들어 애플리케이션 내부에서 url을 통해 페이지를 전환해야 할 때는, Link 컴포넌트를 이용해 효율적으로 이동할 수 있지만, 외부 사이트로 이동할 때는 항상 전체 페이지를 새로 받아와야 하기 때문에 a tag를 사용해야 합니다.
    .

3-4-2. useNavigate hook 사용하기

react-router-dom 에는 Link 컴포넌트 외에도 라우팅을 구현할 수 있게 해주는 hook 이 있습니다. 여기서 hook은 함수 컴포넌트에서 다루지 못했던 기능들을 구현할 수 있게 도와주는 함수입니다.

// Login.js

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

const Login = () => {
  const navigate = useNavigate();                             // 2

  const goToMain = () => {                                    // 3
    navigate('/main');
  };

  return (
    <button className='loginBtn' onClick={goToMain}>          // 4
      로그인
    </button>
  );
}

export default Login;
  • 위의 예시는 로그인 버튼을 눌렀을 때의 예시입니다.
    1. Link 컴포넌트를 사용 했던 것과 마찬가지로 react-router-dom 에서 useNavigate 를 import 합니다.
    2. useNavigate 함수를 실행하고, 해당 함수가 반환한 결과를 navigate 라는 변수에 할당합니다. 여기서 useNavigate가 반환하는 값은 페이지를 이동하는 함수이기 때문에, 결국 navigate 변수는 페이지를 이동하는 함수가 됩니다.
    3. 버튼 클릭 이벤트 발생 시 호출할 함수를 만듭니다. 해당 함수 안에서는 navigate 함수가 호출되도록 하고, 인자에는 이동할 경로를 넣어줍니다. 예를 들어 클릭 이벤트가 발생했을 때 goToMain 이라는 함수를 호출하고, 함수 내부에서 navigate('main') 을 호출하면서 Main 페이지로 이동하는 로직 입니다.
    4. button 태그에 onClick 이벤트를 생성하고, 이벤트 발생 시 실행될 함수를 넣어줍니다. React에서는 JSX 특징을 이용해서 이벤트를 걸어주고 싶은 태그에 속성을 설정하듯 직접 적용할 수 있습니다.

Link 컴포넌트와 useNavigate hook

  • Link 컴포넌트는 to 속성을 통해 무조건 해당 url로 이동하게끔 해주기 때문에 어떠한 조건에 의해 사용될 수 없습니다.
  • useNavigate hook을 사용하면 사용할 수 있습니다.
 // 실제 활용 예시

  const goToMain = () => {
	  if(response.message === 'valid user'){           
      navigate('/main');
    } else {   
      alert('가입된 회원이 아닙니다. 회원가입을 먼저 해주세요.') 
      navigate('/signup');
    }
  }
  • navigate함수의 호출 형태로 경로 이동을 하기 때문에 코드 상에서 조건에 따라 인자를 다르게 부여해 다른 경로로 이동할 수도 있고, 호출 자체를 안할 수도 있습니다.
  • 결국, 로직에 포함되어 특정 조건에서 경로를 이동하게 하고 싶을 떄는 Link 컴포넌트가 아닌 useNavigate hook을 사용하면 됩니다.
profile
프론트엔드 개발자 지망생입니다.

0개의 댓글

관련 채용 정보