React는 기존에 봐 왔던 HTML+CSS+Javascript와 조금 느낌이 다릅니다. 비전공자의 눈에서 React는 HTML +Javascript가 섞여서 조금 복잡하게 다가올 수 있습니다. 제가 그랬습니다. 그렇지만 포스팅을 읽으면서, 구글과 Stackoverflow의 도움을 받으면서 조금씩 해 나가다 보면 React에 익숙해지는 자신을 발견할 수 있게 됩니다. 특히 지금 진행하고 있는 프로젝트 자체가 프론트엔드 / 백엔드 모두를 다루기 때문에 풀스택 개발자를 잠시 맛볼 수도 있을 거라 생각합니다. 시작하겠습니다.
Component, Props, State
여기서는 MVP(Minimum Valuable Product) 개발을 가장 중요하게 생각하기에, React의 Virtual DOM같은 기술적인 개념은 굳이 설명하지 않겠습니다. 본격적으로 개발하기에 앞서, 우리는 Component, Props, State 이 세 가지 중요한 개념을 알아야 합니다.
Component | 프론트엔드 화면을 구성하는 요소를 Component라 합니다. 화면을 구성하는 요소를 잘게 쪼갬으로서 Component 라 명명합니다. 요소들을 Component로 만듦으로서 우리는 화면을 구성하는 요소를 재사용할 수 있다는 큰 이점을 가질 수 있습니다.
State | 화면에 표시되는 데이터를 의미합니다. State가 변경되면 화면이 렌더링되며 우리가 보는 화면에 변화가 일어납니다.
Props | Component를 작은 단위로 쪼개게 되면, 이 Component들은 반드시 부모-자식 관계를 가지게 되는데, 부모 Component에서 자식Component로 데이터가 이동할 때 이를 props라 부릅니다.
말로만 들어서는 설명하기 어렵습니다. 일단 바로 해 보겠습니다.
간단한 폼으로 Components, state 개념 파악하기
1. /client/src에 components 폴더를 만들고 FormTest.js파일을 만듭니다.
//client/src/App.js
import "./App.css";
import FormTest from "./components/FormTest";
function App() {
return (
<div className="App">
<FormTest />
</div>
);
}
export default App;
2. /client/src/App.js를 위와 같이 수정합니다.
//client/src/components/FormTest.js
import React, { useState } from "react"; // State를 사용하기 위해 useState를 선언합니다.
const FormTest = () => {
// counter는 변수, setCounter는 함수로, setCounter를 통해 counter 값을 정합니다. 기본값을 0으로 설정합니다.
const [counter, setCounter] = useState(0);
// text는 변수, setText는 함수로, setText 통해 text 값을 정합니다. 기본값을 ""으로 설정합니다.
const [text, setText] = useState("");
// return 이하의 내용이 페이지에 드러납니다. 반드시 하나의 태그로 감싸져 있어야 합니다.
return (
<div>
{/* 텍스트 필드에 값을 입력했을 때 입력한 값이 드러나도록 value 속성에 text state를 설정합니다. */}
{/* 태그 안에 state나 함수 등의 요소를 추가할 때는 반드시 중괄호를 써야 합니다. */}
<input type="text" value={text} />
<div>{counter}</div>
<button>+</button>
<button>-</button>
</div>
);
};
export default FormTest;
3. /client/src/components/FormTest.js를 위와 같이 수정합니다.
4. 모든 파일을 저장하고 나면 FormTest.js에서 입력한대로 텍스트 필드와, counter, 버튼 두 개가 생겨나는 걸 확인할 수 있습니다. 여기에서 텍스트필드에 값을 입력해보거나 버튼을 눌러보세요. 아무 일도 일어나지 않습니다. 텍스트필드는 심지어 입력도 안됩니다. 모든 요소들이 작동할 수 있도록 수정해보겠습니다. 다음처럼 handleChange, handleAdd 그리고 handleSubtract 함수를 생성해서 요소들이 동작하도록 해 보겠습니다.
//client/src/components/FormTest.js
import React, { useState } from "react"; // State를 사용하기 위해 useState를 선언합니다.
const FormTest = () => {
const [counter, setCounter] = useState(0);
const [text, setText] = useState("");
const handleChange = (e) => {
setText(e.target.value);
};
const handleAdd = (e) => {
setCounter(counter + 1);
};
const handleSubtract = (e) => {
setCounter(counter - 1);
};
return (
<div>
<input type="text" value={text} onChange={handleChange} />
<div>{counter}</div>
<button onClick={handleAdd}>+</button>
<button onClick={handleSubtract}>-</button>
</div>
);
};
export default FormTest;
5. 기존 코드에 handleChange, handleAdd 그리고 handleSubtract 함수를 추가하고, 텍스트 필드가 변화할 때, +버튼을 누를 때, -버튼을 누를 때 함수가 작동하도록 input과 button의 속성을 추가했습니다.
이제 정상적으로 작동합니다. 이렇게 FormTest라는 Component를 만들었고, App Component 내부에 위치시켰습니다. text State를 통해 텍스트필드에서 값을 받아 텍스트필드에 표시되도록 했습니다. counterState를 통해 카운터를 변화시켜봤습니다. Component와 State는 이렇게 동작합니다.
Props
Props는 부모 컴포넌트에서 데이터를 받아올 때 사용합니다. 다음의 예제를 통해 Props를 사용함과 동시에 Component를 재사용하는 예를 확인해보겠습니다.
1. /client/src/App.js를 수정합니다.
import "./App.css";
import FormTest from "./components/FormTest";
function App() {
return (
<div className="App">
<FormTest />
{* FormTest를 하나 더 추가합니다. title이라는 이름의 props를 추가해줍니다.*}
<FormTest title="This text came from Parent-Component" />
</div>
);
}
export default App;
2. FormTest.js를 수정합니다. props파라미터 추가하는 것 잊지 마세요!
//client/src/components/FormTest.js
import React, { useState } from "react";
// FormTest 컴포넌트에 props 파라미터를 추가합니다. 그래야 부모 컴포넌트로부터 props를 받아올 수 있습니다.
const FormTest = (props) => {
const [counter, setCounter] = useState(0);
const [text, setText] = useState("");
const handleChange = (e) => {
setText(e.target.value);
};
const handleAdd = (e) => {
setCounter(counter + 1);
};
const handleSubtract = (e) => {
setCounter(counter - 1);
};
// props.title을 추가해 props가 제대로 받아졌는지 확인합니다.
return (
<div>
<input type="text" value={text} onChange={handleChange} />
<h1>{props.title}</h1>
<div>{counter}</div>
<button onClick={handleAdd}>+</button>
<button onClick={handleSubtract}>-</button>
</div>
);
};
export default FormTest;
Done!
두 개의 FormTest Component가 웹브라우저에 표시됩니다. 하나는 prop를 받지 않았고, 하나는 props.title을 받아서 텍스트가 표시되어 있습니다. 줄 하나 추가함으로서 Component의 재사용했고, props를 받아서 화면에 표시했습니다. 지금은 이런 게 얼마나 중요할까 싶겠지만, 이런 React의 특징은 데이터를 리스트형태로 표현하는 등 재사용이 많이 되는 디자인을 다루는 경우 특히 유용합니다. 다음 포스팅에서는 로그인 UI를 구현해보도록 하겠습니다.
긴 글 읽어주셔서 감사합니다. 도움이 되셨다면 공감+ 광고 클릭 부탁드립니다. 고마움을 표현하는 가장 쉬운 방법입니다.