diff --git a/src/App.css b/src/App.css
index 7d5209f2..f326baa1 100644
--- a/src/App.css
+++ b/src/App.css
@@ -1,7 +1,7 @@
body {
background-color: #e2e8f0;
margin: 0;
- font-family: "Noto Sans KR", sans-serif;
+ font-family: "Pretendard", "Noto Sans KR", sans-serif;
}
.App {
@@ -10,7 +10,7 @@ body {
}
.page-title {
- font-size: 24px;
+ font-size: 30px;
font-weight: bold;
color: #8c02e2;
margin-bottom: 20px;
@@ -24,14 +24,15 @@ body {
}
.movie-card {
- width: 120px;
- background-color: #308cca;
+ height: auto;
+ width: 150px;
+ background-color: #9c47e7;
color: white;
- border-radius: 6px;
+ border-radius: 10px;
display: flex;
flex-direction: column;
align-items: center;
- padding-bottom: 10px;
+ padding-bottom: 15px;
transition: transform 0.2s ease;
}
@@ -39,16 +40,6 @@ body {
transform: scale(1.05);
}
-.poster-box {
- width: 100%;
- height: 160px;
- background-color: #1b6ca8;
- display: flex;
- align-items: center;
- justify-content: center;
- overflow: hidden;
-}
-
.poster-box img {
width: 100%;
height: 100%;
diff --git a/src/App.jsx b/src/App.jsx
index cd8df10b..36fb532d 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -1,14 +1,18 @@
import "./App.css";
import React, { useState } from "react";
import MovieCard from "./component/MovieCard";
-import { Link } from "react-router-dom";
+import { Link, useSearchParams } from "react-router-dom";
import { useEffect } from "react";
function App() {
const [movies, setMovies] = useState([]);
+ const [loading, setLoading] = useState(false);
+ const [searchParams] = useSearchParams();
+ const query = searchParams.get("query");
useEffect(() => {
const fetchMovies = async () => {
+ setLoading(true);
try {
const options = {
method: "GET",
@@ -18,44 +22,62 @@ function App() {
},
};
- const response = await fetch(
- "https://api.themoviedb.org/3/discover/movie?include_adult=false&include_video=false&language=en-US&page=1&sort_by=popularity.desc",
- options
- );
+ let url = "";
+
+ if (query && query.trim() !== "") {
+ url = `https://api.themoviedb.org/3/search/movie?query=${encodeURIComponent(
+ query
+ )}&include_adult=false&language=en-US&page=1`;
+ } else {
+ url =
+ "https://api.themoviedb.org/3/discover/movie?include_adult=false&include_video=false&language=en-US&page=1&sort_by=popularity.desc";
+ }
+
+ const response = await fetch(url, options);
const data = await response.json();
- const filteredMovies = data.results.filter(
- (movie) => movie.adult === false
- );
+ const filteredMovies = data.results
+ ? data.results.filter((movie) => movie.adult === false)
+ : [];
setMovies(filteredMovies);
} catch (error) {
console.error("데이터 불러오는 중 오류가 발생했습니다", error);
+ } finally {
+ setLoading(false);
}
};
fetchMovies();
- }, []);
+ }, [query]);
return (
<>
MovieCard
-
- {movies.map((movie) => (
-
-
-
- ))}
-
+ {loading ? (
+
로딩중
+ ) : (
+
+ {movies.length > 0 ? (
+ movies.map((movie) => (
+
+
+
+ ))
+ ) : (
+
검색 결과가 없습니다.
+ )}
+
+ )}
>
);
diff --git a/src/component/MovieDetail.css b/src/component/MovieDetail.css
index 99754f5d..25dccefe 100644
--- a/src/component/MovieDetail.css
+++ b/src/component/MovieDetail.css
@@ -37,19 +37,20 @@
/* 상세 내용 영역 */
.detail-content {
display: flex;
- align-items: flex-start;
+ align-items: center;
justify-content: center;
- gap: 40px;
- padding: 40px;
background-color: #111;
- flex-wrap: wrap; /* ✅ 반응형 정렬 */
+ flex-wrap: wrap;
}
.poster-box img {
- width: 300px;
- height: auto;
+ width: 150px;
+ height: 250px;
border-radius: 10px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5);
+ margin: 10px;
+ justify-self: start;
+ align-items: flex-start;
}
.info-box {
diff --git a/src/component/NavBar.css b/src/component/NavBar.css
index 916c8bb1..1d777149 100644
--- a/src/component/NavBar.css
+++ b/src/component/NavBar.css
@@ -49,3 +49,12 @@
display: flex;
align-items: center;
}
+
+.logo-link {
+ text-decoration: none;
+ color: inherit;
+}
+
+.logo-link:hover {
+ opacity: 0.8;
+}
diff --git a/src/component/NavBar.jsx b/src/component/NavBar.jsx
index 1deaee6c..ec2a4bb3 100644
--- a/src/component/NavBar.jsx
+++ b/src/component/NavBar.jsx
@@ -1,11 +1,33 @@
-import { Link } from "react-router-dom";
+import { Link, useSearchParams } from "react-router-dom";
import "./NavBar.css";
+import { useState } from "react";
+import useDebounce from "../hooks/useDebounce";
+import { useEffect } from "react";
function NavBar() {
+ const [input, setInput] = useState("");
+ const [searchParams, setSearchParams] = useSearchParams();
+ const debouncedInput = useDebounce(input, 500);
+
+ useEffect(() => {
+ const q = searchParams.get("query") || "";
+ setInput(q);
+ }, []);
+
+ useEffect(() => {
+ if (debouncedInput && debouncedInput.trim() !== "") {
+ setSearchParams({ query: debouncedInput.trim() });
+ } else {
+ setSearchParams({});
+ }
+ }, [debouncedInput, setSearchParams]);
+
return (