개발 일지/주간 개발 일지

[04월 3주차] Vue.js 3 과 Spring

계란💕 2023. 4. 22. 17:04

Note


Vuex 란?

  • Vuex: Vue.js 애플리케이션에서 상태 관리를 위한 라이브러리이다. 
    • Vue 개발에서 상태를 관리해주는 기능을 제공한다. 
    • 상태 관리 패턴이자 라이브러리이다. 
    • 상태 관리: 애플리케이션의 데이터를 중앙에서 관리하고 컴포넌트 간에 공유할 수 있도록하는 것을 말한다. 
    • Vue의 공식 툴이며 ES2015 문법을 기준으로 한다. 
    • Vuex가 없다면 컴포넌트 간의 데이터(상태)를 주고 받기 위해 부모는 자식에서 props를 통해 전달하고 자식은 부모에게 Emit event 방식을 사용해서 처리해야한다. 
    • 데이터를 Store를 통해 관리하고 프로젝트에 존재하는 모든 컴포넌트들이 이 store를 사용한다. 
    • Vuex의 구성 요소
      • State(데이터 객체, 상태): 애플리케이션 전역에서 공유되는 데이터
      • Mutations(동기형 state 변경 처리기, 변이): 상태를 변경하는 함수
      • Actions(Mutation 처리기, 액션): 변이를 수행하는 비동기적인 함수
      • Getters(공통 속성, 게터): 상태를 조회하는 함수
  • Store: 애플리케이션의 모든 컴포넌트들 관리하는 중앙 집중식 저장소
    • 데이터를 저장하는 객체이다. 애플리케이션의 데이터 흐름을 예측 가능하게 만들어주고 유지 보수를 용이하게 한다. 
    • 백엔드에서 데이터를 저장하면 DB 툴(DBeaver 등)을 이용해서 데이터를 확인할 수 있는 것과는 다르게 Store에 저장된 데이터는 Vue.js 개발자 도구를 통해 확인 가능하다.
    • 해당 데이터는 메모리에 저장된다.
    • 또는 console.log(store.state) 를 사용하면 데이터를 확인할 수 있다. 
    • store는 반응형이므로 데이터가 업데이트되면 자동으로 변경된 내용이 반영된다. 
  • 뮤테이션(Mutation): 상태를 변경하는 역할을 한다. (store 참고) 
    • commit() 메서드를 사용해서 호출한다. 
    • 상태를 변경하는 게 아니라 상태 변경하는 방법을 정의한다. 
    • 정의된 뮤테이션은 컴포넌트에서 호출된다. 
    • state()를 첫 번째 인수로 받는다. 
    • 항상 동기적으로 실행한다. 
    • 뮤테이션의 목적은 상태의 변화를 추적하기 위해 이전 상태와 다음 상태를 추적하는 것이다. 
    • 상태 변경 이력을 추적해서 이전 상태와 다음 상태를 비교한다. 

참고) http://ccambo.github.io/Dev/Vue/5.what-is-the-store-in-vuex/#google_vignette


JavaScript, Vue 관련 메서드

  • import문 중 getCookie(): 쿠키를 가져오는 자바스크립트 함수이다. 
    • 웹 사이트를 방문할 때 쿠키가 자동 생성된다. 쿠키는 웹 사이트 정보를 로컬에 저장된다. (Ex) 로그인 정보, 이전 방문 기록)
    • 쿠키 이름을 인수로 받아서 쿠키의 값을 반환한다. 
  • import, export
    • import: 다른 파일에서 내보낸 모듈가져오는데 사용한다. 가져올 함수의 이름을 지정한다.
    • ex) import {변수, 함수} from '파일 경로'; 
    • export: 현재 파일에서 모듈내보내기 위해 사용한다. 

  • routerPush(): URL컴포넌트를 관리하는 기능을 한다. 
    • Vue.js 라우터의 메서드 중 하나이다. 
    • 브라우저의 주소창의 URL을 변경하고 해당 URL에 연결된 컴포넌트를 렌더링한다. 
    • 다음 코드를 통해 현재 URL이 localhost:8080/이면 localhost:8080/${pltfrmId}/model/${modelFindId} 로 변경된다. 
    • Vue.js 라우터는 URL이 변경되면  해당 URL에 맞는 컴포넌트를 렌더링한다. 
    • 따라서, routerPush() 를 호출하면 AiModelDetail 문자열과 query 객체에 매핑된 컴포넌트를 찾아서 렌더링한다. 

  Ex) 

