본문 바로가기
프로그래밍/JS & React

JS & React 정리(1) - SPA를 위한 Router 연결

by 코로디링 2023. 9. 17.

 

2차 팀프로젝트 마무리는 다가오는데 이렇게 끝내면 다시 안쳐다볼 것 같아서 정리하는 글..

JavaScript, React를 배우고 활용하며 느꼈던 점, 그리고 앞으로 어떤 걸 공부하고 익혀야 할 지 정리해보려고 한다.

 

UI와 그에 따른 기능별로 정리하는 거라 굉장히 두서없을 예정ㅎㅎ

그래도 안 하는 거보단 낫겠지...

 

 

그래서 오늘의 주제는 라우터 연결하기!

 

html에서 a태그로 페이지 자체를 이동했다면

이번 프로젝트의 목표는 React로 SPA(Single Page Application)를 구현하는 것이었기 때문에 컴포넌트 간 연결을 해주는 Router가 필수적이었다. (다른 방법도 있지만.. 보통 이걸 많이 쓰는 것 같다...ㅎㅎ)


* SPA 장점, 단점

: 링크 태그를 사용하는 전통적인 방식은 페이지 요청 시마다 페이지를 모두 다시 렌더링하게 되므로 사용성도 좋지 않고 서버에 과부하를 일으킬 수 있음. 필요없는 부분까지 렌더링하게 되면 비효율적임. 따라서 SPA의 개념을 적용해 단일 페이지(Html) 내에서 그때그때 필요한 컴포넌트를 렌더링해주게 되면 UX향상, 서버 과부하 감소 등의 장점이 있음.

파일 자체가 무겁고 초기 구동 속도가 느릴 수 있으나 다른 장점에 비하면 그닥 큰 단점은 아니라고 함..


아무튼.. SPA는 보통 웹페이지보다는 애플리케이션에 많이 적용한다는데 일단 활용해보는 것에 맞춰 우리의 웹페이지에 적용함.

 

그래서!! router 이 자식,,, 막상 해보고 여러 번 써보니 그렇게 어려울건 없고 지금은 너무 당연하게 쓰는데 처음에 할 때는 뭐야? 왜 안돼? 되긴 되는데 왜 내 맘대로 안돼?? 이게 맞아??를 남발했다...

 

 

 

🤔Router 사용 방법

 

1) react-router-dom 설치하기

npm install react-router-dom
 

 

2) <BrowserRouter>태그로 최상위 컴포넌트 감싸기

index.html과 연결되어.. 여러 컴포넌트가 잠들어있는 App컴포넌트를 렌더링해주는 최상위(?) js에.. 가서.. (불분명한 표현 남발)

즉, index.js에서 최상위 컴포넌트(App)를 BrowserRouter로 감싸주어야 함.

(react-router-dom에서 import도 해주기)

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

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

 

3) Routes, Route 사용하기

