setState()의 개념이 확립되자, 팀은 <LikeButton> 컴포넌트를 완성할 마지막 조각을 손에 넣었다. 바로 사용자가 버튼을 클릭했을 때의 동작을 정의하는 handleClick 메서드였다.
조던 워크는 완성된 <LikeButton>의 코드를 스크린에 띄웠다. 그것은 리액트의 핵심 철학을 담은, 살아있는 교과서와도 같았다.
var LikeButton = React.createClass({
getInitialState: function() {
return {
isLiked: this.props.initialIsLiked,
currentCount: this.props.likeCount
};
},
// 버튼이 클릭되었을 때 호출될 이벤트 핸들러
handleClick: function() {
// this.state를 직접 수정하지 않는다!
// this.state.isLiked = !this.state.isLiked; // <--- 금지된 행위!
// 오직 setState를 통해서만 상태 변경을 '요청'한다.
this.setState({
isLiked: !this.state.isLiked,
currentCount: this.state.isLiked
? this.state.currentCount - 1
: this.state.currentCount + 1
});
},
render: function() {
// ... 이전과 동일한 render 코드 ...
// this.state를 기반으로 버튼의 모양과 텍스트를 결정한다.
var text = this.state.isLiked
? '좋아요 취소'
: '좋아요';
return React.createElement(
'button',
{ onClick: this.handleClick }, // DOM 이벤트와 핸들러 연결
text + ' (' + this.state.currentCount + ')'
);
}
});
handleClick 메서드 안의 코드는 지극히 단순했다.
“현재 isLiked 상태를 뒤집고, currentCount를 1 증가시키거나 감소시킨 값으로 state를 변경해 주세요.”
이것이 전부였다. handleClick 메서드는 DOM을 직접 조작하는 어떤 코드도 포함하지 않았다. 화면에 있는 버튼의 텍스트를 바꾸거나, 클래스를 추가하는 등의 ‘어떻게’에 대한 내용은 전혀 없었다. 오직 ‘무엇을’, 즉 변경될 상태의 최종 모습만을 선언하고 있었다.
“자, 이제 사용자가 이 버튼을 클릭하는 순간 어떤 일이 일어나는지 따라가 봅시다.” 조던이 설명했다.
1단계: 이벤트 발생
- 사용자가 렌더링된
<button>DOM 요소를 클릭한다. - 브라우저는
click이벤트를 발생시킨다. - 리액트는 이 이벤트를 감지하고, 우리가
onClickprop으로 넘겨준this.handleClick메서드를 호출한다.
2단계: 상태 변경 요청
handleClick메서드가 실행된다.this.setState()가 호출된다.- 리액트는
{ isLiked: true, currentCount: 11 }와 같은 상태 변경 요청서를 접수하고, 리렌더링을 예약한다.
3단계: 마법의 시작
- 리액트는 이제 ‘화면을 다시 그려야 한다’는 것을 인지했다.
- 가장 먼저, 리액트는
<LikeButton>의render()메서드를 다시 호출한다. - 중요한 점:
render가 호출되는 이 시점에는,this.state가 이미 새로운 값 ({ isLiked: true, ... })으로 업데이트되어 있다. render는 새로운state를 기반으로, 새로운 UI 설계도, 즉 새로운 버추얼 DOM 객체를 생성하여 반환한다.{ tagName: 'button', properties: { className: 'liked' }, children: ['좋아요 취소 (11)'] }
- 변화 감지 및 반영
- 리액트의 Diffing 알고리즘이 깨어난다.
- 이 새로운 버추얼 DOM과 이전에 가지고 있던 옛날 버추얼 DOM을 비교한다.
- 알고리즘은 ‘
className이liked로 바뀌었고, 텍스트 내용이좋아요 취소 (11)로 바뀌었다’는 두 가지 변경점을 정확히 찾아낸다. - 리액트는 이 변경점만을 실제 DOM에 적용한다.
이 모든 과정이 눈 깜짝할 사이에, 완전히 자동적으로 일어난다.
회의실에 있던 모두는 경이로움을 느꼈다. 개발자는 그저 setState를 호출했을 뿐인데, 리액트가 그 뒤에 숨겨진 모든 복잡한 과정을 알아서 처리해주었다. 더 이상 DOM을 수동으로 조작하고, 상태와 UI의 싱크를 맞추기 위해 전전긍긍할 필요가 없었다.
setState()
그것은 복잡한 명령들의 연쇄 작용을 일으키는 단 하나의 도미노 조각이었다. 개발자는 첫 번째 도미노를 쓰러뜨리기만 하면, 나머지는 리액트라는 거대한 시스템이 정해진 법칙에 따라 완벽하게 처리해주는, 완전히 새로운 방식의 UI 프로그래밍이었다.


