본문 바로가기
개발 기초 다지기

내일배움캠프 15일차 : TMDB에서 API로 출연진&감독 정보 가져오기

by 너의고래 2024. 5. 5.
반응형

이번 영화 검색 사이트 만들기 팀프로젝트에서 나는 데이터를 가져오는 부분을 맡았다. 기존 개인과제에서도 Api로 데이터를 가져오긴 했었는데, TOP20을 가져오다 보니 따로 ID값을 통해 정보를 선별해서 가져올 필요는 없었다. 자바스크립트로 ID값을 통해 정보를 가져오는 법과 기존 구현했던 API를 통한 데이터 가져오기를 복습할 겸 정리해보려 한다.

 

우선 회원가입 및 key 발급의 경우 이전에 하기도 했고 다른 블로그에 잘 정리되어있으니 생략하겠다.

 

- TMDB에서 각 영화 상세페이지에 들어갈 '출연진', '감독' 정보 찾기

 

나는 영화에 맞는 '출연진', '감독' 정보를 가져와야하기 때문에 영화 ID를 통해 정보를 얻을 수 있는 카테고리가 필요했다. 열심히 찾아본 결과 MOVIES의 Credits을 통해서 구현해 낼 수 있었다.

 

 

 

사실 TMDB를 이용하는데 익숙하지 않은 상태라 각 카테고리의 속성들이 어떻게 구성되어 있는지 찾는데 고생을 많이 했는데, 위 이미지처럼 'PATH PARAMS'에 movie_id를 입력해 주면 우측에 fetch url에 id 값이 들어가서 미리 결과 값을 확인할 수 있다. 확인해 보면 "cast"는 배우 인물 정보, "crew"는 제작진 인물 정보를 포함하고 있다.

 

 

- 출연진 정보 가져와서 카드 만들기

TMDB 'FETCH REQUEST'를 복사해 api fetch를 가져왔다. 그리고 링크에 기존 상세 페이지에 가지고 있던 ID값을 넣어줌으로써 영화에 맞는 정보들이 불러져 올 수 있도록 했다. 그리고 cast 데이터로 배우 카드를 만드는 함수를 실행하였다.

 

  function makeActor(actors) {
    const actorCard = document.querySelector("#actorCard");
    actorCard.innerHTML = "";

    actors.forEach(function (actor) {
      const cardBox = document.createElement("div");
      cardBox.classList.add("actCard");

      const profileUrl =
        actor.profile_path !== null
          ? `https://image.tmdb.org/t/p/w500${actor.profile_path}`
          : "https://placehold.jp/696969/ffffff/300x450.png?text=NO%20IMAGE";

      cardBox.innerHTML = `
      <div class="imgBox">
                <img src="${profileUrl}"><div/>
                <div class="actInfo">
                    <h4 class="actName">${actor.name}</h4>
                    <p class="actCharacter">${actor.character}</p>
                </div> `;

      actorCard.appendChild(cardBox);
    });
  }
  • makeActor 함수가 실행되면, 우선 카드가 들어갈 위치를 querySelector를 통해 actorCard라는 이름으로 지정해 주었다.
  • 그리고 'actorCard.innerHTML = ""'을 통해 이 위치의 속성(attribute) 지워, 문서의 전체 내용을 지워주었다. 그래서 해당 결괏값을 가진 카드만 깔끔하게 생성될 수 있도록 해주었다. 이 코드를 지우면 forEach의 결과값을 가진 카드 앞쪽으로 빈 카드열이 생성된다.
    * innerHTML - 'element'의 속성으로, element에 포함된 HTML을 가져오거나, 태그와 함께 입력하면 내용을 직접 설정도 가능
  • 받아온 actors 각각의 데이터에 forEach를 통해 함수를 실행시켜 준다.
  • 'document.creatElement'를 통해 div 태그를 생성하는 것을 cardBox라고 명명한다.
  • cardBox로 생성된 <div>에 actCard 클래스 리스트를 생성한다 
  • 카드 이미지를 보여줄 url을 정의해 주는데, 값이 있을 경우 path 값을 통해 불러오고, 이미지가 없을 경우 No image로 대체한다.
  • 또 cardBox를 통해 <div>를 생성하여, 직접 태그와 함께 HTML 코드를 입력해 줌으로써 내용을 설정해 준다.
  • 안쪽 HTML은 백틱을 통해 작성해 주었으며, 카드마다 변경되어야 하는 값은 '${}'을 통해 불러왔다.
  • 생성된 cardBox를 actorCard 위치의 자식 노드 리스트 중 마지막 자식으로 붙인다.
    appendChild() : 한 노드를 특정 부모 노드의 자식 노드 리스트 중 마지막 자식으로 붙인다.

 

- 감독 정보 가져와서 카드 만들기

fetch(
    `https://api.themoviedb.org/3/movie/${movieId}/credits?language=en-US`,
    options
  )
    .then((response) => response.json())
    .then((data) => makeDirector(data.crew))
    .catch((err) => console.error(err));

  function makeDirector(crews) {
    const directorCard = document.querySelector("#directorCard");
    directorCard.innerHTML = "";

    crews.forEach(function (director) {
      const cardBox = document.createElement("div");
      if (director.job === "Director") {
        cardBox.classList.add("drcCard");
        cardBox.innerHTML = `
                <div class="imgBox">
                <img src="https://image.tmdb.org/t/p/w500${director.profile_path}"></div>
                <div class="drcInfo">
                    <h4 class="drcName">${director.name}</h4>
                </div> `;

        directorCard.appendChild(cardBox);
      }; 
    });
  }
});

