React

노마드코더 : React(영화 웹 서비스) - 5. axios, 영화 API, 데이터 접근해서 화면에 그리기, Movie 컴포넌트 map()으로 만들기, CSS 꾸미기

식초 2020. 12. 3. 20:07

영화 API 사용해 보기

영화 데이터를 로딩하려면 자바스크립트의 fetch()함수가 필요하다.

fetch()함수 대신 axios 도구 사용해서 영화 앱을 만든다.

 

 

axios 설치하기

터미널에 입력한다.

> npm install axios

 

YTS 영화 데이터 API 살펴보기

주소창 yts.lt/api 입력 → YTS 영화 데이터 API 사이트 'List Movies API' 기능 사용

 

API특정 주소를 입력하면 그 주소에 맞는 결과 보내준다.

추가로 특정 주소에 조건을 붙여 입력하면 그 조건까지 고려한 결과 보내준다.

 

Endpoint의 가장 위에 있는 주소 사용할 것이다. 

이 주소는 최신 영화 20개에 대한 데이터를 기본으로 보내준다.

 

 

영화 목록 데이터 확인하기

주소창에 Endpoint의 주소 중 .json으로 끝나는 주소 입력해보자.

Endpoint 주소 : yts.mx/api/v2/list_movies.json

 

 

줄바꿈 없는 JSON 데이터가 표시된다.

JSON은 자바스크립트의 객체와 비슷한 데이터이다.

 

 

JSON Viewer 확장 도구 설치하기

편하게 보기 위해서 크롬 브라우저의 'JSON Viewer' 확장 도구 설치하기

 

 

리로드하면 JSON 형식 데이터 깔끔하게 출력된다

 

API가 영화 데이터를 출력한 것이다.

 

status 키값은 응답 상태 메시지다. 정상이므로 "ok" 출력한다.

data 키값에 영화 데이터가 포함되어 있다. 

movie_count 키값은  API가 보내준 영화 데이터의 개수이다.

limit 키값은 보내준 데이터의 개수이다.

    movies 키값이 영화 데이터 알맹이다. movies는 배열[ ]이고, 안에 객체가 들어있다.

        객체에는 id, url, imdb_code, title,... 같은 키값이 있다.

 

음식앱과 비슷하게 영화앱을 만들 수 있을 것 같다.

     

YTS에는 문제가 있다. 불법이라 매번 주소가 바뀐다.

 

 

노마드 코더 영화 API를 사용하자

노마드 코더 영화 API 깃허브 주소 : github.com/serranoarevalo/yts-proxy

깃허브 README에서 How to use 읽어보자.

 

'YTS의 endpoint/list_movies.json을 쓰려면 yts-proxy.now.shlist_movies.json를 붙이면 된다.'

 

endpoint YTS API 노마드 코더 영화 API
list_movies yts.mx/api/v2/list_movies.json yts-proxy.now.sh/list_movies.json
movie_details yts.mx/api/v2/movie_details.json yts-proxy.now.sh/movie_details.json

 

 

yts-proxy.now.sh/list_movies.json 입력하면 같은 JSON 출력된다

 

 

영화 정보 더 자세히 살펴보기

yts-proxy.now.sh/movie_details.json 입력하자.

 

하지만 아무것도 나오지 않는다.

 

 

영화 정보 더 자세히 살펴보기 위해 조건 추가

이 API가 movie_id 조건을 필수로 요구한다.

 

추가하는 방법 : yts.mx/api#movie_details 접속 → Examples에 주소 참고 

 

 

movie_id가 10인 영화 정보

yts-proxy.now.sh/movie_details.json?movie_id=10

 

 

이런 식으로  영화 정보 하나하나 자세히 가져오면, 

year, rating, runtime, genres,... 같은 정보도 영화 앱에 출력할 수 있다.

 

 

노마드 코더 영화 API를 영화 앱에서 호출하기

우리의 영화 앱에서 API를 사용하려면,

App.js 파일 맨 위에 axios를 import한 다음, componentDidMount()함수에서 axios로 API 호출한다.

 

axios.get()함수의 인자에 URL을 전달하여 API 호출하라.

setTimeout()은 지우자.

 

브라우저 여전히 Loading 이라고 나온다.

하지만 중요한 건 axios 동작하고 있다는 것이다.

