리액트는 자바스크립트 기반 라이브러리다.
html, css, javascript로 웹 사이트를 제작할 수는 있지만, 간단한 사이트가 아닌 이상 코드가 밀접되어 있기 때문에 가독성도 떨어지고 유지/보수도 어렵다.
따라서, 가독성 측면과 유지/보수 측면에서 코드를 깔끔하게 작성하기 위한 기능이 절실했고 이를 바탕으로 리액트가 생기게 되었다.
리액트의 핵심은 사용자 정의 태그를 생성하는 것이다.
<main>
<header>
<h1>...</h1>
<p>...</p>
</header>
<nav>
<ol>
<li>...</li>
<li>...</li>
<li>...</li>
</ol>
</nav>
<article>
<h2>...</h2>
<p>...</p>
</article>
</main>
위와 같이 header, nav, article이 포함된 간단한 코드가 있다.
사실상, 지금의 코드는 양이 많지 않기 때문에 가독성 측면이나 유지/보수 측면에서 큰 불편함은 없지만, 만약 header에 수십 개의 코드가, nav에도 수십 개의 코드가, 또 article에도 수십 개의 코드가 포함되어 있다면 그때는 코드를 파악하기 쉽지 않을 것이다.
이렇게 특정 기준으로 나눌 수 있는 코드를 하나의 사용자 정의 태그로 만들고 이를 자동차 부품처럼 필요한 곳에 사용하게 하는 것이 바로 리액트의 핵심인 것이다.
<main>
<Header />
<Header /> // 특정 사용자 정의 태그를 여러번 사용 가능하다.
<Nav />
<Article />
</main>
// 이때 Component는 반드시 대문자로 시작해야 한다!
// 일반 html 태그와 구분하기 위해서
사용자 정의 태그를 생성했다고 가정하고 이를 부품처럼 하나씩 사용하면 위와 같은 코드가 된다.
일반 html 태그를 사용했을 때보다 훨씬 간결해진 것을 볼 수 있다.
이처럼 사용자가 직접 정의한 Header, Nav, Article과 같은 태그를 사용자 정의 태그라고 하고 이를 리액트에서 가장 중요한 개념인 Component
라고 한다.
사용자 정의 태그 = Component
리액트에서 사용하는 대표적인 데이터에는 props
와 state
가 있다.
이 두 개의 데이터의 경우 값이 변경되면 컴포넌트가 다시 실행되는 공통점이 있지만 분명한 차이점도 존재하는데, 바로 props는 외부 컴포넌트를 위한 것이고 state는 자기 자신 컴포넌트를 위한 것이라는 점이다.
props는 컴포넌트의 속성으로 컴포넌트의 외부 데이터를 담는 공간, 그에 반해 state는 컴포넌트 내부에서 제어하는 데이터라고 생각하면 될 것 같다.
앞서 살펴본 간단한 컴포넌트로 props를 사용해 보려고 한다.
<main>
<Header title="header!" content={contentList}/>
<Nav />
<Article />
</main>
위와 같이 Header 컴포넌트에 title과 content라는 props를 넘겨줬다. 이때 title의 경우 문자열인 “title”를 넘겨준 것이고 content의 경우 contentList라는 배열 데이터를 넘겨준 것인데 { }를 사용하면 있는 그대로의 데이터를 전달하게 되는 것이다.
즉, 배열이라는 데이터 타입이 무너지지 않고 그대로 보존되어 넘겨지게 되는 것이다.
이렇게 넘겨받은 props를 해당 컴포넌트 내부에서 props.속성 이름
으로 접근할 수 있다.
const Header = (props) => {
const headerTitle = props.title // 넘겨 받은 식별자 그대로
const headerContent = props.content.headerContent // 넘겨 받은 식별자 그대로
return (...)
}
위와 같이 컴포넌트 함수 내부에서 props의 title와 props의 contentList에 접근하는 것을 볼 수 있다.
props는 외부 컴포넌트를 위한 것으로 컴포넌트 함수 내부에서는 읽기만 가능할 뿐 해당 데이터를 수정하거나 삭제할 수 없다.
즉, 받아온 데이터를 변경 없이 그대로 사용해야 하는 것이다.
그러나, 우리는 컴포넌트 내부에서 유동적으로 변경되는 데이터를 사용해야 하는 경우가 본명 있다. 이를 위해서 리액트의 state를 사용하게 되는 것이다.
state를 사용하기 위해서는 리액트의 hook 함수인 useState를 사용해야 한다.
(useState를 사용하기 위해서는 반드시 useState를 import 해와야 한다.)
const Header = (props) => {
const [state, setState] = useState(초기값)
const headerTitle = props.title
const headerContent = props.content.headerContent
return (...)
}
위 코드와 같이 Header 컴포넌트 내부에 useState로 state라는 데이터를 선언을 했고 그다음으로는 해당 데이터가 변경되는 함수 setState를 선언한 것을 볼 수 있다.
이렇게 useState는 값과, 값이 변경되는 함수를 함께 선언해야 한다.
setState로 값이 변경되면 리액트를 이를 감지하고 해당 컴포넌트를 다시 실행하게 되는 것이다.
앞서 살펴본 props와 state는 리액트의 주요 데이터다.
이 두 데이터의 변경이 감지되면 컴포넌트는 다시 re-rendering을 하기 때문에 해당 데이터를 제대로 이해하고 적절하게 사용하는 것이 중요하다!