써치킴의 우당탕탕 개발 블로그

[Vue.js][Ch4][영화검색 사이트] 영화 검색 추가 요청 본문

완벽하게 Vue.js

[Vue.js][Ch4][영화검색 사이트] 영화 검색 추가 요청

써치킴 2022. 4. 23. 20:51

OMdB API는 한번 데이터를 가져올 때마다 10개씩 가져올 수 있고, 

총 검색 개수를 제공해준다. => 문자열 형식의 totalResults 데이터

Ex) 총 검색 개수가 17개이면 최초에 10개를 가져오고 더 가져올 수 있는 영화의 목록은 7개이고, => 2번 서버에 요청

24개이면 최초에 10개를 가져오고 더 가져올 수 있는 영화의 목록은 14개이다. 또 10개를 가져오면 나머지 4개를 가져올 수 있다.

=> 3번 서버에 요청

따라서

총 검색 개수가 11개 이상일 경우, 영화 검색 추가 요청이 필요하다.

그리고

몇 개를 영화를 출력할 것인지 조건문이 필요하다.

 

movie.js

/* 영화 검색과 관련된 데이터를 취급하는 파일 */
import axios from 'axios'

export default {
  /*
  * namespaced : 해당 파일이 모듈화돼서 사용할 수 있다는 것을 나타내는 옵션.(true / false)
  * state : 실제로 취급해야하는 데이터. store 개념에서는 data를 state라고 부른다.(data와 같은 개념)
  * getters : 계산된 상태를 만들어내는 개념.(computed와 같은 개념)
  * mutations : 변이라는 뜻. 관리하는 데이터를 변경시켜줄 수 있는 methods. mutations에서만 데이터를 수정할 수 있다.
  * actions : 비동기로 동작하는 methods. 데이터를 수정할 수 없다. state 옵션 사용 불가능 -> context 사용해야한다.
  * - context.state / context.getters / context.commit 사용 => 객체구조분해를 통해 {state, getters, commit} 으로 사용할 수 있다.
  */
  namespaced: true,
  state: () => ({
    movies: [],
    message: '',
    loading: false
  }),
  getters: {},
  mutations: {
    /* state를 바꿔줄 수 있는건 mutations 밖에 없기 때문에
    state에 정의된 데이터를 통합적으로 갱신할 수 있는 mutation을 만들어준다. */
    updateState(state, payload) {   // 상태를 갱신할때마다 수정하는 메소드
      // Object.keys : 객체 데이터 속성의 이름만 갖고 새로운 배열 데이터 생성 (ex.['movies', 'message', 'loading'])
      Object.keys(payload).forEach(key => {   // ex. key : movies, message, loading
        // state.movies = payload.movies를 동적으로 전표기법을 제거하고 state['movies']라고 지정할 수 있다.
        // state['movies'] = payload['movies'] => state[key] = payload[key]
        state[key] = payload[key];
      })
    },
    resetMovies(state) {
      state.movies = [];
    }
  },
  actions: {
    // actions의 메소드에는 context, payload 매개변수를 제공한다.
    // context : state, getters.commit 활용
    // payload : 인수로 들어온 데이터를 받아줌
    async searchMovies({ state, commit }, payload) {    // (c, p)로도 사용이 가능하다. (매개변수 이름 변경 가능)
      const { title, type, number, year } = payload;    // payload로 받은 데이터를 객체구조분해
      const OMDB_API_KEY = '7035c60c';

      // 최초 요청은 page가 1
      const res = await axios.get(`https://www.omdbapi.com/?apikey=${OMDB_API_KEY}&s=${title}&type=${type}&y=${year}&page=1`);   // 보간법 사용
      // res 검색결과의 data에 실제 검색결과가 존재하므로 res.data 사용 
      const { Search, totalResults } = res.data;    // 검색 결과의 data를 객체구조분해
      // context의 commit 활용
      commit('updateState', {    // updateState 메소드가 실행될 때, 객체가 payload 인수로 전달된다.
        movies: Search,
        message: 'Hello world!', 
        loading: true
      });
      console.log(totalResults) // ex) frozen을 검색했을 때, 305 => 31번 요청해야함.
      console.log(typeof totalResults); // string

      const total = parseInt(totalResults, 10); // 10진법의 정수로 형변환
      // Math.ceil : 올림 처리
      const pageLength = Math.ceil(total / 10); // 305/10을 올림 처리 -> 31번 요청 처리.

      // 1번 이상 요청해야한다면, 추가 요청 전송
      if(pageLength > 1){
        for (let page = 2; page <= pageLength; page++) {
          // 영화 목록을 몇개 가져올지(number) 조건문을 이용해 for문 종료
          if (page > (number / 10)) break;    // for문 종료

          // 추가 요청은 page가 2부터 검색
          const res = await axios.get(`https://www.omdbapi.com/?apikey=${OMDB_API_KEY}&s=${title}&type=${type}&y=${year}&page=${page}`);   // 보간법 사용
          const { Search } = res.data;
          /*
          * movies에는 이미 영화가 들어가져 있는 상태이기 때문에 
          * 새로운 요청을 할때마다 새로운 배열을 만들어서 movies에 할당
          */
          commit('updateState', {
            // ... : 전개 연산자
            movies: [...state.movies, ...Search] // state.movies를 먼저 전개하고, Search 데이터를 전개
          });
        }
      }
    }
  } 
}
  • actions 옵션 코드 확인

출력

Comments