μν κ²μ κΈ°λ₯ λ° μ° νμ΄μ§ ꡬν
μ΄λ² ν¬μ€ν μμλ μ° νμ΄μ§μ μν κ²μ κΈ°λ₯μ ꡬνν λ΄μ©μ λ€λ€λ³΄κ² μ΅λλ€. μ΄λ₯Ό ν΅ν΄ μ¬μ©μκ° μ¬μ΄νΈμμ μ° λͺ©λ‘μ μ½κ² λ³Ό μ μκ³ μν κ²μμ ν¨μ¨μ μΌλ‘ ν μ μλλ‘ λ§λλ λ°©λ²μ μκ°ν©λλ€.
1. μν κ²μ κΈ°λ₯ ꡬν
μ¬μ©μλ μν κ²μ κΈ°λ₯μ ν΅ν΄ μνλ μνλ₯Ό λΉ λ₯΄κ² μ°Ύμ μ μμ΅λλ€. μ΄ κΈ°λ₯μ TMDB APIλ₯Ό νμ©νμ¬ κ²μλ μν λͺ©λ‘μ νμνκ³ , νν°λ§ μ΅μ μ μ 곡νμ¬ μ¬μ©μκ° μνλ μνλ₯Ό μ 리ν μ μλλ‘ λμ΅λλ€.
1.1 κ²μμ΄ μ λ ₯ λ° API νΈμΆ
μ¬μ©μκ° κ²μμ΄λ₯Ό μ
λ ₯νλ©΄ ν΄λΉ κ²μμ΄λ₯Ό λ°νμΌλ‘ TMDB APIμμ μν λͺ©λ‘μ λ°μμ΅λλ€. μ΄λ₯Ό μν΄ useState
λ‘ κ²μμ΄ μνλ₯Ό κ΄λ¦¬νκ³ , κ²μ λ²νΌμ ν΄λ¦νλ©΄ searchMovies
ν¨μλ₯Ό νΈμΆνμ¬ API μμ²μ 보λ
λλ€.
searchPage.js
//pages/searchPage.js
const handleSearch = useCallback(async () => {
try {
const data = await searchMovies(query, page);
setMovies(data.results);
setTotalPages(data.total_pages);
} catch (error) {
console.error("Error fetching search results:", error);
}
}, [query, page]);
1.2 νν°λ§ κΈ°λ₯
μ¬μ©μλ κ²μ κ²°κ³Όλ₯Ό μ₯λ₯΄, νμ , μ λ ¬ λ°©μμΌλ‘ νν°λ§ν μ μμ΅λλ€. νν°λ§μ filters
κ°μ²΄λ₯Ό ν΅ν΄ κ΄λ¦¬λλ©°, μ₯λ₯΄μ νμ λ±μ κΈ°μ€μΌλ‘ μνλ₯Ό μ νν μ μμ΅λλ€. νν°λ§λ μν λͺ©λ‘μ filteredMovies
μνμ μ μ₯λμ΄ μ¬μ©μμκ² λ³΄μ¬μ§λλ€.
//searchPage.js
const applyFilters = useCallback(() => {
let updatedMovies = [...movies];
if (filters.genre) {
updatedMovies = updatedMovies.filter((movie) =>
movie.genre_ids.includes(parseInt(filters.genre))
);
}
if (filters.rating > 0) {
updatedMovies = updatedMovies.filter(
(movie) => movie.vote_average >= filters.rating
);
}
if (filters.sortBy) {
updatedMovies.sort((a, b) => {
if (filters.sortBy === "popularity.desc") {
return b.popularity - a.popularity;
} else if (filters.sortBy === "release_date.desc") {
return new Date(b.release_date) - new Date(a.release_date);
}
return 0;
});
}
setFilteredMovies(updatedMovies);
}, [movies, filters]);
1.3 νμ΄μ§λ€μ΄μ
κ²μ κ²°κ³Όλ νμ΄μ§λ€μ΄μ
μ ν΅ν΄ μ¬λ¬ νμ΄μ§μ κ±Έμ³ νμλ©λλ€. μ¬μ©μκ° νμ΄μ§λ₯Ό λ³κ²½ν λλ§λ€ μλ‘μ΄ κ²μ κ²°κ³Όλ₯Ό λΆλ¬μ΅λλ€. μ΄λ₯Ό μν΄ Pagination
μ»΄ν¬λνΈλ₯Ό μ¬μ©νμ¬ νμ¬ νμ΄μ§μ μ 체 νμ΄μ§ μλ₯Ό μ λ¬νκ³ , νμ΄μ§λ₯Ό λ³κ²½ν μ μλλ‘ ν©λλ€.
<Pagination page={page} totalPages={totalPages} setPage={setPage} />
Pagination.js
//components/Pagination.js
import React from "react";
const Pagination = ({ page, totalPages, setPage }) => {
const handlePrevPage = () => {
if (page > 1) {
setPage(page - 1);
}
};
const handleNextPage = () => {
if (page < totalPages) {
setPage(page + 1);
}
};
return (
<div className="pagination">
<button onClick={handlePrevPage} disabled={page === 1}>
βοΈ
</button>
<span>
{page} / {totalPages}
</span>
<button onClick={handleNextPage} disabled={page === totalPages}>
βΆοΈ
</button>
</div>
);
};
export default Pagination;
2. μ° νμ΄μ§ ꡬν
WishlistPage.js
//pages/WishlistPage.js
const WishlistPage = () => {
const [wishlist, setWishlist] = React.useState([]);
...
// μ°ν μν λͺ©λ‘μ localStorageμμ κ°μ Έμ€κΈ°
React.useEffect(() => {
const storedWishlist = getFromLocalStorage("favoriteMovies") || []; // localStorageμμ μ° λͺ©λ‘ κ°μ Έμ€κΈ°
setWishlist(storedWishlist);
}, []);
// μ° λͺ©λ‘μμ μν μμ
const handleRemoveFromWishlist = (movie) => {
const updatedWishlist = wishlist.filter((item) => item.id !== movie.id); // μμ ν μν μ μΈν λͺ©λ‘
setWishlist(updatedWishlist); // μν μ
λ°μ΄νΈ
saveToLocalStorage("favoriteMovies", updatedWishlist); // localStorageμ μ° λͺ©λ‘ μ μ₯
};
...
return (
<div className="wishlist-page">
<h1>μ°ν μ½ν
μΈ </h1>
{wishlist.length > 0 ? (
<div className="movie-list">
{wishlist.map((movie) => (
<MovieCard
key={movie.id}
movie={movie}
onClick={() => openModal(movie)}
/>
))}
</div>
) : (
<p>μ°ν μνκ° μμ΅λλ€.</p>
)}
{showModal && selectedMovie && (
<Modal
movie={selectedMovie}
onClose={closeModal}
handleAddToWishlist={() => {}}
handleRemoveFromWishlist={handleFavoriteAction} // μ° μ·¨μ ν¨μ μ λ¬
isFavorite={true} // μ° μνλ νμ trueλ‘ μ€μ (μ°ν μν)
/>
)}
</div>
);
};
export default WishlistPage;
π κ²°κ³Ό νλ©΄
- μν κ²μ κΈ°λ₯

- μ° νμ΄μ§

π‘ μ 리
μ΄λ² ν¬μ€ν
μμλ μ° νμ΄μ§μ μν κ²μ κΈ°λ₯μ ꡬννλ λ°©λ²μ μ΄ν΄λ³΄μμ΅λλ€. μ° νμ΄μ§λ₯Ό ν΅ν΄ μ¬μ©μκ° μ°ν μν λͺ©λ‘μ μμ½κ² νμΈν μ μκ³ , μν κ²μ κΈ°λ₯μμλ TMDB APIλ₯Ό νμ©ν΄ μ¬μ©μκ° μνλ μνλ₯Ό κ²μνκ³ , νν°λ§ν μ μλλ‘ νμ΅λλ€.