Javascript Vue

MovieCart – Movie search site through omdb API communication2 min read

MovieCart

Untitled.mp4

✅ MovieCart란?

OMDB API를 이용해 영화 데이터를 받아온뒤 , 사용자들이 검색한 영화를 화면에 보여줄수있는 간단한 영화검색 사이트 입니다.

🔨 기술스택: Vue, vuex, webpack, scss

Skill
Info

webpack
webpack을 활용한 모듈 번들링

scss
scss를 활용한 component단위 style 처리

vue
component단위의 vue파일 생성

vue-router를 통한 SPA 디자인 패턴 적용

vuex
vuex의 store 기능을 통한 상태 관리

store의 데이터 모듈은 movie,about으로 구성

eslint
eslint를 통한 코드작성 규칙 설정

bable
bable을 통한 크로스브라우징 준수

🔧 상태관리

vuex 를 사용해 필요한 데이터를 movie, about 데이터 모듈로 나눠 필요한 컴포넌트에 사용하고있는 구조 이다.
vuex를 사용해 상태관리를 진행하면 복잡하게 얽힌 컴포넌트간 데이터 통신이, 독립적인 store에 연결해 관리하면 되기때문에 편리해진다.

movie 데이터 모듈

import axios from ‘axios’ // http 통신 도와주는 모듈
import _uniqBy from ‘lodash/uniqBy’

const _defaultMessage = ‘찾고싶은 영화를 검색해 보세요!!’

export default{
//모듈화 가능하다는 의미
namespaced: true,
/*
[ data 형식]
*/
state: () => ({
movies: [],
message: _defaultMessage,
loading: false,
theMovie: {}
}),
/*
[computed 형식]
state와 연결되기 위해 내부 함수는 매개변수로 state를 받아야 한다.
*/
getters: {},

/*
[methods 형식]
데이터 수정은 mutations 에서만 가능 => 데이터 수정을 위한 메서드
즉 mutations는 데이터 변경만을 위한 매서드, 그외 매서드는 actions에서 처리
*/
mutations:{
//state 의 데이터를 갱신하는 매서드
updateState(state,payload){
//새로운 배열데이터 생성
Object.keys(payload).forEach(key => {
state[key] = payload[key]
})
},
resetMovies(state){
state.movies = [],
state.message = _defaultMessage,
state.loading = false
}
},
/*
[methods 형식]
actions는 기본적으로 비동기로 처리되는 매서드(state를 바로 받아서 처리하지는 못한다.)
context는 state, getters, mutations를 활용할수 있는 내용 => context를 구조분해 해서 사용할 요소들만 불러온다. 예: {state,commit}
payload는 searchMovies를 활용할때 인수로 들어온 특정한 데이터 활용
*/
actions:{
async searchMovies({state, commit}, payload){
// state.loading 이 true일 경우 함수 실행 종료
// 사용자가 searchMovies 함수가 동작중일때 여러번 실행하는 것을 방지
if(state.loading){
return
}

// 검색 시작되면 메시지 초기화
// 에러 메시지가 있다면 movieList 컴포넌트에서 movieitem을 출력 안하기 때문에 초기화
commit(‘updateState’,{
message:,
loading: true //로딩 시작
})

try{
// payload로 전달받은 데이터를 채워 넣는다.
const res = await _fetchMovie({
payload, page: 1
})
const {Search, totalResults} = res.data
//state에 데이터를 넣기 위함
//commit으로 updateState 연결
// Search는 omdb에서 받은 영화 정보들, totalResults는 영화 갯수(string 타입)
// commit 안에 mutations을 작성할때 띄어쓰기 하나도 들어가면 안된다.
commit(‘updateState’, {
movies: _uniqBy(Search, ‘imdbID’)
})
// totalResults를 10진법의 숫자로 변환
const total = parseInt(totalResults, 10) // total => 영화 총 갯수
// Math.ceil()는 올림 함수
const pageLength = Math.ceil(total / 10) // pageLength => 페이지 갯수
if(pageLength > 1){
// page 반복문
for(let page = 2; page <= pageLength; page += 1){
// number 가 10일때 요청 x
// number 가 20일때 요청 1번
// number 가 30일때 요청 2번
if(page > (payload.number / 10)){
break
}
//추가 omdbapi 요청
const res = await _fetchMovie({
payload, page: page
})
const {Search} = res.data
// 추가로 commit
// 기존에 state 에 있는 movies 값이 덮어씌워지지 않게 새로요청되는 Search 와 함께 구조분해후 새롭게 배열화
commit(‘updateState’, {
movies: [state.movies,_uniqBy(Search, ‘imdbID’)]
})
}
}
} catch(error){
commit(‘updateState’, {
movies: [],
message : error.message
})
} finally{
commit(‘updateState’,{
//로딩 끝
loading: false
})
}
},
async searchMovieWithId({state, commit}, payload){
// state.loading 이 true일 경우 함수 실행 종료
if(state.loading){
return
}

// 로딩 시작
commit(‘updateState’,{
theMovie: {},
loading: true
})

const { id } = payload
try{
const res = await _fetchMovie({
id: id
})
commit(‘updateState’,{
theMovie: res.data
})
} catch(error){
commit(‘updateState’,{
theMovie: {}
})
} finally{
commit(‘updateState’, {
loading: false
})
}
}
}
}