감독 가져오기도 유사하다. 동일하게 가져오되, 다른 제작자들의 정보는 제외하고 감독의 정보만 가져오도록 만들면 된다.

  • fetch를 통해 정보를 동일하게 가져오는데 data 값을 'cast'가 아닌 'crew'를 가져온다. (감독 정보는 crew에 들어있다.)
  • 출연진을 가져오는 코드와 동일하게 진행하다가 그대로 html로 빼기 전에 조건문을 넣어준다.
  • 우리는 모든 제작자가 아닌 감독만 필요하기 때문에 crew 데이터의 job 키의 값이 "Director"라는 조건문을 넣어주었다.
  • 조건에 일치할 경우, 배우와 동일하게 directorCard 위치에 카드를 넣어준다.

 

헤맸던 부분

(1)  if (director.job === "Director") 조건문

아직 자잘한 실수가 많다고 느꼈던 부분이 완전히 일치한다고 나타낼 때는 '==='을 사용해야 하는데, 아무 생각 없이 '=' 등호 하나만 넣어서 코드를 구현했었다. 그랬더니 아래 이미지의 왼쪽처럼 나와야 할 것이 오른쪽과 같은 누가 봐도 잘못된 것처럼 나와버렸다.

 

이번 실수를 통해 자바스크립트 등호에 대해 자세히 알아보게 되었다.

  • '='는 할당 : 왼쪽에 있는 변수를 오른쪽에 있는 값으로 설정한다 (a=b -> b의 값을 a에 할당)
  • '=='는 비교 : 값이 같으면 'true' 반납
  • '==='는 엄격한 동등 비교 : 값과 데이터 타입까지 같아야 'true'반납

사실상 데이터 타입이 다를 일은 없었기 때문에 '=='만 썼어도 오류가 나지 않았을 것이다.

 

(2) fetch로 ID값을 가져오지 못하던 부분

메인 페이지에서 상세페이지로 연결하는 부분은 다른 팀원분께서 맡은 부분이었다. 팀원분께서 url 속에 movie id를 넣어서 가져오는 것까지는 해주셨기에 나는 url에서 id 값을 가져와서 정의 내려주는 것부터 하면 되는 부분이었다.

내가 이 부분에서 헤맸던 이유는 실행 콘텍스트를 완벽히 이해하지 못했기 때문이다.

id를 정의 내리고 바로 밑에 console을 찍었을 때는 값이 잘 찍히는데, api에서는 작동하지 않았었다. 이 문제로 튜터님께 찾아갔고 너무 쉽고 민망하게도, api 쪽에서 오류를 나타내고 있는 console이 정의 값 아래 console보다 더 먼저 실행되고 있는 것을 확인할 수 있었다.

그러니 movieId를 정의 내리기도 전에 그 값을 넣어버리려고 하는 꼴이었다. 

이 문제는 값을 정의하는 부분이 DOMContentloaded된 후 실행되기 때문이었다. 그래서 fetch 또한 로드가 된 후 실행 될 수 있도록 addEventListener 속으로 넣어줬더니 api가 제대로 작동했다. 지금 코드를 만들어나가면서 가장 힘든 부분이 실행 콘텍스트를 읽는 능력부족이 가장 크다고 생각한다. 이 부분에 대해 어떻게 실력을 늘릴 수 있을지 상담을 해봐야겠다.

- 개선 가능한 부분

코드를 만들고 나서 내가 더 궁금했거나 아쉬운 부분에 대해 적어보려 한다.

 

(1) fetch를 통해 가져오는 데이터는 동일한데 그 안에서 나눠지는 객체만 다르다. 이러한 경우에 내가 짠 것처럼 fetch를 하나씩 불러오는 방법 말고 조금 더 효율적인 방법이 있지 않을까 쉽다. 현재 각자 실행시키는 카드를 만드는 함수 윗단계에 엮어주는 함수를 넣으면 가능하지 않을까 싶긴 한데, 조금 시도해보긴 했는데 실패했다. 이 방법에 대해 더 연구해 봐야겠다.

 

(2) 현재 코드에서는 job이 Director로 일치하는 경우에 값을 가져오는 조건만 넣었는데, 이 조건에 맞는 값이 하나도 없을 때를 가정하지 않았다. 내가 이 DB 전체를 하나하나 확인할 수 없기 때문에 충분히 이러한 경우도 있을 수도 있다고 생각한다. 이러한 경우 'No information'과 같은 결과 값을 반납해야 하지 않을까 싶다.

 

내가 맡은 부분이 지난 과제와 유사해 비교적 빠르게 끝이 났다. 그래도 내가 기존 작성한 코드와 다르게 팀원 코드를 활용하여 만들어냈기에 충분히 복습이 필요했으며, 내가 생각한 개선 가능한 부분까지도 개선해 내는 것이 이 프로젝트의 끝이라고 생각한다. 각자 맡은 부분을 완료하기로 한 날짜까지 하루가 더 남았기 때문에 그 시간 동안 개선을 해보도록 하자.

반응형

댓글