<hide/>
const goToDetail = () => {
  let platform = getCookie("pltfrmId");
  let query = {modelId: modelFindId}
  routerPush(platform, "AiModelDetail", query );
};

  • $apiUrls: Vue에서 전역으로 사용할 수 있는 변수이다. 
    • 애플리케이션에서 사용하는 API 엔드포인트 URL들을 저장하는데 사용된다. 
    • "$"을 사용해서 변수에 접근하고 뒤에 해당 API  엔드포인트의 이름을 입력하면된다. 

  • component의 일부
    • Vue.js에서 제공하는 watch() 함수를 이용하면 변수 상태(state) 객체를 감지하고 매개변수로 들어간 변수 state의  변화가 있을 때마다 메서드가 실행된다. 
    • 아래 코드는 변경될 때마다 호출되는 콜백함수를 정의한 것이다. 
    • store.commit() 메서드를 이용해서 "AiStore/setCommonData" 뮤테이션을 호출한다. 
    • setCommonData 뮤테이션은 Vuex store의 AiStore 모듈에서 정의된 뮤테이션으로 상태 객체의 aimodel 프로퍼티를 인자로 받는다.
    • 세 번째 인자는 옵션 객체이다. deep 프로퍼티를 true로 설정해서 객체의 중첩 구조를 감시하도록 설정한다. 따라서, 객체의 하위 프로퍼티가 변경될 때도 watch() 함수가 호출되도록 설정한 것이다. 
<hide/>
watch (
  state,
  (crr) => {
    console.log(crr)
    store.commit('AiStore/setCommonData', crr.aimodel)
  },
  { deep: true }
)

콜백함수(callback function)란?

  • 다른 함수의 인자로써 넘겨진 후 특정 이벤트에 의해 호출되는 함수를 말한다. 
  • 함수는 포인터나 람다식으로 전달된다. 

HttpHeaders

  • Response 에 Header를 설정할 수 있다. 
  • Http POST 요청을 보낼 때 데이터에 대해 설명해주는 헤더가 필요하다. 
  • 클라이언트서버가 요청하거나 응답할 때 부가적인 정보를 전송해주는 역할이다. 

 

 

  Ex) 

  • Controller 클래스의 메서드 안에 다음과 같이 넣을 수 있다. 
  • HttpHeaders 클래스는 Header를 만들어준다. 
  • 정해진 형식이 있는지?? 프론트와 협의해야하는지??
<hide/>
HttpHeaders headers = new HttpHeaders();
headers.setLocation(new URI("/model/" + modelId + "/modelParam/" + modelParamId));

 

 

  Note) 실행 결과

  • 다음과 같이 응답의 헤더에 URI가 세팅되면 프론트에서 정보를 확인할 수 있다??

 

 

에러 해결


  • 오류:  node-modules 폴더와 관련한? 오류가 난다. 
  • 원인: import 문에 오타가 있으면 발생한다.
  • 해결

  • 오류: ex.esm-bundler.js:999 [vuex] unknown mutation type: PretreatmentStore/setCommonData
  • 원인: index.js에 모든 store에 대해 등록해줘야하는데 아마도 이 부분을 등록하지 않아서 발생한 오류?
  • 해결

 

구현 목록


전처리 등록, 조회

  •  Store
    • Pretreatment module 폴더 안에 Store를 만든다. 
    • 다른 컴포넌트들도 Store 코드가 다음과 같이 동일하다. 
    • store는 vuex의 구성 요소이며 메모리에 값이 저장된다. 