async function _fetchMovie(payload){
// netlify의 서버리스 함수로 payload(영화관련 데이터)를 보낸다
// post 한 이후의 데이터를 반환 할수 있도록 return
// netlify 호출시 앞에 . 을 붙혀야 한다.
return await axios.post(‘/.netlify/functions/movie’, payload)
}

🔧 서버리스 통신(Fass)

서버리스 함수란 서버가 존재하지 않는다는 뜻이 아니라 서버를 직접 관리할 필요가 없는 구조
영화 검색 api 키를 netlify(AWS의 Lamda) 와 같은 호스팅 서버의 서버리스 함수를 통해 보관했다가 사용자에게 데이터를 넘긴다.
사용자에게 넘어간 데이터에는 인증키가 없기때문에, 해커가 사용자의 컴퓨터를 해킹하더라도 api키 정보를 알아낼수 없다.

서버리스함수 movie.js

//[ node.js 동작환경 ]

//aixos를 받아온다.
const axios = require(‘axios’)
// OMDB API 키 -> .env 파일에 환경변수로 선언됬다.
const OMDB_API_KEY = process.env.OMDB_API_KEY

exports.handler = async function(event){
//event.body를 네트워크 통신을 통해 받을때 문자 데이터로 받기때문에 이를 객체형식으로 변환해야 한다 -> JSON.parse()
const payload = JSON.parse(event.body)

// payload 구조분해
// search 컴포넌트의 aply()매서드를 통해 전달받은 데이터가 내부로 들어간다.
const {title, type, year, page, id} = payload
// url주소는 삼항연산자 를 통해 id 값이 있는 경우 와 없는 경우로 나눠 넣는다. 삼항연산자 ======> (조건 ? 참일때실행 : 거짓일때실행)
const url = id
? `https://www.omdbapi.com/?apikey=${OMDB_API_KEY}&i=${id}` //id값이 있을때
: `https://www.omdbapi.com/?apikey=${OMDB_API_KEY}&s=${title}&type=${type}&y=${year}&page=${page}` //id값이 없을때
//const url = `https://www.omdbapi.com/?apikey=${OMDB_API_KEY}`

try{
const res = await axios.get(url)
if(res.data.Error){
return{
statusCode: 400,
body: res.data.Error
}
} else {
return{
statusCode:200,
body: JSON.stringify(res.data)
}
}
}catch(error){
return{
statusCode: error.response.status,
body: error.message
}
}
}

Pin It on Pinterest

Generated by Feedzy