React 개발 방식의 가장 큰 특징은 페이지 단위가 아닌 컴포넌트 단위로 시작한다는 점이 가장 큰 특징이다.
아래의 사진을 바탕으로 컴포넌트를 구분해보자.
오늘 내가 구현한 비디오 플레이어 애플리케이션이다. 가장 큰 틀인 App 컴포넌트가 있고 그 안에 VideoList, VideoListEntry 등이 있다.
페이지를 만들기 이전에 이와 같은 컴포넌트를 먼저 만들고 마지막에 조립하는 형식으로 구현한다.
이를 트리구조로 나타내면 다음과 같다.
Entry 컴포넌트는 컴포넌트 바깥(VideoListEntry 컴포넌트)에서 props를 이용해 비디오의 정보를 전달받을 수 있다. 이와같이 리액트는 부모 컴포넌트에서 자식 컴포넌트 즉, 위에서 아래로 흐르는 단방향 데이터 흐름
(one-way data flow)를 따른다.
따라서 하나의 상태(데이터)를 기반으로 여러 컴포넌트가 공유하고 있을 때에는 공통 부모 컴포넌트에 상태(데이터)를 위치시켜 주어야 한다.
위에서 언급한 비디오 플레이어에서 가지고 있는 상태는 두 가지이다.
- 전체 비디오 목록
- 현재 재생중인 비디오
이 두 개의 상태는 여러 컴포넌트 중 어디에 위치시키는 것이 좋을까?
전체 비디오 목록과 현재 재생중인 비디오는 App.js에서 상태 관리를 하는게 맞다고 생각한다. 왜냐하면 현재 재생중인 비디오는 Entry의 title을 클릭했을 때 VideoPlayer에 재생되는 비디오(상태)가 바뀌어야 하기 때문이다.
위에서 말했듯이, 현재 재생중인 비디오의 목록은 자식 컴포넌트에서 클릭 이벤트가 발생했을 때 부모 컴포넌트의 상태가 바뀌어야 한다.
단방향 데이터 흐름에 따르면 부모 컴포넌트에서 자식 컴포넌트에만 영향을 줄 수 있다고 했었는데, 이런 상황에서는 어떻게 해야 할까?
이 때, Lifting State Up. 상태 끌어올리기를 해야 한다.
상태 끌어올리기란 쉽게 말하면 상태 변경 함수를 상태가 있는 곳에 만들고, 그 함수를 props로 자식에게 넘겨 실행하는 방식이다.
지금 상황에서는 상태 변경 함수가 현재 재생중인 비디오의 상태를 변경해주는 함수이고, 상태가 존재하는 곳은 App.js이다. App의 자식은 VideoListEntry이고 그 자식은 Entry이다. 그렇기 때문에 Entry에서 상태 변경 함수를 실행한다.
코드로 보면 이와 같다.
- App.js에 상태 변경 함수를 넣는다.
- App.js에서 그 자식인 VideoList에게 props로 함수를 전달한다.
- VideoList.js에서 그 자식인 VideoListEntry에게 props로 함수를 전달한다.
- Entry에서 함수를 실행한다.
오늘은 리액트 데이터 흐름과 상태 끌어올리기에 대하여 공부하였다.
다음 시간에는 여기에 AJAX를 결합하여 구현을 해본다
오늘은 여기까지!