[React] 20. TODO LIST 앱 / UI 구현

서회정's avatar
Mar 04, 2026
[React] 20. TODO LIST 앱 / UI 구현

 
TODO LIST 앱을 만들어보자.
먼저 UI를 설계하기 위해 완성본을 보며 구역을 나누어보자.
 
Header / Editor / List 컴포넌트로 나누어 만들 예정이다.
 
notion image
 

1. App 컴포넌트

 

1. 레이아웃 구성하기

 
완성된 이미지에서 보이는 대로 Header, Editor, List 컴포넌트를 만들어야 한다.
먼저 src경로 바로 아래에 components디렉토리를 만들고
각각의 컴포넌트를 만들어주자.
 
const Header = () => { return ( <div>Header</div> ); }; export default Header;
 
const Editor = () => { return ( <div>Editor</div> ); }; export default Editor;
 
const List = () => { return ( <div>List</div> ); }; export default List;
 
그러고 난 다음 App.jsx에서 불러와주자.
 
import Header from "./components/Header"; import Editor from "./components/Editor"; import List from "./components/List"; function App() { return ( <div> <Header /> <Editor /> <List /> </div> ); } export default App;
 
그럼 다음과 같이 각각의 컴포넌트가 정상적으로
렌더링 되고 있는 걸 확인할 수 있다.
 
notion image
 

2. 스타일 추가

 
완성된 이미지를 확인 해보면 각각의 컴포넌트 사이에
일정한 간격으로 마진이 있다.
 
이는 display: flex 속성과 gap을 사용해주자.
 
App.css 에서 스타일을 작성하고 App 컴포넌트에 직접 연결하자.
className을 App이름으로 할당하여 스타일을 주자.
 
.App { width: 500px; margin: 0 auto; display: flex; flex-direction: column; gap: 10px; }
 
import "./App.css"; import Header from "./components/Header"; import Editor from "./components/Editor"; import List from "./components/List"; function App() { return ( <div className="App"> <Header /> <Editor /> <List /> </div> ); } export default App;

2. Header UI

 

1. 레이아웃 구성하기

 
헤더는 다음과 같은 형태로 만들어져야한다.
 
notion image
 
오늘은이라는 문자열 아래에 보이는 날짜는
직접 입력하지 않고 Date 객체를 생성해서 넣어주자.
 
Date 객체를 만들 때 오류가 나지 않도록 toDateString()
메서드를 호출하여 완성본과 같은 형태가 되도록 하자.
 
const Header = () => { return ( <div> <h3>오늘은 📅</h3> <h1>{new Date().toDateString()}</h1> </div> ); }; export default Header;
 

2. 스타일 추가

 
마찬가지로 Header.css를 components 경로 아래에 만들고
스타일을 작성한 뒤 Header컴포넌트에 연결해주자.
 
Header에서는 날짜가 입력된 h1태그의 색상 변경이 필요하다.
Header 가장 상위 태그에 className을 할당하고 스타일을 입히자.
 
.Header > h1 { color: rgb(37, 147, 255); }
 
import "./Header.css"; const Header = () => { return ( <div className="Header"> <h3>오늘은 📅</h3> <h1>{new Date().toDateString()}</h1> </div> ); }; export default Header;
 

3. Editor UI

 

1. 레이아웃 구성하기

 
Editor 컴포넌트에서는 입력을 받을 inputbutton이 필요하다.
레이아웃을 구성하며 className도 미리 넣어놓자.
 
const Editor = () => { return ( <div className="Editor"> <input type="text" placeholder="새로운 TODO..." /> <button>추가</button> </div> ); }; export default Editor;
 

2. 스타일 추가

 
마찬가지로 Editor.css를 만들고 그 안에 스타일을 작성하자.
 
.Editor { display: flex; gap: 10px; } .Editor > input { flex: 1; padding: 15px; border: 1px solid rgb(220, 220, 220); border-radius: 5px; } .Editor > button { cursor: pointer; width: 80px; border: none; background-color: rgb(37, 147, 255); color: #ffffff; border-radius: 5px; }
 

4. List UI

 

1. 반복되는 UI 제외, 레이아웃 구성하기

 
List 컴포넌트는 크게 제목, 검색창, 투두리스트
이렇게 세 가지 영역으로 나눌 수 있다.
 
그 중에서도 두투리스트가 있는 부분은 똑같은 UI가
반복된 형태이기때문에 이는 다시 컴포넌트로 묶어 렌더링하는 것이 좋다.
 
그래서 일단은 두투리스트를 제외한
제목과 검색창부터 UI를 그려보자.
 
import "./List.css"; const List = () => { return ( <div className="List"> <h3>Todo List ☘️</h3> <input type="search" placeholder="검색어를 입력하세요" /> </div> ); }; export default List;
 

2. 반복되는 UI 제외, 스타일 추가

 
.List > input { width: 100%; border: none; border-bottom: 1px solid rgb(220, 220, 220); padding: 15px 0; } .List > input:focus { outline: none; border-bottom: 1px solid rgb(37, 147, 255); }
 

3. TodoItem 컴포넌트 만들기

 
const TodoItem = () => { return ( <div>아이템</div> ); }; export default TodoItem;
 
import "./List.css"; import TodoItem from "./TodoItem"; const List = () => { return ( <div className="List"> <h3>Todo List ☘️</h3> <input type="search" placeholder="검색어를 입력하세요" /> <div> <TodoItem /> <TodoItem /> <TodoItem /> </div> </div> ); }; export default List;
 
화면에 렌더링 되는 것까지 확인!
 
notion image
 

4. TodoItem 레이아웃 구성하기

 
const TodoItem = () => { return ( <div> <input type="checkbox" /> <p className="content">할 일 1</p> <p className="date">Date</p> <button>삭제</button> </div> ); }; export default TodoItem;
 
notion image
 

5. TodoItem 스타일 추가

 
.TodoItem { display: flex; align-items: center; gap: 20px; border-bottom: 1px solid rgb(220, 220, 220); } .TodoItem > input { width: 20px; } .TodoItem > .content { flex: 1; } .TodoItem > .date { font-size: 14px; color: #555; } .TodoItem > button { cursor: pointer; color: #555; font-size: 14px; border: none; border-radius: 5px; padding: 5px; }
 
완성!
 
notion image
Share article

clubnerdy