React Todo 앱 설계하기 - 컴포넌트 트리와 상태 위치 결정
지금까지 배운 개념들을 실전 프로젝트에 적용해볼 차례다. Todo 앱을 만들기 전에 요구사항 정의, 컴포넌트 트리 설계, 그리고 상태를 어디에 둘지 미리 계획하는 과정을 정리한다.
요구사항 정의하기
| 기능 | 설명 |
|---|---|
| 추가 | 입력창에 할 일을 적고 등록하면 목록에 새 항목이 추가된다 |
| 완료 체크 | 항목의 checkbox를 클릭하면 완료 상태로 표시된다 (취소선 등) |
| 삭제 | 항목의 삭제 버튼을 클릭하면 목록에서 사라진다 |
컴포넌트 트리 설계하기
App
├─ TodoForm (할 일을 입력하고 추가하는 부분)
└─ TodoList (전체 목록을 보여주는 부분)
└─ TodoItem (목록 안의 항목 하나하나, 완료 체크·삭제 버튼 포함)| 컴포넌트 | 역할 |
|---|---|
| App | 전체 todos 데이터를 가지고 있는 최상위 컴포넌트 |
| TodoForm | 새 할 일을 입력받아 App에 추가를 요청하는 컴포넌트 |
| TodoList | todos 배열을 map()으로 순회하며 TodoItem을 렌더링하는 컴포넌트 |
| TodoItem | 할 일 하나의 텍스트, 완료 체크박스, 삭제 버튼을 보여주는 컴포넌트 |
state는 어디에 둘 것인가
TodoForm은 입력창의 값을, TodoList는 전체 목록을, TodoItem은 완료 여부를 다뤄야 한다. 그런데 실제로 "할 일 목록(todos) 자체"는 어느 한 컴포넌트만의 것이 아니라, TodoForm(추가), TodoList(표시), TodoItem(삭제·완료 체크)이 전부 함께 다뤄야 하는 데이터다.
이럴 때는 여러 컴포넌트가 공통으로 접근해야 하는 state를, 그 컴포넌트들을 모두 감싸고 있는 가장 가까운 부모 컴포넌트에 둔다. 이 방식을 상태 끌어올리기(Lifting State Up)라고 부른다.
todos를 왜 TodoList가 아니라 App에 둘까? TodoForm은 TodoList의 자식이 아니라 형제 컴포넌트다. 만약 todos를 TodoList 안에 두면, TodoForm에서 새 할 일을 추가하고 싶어도 TodoList의 state에는 접근할 방법이 없다. 두 컴포넌트가 함께 다뤄야 하는 데이터는, 둘을 동시에 감싸고 있는 공통 부모(App)로 끌어올려야 양쪽 모두에게 props로 내려줄 수 있다.
Todo 데이터 구조 설계하기
todos는 할 일 객체들을 담은 배열로 만든다. 각 할 일 객체는 아래 세 가지 값을 가진다.
| 필드 | 타입 | 의미 |
|---|---|---|
| id | 숫자 | 각 할 일을 구분하는 고유 값 (key로 사용) |
| text | 문자열 | 할 일 내용 |
| completed | boolean | 완료 여부 |
const todos = [
{ id: 1, text: "React 공부하기", completed: false },
{ id: 2, text: "장보기", completed: true },
{ id: 3, text: "운동하기", completed: false },
];
실습 정리
실습 1) 요구사항 정리해보기 — 추가/완료 체크/삭제 외에, 나만의 Todo 앱에 추가하고 싶은 기능을 한 가지 적어본다.
실습 2) 컴포넌트 트리 직접 그려보기 — App → TodoForm, TodoList → TodoItem 트리를 직접 그리고, 각 컴포넌트가 하는 일을 한 줄씩 적어본다.
실습 3) Todo 데이터 구조 설계하고 초기 데이터 작성하기
import { useState } from "react";
function App() {
const [todos, setTodos] = useState([
{ id: 1, text: "React 공부하기", completed: false },
{ id: 2, text: "장보기", completed: true },
{ id: 3, text: "운동하기", completed: false },
]);
return (
<div>
<h1>Todo 리스트</h1>
{/* TodoForm, TodoList 구현 예정 */}
</div>
);
}
export default App;
마무리
- 실전 프로젝트는 코드를 바로 작성하기보다 요구사항 정의 → 컴포넌트 트리 설계 → state 위치 결정 → 데이터 구조 설계 순서로 계획을 먼저 세우는 게 중요하다.
- 여러 컴포넌트가 공유해야 하는 데이터는 그 컴포넌트들의 가장 가까운 공통 부모로 상태를 끌어올린다(Lifting State Up)는 원칙을 기억하자.
- Todo 데이터는
id(구분용),text(내용),completed(완료 여부) 세 필드를 가진 객체 배열로 설계하면, 이후map()으로 렌더링하거나id기준으로 삭제/수정하기 편하다.
'FullStack FrontEnd' 카테고리의 다른 글
| React Todo 앱 - 추가 기능 구현 (콜백 패턴, 불변성) (0) | 2026.09.18 |
|---|---|
| React Todo 앱 - 컴포넌트 분리하기 (0) | 2026.09.17 |
| React 폼 다루기 - Controlled Component 정리 (0) | 2026.09.17 |
| React useEffect 기초 정리 - 컴포넌트 생명주기, 의존성 배열 (0) | 2026.09.17 |
| React 리스트 렌더링 정리 - map()과 key (0) | 2026.09.16 |