도움말 - 글감 수집하기 (인용)

도움말 - 부분 리뷰 작성하기

리액트 State 비쥬얼 가이드(A Visual Guide to State in React)

리액트의 "state"는 단순히 State에 어떤 값을 넣을지 보다는, 실제로 그것(state)이 무엇이고, 무엇을 위한 것이고, 그리고 어떻게 Redux가 React state와 관계가 있는지에 대해 배우기 어려운 컨셉 중 하나이다.

이 글을 통해 일정 부분 헷갈리는 부분이 정리 되길 바란다. 

그 단어를 당신은 계속 사용하고 있다...

 우선, "state"라는 단어는 조금 모호하다. 어떤 의미에선, "state"는 앱의 현재의 비쥬얼 적인 표현을 의미한다. 이것은 "loading"이나 "error" 상태를 의미 할 수 있다. 하지만, 리액트에서 "state"라는 용어의 의미는 조금 다를 수 있다. 

리액트에서 "state"는 앱의 변경될 수 있는 객체(object)를 의미한다. 또한, 앱의 각 컴포넌트는 this.state라는 객체를 가질 수 있다. 

간단히 얘기하자면, 당신의 앱이 어떤 것을 하도록 하고 싶다면 - 예를들어, 상호작용(interactivity)을 한다거나, 어떤 것을 추가하거나 삭제한다거나, 로그인 또는 로그아웃을 하게 한다거나 - 이러한 것들이 state를 포함한다.

리액트 State는 어떤 모습일까

특정 시점의 이렇게 생긴 앱을 상상해보자:


위의 이미지를 보고, 시간이 지남에 따라 변할 수 있는 부분을 골라보자(아래 이미지의 주황색으로 표시된 부분이다.)

이제 여기에 이름을 붙여보자(시간, 전력 사용량, 실내 온도, 실외 온도), 그리고 이것을 자바스크립트 객체로 표현 해보자:

{
currentTime: "2016-10-12T22:25:42.564Z",
power: {
min: 0,
current: 37,
max: 100
},
indoorTemperature: {
min: 0.0,
current: 72.0,
max: 100.0
},
outdoorTemperature: {
min: -10.0,
current: 84.0,
max: 120.0
},
tempUnits: "F"
}

이 객체 이 앱의 전체 state를 표현 한 것이고, 이것이 곧 리액트의 state이다.

이 필드들이 앱의 UI와 완벽하게 일치하지 않는다는 것에 주목하자. 날짜를 입력하고, 최소 및 최대 값을 사용하여 그래프를 올바르게 그리는 것은 충분히 쉬울 겁니다.이 필드들이 앱의 UI와 완벽하게 일치하지 않는다는 것에 주목하자. 날짜를 입력하고, 최소 및 최대 값을 사용하여 그래프를 올바르게 그리는 것은 충분히 쉬울 겁니다.

중요한 점은 그대로 남아있습니다: state를 변경하는 것은 앱의 모습을 변경 한다는 것.

최소 및 최대 값은 절대로 변하지 않는데, 왜 그 값들이 state에 포함 되어 있는지에 대해서 foobarwtf 씨가 지적했다. 사실, 서버로부터 받은 값들을 state에 저장하는 것은 일반적이다. 만약 당신이 받아온 현재 온도 데이터가 최소 및 최대 값을 포함하고 있다면, 그것들을 나머지 부분들과 함께 저장하는 것이 가장 좋다. 왜나하면, 이런 값들이 변경 되지 않을 것이라는 것이 명백하더라도, hard-coded된 값들을 서버와 클라이언트 모두에 중복된 값을 저장하고 싶진 않을 것이기 때문이다. 서버에서 측정 값을 변경 한다거나, 사용자가 200A 파워 시스템을 설치 했다거나 한다면 말이다.

정리하자면, state는 일반적으로 값이 변하는 것이지만, 서버 호출에서 나온 데이터와 같이 "휘발성(volatile)" 데이터를 담는 것도 좋다.

State 변경 방법

