본문 바로가기
Side Projects/클론코딩

Vue3 - 영화 검색 사이트 코드분석

by devraphy 2021. 6. 30.

- 본 포스팅은 아래의 프로젝트를 기반으로 다뤄진 내용입니다. 

 

https://devraphy.tistory.com/235

 

Vue3 - 영화 검색 사이트

1. 개요 - Vue 공부를 위한 클론 코딩 - 본 프로젝트는 패스트캠퍼스의 프론트엔드 초격차 패키지의 Vue 파트 강의 내용을 따라 만든 것입니다. 2. 사이트 소개 https://silly-banach-bd5250.netlify.app/#/ Hell..

devraphy.tistory.com


1. 개요

- 본 프로젝트는 Vue3 강의에서 진행한 내용을 그대로 클론코딩한 프로젝트이다.

- 강의내용을 따라서 프로젝트를 만들다 보니, 코드와 데이터 흐름에 대한 이해가 부족함을 느꼈다. 

- 이와 같은 이유로 해당 프로젝트의 핵심 기능을 분석해보려고 한다. 

 


2. 프로젝트의 구조 

클릭하면 확대됩니다.

- 전체적인 코드의 흐름을 분석해본 결과, Vue 프로젝트의 핵심은 main.js 라는 것을 알게 되었다. 

- main.js가 하는 역할은 다음과 같다.

    ▶ index.html과 App.vue(뷰 어플리케이션) 연결한다.

    ▶ Vue 어플리케이션과 Vue 어플리케이션 개발에 필요한 Router, Store 등의 다양한 Plugin과 연결한다. 

 

- main.js의 코드는 다음과 같다.

import {createApp} from 'vue'
import App from './App'
import router from './routes/index.js'
import store from './store'
import loadImage from './plugins/loadImage'

createApp(App)
  .use(router) // 플러그인 $route, $router
  .use(store) // 플러그인 $store
  .use(loadImage) // 플러그인 $loadImage
  .mount('#app')

 

a) createApp(App)

- Vue 어플리케이션 인스턴스(=객체)를 생성하는 함수다.

- 이 함수를 통해, 하나의 뷰 어플리케이션을 생성한다.

- 쉽게 말해서, Vue 프로젝트가 생성되었음을 의미하는 것이다. 

 

b) mount('#app')

- mount가 무슨 의미일까? UFC 경기를 본적이 있다면 한번쯤은 들어봤을 것이다. Mount 포지션을 말이다.

마운트 포지션

- 이처럼 어떤 대상 위에 올라간다는 의미를 마운트라고 한다. 그렇다면 Vue 객체가 어디에 올라가는 것일까?

- '#app' 이 부분에 올라간다는 의미다. 즉, app이라는 id를 갖고있는 HTML 엘리먼트에 올라간다는 뜻이다.

 

- 그럼 'app'이라는 id값을 가진 HTML 엘리먼트는 어디 있을까? index.html을 살펴보자. 

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Hello Vue Project!</title>
    <link
      rel="stylesheet"
      href="https://cdn.jsdelivr.net/npm/reset-css@5.0.1/reset.min.css"
    />
    <link rel="preconnect" href="https://fonts.gstatic.com">
    <link href="https://fonts.googleapis.com/css2?family=Oswald:wght@500&family=Roboto:wght@400;700&display=swap" rel="stylesheet">
    <style>
      body  {
        line-height: 1.4;
        font-family: "Roboto", sans-serif;
      }
    </style>
  
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>

- 가장 아래쪽에 body부분을 살펴보면  <div id="app"></div> 부분에 Vue 어플리케이션 객체가 올라간다.

- 쉽게 설명하자면, Vue 컴포넌트들이 앞으로 해당 엘리먼트 부분에서 출력된다는 뜻이다.(SPA)  

- 이로써 main.js를 중심으로 App.vue와 index.html이 연결된 것이다.  

 

c) use()

- 위에 있는 main.js의 코드를 살펴보면 use() 메소드를 사용하여 router와 store를 연결한다. 

