본문 바로가기
Front-end/React

[React][NFasT 프로젝트] mainpage 처음부터 다시 만들어보기 1

by 지니어스팍 2023. 12. 11.

♥ 목차 ♥

    728x90
    728x90

    계기

    NFasT 프로젝트를 다시 복습하며 처음부터 새로 만들어보기로 했다.

    다시 만들어보는 이유는 첫째, 컴포넌트의 사용과 상태관리를 다시 복습하고 싶었고 둘째 코드 리팩토링을 하기 위해서다.

    그리고 마지막에 시간이 없어서 반응형으로 만들어보지 못했는데 반응형으로 구현하는 것도 추가해보려한다.

    그리고 redux 폴더 구조를 더 편리하게 짤수는 없을까 검색해본 결과 Ducks Pattern을 발견했는데 

    기존 ActionCreator,reducer,type이 계속 한벌씩 생성되는걸 한 묶음으로 모듈화 하여 관리하는 패턴이다.

    깔끔하다고 해서 이번 기회에 적용해보기로 했다!!

    NFasT 프로젝트를 진행하는 동안 느꼈던건 상태관리가 중요하고 어렵다는 것이다. 컴포넌트에 속한 state가 변화할 때마다 props로 넘겨줘야하는데 컴포넌트가 겹겹이 있으면 깊숙한 곳의 state를 추적하기 어려웠다ㅠ 이때 상태관리를 위해 Redux를 사용했고 그 과정이 어려웠어서 Redux의 사용을 다시 복습해보며 익히고 싶었다.

     

    또한 프론트엔드 2명이서 작업을 진행하다보면 서로 수정해놓고 지워도 되나 싶은 코드들을 모두 주석처리 시켰는데

    이러한 주석들도 다시 깨끗하게 필요 없는 부분을 삭제하고 파일 이름을 좀 더 직관적으로 정리될 수 있게 정리하고 싶었다.

     

    react 시작하기

    npx create-react-app NFasT

     

    + 처음으로 react를 시작하면 파일들이 많은데 직관적으로 편리하게 파일을 관리하기 위해 안쓰는 파일들을 지웠다.

    삭제 목록 :

    public/ logo192,logo512,mamifest,robots

    src/ App.css,App.test.js,index.css,logo.svg,reportwebvitals,setuptests

    처음 리액트를 시작했을 때 파일들

     

    정리된 구조

     

    redux 설치

    npm install redux   // 라이브러리 설치 
    npm install react-redux   // redux 라이브러리 사용

     

    action --> dispatch --> reducer --> store 순으로 데이터가 단 방향으로 흐른다.

     

    redux 라이브러리에 있는 createStore 메소드를 통해 Store 객체를 만든다.

    react-redux 라이브러리에 있는 Provider 컴포넌트를 가져와 스토어를 통해 상태관리를 해줄 컴포넌트 index.jsx 를 감싼다.

     

    여기서 원래 프로젝트에서는 createStore를 사용했는데 취소선이 무엇인가하고 봤더니 공식문서에서는 ReduxToolkit을 권장하고 있다는 내용이었다. 취소선 없이 쓰려면 legacy_createStore를 사용하면 된다고 했다. 

    이번에는 reduxjs/tookit을 권장에 따라 사용해보고자한다.

     

    import React from "react";
    import ReactDOM from "react-dom/client";
    import App from "./App";
    import { Provider } from "react-redux";
    import { legacy_createStore } from "@reduxjs/toolkit";
    import rootReducer from "./modules/index";
    
    const root = ReactDOM.createRoot(document.getElementById("root"));
    
    const store = legacy_createStore(rootReducer);
    
    root.render(
      <Provider store={store}>
        <App />
      </Provider>
    );

     

    아래는 configureStore의 예시

    reducer을 지정하는 방식이 기존의 방식과 조금 다르지만 쉽게 익힐 수 있는걸 볼 수 있다. 

    아래 방식대로 middleware를 지정할수 있고  devTools는 개발자 도구의 사용 여부로 기본적으로 true로 설정되어있다.

    // createStore대신 configureStore를 사용한다
    const store = configureStore({
      reducer: rootReducer, // combineReducers로 리듀서를 묶은 리덕스 모듈 파일
      middleware: [ReduxThunk, logger], // 사용할 미들웨어들을 나열
      devTools: true, // 기본은 true로 설정되어있다. 개발자 도구의 사용 여부를 정한다.
      preloadedState : {
        loading: {
          loadingState: true,
          loadingTest: "123 Loading!",
        }
      }, // 리덕스 스토어가 생성될 때, 초기값을 정의한다.
      
    });
    
    //https://phsun102.tistory.com/103

    Link

    웹페이지에서는 원래 링크를 보여줄 때 a태그를 사용하지만 a태그는 클릭시 페이지를 새로 불러오기 때문에 사용하지 않고 react에서는 Link 컴포넌트를 사용한다.

     

    <Link to="/market/가게번호"> 를 하게되면 해당 경로로 이동하게 된다.

     

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

     

    Redux Ducks Pattern

    redux 모듈을 만들기 위한 작성방식으로 한 파일에 action,reducer,type이 모두 포함되어있는 것을 이야기한다.

    ducks 패턴 규칙
    1. 항상 reducer()란 이름의 함수를 export default 해야한다.
    2. 항상 모듈의 action 생성자들을 함수형식으로 export한다.
    3. npm-module-or-app/reducer/ACTION_TYPE 형태의 action 타입을 가져야한다.

    redux 폴더가 아닌 modules 폴더를 만들어서 관리한다.

    여기서 index.js를 만들어 리듀서들을 하나로 합쳐주는데  combineReducers 함수로 rootReducer를 지정해서 내보낸다.

    // src/modules/index.js
    import { combineReducers } from "redux";
    import mainpageReducer from "./mainpage";
    
    const rootReducer = combineReducers({
      mainpageReducer,
    });
    
    export default rootReducer;

    MUI

    모바일과 데스크탑 모두를 지원하는 반응형 UI를 빠르게 개발할 수도 있고 필요로하는 대부분의 컴포넌트를 제공하는 MUI를 사용했었다.

    npm install @mui/material @emotion/react @emotion/styled

     

    react-responsive

    그리고 드디어 반응형으로 만들기위해 react-responsive를 설치한다.

    npm install react-responsive

     

    styled-component

    npm install --save styled-components

    컴포넌트 자체로 사용하기에 더욱 직관적으로 스타일 코드를 볼 수 있는 styled-component를 사용했다.

     

    이 전 프로젝트 RealCart에서는 inline 스타일을 사용했었는데 바로바로 해당 html 안에 스타일을 줄 수 있어서 

    직관적이고 편리했지만

    1. 코드가 지저분해진다.

    2. 리렌더링시에 인라인 스타일이 적용된 컴포넌트/일반태그가 다르다고 판단해서 돔을 새로 그리게 되어 불필요한 리로딩이 발생한다고 하여 styled-component를 사용해보기로 했다.

    3. 또한 styled-component를 사용하면 style 속성의 재사용성을 높일 수 있다는 장점이 있다.

     

    inline style 적용방식보다 styled-components style 적용방식이 성능적으로 우수하다는 걸 테스트 해보았다.

    https://long-backpackstrap.tistory.com/entry/Styled-Component의-성능향상-체험하기-ReactNFasT와-RealCart-프로젝트-회고

     

    Styled Component의 성능향상 체험하기 [React][NFasT와 RealCart 프로젝트 회고]

    싸피에서 프론트엔드 역할로 프로젝트를 진행하며 처음 react를 접했을 때는 inline 방식으로 style를 적용했다. Real Cart 프로젝트 : inline style 방식 NFasT 프로젝트 : styled-component 방식 그 때에는 style

    long-backpackstrap.tistory.com

     

     

    React Router

    신규 페이지를 불러오지 않는 상황에서 각각의 url에 따라 선택된 데이터를 하나의 페이지에서 렌더링 해주는 라이브러리

    npm install react-router-dom

     

    import React from "react";
    import {BrowserRouter,Routes,Route} from "react-router-dom";
    import MainPage from "./pages/customer/MainPage";
    
    function App() {
      return( 
      <div>
        <BrowserRouter>
        <Routes>
          <Route path="/" element={<MainPage/>}/>
        </Routes>
        </BrowserRouter>
      </div>
      );
    }
    
    export default App;

     

    1. <BrowserRouter> 태그로 컴포넌트를 감싸준다.

    2. <Routes>은 여러<Route> 컴포넌트를 감싸서 그중 규칙이 일치하는 라우트 단 하나만을 렌더링 시켜준다.

    3. <Route>의 path 속성에는 경로, element 속성에는 컴포넌트를 넣어준다.

    여기서 참고로 여러 라우팅을 매칭하고 싶으면 URL 뒤에 *를 사용하면 된다.

    그리고 만약 path를 /market/가게번호 로 접근하면 market.js를 보여주게된다.

    728x90
    728x90