
1. 모달창 구현부터 복기 해보자..!
우선 html파일에 모달창이 들어갈 부분 <div id="modal-content"></div> 만들어주고 자바스크립트 시작@!
function createModal(movie) {
// 모달 창 생성
const movieModal = document.createElement("div");
movieModal.className = "movie-modal";
movieModal.innerHTML = `
<span class="close"><i class="fa-regular fa-circle-xmark"></i></span>
<img src="https://image.tmdb.org/t/p/w500${movie.poster_path}" alt="${movie.title}" />
<h3>${movie.title}</h3>
<p>${movie.overview}</p>
<p>개봉일 : ${movie.release_date}</p>
<p>평점 : ${movie.vote_average}/10</p>
<button id="addBookmark" class="modalBookmark">북마크 추가</button>
<button id="removeBookmark" class="modalBookmark">북마크 삭제</button>
`;
// => html에 있는 <div id="modal-content"></div> 안에 들어갈 태그들 생성
// 모달 창을 modal-content에 추가
const modalContainer = document.getElementById("modal-content");
if (modalContainer) {
modalContainer.innerHTML = ""; // 기존 모달 초기화
modalContainer.appendChild(movieModal); // html에 작성한 모달 태그에 지금 만든 모달창 태그 붙이기
modalContainer.style.display = "block"; // 모달 보이기
console.log("모달이 modal-content에 추가됨");
} else {
console.error("modal-content 요소를 찾을 수 없습니다.");
}
// 모달 창 스타일링 및 표시
movieModal.style.display = "block";
이렇게 하면 코드상에서 html의 <div id="modal-content"></div> 이 안에 innerHTML로 넣어준 태그들이 다 들어가 있다.
우선 이렇게 하면 모달창 1차 구현은 됐고, 이제 카드를 클릭하면 모달창이 뜨도록 설정하러 가보자
// 카드 클릭 시 모달 창 표시
card.addEventListener("click", () => {
console.log("클릭 완료");
createModal(movie); // 클릭된 영화 정보를 모달에 표시
});
이건 어제 만들어둔 카드리스트 함수 displayMovies()안에 위치시켜놓는다.
우선 이정도 해두고 이제 모달css를 만지러 가보자. css가 설정되어있지 않으면 모달이 안보이니께...

제일 위에 보여야 할 모달창을 z-index를 줘서 제일 위로 올리고, 모달이 처음부터 보이면 안되고 카드를 클릭했을때 보여야 하기때문에 display="none"으로 설정한다.
나머지는 모달 이쁘게 꾸미는...
그리고 모달 태그를 확인해보면 닫기 버튼과 북마크 추가, 북마크 삭제 버튼이 3개 있다. 이 버튼들도 각각 제 기능을 할 수 있도록 설정한다. 먼저 닫기버튼부터!
JS
// 모달 닫기 버튼
movieModal.querySelector(".close").addEventListener("click", () => {
const modalContainer = document.getElementById("modal-content");
modalContainer.style.display = "none"; // 버튼 클릭 시 안보이게 하기
modalContainer.innerHTML = ""; // 클릭시 innerHTML 없어지게 하기
});
// 모달 외부 클릭시 모달창 꺼지기
document.addEventListener("click", function (e) {
if (e.target === modalContainer) {
modalContainer.style.display = "none";
}
// => 이거는 그냥 외우자. 이 형태 그대로 modalContainer 이 변수만 때에 따라 다르게 하면 됨
});
CSS
.close {
float: right;
font-size: 24px;
cursor: pointer;
color: black;
}
닫기버튼은 이렇게!!
북마크 버튼이 골치 아픔.. 토글마냥 북마크 추가버튼 누르면 삭제버튼이 뜨고 삭제버튼 누르면 추가버튼이 뜨게 해야되기 때무네..
JS
// 북마크 버튼 이벤트리스너
const addBookmark = document.querySelector("#addBookmark");
const removeBookmark = document.querySelector("#removeBookmark");
removeBookmark.style.display = "none"; // 처음에는 삭제 버튼을 숨김
// 북마크 추가 버튼을 눌렀을 때
addBookmark.addEventListener("click", () => {
addBookmark.style.display = "none"; // 추가 버튼 숨기기
removeBookmark.style.display = "flex"; // 삭제 버튼 보이기
});
// 북마크 삭제 버튼을 눌렀을 때
removeBookmark.addEventListener("click", () => {
removeBookmark.style.display = "none"; // 삭제 버튼 숨기기
addBookmark.style.display = "flex"; // 추가 버튼 보이기
});
짜고 보니까 쉬운거같은데 이거 은근히 헷갈림...
CSS => 추가버튼이랑 삭제버튼에 같은 className을 붙여서 한꺼번에 설정해줌!
.modalBookmark{
font-weight: 600;
font-size: 15px;
background-color: black;
color: white;
width: 600px;
border: 0;
padding: 8px ;
border-radius: 5px;
justify-content: center;
}
.modalBookmark:hover{
transition: 0.2s;
background-color: #343434;
}
그 결과!!
푸슈-ㄱ 고된 시간이였따... 누구는 빨리 후딱 끝낼수도 있는거였지만 모든게 새롭다거 나는!!!!!! 빨리 하고싶다고 나도!!!!! 어쨌든 완성되서 뿌듯-☆ 하지만 아직 갈길이 멀다...ㅋㅋㅋ
영화 검색 기능 구현!!!!
(이거 한다고 반나절은 걸린 느낌적인 늒낌...🤯)
계속 헤맸던 이유를 생각해보자면
1. 영화 데이터를 가져오는데 그에 대한 개념이 잡혀있지 않았다 => 이게 제일 큰 원인
2. filter(), includes()에 대한 개념도 부족 : 그냥 이건 내가 잘 몰랐음ㅋ
3. toLowerCase() 또한 마찬가지 : 과제 조건중 대소문자 구분없이 검색이 되라고 했는데 뭔소린지 몰랐음ㅋ
toLowerCase()는 대문자로 써도 소문자로 만들어주는 메소드이기때문에 이걸 쓰면 되는거였음
우선 코드를 보자
먼저 html에 form - input 으로 태그 만들어줌

// 영화 검색 기능 구현
const movieInput = document.querySelector("#movieInput");
movieInput.addEventListener("input", () => {
const searchTerm = movieInput.value.toLowerCase();
if (searchTerm) {
const filteredMovies = movies.filter((movie) =>
movie.title.toLowerCase().includes(searchTerm)
);
displayMovies(filteredMovies);
} else {
displayMovies(movies);
}
});
처음에 displayMovies(movies) 여기서 movies가 계속 undefined라고 나오는거다.. 왤까..
한참을 고민하다가 튜터님께 쪼르르 달려감
그 원인은 바로 위에 있는 카드 생성 함수에 있었으니...
// 카드 생성하는 함수
function displayMovies(movieList) {
// movies 배열을 초기화해 중복된 데이터 추가 방지
if (movies.length === 0) {
movies = movieList; // 처음 데이터만 저장
}
const movieContainer = document.getElementById("movies-container");
movieContainer.innerHTML = ""; // 기존 카드 초기화
movieList.forEach((movie) => {
// 카드 생성
const card = document.createElement("div");
card.classList.add("movie-card");
// 포스터 이미지, 제목, 출시일, 평점 추가
card.innerHTML = `
<img src="https://image.tmdb.org/t/p/w500${movie.poster_path}" alt="${movie.title}" />
<h3>${movie.title}</h3>
<p>개봉일 : ${movie.release_date}</p>
<p>평점 : ${movie.vote_average}/10</p>
`;
// 카드 클릭 시 모달 창 표시
card.addEventListener("click", () => {
console.log("클릭 완료");
createModal(movie); // 클릭된 영화 정보를 모달에 표시
});
// 컨테이너에 카드 추가
movieContainer.appendChild(card);
});
}
지금은 수정된 코드지만 원래 코드는 displayMovies(movieList) 이 함수의 파라미터인 movieList가
movies였다.. 대혼란의 서막...
부끄럽네 ㅋㅋㅋ
근데 내가 파라미터를 제대로 이해하고 있지 않아서 카드 함수에도 movies가 있고 검색 구현 함수에도
movies가 있네..? 한번 안에 넣어봐..? 라는 아주 바보같은 생각을 했더랬다 ㅋㅋㅋㅋ
근데 넣으니깤ㅋㅋㅋㅋ 안됨ㅋㅋㅋ 당연함 ㅋㅋㅋㅋㅋ
튜터님께 달려간 결과 저 displayMovies(movies)를 displayMovies(movieList)로 바꾸고 검색 함수는 밖으로 빼는것으로 결론남. 근데 문제는 여전히 안되는거임. 당연함 여전히 필터링 해야되는 movies는 정의되지 않았으니깐요,, 존재하지 않는걸 어찌 필터링 하겠읍니꽈아아악!!!
displayMovies(movies) 이 함수가 어디서부터 시작되었는가 거슬러 올라가기 시작한다..
function fetchMovies() {
fetch(
"https://api.themoviedb.org/3/movie/popular?language=en-US&page=2&language=ko",
options
)
.then((response) => response.json())
.then((data) => displayMovies(data.results)) // 영화 데이터의 results 부분을 사용
.catch((err) => console.error(err));
}
영화 데이터 가져오는 fetchMovie에서부터 시작된 함수였다.
그렇다 내가 원하는 movies는 data.result 였던것!
그럼 이제 실마리가 조금씩 보인다.
우선 let movies = []; 로 movies라는 변수를 선언해준다!
이제 저 movies는 영화 데이터를 가지고 있는 배열이 된다.
if (searchTerm) {
const filteredMovies = movies.filter((movie) =>
movie.title.toLowerCase().includes(searchTerm)
);
displayMovies(filteredMovies);
} else {
displayMovies(movies);
}
이것도 당연히 성립이 됨!

검색창 구현 끝... 힘겨웠다...
오늘의 회고
갈 길이 멀고도 멀다.. 그래도 잘 하고 있다...!
'JavaScript 프로젝트' 카테고리의 다른 글
| [JavaScript] 개인 과제 수행 - 4일차 (localStorage 삭제) (0) | 2024.10.22 |
|---|---|
| [JavaScript] 개인 과제 수행 - 3일차 (localStorage) (1) | 2024.10.19 |
| [JavaScript] 개인 과제 수행 - 1일차 (TMDB API 발급 받기, 카드리스트 만들기) (14) | 2024.10.16 |
| [첫번째 프로젝트] 마무리하며... KPT 회고란 무엇인가 (1) | 2024.10.07 |
| [첫번째 프로젝트] 팀원 소개 페이지 만들기4 (0) | 2024.10.04 |