axios는 분명 API에 영화 데이터를 요청하고 있다.

 

 

axios의 동작 확인하기

[Network]탭을 열고 영화 앱 새로고침 한다.

Name 항목에 list_movies.json이라고 나온다. 

axios가 API를 호출하고 있다는 증거이다. 잘 동작하고 있는 중.

 

axios는 네트워크를 사용하므로 느리게 동작한다.

axios.get()이 반환한 영화 데이터를 잡으려면,

자바스크립트에게 axios.get()을 포함하고 있는 함수의 실행이 끝날 때까지 시간이 걸릴 수 있다고 말해야 한다.

 

 

getMovies()함수 기다린 다음, axios.get()함수가 반환한 데이터 잡기

getMovies()함수 만들고,

그 함수 안에서 axios.get()실행되도록 만들자.

axios.get()이 반환한 값movies에 저장했다.

 

 

componentDidMount()함수가 실행되면,  this.getMovies()가 실행된다

async, await 두가지 키워드가 필요하다.

 

 

getMovies()에 async 붙이고, axios.get()에 await 붙인다

자바스크립트에게 'getMovies()함수는 시간이 필요해'라고 말하려면

async()앞에 붙이고실제 시간이 필요한 대상 axios.get() 앞에 await를 붙이면 된다.

async는 자바스크립트에게 getMovies()함수가 비동기라고 말해준다.

await는 자바스크립트에게 axios.get()의 실행 완료를 기다렸다가 끝나면 진행하라고 말해준다.

 

 

영화 앱의 실행 시나리오 복습

리액트 앱 실행 → 최초로 render()함수 실행 → 최초의 state에는 isLoading, movies가 있다 → isLoading은 true이고, movies는 빈배열 → 최초 실행 화면 Loading... 표시

 

App 컴포넌트 마운팅 → componentDidMount()함수 실행 → getMovies()함수 실행 → 시간이 많이 걸리는 axios.get()이 포함되어 있다 → getMovies()함수에 async를, axios.get()에 await를 붙였다 → async와 await는 짝꿍이다

 


영화 데이터 화면에 그리기

앞에서 async, await 키워드와 axios.get()을 통해 API를 호출했다.

API가 보내준 데이터가 movies에 들어 있다.

 

 

console.log() 함수로 영화 데이터 출력해보기

axios.get()으로 잡은 영화 데이터가 movies 변수 안에 들어 있으니까 console.log(movies)로 출력해보자

콘솔 탭을 보면 객체가 보인다.

 

 

영화 데이터 자세히 살펴보기

data 키에 집중할 것이다. 영화 데이터data 키에 들어 있다.

 

 

 

data 키를 또 펼쳐본다. 그 안에 다시 data 키가 있다. 그 안에 movies 배열이 있다. movies 배열 펼쳐본다.

 

 

 

movies 키 안에 영화 데이터가 들어 있다.

id, url, title, title_english 같은 키가 들어 있다. 

data → data → movies 순서대로 객체에 접근하면 원하는 데이터를 추출할 수 있다.

 

 

객체에 있는 movies 키에 접근하기

원하는 데이터를 추출하기 위해 movies 변수에 있는 movies 키의 값을 추출해 보자.

movies.data.data.movies 로 수정한다.

 

movies 변수에는 이제 배열이 들어 있다. 배열에는 객체 20개가 들어 있다.

진짜 영화 데이터만 추출한 것이다.

 

 

객체에 있는 movies 키에 조금 더 똑똑하게 접근하기

구조 분해 할당을 사용한다. (점 연산자 적용 순서대로 구조 분해 할당을 적용한다.)

 

 

movies state에 영화 데이터 저장하기

this .setState({ movies: movies }) 와 같이 작성하면 movies.state에 영화 데이터를 저장할 수 있다.

 

이름이 같다고 해서 둘을 혼동하면 안 된다. 하나는 state하나는 axios.get()의결과를 담을 변수이다.

 

 state에 영화 데이터가 저장되면 → movies state가 변경 render()함수 다시 실행  

 

 

ES6에서는 객체의 키와 대입할 변수의 이름이 같다면 코드 축약 가능

this.setStat({ movies })로 수정한다.

 

 

isLoading state 의 값을 true에서 false로 바꾼다

브라우저에 We are ready가 출력된다.

 

