mini project - 영화 페이지 만들기 (1단계)
오~ 리액트 왜 머리 빠진다는지 진심 이해했고 ~ ...
하지만 프로젝트 만큼 날 채찍질 하는건 없어. .
괴롭지만 도움은 킹왕짱 됩니다.. 💗
아직... 디자인이 전혀 없는.. 조금 웃긴.. (ㅋㅋ..,...ㅋㅋㅋ)
기능 구현에 우선. 초점을 뒀습니다 :>
얼른 프로젝트 마무리 하고,, 수정 하기....
1단계는
리액트, 상태관리는 useState, css는 tailwilnd를 사용하여 구현 했습니다.
👏🏻 알게된 점.
1. 더미데이터를 받았는데,
이 json파일은 export할 때 따로 export를 쓰지 않아도 되었다.
2. 리액트 라우터를 사용하려고 보니까,
main.jsx 부분에서, strictMode.. 누구세요 ?
<StrictMode>
<App />
</StrictMode>,
//이렇게 감싸져있는데, 이 스트릭모드가 뭐야 ?
→🔒 <StrictMode>는 개발 중에 더 안전하고 미래에 잘 작동하는 React 앱을 만들도록 도와주는 디버깅 도구예요.
사용자한테는 보이지 않아요.
라우터는 이렇게 감싸면 됩니다 :)
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>
3. route와, link의 차이가 어려웠다.
근데 직접 코드를 작성해보니, 조금은 이해가 갔음
정리하자면:
- **Route**는 "어떤 경로에서 어떤 컴포넌트를 보여줄 것인가?"를 설정하는 곳.
- **Link**는 "이 링크를 클릭하면 그 경로로 이동할 수 있다"는 걸 만드는 곳.
route는 이 경로에선 이 페이지 보여줄게. 페이지 설정
링크는 경로를 이동해주는 걸 만드는 것!
4. 데이터를 리액트(React) 컴포넌트나 자바스크립트 객체로 사용하고 싶다면 ?
JSON 객체에서 필요한 값들을 **구조 분해 할당(destructuring)**이나 **점 표기법(dot notation)**을 사용해서 추출하면 됌
* 구조분해 없이
<p>{data.title}</p>
<p>{data.description}</p>
*구조분해 할당 후
const { title, description } = data;
<p>{title}</p>
<p>{description}</p>
자주 쓰는 값들을 구조분해로 꺼내두면, 반복되는 data.를 줄일 수 있고 실수도 줄일 수 있다 ~
5. Router 쓸 때, <Route path="details/:id" element={<MovieDetail/>} 이렇게 details/ 뒤에 :id를 붙이는 이유 ?
→ <Route path="details/:id" element={<MovieDetail />} 처럼 :id를 붙이는 이유는
동적 URL 파라미터를 사용하기 위해서.
📌 간단히 설명하면:
details/:id에서 :id는 **변하는 값(동적인 값)**을 의미해요.
예를 들어 아래와 같은 주소들이 있을 수 있어요:
- /details/1
- /details/42
- /details/abc
이 각각의 URL에서 :id 자리에 1, 42, abc 같은 실제 값이 들어가게 돼요.
💡 왜 필요할까요?
이렇게 하면 **하나의 컴포넌트(MoveDetail)**를 재사용해서,
다른 영화의 상세 정보를 불러올 수 있어요.
예시:
<Route path="details/:id" element={<MovieDetail />} />
그리고 MovieDetail 컴포넌트 안에서는 useParams() 훅을 써서 id 값을 가져와요:
import { useParams } from 'react-router-dom';
function MovieDetail() {
const { id } = useParams();
// 이 id로 fetch 하거나, 영화 정보 가져오기 등 가능
return <div>Movie ID: {id}</div>;
}
정리
- :id는 URL 안에서 변하는 값을 의미함
- 여러 개의 상세 페이지를 한 컴포넌트로 처리할 수 있음
- useParams()로 그 값을 꺼내서 사용 가능함
6. Router에서 index와 path의 차이 ??
항목 | index | path |
의미 | 기본 경로 (부모 경로의 루트) | 명시적인 하위 경로 |
작성 방식 | <Route index element={...} /> | <Route path="about" element={...} /> |
사용 시점 | 중첩 라우트에서 기본 콘텐츠로 보여줄 때 | 명확한 경로(/about, /contact 등)에 사용할 때 |
결과 경로 | 부모 경로 그대로 사용됨 (/) | 부모 경로 + 하위 경로 (/about) |
요약
- index는 기본 페이지 (예: 홈 화면) 용도로.
- path는 명확한 경로가 있는 페이지 용도로.
7. a태그대신 리액트 라우터 사용 하는 이유. 조교님 기습 질문 ~ 🙋
리액트에서 <a> 태그 대신 React Router의 <Link> 컴포넌트를 사용하는 주된 이유는 페이지를 새로 고치지 않고 클라이언트 사이드에서 라우팅하기 위해서입니다.
1. 페이지 새로 고침 없이 이동 (SPA 방식)
- <a href="/about">를 쓰면 브라우저는 전체 페이지를 새로 로드함.
- 반면 <Link to="/about">를 쓰면 React가 내부적으로 컴포넌트만 바꿔줌.
- 덕분에 앱이 더 빠르고, 부드러운 사용자 경험을 제공함.
2. 상태 유지
- 새로 고침이 없으니, 페이지 간 이동 시에도 **앱 상태(state)**가 유지됨.
- 예: 로그인 상태, 폼에 입력한 값 등 유지됨.
3. React Router의 기능 활용
- <Link>나 useNavigate()를 통해 조건부 이동, 동적 경로, 기록(history) 조작 등 다양한 기능 사용 가능.
4. 접근성과 SEO
- <Link>는 실제로는 <a>로 렌더링되기 때문에 기본적인 **접근성(키보드 탐색 등)**과 SEO도 유지됨.
❌ 안 좋은 방식 (전체 새로고침 발생)
<a href="/about">About</a>
✅ 좋은 방식 (React Router 사용)
import { Link } from 'react-router-dom';
<Link to="/about">About</Link>
7. / 을 app으로 했더니. 무한 렌더링? 이 부분은 좀 더 공부가 필요하다.
Jane, 네 코드를 보면 App 컴포넌트 안에서 또 <Route path='/' element={<App />}> 이렇게 자기 자신을 렌더링하고 있어요. 이건 무한 루프를 만들 수 있어서 화면이 아예 안 뜨거나 이상하게 작동할 수 있어요.
이게 문제의 핵심입니다.
🔧 해결 방법
<Route path='/' element={<App />}> 를 다른 컴포넌트로 바꿔야 해요. 예를 들어, 홈 페이지에 보여줄 내용을 담당하는 별도의 컴포넌트를 만들고 그걸 라우터에 연결하세요.
✅ 수정 방법 예시
// App.jsx
import { useState } from 'react'
import './App.css'
import MovieCard from './components/MovieCard.jsx'
import movieListData from './data/movieListData.json'
import NavBar from './components/NavBar.jsx'
import { Routes, Route } from 'react-router-dom';
import MovieDetail from './components/MovieDetail.jsx'
function Home({ movies }) {
return (
<main>
<div className="moviecard">
{movies.map((movie, id) => (
<MovieCard
key={id}
title={movie.title}
poster={movie.poster_path}
rating={movie.vote_average}
/>
))}
</div>
</main>
)
}
function App() {
const [movies, setMovies] = useState(movieListData.results)
return (
<>
<header>
<NavBar />
</header>
<Routes>
<Route path='/' element={<Home movies={movies} />} />
<Route path='/details' element={<MovieDetail />} />
</Routes>
</>
)
}
export default App
이렇게 하면 App 안에서 자신을 다시 부르지 않아서 무한 루프를 피할 수 있어요. 이제 화면이 제대로 뜰 거예요.
혹시 white screen만 나오고 있다면 index.jsx나 main.jsx에서 <BrowserRouter>로 감싸줬는지도 확인해볼까요?
✨하면서 놓쳤던 부분.
json파일은 객체였는데, 객체는 map을 돌릴 수 없다. [] 배열로 변환해주고 돌렸음
팁: JSON 구조 파악 방법
- API 응답을 받을 때 console.log(response)나 console.log(response.data)로 구조를 꼭 확인하세요.
- 구조가 중첩되어 있을 수 있기 때문에 response.result, response.data.result, response.data.movies 등 정확한 경로를 확인해야 합니다.
- 구조를 한 번 파악하면 이후 코드는 훨씬 쉬워집니다!
✓추가 적으로 공부 해야할 부분
1. 경로 작성하는 법
2. css.. (언제까지 미룰 순 없어 ~). 얼른 완성 다 하고 발전 시켜 봅시다.