파진기와 함께 코딩을
GDGoC 프론트엔드 과제 #2 - state 본문
이 기능은 사용자가 각 영화 카드에서 "봤어요 👀" 버튼을 클릭하면,
해당 영화의 id를 watched 상태(state)에 저장하고,
상단의 "본 영화만 보기" 토글 버튼을 사용하면
watched 상태에 포함된 영화만 필터링해서 보여주는 기능입니다.
사용된 React 개념
✔ 1. useState를 이용한 상태 관리
- watched: 내가 본 영화들의 id를 저장하는 배열.
- showWatched: "본 영화만 보기" 모드인지 여부(true/false)를 저장하는 boolean.
✔ 2. 부모(App.jsx) → 자식(MovieList → MovieCard) Props 전달
상태는 최상위(App.jsx)에서 관리하며
필요한 하위 컴포넌트로 props를 내려서 사용자가 클릭한 행동에 따라 데이터를 업데이트합니다.
✔ 3. 조건부 렌더링(Conditional Rendering)
showWatched가 true일 경우
movies 배열을 필터링하여 내가 본 영화만 보여줍니다.
✔ 4. 배열 조작
- includes(): 영화가 watched 배열에 포함되어 있는지 확인
- filter(): watched에서 제거하거나, movies에서 필요한 영화만 골라내기
- ...spread: 새 배열 만들기
코드 흐름 설명 (전체 동작 흐름)
사용자 클릭 → toggleWatched 실행 → watched 업데이트 → showWatched가 true면 필터링된 목록만 MovieList로 전달 → MovieCard에서 watched 포함 여부 표시
App.jsx 상세 설명
✔ ① watched 상태
const [watched, setWatched] = useState([]);
- 내가 본 영화의 id를 저장하는 배열
- 빈 배열로 시작
- 예: [1, 3, 5] 이런 형태로 저장됨
✔ ② showWatched 상태
const [showWatched, setShowWatched] = useState(false);
- true면 “본 영화만 보기” 모드
- false면 전체 영화 보기
✔ ③ watched 토글 함수
const toggleWatched = (id) => { if (watched.includes(id)) { setWatched(watched.filter(m => m !== id)); } else { setWatched([...watched, id]); } };
동작 방식:
- 이미 본 영화라면 배열에서 제거
- 처음 누르는 영화라면 배열에 추가
즉, 토글 방식(toggle)
✔ ④ 필터링된 영화 목록 생성
const filteredMovies = showWatched ? movies.filter(m => watched.includes(m.id)) : movies;
- showWatched가 true일 때는
watched에 포함된 영화만 추려서 MovieList로 전달 - false일 때는 전체 목록 전달
→ 이렇게 해서 "본 영화만 보기" 기능이 작동함
✔ ⑤ MovieList로 props 전달
<MovieList movies={filteredMovies} watched={watched} toggleWatched={toggleWatched} />
- MovieList는 movies뿐 아니라
watched, toggleWatched 모두 전달받음
→ 자식 컴포넌트에서 액션을 수행할 수 있도록 함
MovieList.jsx 설명
<MovieCard key={movie.id} movie={movie} watched={watched} toggleWatched={toggleWatched} />
- MovieList는 단순히 반복 렌더링 역할을 수행
- props로 받은 movies 배열을 map으로 돌려
각 MovieCard에 movie 정보를 전달하고
watched 상태와 toggle 함수를 그대로 전달해줌 (중간 전달자 역할)
→ 데이터를 직접 변경하지 않고, 전달만 하는 역할
MovieCard.jsx 설명
✔ ① movie 정보 구조 분해
const { id, title, posterUrl, rating, genre } = movie;
✔ ② watched 배열에 포함되었는지 체크
const isWatched = watched.includes(id);
- 현재 카드의 영화 id가 watched 배열 안에 있는지 확인
- 있으면 이미 본 영화
- 없으면 아직 안 본 영화
✔ ③ 버튼 UI 변경 + 클릭 이벤트
<button onClick={() => toggleWatched(id)}> {isWatched ? "✔️ 이미 봤음" : "👀 봤어요"} </button>
- isWatched 값(true/false)에 따라 버튼 텍스트가 달라짐
- 클릭하면 부모(App)의 toggleWatched를 호출하여 watched 상태 업데이트
사용자가 보게 되는 실제 UX
✔ 처음에는 모든 영화 카드에
“👀 봤어요” 버튼이 표시됨
✔ 사용자가 누르면
→ 버튼이 “✔️ 이미 봤음”으로 바뀜
→ watched 배열에 id 추가
✔ 상단 버튼 “본 영화만 보기” 클릭 시
→ showWatched = true
→ filter 실행
→ watched에 포함된 영화만 화면에 렌더링됨
✔ “전체 영화 보기” 클릭 시
→ showWatched = false
→ 다시 전체 목록 렌더링