첫 번째 프로젝트 카운터 앱에 이어서 두 번째 프로젝트로 할 일 관리 앱을 만들자.
이 프로젝트에서는 요구사항 분석, UI, 기능 구현의 흐름을 이해하는 것이 목표다.또한, CRUD 기능 구현이란 무엇인지 이해해 보자.
[ 요구사항 분석 ]
프로젝트1 카운터앱을 준비할 때와 마찬가지로 앱의 요구사항을 분석하고, 이를 토대로 필요한 기능을 하나씩 구현해 보자. 아래는 할 일 관리 앱을 최종적으로 구현한 모습이다.
이처럼 할 일 관리 앱에는 다음과 같은 기능이 있다!
이를 컴포넌트 단위로 나눠보자. UI 요소를 컴포넌트 단위로 생각하는 것이 중요 포인트다!
위의 그림을 기준으로 해서 UI 요소를 컴포넌트 단위로 나눠본다면 다음과 같다.
1. 문서 아래에 새로운 폴더 project2 만들기
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
import "./App.css";
function App() {
return <div className="App"></div>;
}
export default App;
5. 터미널을 열어 명령어 npm run start를 입력한다.
리액트 앱 실행의 준비가 완료되었다!
UI 구현을 흔히 퍼블리싱 또는 UI 개발이라고 한다. 데이터를 가공하고 상태를 관리하는 구현 기능과 더불어 프론트 엔지이어의 기본소양 중 하나!
우리가 다루고 있는 할 일 관리 어플에서의 UI의 구현 순서는 다음과 같다.
1. 페이지 레이아웃 만들기
2. Header 컴포넌트 만들기
3. TodoEditor 컴포넌트 만들기
4. TodoList, TodoItem 컴포넌트 만들기
코드를 저장한 뒤 개발자 도구에서 스타일링이 바르게 적용되었는지 렌더링 결과를 확인한다.
렌더링 오류가 발생한다면 파일명을 제대로 작성했는지, 스타일 파일을 바른 경로로 불러왔는지 확인하자!
데이터를 다루는 4가지 기능, 즉 추가 조회 수정 삭제,
Create Read Update Delete 기능의 앞글자를 따 CRUD라고 한다.
[ 기초 데이터 설정 ]
먼저 할 일 아이템부터 생성해 보자.
App.js를 다음과 같이 수정한다. 이때, 함수 useState는 리액트 훅의 일종으로, react 라이브러리에서 불려온다.
이때 State 변수 todo는 할 일 관리 앱에서 데이터를 저장하는 배열인 동시에 일종의 DB역할을 수행한다.
예를 들어, 사용자가 새 할 일 아이템을 만들면 빈 배열이었던 todo값은 아이템이 추가된 배열로 업데이트된다.
수정과 삭제에서도 동일하게 동작한다.
import { useState } from "react";
(..)
function App() {
const [todo, setTodo] = useState([]); ①
return (
(...)
);
}
export default App;
[데이터 모델링하기]
데이터 모델링은 현실의 사물이나 개념을 프로그래밍 언어의 객체와 같은 자료구조로 표현하는 행위를 말한다.
데이터 모델링은 왜 필요할까? 현실 세계의 사물이나 개념을 프로그래밍 언어로 표현하고 다뤄야하기 때문이다. 음 그렇겠지
데이터 모델링의 완성도를 높여야 프로젝트의 시간이나 비용 측면에서 효율적이다.
모델링한 정보를 토대로 할 일 아이템을 자바스크립트 객체로 만들면 다음과 같다!
{
id: 0, ①
isDone: false, ②
content: "React 공부하기", ③
createdDate: new Date().getTime(), ④
}
1. id는 특정 아이템을 식별하는고유한 값!
2. isDone은 불리언 자료형으로, 현재 상황에서 할 일이 완료되었는지 여부를 확인할 때 이용한다.
3. content는 할 일이 무엇인지 알려주는 문자열
4. createDate는 할 일의 생성 시간으로, new Date()로 Date 객체를 만들고 getTime 메서드를 이용해 이 객체를 타임 스탬프값으로 변환한다.
[목 데이터 설정하기]
Mock Data는 모조품 데이터라는 의미!
기능을 완벽히 구현하지 않은 상태에서 테스트를 목적으로 사용하는 임시 데이터.
기능을 아직 개발하지 않아 데이터가 없는 상황일 때 목 데이터를 사용한다.
App.js에서 목 데이터를 다음과 같이 작성하자.
(...)
const mockTodo = [ ①
{
id: 0,
isDone: false,
content: "React 공부하기",
createdDate: new Date().getTime(),
},
{
id: 1,
isDone: false,
content: "빨래 널기",
createdDate: new Date().getTime(),
},
{
id: 2,
isDone: false,
content: "노래 연습하기",
createdDate: new Date().getTime(),
},
];b
function App() {
const [todo, setTodo] = useState(mockTodo); ②
b
return (
(...)
);
}
export default App;
CRUD의 첫 번째 기능인 Create를 구현해 보자!
[ 기능 흐름 살펴보기 ]
1. 사용자가 새로운 할 일을 입력한다.
2. TodoEditor 컴포넌트에 있는 추가 버튼을 클릭한다.
3. TodoEditor 컴포넌트가 부모인 App에게 아이템 추가 이벤트가 발생했음을 알리고, 사용자가 추가한 할 일 데이터를 전달한다.
4. App 컴포넌트가 TodoEditor 컴포넌트에서 받은 데이터를 이용해 새 아이템을 추가한 배열을 만들고 State 변수 todo 값을 업테이트한다.5. TodoEditor 컴포넌트가 자연스러운 UX를 위해 할 일 입력 폼을 초기화한다!
[ 아이템 추가 함수 만들기 ]
1. App.js에서, App 컴포넌트에 새 할 일 아이템을 추가하는 함수 onCreate를 만든다.
(...)
function App() {
const [todo, setTodo] = useState(mockTodo);
const onCreate = (content) => { ①
const newItem = {
id: 0,
content,
isDone: false,
createdDate: new Date().getTime(),
};
setTodo([newItem, ...todo]); ②
};
return (
(...)
);
}
export default App;
하지만 이때 모든 아이템이 고유한 id를 가지고 있어야 하는데, onCreate에서는 새롭게 추가할 아이템의 id가 모두 0으로 고정되는 문제가 발생한다. 이 문제를 Ref 객체 생성으로 해결할 수 있다!
2. Ref 객체를 생성한다. Ref 객체는 리액트 훅인 함수 useRef로 생성한다. Ref 객체는 주로 돔을 조작할 때 사용하나 컴포넌트의 변수로도 자주 활용된다.
(...)
function App() {
(...)
const idRef = useRef(3);
const onCreate = (content) => {
const newItem = {
id: idRef.current, ①
content,
isDone: false,
createdDate: new Date().getTime(),
};
setTodo([newItem, ...todo]);
idRef.current += 1; ②
};
return (
(...)
);
}
export default App;
[ 아이템 추가 함수 호출하기 ]
전체적인 흐름
1. 사용자가 할 일 입력 폼에서 아이템을 입력하고 추가 버튼을 클릭한다.
2. TodoEditor 컴포넌트가 새 할 일을 생성하기 위해 App에서 Props로 받은 함수 onCreate를 호출하고 현재 사용자가 작성한 할 일을 인수로 전달한다.
여기서 함수 onCreate를 사용하고, 사용자가 입력하는 새 할 일 데이터를 저장하기 위해 TodoEditor 컴포넌트를 수정해 보자. Props 객체를 구조 분해 할당하고, 새 할 일 데이터를 저장하는 State를 만든다.
입력 폼의 onChange 이벤트 핸들러로 onChangeContent를 만들고, 입력폼의 value 속성으로 content값을 설정해 이벤트 핸들러로 onChangeContent를 설정한다.
import { useState } from "react";
import "./TodoEditor.css";
const TodoEditor = ({ onCreate }) => {
const [content, setContent] = useState(""); ①
const onChangeContent = (e) => { ②
setContent(e.target.value);
};
return (
<div className="TodoEditor">
<h4>새로운 Todo 작성하기 ✏ </h4>
<div className="editor_wrapper">
<input ③
value={content}
onChange={onChangeContent}
placeholder="새로운 Todo..."
/>
<button>추가</button>
</div>
</div>
);
};
export default TodoEditor;
코드 확인은 개발자 도구로 진행한다. 아직 App 컴포넌트의 todo 값을 페이지에 렌더링하는 Read 기능이 개발되지 않았기 때문에, 추가되는 데이터는 개발자 도구의 Components 탭에서 직접 확인해야 한다.
또한, 더 자연스럽고 편리한 사용자 경험을 위해 고급 기능을 추가할 수도 있다.
빈 입력 방지하기, 아이템 추가 후 입력 폼 초기화하기, 엔터키를 눌러 아이템 추가하기
!!! QUIZ !!!
1. 요구사항 분석 시, 요소를 _ _ _ _ 단위로 나누어야 한다.
2. UI 개발을 흔히 _ _ _ _이라고 한다. (단어에 UI가 들어가지 않는 4글자)
3. 적용된 스타일링과 요소의 배치 상황을 확인하려면 _ _ _ _ _를 사용한다.
4. CRUD는 Create Read Use Delete의 약어이다. (O/X).
5. 현실의 사물이나 개념을 프로그래밍 언어의 객체와 같은 자료구조로 표현하는 행위를 _ _ _ _ _ _이라고 한다.
6. 함수 onCreate의 id중복 문제를 해결하기 위해 사용되는 객체의 이름은 _ _ _이다.
7. 3번째로 등록된 할 일의 내용은 "푸지게 낮잠자기"이고 아직 처리되지 않았다. 이 할 일의 Mock 데이터를 생성해보자. 이때, 할 일의 생성 시간은 타임 스탬프값으로 저장된다. (중괄호 안에 필요한 정보 4줄만 작성, id는 0부터 시작)
!!! 정답 !!!
1. 컴포넌트
2. 퍼블리싱
3. 개발자도구
4. X, Create Read Update Delete이다.
5. 데이터 모델링
6. Ref
7.
{
id: 2,
isDone: false,
content: "푸지게 낮잠자기",
createdDate: new Date().getTime(),
}
출처: 이정환, 『한 입 크기로 잘라먹는 리액트』, 프로그래밍인사이트(2023), https://reactjs.winterlood.com/.
Corner React.js 2
Editor: Borybop
[React.js 2팀] 8장. Hooks (0) | 2024.11.29 |
---|---|
[React.js 2팀] project 1 [카운터] 앱 만들기 ~ 6장. 라이프 사이클과 리액트 개발자 도구 (0) | 2024.11.22 |
[React.js 2팀] 5장. 리액트의 기본 기능 다루기 (2) (1) | 2024.11.15 |
[React.js 2팀] 5장. 리액트의 기본 기능 다루기 (1) (0) | 2024.11.08 |
[React.js 2팀] 3장. Node.js ~ 4장. 리액트 시작하기 (10) | 2024.10.11 |