그리고 보통 어떻게 하는지 모르겠지만 일단 실행되니 냅둔 우리의 App.js

 

  • 일단 라우터로 연결한 컴포넌트를 경로대로 import하고 Routes, Route도 import 하기
    • import { Route, Routes } from "react-router-dom";
  • <Route>를 <Routes>로 감싼 상태에서 Route안에 path와 element명시하기
    • <Routes><Route path="/main/*" element={<Main />}"/></Routes>
  • path는 "/"뒤에 컴포넌트 이름을 써주면 되는데 (추후에 백엔드..와 소통하기 위해서는) 소문자로 써야된다고 함..
  • /*은 여러 라우팅을 매칭할 때 씀.
    • 경로 뒤에 /*을 사용하면 해당 경로의 하위 경로들도 모두 일치시켜 같은 컴포넌트를 렌더링하는 것이 가능해집니다. ...라고 gpt님께서 설명해주심.
  • element에는 컴포넌트를 넣어주기
import "./App.css";
import Header from "./components/common/Header";
import Footer from "./components/common/Footer";
import Main from "./components/common/Main";

// router
import { Route, Routes } from "react-router-dom";
import Login from "./components/login/Login";
import Join from "./components/join/Join";
import Board from "./components/board/Board";
import ItemList from "./components/item/ItemList";
import Lounge from "./components/community/Lounge";
import ItemDetail from "./components/item/ItemDetail";
import Agree from "./components/join/Agree";
import Details from "./components/join/Details";
import Information from "./components/join/Information";
import Profile from "./components/join/Profile";
import Payment from "./components/payment/Payment";
import Payment2 from "./components/payment/Payment2";
import MyPage from "./components/common/MyPage";

// 커뮤니티 링크 페이지 import
import Community from "./components/community/Community";

// 로그인
import FindId from "./components/login/FindId";
import FindPw from "./components/login/FindPw";

// 게시판
import BoardFaq from "./components/board/BoardFaq";
import BoardQna from "./components/board/BoardQna";

// 장바구니
import EmptyItem from "./components/cart/EmptyItem";
import Cart from "./components/cart/Cart";
import CartItem from "./components/cart/CartItem";

import styles from "./css/common/common.module.css";
function App() {
  return (
    <div className="App" id={styles.wrap}>
      <Header />
      <Routes>
        {/* header 링크 */}
        <Route path="/*" element={<Main />} />
        <Route path="/main/*" element={<Main />} />
        <Route path="/login/*" element={<Login />} />
        <Route path="/join/*" element={<Join />} />
        <Route path="/cart/*" element={<Cart />} />
        <Route path="/board/*" element={<Board />} />
        <Route path="/itemlist/*" element={<ItemList />} />
        <Route path="/itemdetail" element={<ItemDetail />} />

        {/* 커뮤니티 링크 */}
        <Route path="/community/*" element={<Community />} />

        {/* 상세페이지, 장바구니, 결제 */}
        <Route path="/cartitem/*" element={<CartItem />} />
        <Route path="/emptyItem/*" element={<EmptyItem />} />
        <Route path="/myPage/*" element={<MyPage />} />

        {/* 로그인 */}
        <Route path="/findid/*" element={<FindId />} />
        <Route path="/findpw/*" element={<FindPw />} />

        {/* 게시판 */}
        <Route path="/boardfaq/*" element={<BoardFaq />} />
        <Route path="/boardqna/*" element={<BoardQna />} />

        <Route path="/agree/*" element={<Agree />} />
        <Route path="/profile/*" element={<Profile />} />
        <Route path="/details/*" element={<Details />} />
        <Route path="/information/*" element={<Information />} />

        <Route path="/itemdetail" element={<ItemDetail />} />
        <Route path="/payment" element={<Payment />} />
        <Route path="/payment2" element={<Payment2 />} />
      </Routes>

      {/* 회원가입 */}
      <Footer />
    </div>
  );
}

export default App;
 

 

4) Link 컴포넌트 적용하기

  • Link컴포넌트는 기존에 htm에서 a tag를 적용하던 방식대로 원하는 내용을 감싸주면 됨.
  • 그리고 to에 경로를 입력해주면 됨. <Link to="경로">내용</Link>
      <ul className={styles.gnb_list}>
        <li>
          <img src={"/images/header/food_img.png"} alt="" />
          간식&#183;사료
        </li>
        <li>
          <Link to="/itemlist">
            <img src={"/images/header/toy_img.png"} alt="" />
            장난감
          </Link>
        </li>
        <li>
          <img src={"/images/header/living_img.png"} alt="" />
          리빙&#183;패션
        </li>
        <li>
          <img src={"/images/header/stroll_img.png"} alt="" />
          산책&#183;케어
        </li>
        <li>
          <Link to="/community">
            <img src={"/images/header/community_img.png"} alt="" />
            커뮤니티
          </Link>
        </li>
      </ul>
 

 


정리 및 느낀 점

  • 처음에 간단한 예제만 보고 프로젝트에 적용시키려 할 때는 Routes, Route, Link를 모두 한 컴포넌트 내에 써야 하는 줄 알고 이리저리 써보며 조금 헤맸다.
  • 하지만 다른 팀을 살짝 보니 (ㅎㅎ) 상위 컴포넌트에 모두 Route를 몰고 필요한 컴포넌트에서 Link를 사용하길래 우리도 그렇게 했다 ^^
  • 현재 대부분의 링크는 구분하기 쉽게 App.js에 넣어져 있으나 Community 페이지의 하위 링크들은 useContext로 데이터 값을 전달하기 위해 따로 Community 컴포넌트 안에 Routes, Route를 명시해두었다. (....일관성도 없고 효율도 없는 것 같지만 일단 기능 구현에 급급했다.. 최적화 바라지마...!! ㅠㅠ )
      <CreatePostContext.Provider
        value={{ addedPostArray, addPostFromLocalStorage, loungePostArray2 }}
      >
        <Routes>
          <Route path="/*" element={<Lounge />} />
          <Route path="/lounge/*" element={<Lounge />} />
          <Route path="/event/*" element={<Event />} />
          <Route path="/neighborhood/*" element={<Neighborhood />} />
          <Route path="/createpost/" element={<CreatePost />} />
        </Routes>
      </CreatePostContext.Provider>
 

이건 나중에 정리할 것!!