[TIL] 영화 검색 페이지 팀프로젝트를 마치며

기성·2024년 8월 7일
1

TIL

목록 보기
34/81
post-thumbnail

옹기종기 모여있는 우리 팀을 썸네일로 보여주면서 이번 팀프로젝트 마무리를 해보려 한다.

팀 프로젝트 목표

일단 개인 과제로 진행했던 영화 검색 페이지를 팀원들 사이에서 하나를 골라 발전시키는 팀 프로젝트가 되었다. 팀 프로젝트니까 이름부터 정해야지.

우리의 프로젝트명은 MovieHub가 되었다. Github처럼 영화의 저장소 느낌인 이름을 만들게 되었는데 생각보다 입에 붙(?)더라.

팀 목표

  1. 중간에 깃발 꽂지 않기
  2. 디자인에 집착하지 않기(기능 구현 우선으로)

기능을 구현하기 전에 디자인에 손을 대기 시작하면 진짜 끝도 없이 물고 늘어지게 되는 경향이 있는 것 같다. 이거 때문에 기능을 먼저 다 만든 월요일부터 CSS를 건들기 시작해서 완성할 수 있었다. 월요일 하루종일 CSS만 건들었던 것 같다. 중간에 깃발 꽂지 않기는 부트캠프 중간에 포기하지 않기인데 팀 프로젝트 시작 전에 한 분이 이미 꽂아버리셔서 4명에서 진행하게 되었다...

결과물

우선 전과 후를 보여주자면 이렇다.

  • 개인과제

  • 팀 과제

메인 페이지

ezgif com-optimize

상세 페이지

캐러셀

캐러셀

댓글

수정, 삭제 유효성검사

내 하찮은 개인 과제에서 꽤 그럴싸한 페이지가 만들어졌다. 각자 맡은 기능들을 잘 구현해줘서 프로젝트를 잘 끝낼 수 있었던 것 같다.

대표 코드

내가 맡은 부분이나 수정본 부분의 코드를 한 두개만 설명하려한다.

캐러셀

  const getItemsToShow = () => {
    if (window.innerWidth <= 600) {
      return 1;
    } else if (window.innerWidth <= 1140) {
      return 2;
    } else if (window.innerWidth <= 1500) {
      return 3;
    } else {
      return 4;
    }
  };
  let itemsToShow = getItemsToShow();
  const totalItems = movies.length;
  let index = 0;

  const updateCarousel = () => {
    const offset = -index * (100 / itemsToShow);
    carouselInner.style.transform = `translateX(${offset}%)`;
  };

  const showNextItem = () => {
    index = (index + itemsToShow) % totalItems;

    if (itemsToShow === 3 && (index === 1 || index === 2)) {
      index = 0;
    }
    updateCarousel();
  };

  const showPrevItem = () => {
    index = (index - itemsToShow + totalItems) % totalItems;
    if (itemsToShow === 3 && (index === 19 || index === 17)) {
      index = 18;
    }
    updateCarousel();
  };

  window.addEventListener("resize", () => {
    itemsToShow = getItemsToShow();
    updateCarousel();
  });

개인 과제에서 구현했던 거기 때문에 전에 TIL에서 써놨던 [TIL] 개인 과제 구현 - (2) 요기서 확인 할 수 있다.
이 위의 코드는 새로 옮기면서 반응형을 구현하기 위해 getItemsToShow()함수를 만들어서 한번에 보여줄 아이템 개수를 정해주고 showNextItem()showPrevItem()에서는 아이템이 3개씩일 때 총 데이터 개수가 20개기 때문에 캐러셀이 꼬이는 현상을 방지하고자 인덱스를 고정시켜주었다.

index.js

import renderCarousel from "./carousel.js";
import createHeaderSearchInput from "../../js/header.js";
import { createMovieDetailTop } from "./detail.js";

const initialize = async () => {
  createHeaderSearchInput();
  await createMovieDetailTop();
  await renderCarousel();
};
initialize();

