DevYoon

[Vue] TMDB API로 영화 관련 페이지를 만들어 보자 ⚒️ 본문

Web/Vue

[Vue] TMDB API로 영화 관련 페이지를 만들어 보자 ⚒️

gimewn 2022. 5. 13. 18:51

1️⃣ HOME : 영화 목록 조회 페이지

TMDB API에 popular로 요청 보내서 상위 40개의 영화를 보여준다.

<template>
  <div class="home">
    <div class='row'>
    <movie-card v-for="movie in movies" :key="movie.id" :movie="movie"/>
    </div>
  </div>
</template>

<script>
import axios from 'axios'
import MovieCard from '../components/MovieCard.vue'
// @ is an alias to /src

const getWhat = 'popular'
const API_KEY = '#'

export default {
  name: 'HomeView',
  components: {
    MovieCard
  },
  methods:{
    getMovieData(){
      axios.get(`https://api.themoviedb.org/3/movie/${getWhat}?api_key=${API_KEY}&language=ko-KR&page=2&region=KR`)
        .then(response => {
          this.$store.state.movieList = response.data.results
        })
    }
  },
  mounted(){
    this.getMovieData()
  },
  computed:{
    movies(){
      return this.$store.state.movieList
    }
  }
}
</script>

 

🎞️ Vue LifeCycle Hook mounted를 활용해 따로 어떤 버튼을 클릭하지 않아도 요청 후 영화 목록 데이터를 가져와 화면에 보여주었다.

 

🎞️ API에서 받아온 데이터 안에 id값이 있길래, for문의 key로 사용했다.

 

2️⃣ Random : 영화 추천 페이지

과제는 랜덤으로 영화를 하나 뽑아서 보여주는 거였는데, 좀 더 실존하는 서비스 느낌을 내보고 싶어서 문구를 추가해봤다.

오늘 뭐 보지? 버튼을 클릭하면 🔽 이렇게 변한다.

<template>
  <div class='random'>
    <h3>뭘 봐야 할지 모르겠다면, 저희가 대신 골라드릴게요!</h3>
    <b-button variant="success" @click="randomMovie" class='pickButton'>오늘 뭐 보지?</b-button>
    <div v-if="pick" class='pickText'>
      <span>오늘은</span>
      <span class='pickTitle'>{{pick.title}}</span>
      <span>어때요?</span>
    </div>
    <div class='pickCard' v-if="pick">
      <b-card
      :title= "pick.title"
      :img-src="Poster+pick.poster_path"
      img-alt="Image"
      img-top
      tag="article"
      style="max-width: 20rem;"
      class="card">
      <b-card-text class='card-text'>
        {{pick.overview}}
      </b-card-text>
    </b-card>
    </div>
  </div>
</template>

<script>
import _ from 'lodash'

export default {
  name:'randomView',
  data(){
    return{
      pick:'',
      Poster:"https://www.themoviedb.org/t/p/w600_and_h900_bestv2/"
    }
  },
  methods:{
    randomMovie(){
      this.pick = _.sample(this.$store.state.movieList)
    }
  },
}
</script>

 

🎞️ 처음엔 Home에서처럼 요청을 보냈었는데, 생각해보니 store에 vuex-persistedstate를 사용했으니 굳이 API 요청을 보낼 필요가 없을 것 같아서 해당 부분 코드를 삭제했다. (local storage에 데이터가 남아 있으니)

 

🎞️ lodash의 sample로 영화 목록 중 하나를 랜덤으로 뽑았다.

 

🎞️ API 요청으로 받아온 데이터에는 poster_path 속성에 온전한 주소값이 들어가 있지 않다. (https://~~~.~~~ 이런 형식이 아님🥲) 그래서 data에 앞부분 주소를 추가했고, 화면에 보여줄 때는 둘을 합쳐주는 방식으로 작성했다.

 

3️⃣ WatchList : 영화 기록 페이지

💫 Form

<template>
  <div class='WatchListForm'>
    <h1><i>Movie Archive</i></h1>
    <p>그동안 감상한 영화를 기록해보세요!</p>
    <input type="text" v-model="watchedMovie" @keyup.enter="addWatched">
    <b-button variant="success" @click="addWatched">add</b-button>
  </div>
</template>

<script>
export default {
  name:'WatchListForm',
  data(){
    return{
      watchedMovie:'',
    }
  },
  methods:{
    addWatched(){
      const watchedItem = {
        title:this.watchedMovie,
        date:new Date().getTime()
      }
      if(this.watchedMovie){
        this.$store.dispatch('addWatched', watchedItem)
        this.watchedMovie = ''
      }
    }
  }
}
</script>

💫 Item

<template>
  <div>
    <div v-for="item in items" :key="item.date" class='item'>
      <p>{{item.title}}</p>
    </div>
  </div>
</template>

<script>
export default {
  name:'WatchListItem',
  computed:{
    items(){
      return this.$store.state.userWatch
    }
  }
}
</script>

 

🎞️ Form에서 작성한 데이터를 store에 등록하고, Item에서는 store에 있는 데이터를 하나씩 보여준다.

 

🎞️ for문을 돌려줘야 하기 때문에 사용자가 입력한 값과 함께 작성 시간도 넣어 key로 사용했다.

 

4️⃣ Store

import Vue from 'vue'
import Vuex from 'vuex'
import createPersistedState from "vuex-persistedstate";

Vue.use(Vuex)

export default new Vuex.Store({
  plugins:[createPersistedState()],
  state: {
    movieList:'',
    userWatch:[]
  },
  getters: {
  },
  mutations: {
    ADD_WATCHED(state, movieItem){
      state.userWatch.push(movieItem)
    }
  },
  actions: {
    addWatched({commit}, movieItem){
      commit('ADD_WATCHED', movieItem)
    }
  },
  modules: {
  }
})

 

🎞️ API에 요청해 받아 올 영화 목록과 사용자가 입력할 영화 목록을 분리해주었다.