개발/사이드프로젝트

Side Project - RMS 개발 일지

RavenKim 2024. 1. 19. 11:41
반응형

RMS - (Rental Management System)

참여한 차수

1차: 23년 11월 28일 ~ 24년 1월 19일

  • FE Lead개발자

2차: 24년 1월 22일  ~ 

 

 

만들게 된 계기:
회사 복지중 직원들을 위해 인터넷 강의를 제공중이다. 하지만 액셀로 강의 리스트와 대여자를 관리하고, 구글폼으로 신청과정이 번거롭게 여겨지고 시간이 많이 소요된다고 느껴 마음맞는 팀원들과 이것을 개선하는 시스템을 만들고자 프로젝트를 진행하였다. 

 

작업과정

 

기능 설계 과정

 

 

 

 

Frontend Dev(프론트 개발 상세)

회사에서 주니어닌 내가 Side 에서는 리드개발자!? 

 

 VIte

도입이유: 

  1. 지루할 정도로 길었던 서버 구동 &느렸던 소스 코드 갱신 (https://ko.vitejs.dev/guide/why.html

    결과: 기존 npm을 사용했을 시보다 속도가 크게 개선되었다. 

    수치: npx create-react-app 으로 react앱을 만들고 로컬환경에서 실행한 시간을 측정해 보았다. (순정 react)
    우리 프로젝트 'yarn start' 시 최초 'npm start' 시 안정된 후 'npm start' 시
    333ms 57990ms 8470ms
    # 뒤에 두 수치는 프로젝트가 무거워지면 더 오래 걸릴것으로 예상됨 (순정으로 테스트후 측정 환경은 동일)


    이제 최초에 로컬 서버 접속시 기다리던 지루한 시간들을 없애서 여러가지 환경설정을 빠르게 진행 할 수 있었다. 


     또한build시
    적은 용량의 index.html로 사용자가 화면을 빨리 볼 수 있는 기능적 이점또한 가지게 된다. 


  2. 편리한 url 을 통한 에셋(이미지) 가져오기 (https://xn--ko-9f0k.vitejs.dev/guide/assets.html)
    이미지를 Public 폴더가 아닌 src안에 일괄적으로 보관하여 파일 관리가 편하다.
    별도의 이미지 관련 설정 없이 import 시
    사진과 같이 원하는 변수명으로 import 하고 사용하면 된다.

상태관리

 Redux + ReduxToolkit  + Redux Saga

도입이유: 

  1. 많은 사람이 사용해서(공부가 편하고, 회사에서 하는 프로젝트도 연관이 있다. 회사 프로젝트 개선 & 물어볼 사람이 존재 한다는 것만으로도 큰 힘이 되었다.)
  2. 편리하고 확장 가능한 미들웨어
  3. 튜닝이 편하다
  4. 개발자 도구가 잘 되어있다. 

https://chromewebstore.google.com/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd?hl=ko

 

Redux DevTools

Redux DevTools for debugging application's state changes.

chrome.google.com

크롬 스토어에서 개발자 도구 설치시 모든 요청과 state를 한눈에 볼 수 있다.

 

 

 

 

 

보일러 플레이트 개선

기존 회사 api 요청을 위한 보일러 플레이트 (반복 작성이 너무 많음)

import { createSlice } from '@reduxjs/toolkit'
import {
  getKeyword,
  getKeywordHist,
} from './searchAPI'

import { createActionState, createRequestSaga, handleAsyncAction, reducerUtils, } from 'utils/asyncUtils'

import { takeLatest } from 'redux-saga/effects'

const prefix = 'search'

const GET_KEYWORD_HIST = 'search/getKeywordHist'

const initialState = {
  keywordHistList: reducerUtils.init(),
};

const defaultState = {
  [GET_KEYWORD]: 'keywordList',
};


export const getKeywordHistSaga = createRequestSaga(
  GET_KEYWORD_HIST,
  getKeywordHist
);

export const getKeywordSaga = createRequestSaga(GET_KEYWORD, getKeyword)

export function * searchSaga () {
  yield takeLatest(GET_KEYWORD_HIST, getKeywordHistSaga)

}

const searchReducers = {
  initializeAll: (state, action) => {
    return initialState;
  },
  initialize: (state, action) => {
    return {
      ...state,
      [action.payload]: reducerUtils.init(),
    };
  },
  getKeywordHist: (state, action) => {},

};

export const searchSlice = createSlice({
  // 액션 타입 문자열의 prefix
  name: "search",

  // 초기값
  initialState,

  // 리듀서
  reducers: searchReducers,

  // 서버통신 reducer
  extraReducers: (builder) => {
    builder.addMatcher(
      (action) => {
        return action.type.includes(prefix);
      },
      (state, action) => {
        state[createActionState(action, defaultState)] =
          handleAsyncAction(action);
      }
    );
  },
});

export const searchAction = searchSlice.actions;

 

변경후 새 프로젝트에 적용한 보일러 플레이트 

import {reducerUtils, reduxMaker} from "src/common/utils/asyncUtils.jsx";
import {
    getBoardList,
} from "./cmsAPI.jsx";


const prefix = 'cms'


//비동기 처리용 input
const asyncRequest = {
    getBoardList: [
        {boardList: reducerUtils.init()},
        getBoardList
    ]
}

//이름만 바꿔서 사용
export const {cmsSlice, cmsSaga, cmsAction} = reduxMaker(prefix, asyncRequest);

 

api 작성시 작성해야 하는게 하나로 줄음

 

사용 방법 개선

변수들을 모아서 한번에 추가할 수 있도록 만들었음. 

    const {
        path,
        contentype,
        likeContentStatus,
        dislikeContentStatus,
    } = useSelector(({router, cmsReducer}) => ({
            path: router.location?.pathname,
            contentype: cmsReducer.contentDetail.data,
            likeContentStatus: cmsReducer.likeContentStatus.data,
            dislikeContentStatus: cmsReducer.dislikeContentStatus.data,
        }),
        shallowEqual
    )

 

디스패치 시  param만 넘길수 있게끔 바꿈

          dispatch(cmsAction.getContentDetail(contentId))
          dispatch(cmsAction.initialize('likeContentStatus'))

 

 

파일 구조

dist - yarn build시 생성됨

nginx - nginx 관련 설정 파일

api - axios 를 통해서 url 요청 관련 파일

app -  cookie와 store관련 

assets - colors, img, text, logo 등 에셋 파일 보관

common - 공통으로 사용되는 컴포넌트 혹은 기능들 보관

pages - page 분리 (페이지 분리시 state 관리 및 랜더링 관리에서 이점을 가짐)

features - page마다 들어가는 컴포넌트 혹은 기능들을 단위별로 묶어서 작성 (API + Reducer + 기능)

routes - 라우터 설정 (url 관리)

 

 

 

배포

포트번호는 임의의 숫자

 

 

 

Nginx

정적 파일 처리에 탁월한 성능을 보여주며, 리액트 애플리케이션은 정적 파일들로 구성되어 있기 때문에 이 둘을 함께 사용

  • Nginx는 리버스 프록시 기능을 제공하여, 백엔드 서버와 프론트엔드 서버 간의 통신을 효과적으로 관리할 수 있다.
  • Nginx는 클라이언트에게 전달되는 리액트 애플리케이션 파일에 대해 캐싱 및 압축을 적용할 수 있어, 로딩 속도를 향상시킬 수 있다.
  • Nginx를 사용하면 SSL/TLS 설정을 쉽게 할 수 있어, 리액트 애플리케이션에 HTTPS를 적용하여 보안성을 높일 수 있다.
  • ginx는 높은 확장성과 안정성을 가지고 있어, 리액트 애플리케이션을 대규모로 배포할 때도 문제 없이 사용할 수 있다. 이는 대규모 트래픽을 처리할 때 유용하다.

Docker

  • 도커를 사용하면 개발, 테스트, 운영 환경 간의 일관성 유지할 수 있다.
  • 도커 컨테이너를 사용하면 프로젝트에 필요한 환경을 빠르게 구성할 수 있다. 리액트 애플리케이션과 Nginx를 도커 컨테이너로 구성하면 배포 및 관리가 쉽다.
  • 도커를 사용하면 리액트 애플리케이션과 Nginx가 격리된 환경에서 실행된다. 이로 인해 다른 프로젝트나 환경과의 충돌을 방지할 수 있다.
  • 리액트 애플리케이션과 Nginx를 수평적으로 쉽게 스케일링할 수 있다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

성능개선(Lighthouse)

텍스트 압축 사용

https://developer.chrome.com/docs/lighthouse/performance/uses-text-compression?utm_source=lighthouse&utm_medium=devtools&hl=ko

 

텍스트 압축 사용  |  Lighthouse  |  Chrome for Developers

텍스트 압축을 사용하여 웹페이지 로드 성능을 개선하는 방법에 대해 알아보세요.

developer.chrome.com

 

 

해결법 

 

1.  빌드 단계에서 압축

 

보통 이런 플러그인을 사용

vite-plugin-compression2 

https://github.com/nonzzz/vite-plugin-compression

 

GitHub - nonzzz/vite-plugin-compression: vite plugin. compress your bundle file.

vite plugin. compress your bundle file. Contribute to nonzzz/vite-plugin-compression development by creating an account on GitHub.

github.com


빌드 단계에서 압축을 적용한다면 1회만 압축하면 되므로 더 효율적으로 동작


하지만 vite에서 자동으로 지원을 해주기 때문에 우리는 이미 

 

gzip 형태로 보내준다.

그렇다면 이걸 보내주는 쪽이 문제가 있을 것으로 예상

 

2. nginx 에서 설정 
nginx.conf 에 다음과 같이 코드 추가

 

 

 

그러자 마법처럼 

 

77점 에서 93점 안정권으로 성능 향상

 

 

 

 

 

 

 

공부를 위한 글이 아닌 발표를 위한 글을 오랜만에 작성해 보았습니다. 피드백과 질문은 언제나 환영입니다.