카운터앱 만들기
카운터앱 만들기
1. 프로젝트 준비하기
- 요구사항 분석하기
- 컴포넌트 단위로 생각하기
- App 컴포넌트 : Viewer, Controller 컴포넌트를 감싸는 템플릿
- Viewer 컴포넌트 : 현재의 컴포넌트 표시
- Controller 컴포넌트 : 카운트를 제어할 수 있는 기능을 제공
컴포넌트 단위로 쪼개는 이유
1
2
3
| 하나의 페이지를 하나의 컴포넌트로 구성해도 문제는 없으나, 하나의 컴포넌트가 여러 기능을 갖게되면 코드가 복잡해져 관리가 어려워짐.
따라서 컴포넌트는 재사용이 가능한 수준에서 최대한 잘게 쪼개어 개발하는 것이 필요.
__하나의 컴포넌트는 단 하나의 역할만 수행한다.__
|
- 리액트 앱 만들기
https://hyoreal.github.io/posts/React-React.js-%EA%B0%9C%EB%A1%A0/\
https://hyoreal.github.io/posts/React-React.js-%EC%9E%85%EB%AC%B8%ED%95%98%EA%B8%B0/
2. UI 구현하기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| // App.jsx
import "./App.css";
import Viewer from "./components/Viewer";
import Controller from "./components/Controller";
function App() {
// 컴포넌트마다 백그라운드 및 여백 설정 위해 section으로 묶어줌
return (
<div className="App">
<h1>Simple Counter</h1>
<section>
<Viewer />
</section>
<section>
<Controller />
</section>
</div>
);
}
export default App;
|
1
2
3
4
5
6
7
8
9
10
11
12
| // Viewer.jsx
const Viewer = () => {
return (
<div>
<div>현재 카운트: </div>
<h1>0</h1>
</div>
);
};
export default Viewer;
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| // Controller.jsx
const Controller = () => {
return (
<div>
<button>-1</button>
<button>-10</button>
<button>-100</button>
<button>+100</button>
<button>+10</button>
<button>+1</button>
</div>
);
};
export default Controller;
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| // App.css
body {
padding: 20px;
}
.App {
margin: 0 auto;
width: 500px;
}
.App > section {
background-color: rgb(245, 245, 245);
border: 1px solid rgb(240, 240, 240);
border-radius: 5px;
padding: 20px;
margin-bottom: 10px;
}
|
3. 기능 구현하기
- State를 이용해 카운터 기능 구현하기
- Controller 컴포넌트에 있는 버튼을 클릭하면 Viewer 컴포넌트에 있는 카운트가 증가하거나 감소해야한다.
- 위 목적을 갖고 State를 생성할 때, 어떤 컴포넌트에 생성해야할까?
Viewer 컴포넌트
1
2
| 오답. __Viewer 컴포넌트가 Controller 컴포넌트에 setCount를 전달할 방법이 없다.__
리액트에서 컴포넌트가 다른 컴포넌트에 데이터를 전달할 때는 Props를 사용하는데, Props는 부모만이 자식에게 전달할 수 있기 때문.
|
Controller 컴포넌트
1
2
| 오답. __Controller 컴포넌트가 Viewer 컴포넌트에 state릁 전달할 방법이 없다.__
리액트에서 컴포넌트가 다른 컴포넌트에 데이터를 전달할 때는 Props를 사용하는데, Props는 부모만이 자식에게 전달할 수 있기 때문.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| // App.jsx
import "./App.css";
import { useState } from "react";
import Viewer from "./components/Viewer";
import Controller from "./components/Controller";
function App() {
const [count, setCount] = useState(0);
const handleSetCount = (value) => {
setCount(count + value);
};
// 컴포넌트마다 백그라운드 및 여백 설정 위해 section으로 묶어줌
return (
<div className="App">
<h1>Simple Counter</h1>
<section>
<Viewer count={count} />
</section>
<section>
<Controller handleSetCount={handleSetCount} />
</section>
</div>
);
}
export default App;
|
1
2
3
4
5
6
7
8
9
10
11
12
| // Viewer.jsx
const Viewer = ({ count }) => {
return (
<div>
<div>현재 카운트: </div>
<h1>{count}</h1>
</div>
);
};
export default Viewer;
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| // Controller.jsx
const Controller = ({ handleSetCount }) => {
return (
<div>
<button onClick={() => handleSetCount(-1)}>-1</button>
<button onClick={() => handleSetCount(-10)}>-10</button>
<button onClick={() => handleSetCount(-100)}>-100</button>
<button onClick={() => handleSetCount(100)}>+100</button>
<button onClick={() => handleSetCount(10)}>+10</button>
<button onClick={() => handleSetCount(1)}>+1</button>
</div>
);
};
export default Controller;
|
- 카운트 기능을 구현한것처럼 state나 set함수를 여러 컴포넌트에서 사용하는 경우, 상위 컴포넌트에서 관리한다.
- 이를 State 끌어올리기(State Lifting) 이라고 한다.
- 리액트답게 설계하기
- 리액트에서 컴포넌트 간에 데이터를 전달할때는 Props를 사용하는데, 전달방향은 언제나 부모 -> 자식 방식이다. 이를 단방향 데이터 흐름 이라고 한다.
- 단, 이벤트는 자식 -> 부모 로 향하도록 설계해야한다.