- use() 메소드를 사용하여 플러그인을 Vue 어플리케이션 객체와 연결하여 사용한다. 

- 이처럼 main.js는 Vue 프로젝트 개발에 필요한 다양한 플러그인 연결도 주관한다. 


3. 컴포넌트와 라우트의 관계도와 역할

- 본 영화검색 프로젝트에서는 다양한 컴포넌트와 라우트를 갖고 있다.

- 각 컴포넌트와 라우트가 어떻게 이어져 있나 그 관계도를 그림으로 그려보았다. 

 

클릭하면 확대됩니다.

 

- 각 컴포넌트의 역할은 다음과 같다. 

 

a) Header.vue

- 해당 컴포넌트는 App.vue의 컴포넌트로 등록되어 사용된다. 

- 역할: 네비게이션(메뉴)을 v-for와 <RouterLink>를 이용하여 구성한다. 

- data(): navigations라는 배열 내부에 name과 href 등 링크를 위한 속성값을 갖는 객체를 삽입하여 관리한다.

- computed: 전개연산자와 ...mapState()를 사용하여 store의 'about' 모듈에 있는 state값을 가져온다. 

- methods

     ▶ isMatch(): 특정 형식의 url 접근 시 fullpath를 콘솔에 반환한다. 

     ▶ toAbout(): routerLink와 to 속성 없이 페이지 이동을 구현하기 위한 함수

 

b) Footer.vue

- 해당 컴포넌트는 App.vue의 컴포넌트로 등록되어 사용된다. 

- 역할: 웹페이지 가장 아래에 표시되는 로고와 개발자 링크를 표시한다. 

 

c) Headline.vue 

- 해당 컴포넌트는 Home.vue의 컴포넌트로 등록되어 사용된다. 

- 역할: Header 바로 아래에 위치하는 웹사이트 소개글을 담당한다.

 

d) Loader.vue

- 해당 컴포넌트는 MovieList.vue, MovieItem.vue, Movie.vue, About.vue의 컴포넌트로 등록되어 사용된다. 

- 역할: 페이지 로딩 중 화면에 출력되는 로딩 아이콘(spinner)

- props: spinner의 기본 속성값을 설정하여 등록한다. 

 

e) Logo.vue

- 역할: 로고 클릭 시 Home으로 이동하는 링크를 담당한다. 

 

f) Search.vue

- 해당 컴포넌트는 Home.vue의 컴포넌트로 등록되어 사용된다. 

- 역할: 영화 검색에 필요한 input 태그 및 필터(select - options), 검색기능을 관리한다. 

- data(): 검색 필터의 기본값 및 필터의 선택 가능한 값의 범주를 설정 

- methods

    ▶ apply(): 입력된 검색정보를 dispatch()를 통해 store - movie.js - searchMovies() 메소드의 매개변수로 전달한다. 

 

g) MovieList.vue

- 해당 컴포넌트는 Home.vue의 컴포넌트로 등록되어 사용된다. 

- 역할: 검색 정보를 바탕으로 OMDb_API 에서 반환된 영화 리스트를 출력한다. 

- components: MovieItem(각 영화의 상세정보), Loader(로딩 중 출력되는 spinner)

- computed: ...mapState()를 통해 store의 'movie' 모듈에 있는 state를 가져온다. 

 

h) MovieItem.vue

- 해당 컴포넌트는 MovieList.vue의 컴포넌트로 등록되어 사용된다. 

- 역할: MovieList.vue에서 출력된 영화 리스트 중 하나를 클릭하면 해당 영화의 상세정보를 출력하는 부분

- components: Loader

- props: movie 객체를 상위 component인 MovieList.vue로 부터 받아온다.

- data(): imageLoading 변수를 이용하여 Loader의 출력 여부를 설정한다.

- mounted(): 해당 라이프 사이클 시점에서 this.init() 메소드를 실행한다. 

- methods

    ▶ init(): 영화 poster가 로딩되는 동안 동작하는 함수로, 각 영화의 poster 유무를 확인하여 포스터가 없는 경우 예외처리 후 Loader의 작동을 종료한다. poster가 있는 경우, loadImage 플러그인을 실행 후 Loader의 작동을 종료한다. 

 