원래는 따로 이렇게 묶지 않고 바로바로 실행시켜주었는데 이게 웬걸. renderCarousel()에서 insertBefore()함수와 appendChild()null의 다음 위치를 가리켜 렌더링을 할 수 없는 에러가 발생해서 상세 페이지가 나오지 않게 되는 현상을 발견하게 되었다. JS가 비동기로 실행되기 때문에 간헐적으로 renderCarousel()createMovieDetailTop()이 실행되기 전에 먼저 실행되어 부모요소가 없어 나타나는 에러였다. 이걸 해결하기 위해 구글링도하고 생각도 해본 결과. asyncawait을 사용해서 동기처럼 렌더링을 하게 된다면 null이 아니라 렌더링이 된 후의 요소를 가리키게 되어 에러를 해결할 수 있게 되었다.

타이핑마다 검색

searchInput.addEventListener("input", async (e) => {
    let keyUpValues = e.target.value;
    if (timer) {
      clearTimeout(timer);
    }
    timer = setTimeout(async () => {
      const language = getLanguage();
      let searchData;
      if (keyUpValues === "") {
        searchData = await getTopRatedMoviesList(language, 1);
      } else {
        searchData = await getSearchData(language, keyUpValues, 1);
      }
      const cardList = document.querySelector("#card-list");
      cardList.innerHTML = makeCards(searchData);
      updatePagination(searchData.total_pages, 1);
      addPaginationEventListeners(searchData.total_pages);
      if (keyUpValues) {
        upcomeContainer.style.display = "none";
      } else {
        upcomeContainer.style.display = "flex";
      }
    }, 200);
  });

개인적으로 가장 마음에 들었던 기능이다. 팀원 중에 하영님이 개인 과제에 filter를 통해서 매 타이핑마다 해당 단어에 대한 영화들을 걸러 카드로 보여주는 기능이 있었는데 나는 이걸 api를 활용해서 매 타이핑을 검색하는 기능이 있으면 어떨까? 하는 생각이 들어 만들게 되었다. 이벤트리스너를 통해 input마다 입력값을 가져와서 바로바로 api를 호출하고 그에 따른 데이터를 다시 카드와 페이지네이션에 넣어주고 다시 업데이트를 하는 방식을 사용했다. 완성되었을 때는 이거지! 하는 생각이 딱 들더라. 그러고 중간에 재상님이 디바운싱이란것이 있는데 시간이 괜찮다면 한 번 알아보고 적용해보면 좋겠다 라고 하셔서 바로 알아보았다.

디바운싱

연이어 호출되는 함수들 중 마지막 함수(또는 제일 처음)만 호출하도록 하는 것

디바운싱과 쓰로틀링이라고 두 가지 기법이 있는데 이것들은 디바이스의 무리를 주지 않기 위해 사용되는 최적화 기법이라고 한다. 그래서 디바운싱은 무엇인가. 이벤트핸들러가 너무 자주 호출되지 않게 timeout을 주어 방지하고자 할 때 사용하는 기법이다. 그렇기 때문에 입력값을 input마다 받지만 200ms후에 api를 호출하기 때문에 타이핑이 완성이 된 후에 api를 불러오는 결과를 볼 수 있는 것이다. 이전에는 매 타이핑 api를 호출하여 서버에 무리가 갈 수 있지만 이렇게 사용하면 서버에 부하를 상당히 줄여줄 수 있는 것이다.

후기

확실히 독학 때 보다 부트캠프를 통해서라도 협업을 통해 결과물을 만들어내니 재밌다. 이번 팀 프로젝트를 진행하면서 엄청 크게 막히는 부분도 없었을 뿐더러 예전부터 VanillaJS로 만들고 싶었던것도 만들고 팀원들도 분위기가 좋고 의도한대로 순조롭게 진행이 되니 즐거운 팀프로젝트가 되었던것 같다. 발표 또한 평소와 다르게 많이 더듬지도 않고 잘 넘어갔던 것 같다. 남은 기간도 이렇게만 진행된다면 좋겠다.

profile
프론트가 하고싶어요

0개의 댓글