영화 데이터를 가져오는 데 성공했고, 로딩 상태 변경까지 성공했다. 

다만 영화 데이터를 출력하고 있지는 않는다.

출력하려면 movies state를 화면에 그려야 한다. Movie 컴포넌트가 필요하다.

 

 

 


Movie 컴포넌트 만들기

 

Movie 컴포넌트 만들기

src 폴더에 Movie.js 파일을 새로 만들고, Movie 컴포넌트기본 골격을 작성하자.

Movie 컴포넌트는 state가 필요하지 않으므로 클래스형 컴포넌트가 아니라 함수형 컴포넌트로 작성한다.

 

Movie에 넘어와야 하는 영화 데이터를 정의하고 관리하기 위해 prop-types를 사용한다.

Movie.propTypes의 내용을 우선 채운다. 그러기 위해 노마드코더 영화 API로 받은 데이터를 다시 살펴본다.

 

 

영화 데이터 다시 살펴보기

yts-proxy.now.sh/list_movies.json 에 접속해서 영화 데이터 다시 확인한다.

 

영화 데이터 중 필요한 것만 골라서 영화 앱에 반영한다. id, title, rating과 같은 데이터.

 

 

Movie.prop.Types 작성하기

id자료형이 Number이고, 반드시 있어야 하니까 PropTypes.number.isRequired로 작성했다.

year 는 자료형 숫자, title, summary 는 문자열이다.

poster 에는 이미지 주소(문자열)가 저장된다.

 

 

영화 포스터 이미지 주소 키와 키값 확인하기

poster props는 영화 포스터 이미지 주소를 저장하기 위한 것이다. (음식 앱 이미지 주소 원리 이용)

 

yts-proxy.now.sh/list_movies.json 에 접속하고 medium_cover_image 키와 키값을 살펴보자.

 

 

키값에 영화 포스터 이미지가 저장되어 있는 주소가 있다. 이 값을 이용한다.

props의 이름을 poster 라고 지정한다.

 

 

노마드 코더 영화 API 정렬 기능 사용해 보기

API 문서를 살펴보자.

yts.lt/api#list_movies에 접속한 다음 Endpoint Parameters를 주목하자.

sort_by 라는 Parameter 가 보인다.

 

sort_by를 사용하면 영화 데이터를 정렬할 수 있다.

 

Example를 보자.

quality가 3D인 영화만 불러오는 URL이 적혀 있다.

? 오른쪽에 무엇이 적혀 있는지 보자.

Parameter(quality)와 Parameter에 넘겨줄 값(3D)을 =으로 이어서 작성하면 된다.

 

 

 

yts-proxy.now.sh/list_movies.json?sort_by=rating 접속한다

평점 내림차순으로 영화 데이터를 보여준다.

 

API를 잘 활용하면 정렬 기능을 굳이 직접 만들지 않아도 된다.

 

 

axios.get() 수정하기

axios.get()에 yts-proxy.now.sh/list_movies.json?sort_by=rating 전달한다.

 

평점 내림차순으로 영화 데이터를 가져올 수 있게 되었다.

App 컴포넌트에서 Movie 컴포넌트로 id, title, year, summary, poster props를 넘겨주면 된다.

 

 

Movie 컴포넌트에 props 추가하고 출력해 보기

우선 title만 출력하도록 만들어 보자.

 

App 컴포넌트에서 Movie 컴포넌트를 그리면 title이 출력되도록 만든다. 

map()함수로 출력하는 방법 이용한다.

 

 

App 컴포넌트에서 Movie 컴포넌트 그리기

구조 분해 할당으로 this.state에 있는 movies를 얻은 다음

App 컴포넌트에서 We are ready를 출력하고 있는 자리 (로딩이 다 되면 실행되는 자리) 에 movies.map() 사용한다.

 

음식앱에서 map()함수의 첫 번째 인자컴포넌트를 반환하는 함수를 전달했었다.

 

 

map() 함수에 컴포넌트를 반환하는 함수 전달하기

우선 콘솔 탭에 영화 데이터를 출력한 다음, 아무것도 반환하지 않는 함수를 전달해 보자.

movies는 배열이고, 배열의 원소 1개movie로 넘어온다.

return에서 Moive 컴포넌트를 반환하면 된다.

 

 

