구조 수정
1단계에서 만든 구조를 벗어나 관심사 분리를 위해 구조 재설계
- src/pages/ : 각 메뉴(인기, 상영 중 등)에 맞는 페이지 컴포넌트 배치
- src/components/ : 공통 레이아웃(Layout), 네비게이션(Navbar), 로딩 상태(LoadingsPinner) 등을 재사용 가능한 컴포넌트 단위로 분리
- src/api/ : Axios인스턴스 통해 API통신 모듈화
구현 내용
1. React Router 이용하여 멀티 페이지 구현
- 적용코드: src/main.tsx
- 흐름: 사용자가 상단에 있는 메뉴 클릭 > URL 변경 > Layout 컴포넌트 내부의 <Outlet /> 자리에 해당 페이지 컴포넌트가 동적으로 변함
const router = createBrowserRouter([
{
path: '/',
element: <Layout />, // 공통 레이아웃 적용
children: [
{ index: true, element: <HomePage /> }, // 주소가 '/' 일 때
{ path: 'movies/popular', element: <PopularPage /> },
{ path: 'movies/now-playing', element: <NowPlayingPage /> },
{ path: 'movies/:movieId', element: <MovieDetailPage /> },
{ path: 'movies/top-rated', element: <TopRatedPage /> },
{ path: 'movies/upcoming', element: <UpcomingPage /> },
],
},
]);
2. 로딩 및 에러 처리
- 상단 바 누른 후 데이터 로딩되는 동안 사용자에게 로딩하는 것을 알리기 위해 isLoading상태와 스피너 사용
- 적용코드: src/components/LoadingSpinner.tsx
- useEffect 내에서 API 호출 직전 setIsLoading(true)를 설정
const LoadingSpinner = () => {
return (
<div className="flex justify-center items-center min-h-[50vh]">
<div className="animate-spin rounded-full h-16 w-16 border-t-4 border-b-4 border-pink-500"></div>
</div>
);
};
export default LoadingSpinner;
3. 페이지네이션
- TMDB API의 page 파라미터 활용해서 대량의 데이터를 페이지 단위로 불러오도록 구현
const [page, setPage] = useState(1);
useEffect(() => {
const fetchMovies = async () => {
// API 요청 시 page 번호 전달
const response = await api.get(`/movie/popular?language=ko-KR&page=${page}`);
setMovies(response.data.results);
};
fetchMovies();
}, [page]); // page 상태가 바뀔 때마다 useEffect가 다시 실행
구현 화면

'Web' 카테고리의 다른 글
| 사용자 인증 Token : Access vs Refresh (0) | 2026.04.06 |
|---|---|
| 영화 웹사이트 - 3단계 ( 상세 페이지 구현 ) (0) | 2026.04.03 |
| 영화 웹사이트 - 1단계 (API 데이터 불러오기) (0) | 2026.04.03 |
| useEffect와 Axios를 이용한 영화 API 연동 실습 (0) | 2026.03.30 |
| useState vs useReducer (0) | 2026.03.27 |