만약 state의 어떤 값이 변경 된다면, 예를들어 온도가 75° 이내로 올라간다면, 앱에 새로 변경된 값이 반영되야 될 것이다. 이것이 리액트가 state가 변경됐을 때 하는 일이다. 말하자면, 리액트는 state가 변경 됐을 때, 전체앱을 re-render 한다.

다음은 state가 변경 될 수 있는 몇가지 이유이다:

  • 사용자가 버튼을 클릭 또는 탭 한다.
  • 어떤 데이터를 서버로 부터 받는다 - 웹소켓 메세지나, 전의 요청에 대한 응답
  • 타이머가 꺼진다 - 예를들어, 화면에 5초마다 현재 시간을 변경하는 타이머가 있다고 가정하자.

그렇다면, 어떻게 리액트는 state가 변경 됐다는 걸 알 수 있을까? 계속해서 변경을 폴링(polling) 할까? 앵귤러(Angular)처럼 이벤트를 지켜볼까? 아니다. 그렇게 멋드러진 방법을 사용하진 않는다.

리액트는 당신이 컴포넌트의 this.setState를 호출해서 명백히(explicitly) 알리기 때문에 state가변경 됐다는 것을 안다. 다시말하면, 리액트에 "마술"같은 것은 없다. 리액트는 당신이 그렇게 하라고 지시할때만 리렌더링을 한다.

카운터(Counter)의 State 변화

위에 홈 모니터링 앱은 state가 작동하는 좋은 예제이긴 하지만, 시간이 지남에 따라 state가 어떻게 변하는지 보여 주기 위해 간단한 "카운터"을 예제로 들것이다.

카운터 앱의 작동 방법은 이렇다:

  • 0부터 시작하는 숫자가 있다.
  • 버튼을 클릭하면 지정된 함수(handleClick)를 호출 한다.
  • 카운터가 1 증가한다.(setState를 호출하여 이것을 하게 한다)
  • 리액트가 변경 사항에 대응하여 앱을 리렌더링 한다.

Show Me The Code

빠른 리뷰:

  • 리액트는 state를 객체 형태로 유지한다.
  • state의 값을 setState를 통해 변경한다.
  • 리액트는 setState가 호출될때마다 리렌더링한다.

2가지 더 중요한 점:

  • 절대 직접 this.state 객체를 변경하면 안된다. this.setState를 사용해라.
  • state 변경은 비동기로 실행된다. this.state를 this.setState를 호출한 바로 다음에 읽는다면, 변경된 state 값을 반영하지 않을 수 있다.

위의 카운터 컴포넌트 코드는 다음과 같다:

디버거에서 코드가 어떻게 실행 되는지 확인하자

디버거는 버그를 추적하는데 매우 유용 할 뿐만아니라, 당신의 코드가 실행되는 순서를 보기에도 매우 좋다. 중단점(breakpoint)을 설정하고 "재생"(또는 새로고침)을 누른다. 아래를 확인하여 카운터 앱이 작동되는 화면을 확인해보자:


Details, Details

이 글에서, state는 전체 앱을 설명하는 단일 객체라고 얘기했다. 하지만, 실제로는 작은 조각들로 나뉘어 진다. 가장 좋은 방법은 state를 "컨테이너" 컴포넌트로 분리하여, "표현" 컴포넌트로부터 분리하는 것이다.

Redux를 사용한다면, 당신은 전체 앱을 설명하는 한 개의 큰 state 객채를 갖고 있을 것이다. Redux가 하는 가장 기본적인 것은 이것이다: 한 개의 엄청 큰 객체가 앱의 state를 대표하고, reducers와 mapStateToProps가 관련된 각각의 컴포넌트로 그 값(state)를 나누게 된다. 

state에 대해 명확해졌기를 바란다. 궁금한 점이 있다면 아래의 커멘트에 남겨주길 바란다. 



이 글은 DAVE CEDDIA의 A Visual Guide to State in React를 번역 한 글입니다. 전문 번역가가 아니라 오역이 있을 수 있습니다. 지적해주시면 빠르게 고치겠습니다. 원문은 아래에서 확인 할 수 있습니다. 


함께 읽으면 좋을 글:


리뷰