Movie 컴포넌트 반환하도록 movies.map() 수정하기

Movie 컴포넌트를 임포트한 다음, movies.map()에 전달한 함수가 <Movie />를 반환하도록 만든다.

 

 

Movie 컴포넌트에 props 전달하기

설정한 props를 모두 전달해야 한다.

대부분 props의 이름은 노마드 코더 영화 API에서 받아온 키 이름과 똑같이 만들었다.

단,  poster props의 경우, 이름이 medium_cover_image 이므로 movies.medium_cover_image 라고 작성해야 한다.

 

브라우저에는 영화 제목이 주르륵 출력된다.

 

 

콘솔 탭에서 영화 데이터 확인해 보기

영화 정보가 평점순으로 잘 들어오고 있다.

 

key props 경고 메세지가 나온다.

 

 

key props 추가하기

key props는 유일해야 하므로 노마드 코더 영화 API에서 넘겨주는 id를 그래도 사용한다.

컴포넌트를 여러개 출력할 때는 유일한 값을 이용하여 key props를 추가해야 한다.

 

경고 메시지 사라졌다.

 

만든 내용 정리

노마드 코더 영화 API를 통해 영화 데이터를 가져옴

영화 데이터 가져올 때 axios.get( )함수 사용함

axios.get( )함수는 시간이 필요한 함수이므로 async, await 사용함

state에 영화 데이터가 저장되면(업데이트되면) isLoading...을 보여주던 화면을 Movie 컴포넌트를 보여주도록 만듦

 

 

 


영화 앱 스타일링하기 ㅡ 기초

영화 앱을 만들었으니 예쁘게 꾸밀 차례이다. 

CSS와 CSS를 적용할 HTML이 필요하다.

App 컴포넌트, Movie 컴포넌트에 HTML을 추가한다.

 

 

App 컴포넌트에 HTML 추가하기

App 컴포넌트가 반환할 JSX의 바깥쪽을 <section class="container"></section>로,

Loading ...<div class="loader"><span class="loader__text"></span></div>으로,

movies.map( )<div class="movies"></div>로 감싼다.

 

소괄호, 중괄호 여닫는 부분 주위하기

 

 

Movie 컴포넌트에 HTML 추가하기

Movie 컴포넌트가 반환할 JSX를 <div class="movie__data"></div>로 감싸고,

그 안에서 title, year, summary를 목적에 맞는 엘리먼트로 감싼다.

 

브라우저에서 보면 title, year, summary 정보가 다른 스타일로 출력된다.

 

class 속성 관련 경고 메시지

여기까지 만들고 콘솔탭 열면 class 속성 관련 경고 메시지 보인다.

 

Warning : Invalid DOM property 'class'. Did you mean 'className' ?

JSX에서 반환할 엘리먼트에 'class'라는 이름으로 class 속성을 사용했기 때문에 나타났다.

리액트에서 class 속성을 사용하기 위해서는 'className'을 써야 한다.

 

 

영화 포스터 이미지 추가하기

영화 앱에 포스터 이미지가 추가되지 않았다.

poster props를 추가하자.

전체 엘리먼트를 감싸는 div 엘리먼트(class가 movie인)를 추가하고, 

img엘리먼트를 <div class="movie__data"> 위에 추가해서 src 속성에는 poster props를, alt, title 속성에는 title props 전달한다.

 

브라우저에 영화 포스터까지 나온다. 

이미지 위에 마우스 커서 올리면 alt 속성값 나온다.

 

 

Movie 컴포넌트 정리하기

Movie 컴포넌트에는 id props가 필요하지 않다. 제거한다.

 

 

style 속성으로 title 스타일링하기

title props를 포함하고 있는 h3 엘리먼트에 style 속성을 추가하고 {{backgroundColor : "red"}} 속성 입력한다.

그러나 CSS파일을 만들고 임포트하는 방법을 쓰자.

 

 

CSS 파일 생성하기

src 폴더에 Movie.css, App.css 파일 만든다.

 

 

App, Movie 컴포넌트에 CSS파일 임포트하기

각각 임포트하자. 맨 위에 1줄씩 추가하면 된다.

style 속성은 지우자.

 

 

App.css 파일 작성하기

배경색을 어둡게 바꾼다.

브라우저를 보면 배경이 회색으로 변해있다.