export const AiStore = {
    namespaced: true,
    state: () => ({
        common: {},
        hyperParams: [],
    }),
    mutations: {
        setCommonData(state, payload) {
            state.common = payload;
        },
        setHyperParamsData(state, payload) {
            state.hyperParams = payload;
        },
    },
    getters: {
        getCommonData(state) {
            return state.common;
        },
        getHyperParamsData(state) {
            return state.hyperParams;
        },
    },
    actions: {

    },
};

 


  • ApiUrls
    • 백엔드로 보내기 위한 API 주소를 설정한다. 

  Ex) ApiUrls에 model에 대한 다음과 같은 url을 정의할 수 있다. 

  • 그러면 다른 컴포넌트에서 해당 key를 메서드처럼 호출해서 백엔드로 API 요청을 보낼 수 있다. 
  • 다른 서버에 대해 Request 를 보내고 Response를 받아오는 과정이 Spring 에서 OkHttp 를 사용하는 것과 유사하다고 느꼈다. 
<hide/>
"ai": {
    "model": {
      "getAiModelList"    : "/api/v2/ai/model,
    }
}

  • ModelList
    • 앞에서 만든 key, value를 가지고 key와 같은 메서드를 만들 수 있다. 
    • 그러면 html  코드 안에서 해당 메서드를 호출할 때, 백엔드 쪽으로 API가 호출되는 것이다. 
    • 아래와 같은 메서드를 만들고 

 

  (1) view 페이지

  • $axios를 이용해서 백엔드로 get Request를 보낸다. 
  • onMounted(): 컴포넌트가 초기 렌더링 및 dom 노드 생성이 완료된 후에 코드를 실행하는데 사용할 수 있다. 
  • nextTick(): 노드에서 제공하는 비동기 처리 함수 중 하나이다. 
    • 이벤트 루프에 다음 번 실행될 콜백 함수를 등록한다. 
    • 현재 작업이 완료된 후에 실행되며 다음 이벤트 루프 사이클에서 실행될 함수를 등록한다. 
    • nextTick()에 등록된 콜백 함수는 현재 실행 중인 코드의 모든 작업이 완료된 후에 실행되며 다음 이벤트 루프 사이클에서 실행되는 것이다. 이를 통해 비동기 코드를 동기적으로 처리할 수 있다. 
  • pageMove()는 다음 페이지로 바꿔주는 메서드?
  • state 안에 페이지 정보, 검색에 대한 상태 정보를 저장하기 위한 변수를 선언한다. 
<hide/>
const state = reactive({
  aiModelList: [],
  searchInfo: {},
  pageInfo: {
    curPage: 1,
    totalListSize: 0,
    pageListSize: 10,
  },
});

onMounted(() => {
  getCodeList();
  nextTick(() => {
    getAiModelList();
  });
});


const getAiModelList = () => {
  let param = Object.assign({}, state.pageInfo, state.searchInfo);
  console.log(param);

  $axios
    .get($apiUrls.ai.aimodel.getAiModelList, {
      params: param,
    })
    .then((res) => {
      console.log("result");
      console.log(res);

      state.aiModelList = res.data.data;
      state.pageInfo.totalListSize = res.data.page.totalListSize;
    })
    .catch((err) => {
      console.log(err);
    });
};


const pageMove = (curPage) => {
  state.pageInfo.curPage = curPage;
  getAiModelList();
};

 

 

  (2) component

  • 아래의 메서드를 스크립트 태그 안에 만들고 <template> 안에서 해당 메서드를 클릭 이벤트로 적용 가능하다. 
  • @click = "메서드명"
  •  
  <el-button type="primary" @click="getAiModelList()">검색</el-button>

 

  • emits: 이벤트 처리를 위한 메서드로 사용된다. 이벤트를 발생시키는 객체에서 사용되는 메서드 중 하나이다.
    • searchAiModel () 이벤트를 발생시킨 다음 결과에서 pageInfo.value라는 값을 전달 받는다. 
const getAiModelList = () => {
  emits("searchAiModel", pageInfo.value);
};