[React] Day06 - Zustand Todo Filter 구현하기

곽숭아·2026년 3월 9일

기록일기장📗

목록 보기
8/10
post-thumbnail

🔥오늘 목표🔥

단순한 Todo 리스트를 넘어, 실무에서 필수적인 상태 제어 기능을 구현해봄.

  • 상태별 필터링: 전체,완료,미완료 버튼을 누르면 목록이 실시간으로 바뀐다.
  • 실시간 통계: 현재 총 개수, 완료 개수, 남은 개수를 계산하여 보여준다.
  • 전역 상태 관리: Zustand를 사용해 모든 데이터를 한 곳(store)에서 관리하고, 여러 컴포넌트가 공유하도록 설계했다.

내가 마주친 벽 : "왜 이렇게 어렵게 해야하나?"

오늘 공부하면서 가장 큰 의문과 답답함이 밀려왔던 포인트는 두가지

막혔던 포인트 1: "왜 App.jsx에 다 안적고 파일을 쪼갤까?"
  • 고민: 한 파일에 다적으면 한눈에 보이고 편한데, 왜 굳이 폴더를 만들어서 일을 어렵게 만드는지 궁금했음.
  • 해결: '관심사 분리'라는 개념을 배움. App은 전체 배치만 하고, 일꾼(components)들에게 일을 시키는 구조여야 나중에 고장이 났을 때 범인을 찾기 쉽다는걸 깨달음.(공장과 단톡방 비유로 이해 완!)
막혔던 포인트 2: "필터 버튼을 눌러도 화면이 안변한다!"
  • 실수: 수첩(store)의 필터 값은 바꾸고 있었지만, 화면을 그리는 TodoList.jsx에서는 여전히 원본목록(todos)만 보고 있었음.
  • 해결: 데이터는 바뀌고 있었지만, 화면을 그리는 도구가 엉뚱한 곳을 보고 있었다는걸 알게됨.

🛠️코드 / 이유

1) 전역 상태 확장 (TodoStore.js)
가장 먼저 공유 수첩(Store)에 새로운 기준을 추가함.

const useTodoStore = create((set) => ({
  todos: [], 
  filter: "all", // 1. 기준값 추가 (전체, 미완료, 완료)
  
  // ... (생략)
  
  setFilter: (filter) => set({ filter }), // 2. 기준값을 바꾸는 리모컨 추가
}));
  • 이유: 지금 화면에 "무엇을 보여줄지" 결정하는 기준이 필요하기 때문
  • 작동: 사용자가 버튼을 누르면 단톡방에 "지금부터 미완료만 보자!"라고 공지를 띄우는 것과 같다.

2) 필터 버튼 컴포넌트 (TodoFilter.jsx)
사용자의 명령을 받는 스위치를 만들었음.

function TodoFilter() {
  const { filter, setFilter } = useTodoStore(); // 수첩에서 리모컨 가져오기

  return (
    <div>
      <button onClick={() => setFilter("all")}>전체</button>
      <button onClick={() => setFilter("active")}>미완료</button>
      <button onClick={() => setFilter("completed")}>완료</button>
    </div>
  );
}
  • 이유: 버튼을 클릭이라는 역할만 따로 떼어내어 관리하기 위함임.(관심사 분리)

3) 필터링 로직 구현(TodoList.jsx)
오늘의 가장 중요한 하이라이트

const { todos, filter } = useTodoStore(); // 수첩에서 데이터 가져오기

// 중요! 원본은 건드리지 않고 '보여줄 목록'만 새로 만듭니다 (파생 상태)
const filteredTodos = todos.filter((todo) => {
  if (filter === "completed") return todo.completed; // 완료만 통과!
  if (filter === "active") return !todo.completed;  // 미완료만 통과!
  return true; // 전체보기
});

// 화면에는 거른 목록(filteredTodos)을 뿌려줍니다.
{filteredTodos.map((todo, index) => ( ... ))}
  • 이유: 원본 창고(todos)를 뒤섞지 않고, 출력할 때만 실시간 장바구니(filteredTodos)를 만들어 화면을 갈아 끼우기 위해서임.

깨달은 핵심 개념

이번 프로젝트를 통해 머릿속에 확실히 박힌 3단계 흐름이다.

  1. 입력(App): useState로 잠깐 들고 있다가 단톡방에 전달.
  2. 보관(Store): Zustand라는 큰 수첩에 저장하고 공지사항 업데이트.
  3. 출력(Components): 수첩을 보고 있던 일꾼들이 자기 스타일대로 요리해서 화면에 출력.

결과물


🐙 GitHub Repository
👉 https://github.com/wjdtor2-design/Frontend-portfolio
📝 Velog Study Log

profile
곽숭아_놀이터

0개의 댓글