4. 영화 검색 메카니즘 설명 

1) Search.vue - 검색정보 입력

클릭하면 확대됩니다. 

- Search.vue 컴포넌트에서 검색어 및 검색조건을 입력한다.

- apply 버튼을 누르면 apply() 메소드가 실행된다.

- store의 'movie' 모듈의 searchMovies() 메소드의 매개변수로 title, type, number, year의 데이터가 넘어간다. 

 

2) searchMovies() 메소드

클릭하면 확대됩니다.

- Search.vue에서 넘어온 데이터는 payload라는 매개변수 안에 담긴다.

 

 

클릭하면 확대됩니다.

- _fetchMovies() 메소드에서 payload 내부의 데이터를 사용하여 OMDb_API에게 값을 넘긴다. 

 

 

클릭하면 확대됩니다.

- serverless 함수로 지정해 놓은 API를 실행하게 되고, 올바른 요청일 경우 body에 검색 결과가 담겨서 반환된다. 

 

 

- API로 부터 반환받은 데이터를 res라는 변수에 담는다.

- res를 객체구조분해를 사용하여 필요한 데이터만 store의 'movie'모듈의  movies라는 state에 저장한다. 

 

3) MovieList.vue

- MovieList.vue 에서 computed 속성을 통해 movies라는 state값을 읽어온다. 

 

 

- movies 배열에 담긴 데이터를 MovieItem.vue 컴포넌트에서 읽는다.

- MovieItem.vue 에게 movies의 단일 객체인 movie가 전달된다. 

- v-for를 사용하여 영화 리스트를 출력한다. 

 

4) MovieItem.vue

클릭하면 확대됩니다.

- MovieList.vue에서 넘어온 movie 객체를 props 옵션을 통해 MovieItem.vue에서 받아온다. 

- MovieItem.vue가 MovieList.vue의 하위 컴포넌트로 설정 되어 있기 때문에 가능한 것이다. 

 

 

- 각 MovieItem.vue가 MovieList.vue 안에서 영화 포스터를 출력하게 된다. 

- 더불어, RouterLink를 사용하여 MovieItem.vue 컴포넌트를 클릭하면 해당 영화의 상세정보 페이지(Movie.vue)로 넘어간다.

- 각 영화의 고유값인 ID를 URL로 전달한다. 

 

5) Movie.vue

클릭하면 확대됩니다.

- MovieItem.vue 컴포넌트를 클릭하면 RouterLink를 통해서 선택된 영화의 ID값이 URL에 담겨서 전달된다.

- URL을 통해 전달받은 ID값은 route 객체를 통해서 확인할 수 있다. 

- Movie.vue에서 route객체를 통해 영화 ID를 전달 받고, 해당 ID값을 store의 'movie' 모듈에 있는 searchMovieWithId() 메소드에게 매개변수로 넘긴다. 

- searchMovieWithId() 메소드에서 Movie.vue로부터 전달받은 데이터를 payload에 담는다. 

 

 

클릭하면 확대됩니다.

- searchMovieWithId() 메소드에서 OMDb_API에게 payload를 전달하고 영화검색 정보를 반환받는다. 

 

 

클릭하면 확대됩니다.

- API로 부터 반환 받은 개별 영화 정보는 theMovies라는 객체에 저장된다. 

- Movie.vue에서 computed 속성을 통해  theMovies 객체정보를 읽어온다. 

 

 

- theMovies 객체의 정보를 기반으로 한개의 영화의 상세 정보 페이지가 출력된다.


여기까지 Vue로 만든 영화검색 프로젝트의 구조와 핵심기능이 동작하는 흐름에 대해 알아보았다.

'Side Projects > 클론코딩' 카테고리의 다른 글

Vue3 - 영화 검색 사이트  (0) 2021.06.22
Vanilla JS - Pastel Browser  (0) 2020.10.17
HTML/CSS - 음악 플레이어(Music Player)  (0) 2020.10.13
코코아톡(HTML/CSS)  (0) 2020.09.20

댓글