군만두의 IT 개발 일지

[DAY13] 프로젝트 - Version Control System 본문

개발일지/SW직무역량 부트캠프

[DAY13] 프로젝트 - Version Control System

mandus 2023. 7. 14. 10:06

목차

    🚀 진행기간: 2023년 6월 26일 ~ 2023년 7월 13일

    ⭐요약


    React 기반 SPA로 앱 버전 정보를 관리하는 Version Control System(VCS)을 구현한 프로젝트이다. Axios를 통해 REST API 서버와 통신하고, React Query와 React Bootstrap을 활용하여 데이터 추가, 수정, 삭제, 조회 기능을 구현했다.

    더보기

     

    프로젝트 개요 앱 버전 정보(OS, 버전, 업데이트 타입, 메시지, 패키지 정보 등)를 관리하는 SPA. EC2 서버와 REST API로 통신함.
    기술 스택 React 18, Axios, React Query, React Bootstrap, Styled-components를 사용함.
    주요 기능 버전 목록 조회(GET), 버전 추가(POST), 버전 수정(PUT), 버전 삭제(PUT), App Test(클라이언트 버전 확인) 기능을 구현함.
    컴포넌트 구조 App.js가 루트 컴포넌트이며, AddButton, AppTestButton, UpdateButton, DeleteButton, TestButton 5개의 자식 컴포넌트로 구성됨.

     

    ⭐프로젝트 소개


    1. 프로젝트 소개

    • Version Control System(VCS): 앱의 버전 정보를 관리하는 React SPA 프로젝트이다.
    • 서버에 저장된 버전 데이터를 테이블로 조회하고, 추가·수정·삭제 기능을 제공한다.
    • App Test 기능을 통해 클라이언트 측에서 특정 버전의 업데이트 필요 여부를 확인할 수 있다.

    2. 기술 스택

    기술 버전 사용 목적
    React ^18.2.0 UI 컴포넌트 기반 SPA 구성
    Axios ^1.4.0 REST API 서버와의 HTTP 비동기 통신
    React Query ^3.39.3 서버 상태 관리 및 데이터 추가(useMutation) 처리
    React Bootstrap ^2.8.0 Modal, Button 등 UI 컴포넌트 활용
    Styled-components ^6.0.4 컴포넌트 단위 CSS-in-JS 스타일링

     

    ⭐프로젝트 구조


    1. 컴포넌트 구조

    App.js가 루트 컴포넌트 역할을 하며, 서버에서 전체 버전 목록을 가져와 테이블로 렌더링한다. 각 행(row)에는 수정, 삭제, 테스트 버튼이 포함된다.

    컴포넌트 역할
    App.js 루트 컴포넌트. 서버에서 전체 버전 목록을 조회하여 테이블로 렌더링함
    AddButton.js 새로운 버전 데이터를 입력·추가하는 Modal 폼 컴포넌트
    AppTestButton.js 클라이언트 버전을 선택하여 업데이트 필요 여부를 확인하는 컴포넌트
    UpdateButton.js 기존 버전 데이터를 수정하는 Modal 폼 컴포넌트
    DeleteButton.js 버전 데이터를 삭제(논리적 삭제)하는 Modal 확인 컴포넌트
    TestButton.js 테스트용 메시지를 입력하는 Modal 컴포넌트

    2. API 서버 정보

    • 서버: AWS EC2 인스턴스 (http://ec2-13-211-88-63.ap-southeast-2.compute.amazonaws.com:8080)
    • package.jsonproxy 설정과 setProxy.jsx를 통해 CORS 문제를 해결했다.
    // setProxy.jsx - CORS 해결을 위한 프록시 미들웨어 설정
    const { createProxyMiddleware } = require("http-proxy-middleware");
    
    module.exports = function (app) {
      app.use(
        createProxyMiddleware("/api/v1", {
          target:
            "http://ec2-13-211-88-63.ap-southeast-2.compute.amazonaws.com:8080/",
          changeOrigin: true,
        })
      );
    };

     

    ⭐주요 기능


    1. 버전 목록 조회

    useEffectaxios.get()을 사용하여 컴포넌트가 처음 렌더링될 때 서버에서 전체 버전 목록을 가져온다. 가져온 데이터는 useState로 관리하며, versionList() 함수로 테이블 행을 동적으로 렌더링한다.

    // App.js - 서버에서 전체 버전 목록 조회
    const [data, setData] = useState('');
    
    useEffect(() => {
      const getConfigData = async () => {
        try {
          const response = await axios.get(
            'http://ec2-13-211-88-63.ap-southeast-2.compute.amazonaws.com:8080/vercontrol/getConfigAll'
          );
          setData(response.data);
        } catch(e) {
          // 에러 처리
        }
      };
      getConfigData();
    }, []);

    조회된 데이터는 아래와 같이 반복문으로 테이블 행을 생성하여 렌더링한다.

    // App.js - 데이터를 테이블 행으로 렌더링
    function versionList(data) {
      let arr = [];
      for (let i = 0; i < data.length; i++) {
        arr.push({data[i].id}{data[i].os}{data[i].ver}{(data[i].updatetype === 1) ? 'true' : 'false'}{(data[i].message) === '' ? 'null' : (data[i].message)}{data[i].packageInfo}{data[i].regdate}
    
          
        );
      }
      return arr;
    }

    2. 버전 추가

    React Query의 useMutation을 활용하여 새로운 버전 데이터를 서버에 POST 요청으로 전송한다. Modal 팝업 안에서 OS, 버전, 업데이트 타입, 메시지, 패키지 정보를 입력받는다.

    // AddApi.js - POST 요청으로 새 버전 데이터 저장
    import axios from "axios";
    
    export async function addVersion(newData) {
      const data = await axios.post(
        `http://ec2-13-211-88-63.ap-southeast-2.compute.amazonaws.com:8080/vercontrol/save`,
        newData
      );
      return data.data;
    }
    // AddButton.js - useMutation으로 API 호출 및 성공/실패 처리
    const { mutate: version } = useMutation(addVersion, {
      onSuccess: (response) => {
        console.log("response");
        setData(response);
      },
      onError: () => {
        console.log("error");
      },
    });
    
    function submitNewData() {
      if (os && ver && updatetype && message && packageInfo) {
        setOs(""); setVer(""); setUpdatetype(""); setMessage(""); setPackageInfo("");
        version(newData); // API 호출
      }
    }

     

    • useMutation은 서버의 데이터를 변경(생성·수정·삭제)할 때 사용하는 React Query Hook이다.
    • onSuccessonError 콜백으로 요청 결과에 따른 처리를 분리할 수 있다.
    • updatetype은 숫자 타입으로 서버에 전달해야 하므로 Number(updatetype)으로 변환하여 전송한다.

    3. 버전 수정

    부모 컴포넌트(App.js)에서 props로 전달받은 행 데이터를 초기값으로 설정한 후, 수정된 값을 PUT 요청으로 서버에 전송한다.

    // UpdateButton.js - props로 기존 데이터를 받아 초기값 설정 후 수정
    function UpdateButton(props) {
      const [os, setOs] = useState(props.data.os);
      const [ver, setVer] = useState(props.data.ver);
      const [updatetype, setUpdatetype] = useState(props.data.updatetype);
      const [message, setMessage] = useState(props.data.message);
    
      const handleSubmit = () => {
        setShow(false);
        var id = props.data.id;
        axios({
          url: `http://ec2-13-211-88-63.ap-southeast-2.compute.amazonaws.com:8080/vercontrol/getConfig/${id}`,
          method: 'put',
          data: { "os": os, "ver": ver, "updatetype": updatetype, "message": message },
          headers: { 'Content-Type': 'application/json' }
        }).then(function (response) {
          console.log(response.data);
        });
      }
    }

     

    • props.data로 전달받은 기존 값을 useState의 초기값으로 설정하여, 수정 Modal이 열릴 때 기존 데이터가 미리 채워진다.
    • 수정 API는 DELETE가 아닌 PUT 메서드로 호출된다.

    4. 버전 삭제

    삭제 버튼 클릭 시 확인 Modal을 띄운 후, 사용자가 '삭제'를 선택하면 서버에 PUT 요청을 보낸다. 서버에서 실제 데이터를 삭제하는 것이 아닌 논리적 삭제(soft delete) 방식으로 처리된다.

    // DeleteButton.js - 삭제 확인 후 PUT 요청으로 논리 삭제 처리
    const handleSubmit = () => {
      setShow(false);
      var id = props.data.id;
      axios({
        url: `http://ec2-13-211-88-63.ap-southeast-2.compute.amazonaws.com:8080/vercontrol/deleteConfig/${id}`,
        method: 'put',
        headers: { 'Content-Type': 'application/json' }
      }).then(function (response) {
        console.log(response.data);
        window.location.reload(); // 삭제 후 페이지 새로고침
      });
    }

     

    • 삭제 API의 HTTP 메서드가 DELETE가 아닌 PUT인 이유는 서버에서 데이터를 실제로 삭제하지 않기 때문이다.
    • 테이블에서 항목이 사라져도 서버 DB에는 데이터가 유지된다. 이를 논리적 삭제(Soft Delete)라고 한다.
    • 삭제 완료 후 window.location.reload()로 페이지를 새로고침하여 변경 사항을 반영한다.

    ⭐스타일링


    컴포넌트별로 CSS 파일을 분리하여 스타일을 관리했다. 공통으로 사용되는 Modal 팝업 스타일은 CommonPopup.css로 통합하고, 기능별로 별도 CSS를 적용했다.

    파일 적용 범위
    App.css 테이블 전체 레이아웃, ADD/AppTest 메인 버튼 스타일 적용
    CommonPopup.css ADD, UPDATE, DELETE 팝업 Modal의 공통 스타일 적용
    ActionButton.css 테이블 행의 Test(노란색), 수정(초록색), 삭제(빨간색) 버튼 스타일 적용
    AppTestButton.css App Test 메인 버튼(초록색) 스타일 적용
    AppTestPopup.css App Test 팝업 Modal 전용 스타일 적용
    TestPopup.css Test 팝업 Modal 전용 스타일 적용

     

    버튼별 색상 구분은 ActionButton.css에서 CSS ID 선택자로 관리했다.

    /* ActionButton.css - 버튼별 색상 구분 */
    #testBtn   { background-color: yellow; }
    #testBtn:hover { background-color: gold; }
    
    #updateBtn { background-color: rgb(30, 172, 30); }
    #updateBtn:hover { background-color: Forestgreen; }
    
    #deleteBtn { background-color: red; }
    #deleteBtn:hover { background-color: Firebrick; }

    ⭐후기


    • 초반에 프로젝트 내용을 제대로 이해하지 못하여 App Test, 삭제 버튼 기능 구현을 번복했던 점이 아쉬웠다. 프로젝트 시작 전에 요구사항을 충분히 파악하는 것이 얼마나 중요한지 다시 한번 느꼈다.
    • 특히 삭제 버튼의 경우, 테이블에서 항목이 삭제되어도 데이터는 서버에 그대로 유지해야 한다는 논리적 삭제(Soft Delete) 개념을 처음에는 생각하지 못했다. 실무에서 데이터를 완전히 삭제하지 않고 유지하는 이유(복구 가능성, 감사 로그 등)를 이번 프로젝트를 통해 이해할 수 있었다.

    ⭐참고자료


    1) React 공식 문서, "Hooks API Reference", https://react.dev/reference/react

    2) TanStack Query 공식 문서, "useMutation", https://tanstack.com/query/v3/docs/react/reference/useMutation

    3) Axios 공식 문서, https://axios-http.com/kr/docs/intro

    4) React Bootstrap 공식 문서, "Modal", https://react-bootstrap.github.io/docs/components/modal

     

    이 글은 코드스테이츠 x KNU가 주최한 직무역량캠프에서 공부한 내용을 작성한 것입니다.

    '개발일지 > SW직무역량 부트캠프' 카테고리의 다른 글

    [DAY12] JavaScript 기초  (0) 2023.07.13
    [DAY11] HTML/CSS 활용 + 과제  (0) 2023.07.12
    [DAY10] 클라이언트 Ajax 요청  (0) 2023.07.11
    [DAY9] React State & Props  (0) 2023.07.10
    [DAY8] React SPA  (0) 2023.07.10
    Comments