Studying/미니 프로젝트

mini project - 영화 페이지 만들기 (1단계)

creamymood 2025. 5. 2. 16:38

정신이 좀 드니.. ?

 

오~ 리액트 왜 머리 빠진다는지 진심 이해했고 ~ ...

 

하지만 프로젝트 만큼 날 채찍질 하는건 없어. . 

괴롭지만 도움은 킹왕짱 됩니다.. 💗


 

아직... 디자인이 전혀 없는.. 조금 웃긴.. (ㅋㅋ..,...ㅋㅋㅋ)

기능 구현에 우선. 초점을 뒀습니다 :>

얼른 프로젝트 마무리 하고,, 수정 하기....


 

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.. (언제까지 미룰 순 없어 ~). 얼른 완성 다 하고 발전 시켜 봅시다.