React 공식문서 이해하기 (16)

Syoee·2023년 11월 24일
0

React

목록 보기
16/30
post-thumbnail

Chapter 3. Managing State

#1 state로 입력에 반응하기

학습 목차

1. 선언형 UI와 명령형 UI의 차이점
2. UI를 선언적인 방식으로 생각하기


1. 선언형 UI와 명령형 UI의 차이점

  • UI인터렉션을 디자인할 때 사용자의 행동에 따라 UI가 어떻게 변하는지에 대해서 생각해 보았을 것이다.
    사용자가 답변을 제출할 수 있는 양식을 생각해 보자.

    • 폼에 무언가를 입력하면 “Submit” 버튼이 활성화될 것이다.
    • “제출” 버튼을 누르면 폼과 버튼이 비활성화 되고 스피너가 나타날 것이다.
    • 네트워크 요청이 성공한다면 form은 숨겨질 것이고 “Thank you”메세지가 나타날 것이다.
    • 네트워크 요청이 실패한다면 오류 메세지가 보일것이고 form은 다시 활성화 될 것이다.
  • 명령형 프로그래밍에서 위의 내용은 인터랙션을 구현하는 방법에 직접적으로 해당한다.
    방금 일어난 일에 따라 UI를 조작하기 위한 정확한 지침을 작성해야한다.

    • 다른 방식으로 생각해보면, 자동차를 타고 가는 사람 옆에서 어디로 가야하는지 차례대로 알려주는 상상을 해보자.


Illustrated by Rachel Lee Nabors

  • 운전자는 사용자가 어디로 가고 싶은지 모른 채 명령만 따를 뿐이다.
    (지시를 잘못 내리면 엉뚱한 곳에 가게 된다!)

  • 컴퓨터에게 스피너부터 버튼까지 각 요소에 “명령”을 내려 컴퓨터에 어떻게 UI를 업데이트할 내용을 지시해야 하므로, 이를 명령형이라고 부른다.

  • 다양한 form 양식으로 가득 찬 페이지를 업데이트 해야 한다고 생각해보자.
    새로운 UI 요소나 새로운 인터랙션을 추가하려면 기존의 모든 코드를 주의 깊게 살펴 버그의 발생 여부(예를 들어, 무언가를 표시하거나 숨기는 것을 잊는 등)를 확인해야 한다.

  • React는 이런 문제를 해결하기 위해 만들어졌다.

  • React에서는 직접 UI를 조작하지 않는다.
    즉, 컴포넌트를 직접 활성화하거나 비활성화 하지도, 보여주거나 숨기지도 않는다.

  • 대신 표시할 내용을 선언하면 React가 UI를 업데이트할 방법을 알아낸다.

    • 택시를 타고 기사에게 정확히 어디서 꺾어야 할지를 알려주는 대신 어디로 가고 싶은지만 말한다고 생각해 보자.
      목적지까지 데려다주는 것은 택시기사의 몫이며, 기사는 여러분이 미처 생각하지 못한 지름길을 알고 있을 수도 있다.


Illustrated by Rachel Lee Nabors

2. UI를 선언적인 방식으로 생각하기

  • 위에서 form을 명령형으로 구현하는 방법을 살펴보자.
    아래에서는 React로 사고하는 방법을 더 잘 이해하기 위해 이 UI를 React로 다시 구현하는 과정이다.

    1. 컴포넌트의 다양한 시각적 상태를 식별한다.
    2. 상태 변화를 촉발하는 요소를 파악한다.
    3. useState를 사용하여 메모리의 상태를 표현한다.
    4. 비필수적인 state 변수를 제거한다.
    5. 이벤트 핸들러를 연결하여 state를 설정한다.

2-1. 컴포넌트의 다양한 시각적 상태 식별하기

  • 컴퓨터 과학에서 “상태 머신” 이란 여러가지 “상태”들 중 하나라는 말을 들어보셨을 것이다.
  • 디자이너와 함께 일한다면 다양한 “시각적인 상태”에 대한 목업을 보았을 것이다.
  • React는 디자인과 컴퓨터 과학의 교차점에 서있기 때문에 이 두 아이디어 모두 영감의 원천이 된다.
  • 먼저 사용자에게 표시될 수 있는 UI의 다양한 “상태”를 모두 시각화해야 한다.
    • 비어있음: form의 “Submit”버튼은 비활성화되어 있다.
    • 입력중: form의 “Submit”버튼이 활성화되어 있다.
    • 제출중: form은 완전히 비활성화되어있고 Spinner가 표시된다.
    • 성공시: form 대신 “Thank you”메세지가 표시된다.
    • 실패시: ‘입력중’ 상태와 동일하지만 추가로 오류 메세지가 표시된다.

2-2. 상태 변경을 촉발하는 요인 파악하기

  • 두 종류의 입력에 대한 응답으로 상태 변경을 트리거 할 수 있다.
    • 사람의 입력 : 버튼 클릭, 필드 입력, 링크 이동 등
    • 컴퓨터의 입력 : 네트워크에서 응답 도착, 시간 초과, 이미지 로딩 등


Illustrated by Rachel Lee Nabors

  • 두 경우 모두 state 변수를 설정해야 UI를 업데이트할 수 있다.
    개발중인 form의 경우 몇 가지 다른 입력에 따라 state를 변경해야한다.

    • text 입력을 변경(사람) 하면 text box가 비어있는지 여부에 따라 비어있음 state에서 입력중 state로, 또는 그 반대로 전환해야한다.
    • 제출 버튼을 클릭(사람)하면 제출중 state로 전환해야한다.
    • 네트워크 응답 성공(컴퓨터)시 성공 state로 전환해야한다.
    • 네트워크 요청 실패(컴퓨터)시 일치하는 오류 메세지와 함께 오류 state로 전환해야한다.

KeyNote

  • 이 흐름을 시각화하는 데 도움이 되도록 종이에 각 상태가 적힌 원을 그리고 각 상태 사이의 변경 사항을 화살표로 아래와 같이 그려 보자.
    이 방식으로 흐름을 파악할 수 있을 뿐 아니라 구현하기 훨씬 전에 버그를 분류할 수 있다.

  • Form State


2-3. 메모리의 상태를 useState 로 표현하기

  • 다음으로 메모리에서 컴포넌트의 시각적 상태를 useState로 표현해야한다.
    이 과정은 단순함이 핵심이다.
  • 각 상태 조각은 “움직이는 조각”이며, 가능한 적은 수의 “움직이는 조각”을 원한다.
    복잡할수록 버그가 더 많이 발생한다.
  • 반드시 필요한 state부터 시작하자.
    예를 들어, 입력에 대한 answer를 저장하고, 가장 마지막에 발생한 error(존재한다면)도 저장해야 한다.
const [answer, setAnswer] = useState('');
const [error, setError] = useState(null);
  • 그런 다음 앞서 설명한 시각적 상태 중 어떤 상태를 표시할지를 나타내는 state 변수가 필요하다.
    일반적으로 메모리에서 이를 표현하는 방법은 여러가지가 있으므로 실험해봐야 한다.
  • 가장 좋은 방법을 즉시 생각하기 어렵다면 가능한 모든 시각적 상태를 확실하게 다룰 수 있을 만큼 충분한 state를 추가하는 것부터 시작하라.
const [isEmpty, setIsEmpty] = useState(true);
const [isTyping, setIsTyping] = useState(false);
const [isSubmitting, setIsSubmitting] = useState(false);
const [isSuccess, setIsSuccess] = useState(false);
const [isError, setIsError] = useState(false);

2-4. 비필수적인 state 변수 제거하기

  • state 콘텐츠의 중복을 피해 필수적인 것만 추적하고 싶을 것이다.
  • state 구조를 리팩토링하는 데 약간의 시간을 투자하면 컴포넌트를 더 쉽게 이해하고, 중복을 줄이며, 의도하지 않은 경우를 피할 수 있다.
  • 목표는 state가 사용자에게 보여주기를 원하는 유효한 UI를 나타내지 않는 경우를 방지하는 것이다.
    예를 들어, 오류 메세지를 표시하면서 동시에 입력을 비활성화하면 사용자는 오류를 수정할 수 없게 된다.
  • 다음은 state 변수에 대해 물어볼 수 있는 몇가지 질문이다.
    • state가 모순을 야기하는가?
      예를 들어, isTypingisSubmitting은 동시에 true일 수 없다.
      이러한 모순은 일반적으로 state가 충분히 제약되지 않았음을 의미한다.
    • 두 boolean의 조합은 네 가지가 가능하지만 유효한 state는 세 가지뿐이다.
      “불가능한” state를 제거하려면 세 가지 값을 하나의 status로 결합하면 된다.
      • 'typing', 'submitting', 'success'.
    • 다른 state 변수에 이미 같은 정보가 있는가?
      isEmptyisTyping은 동시에 true가 될 수 없다.
      이를 각 state 변수로 분리하면 동기화되지 않아 버그가 발생할 위험이 있다.
      다행히 isEmpty를 제거하고 대신 answer.length === 0으로 확인할 수 있다.
    • 다른 state 변수를 뒤집으면 동일한 정보를 얻을 수 있는가?
      isErrorerror !== null을 대신 확인할 수 있기 때문에 필요하지 않다.
  • 이렇게 정리하고 나면 3개(7개가 줄어든!)의 필수 state 변수만 남는다.
const [answer, setAnswer] = useState('');
const [error, setError] = useState(null);
const [status, setStatus] = useState('typing'); // 'typing', 'submitting', or 'success'

2-5. 이벤트 핸들러를 연결하여 state 설정하기

  • 모든 상호작용을 state 변화로 표현하면 나중에 기존 상태를 깨지 않고도 새로운 시각적 상태를 도입할 수 있다.
  • 또한 인터랙션 자체의 로직을 변경하지 않고도 각 state에 표시되어야 하는 항목을 변경할 수 있다.

요약

  • 선언형 프로그래밍은 UI를 세밀하게 관리(명령형)하지 않고 각 시각적 상태에 대해 UI를 기술하는 것을 의미한다.
  • 컴포넌트를 개발할 때,
    1. 모든 시각적 상태를 식별하라.
    2. 사람 및 컴퓨터가 상태 변화를 촉발하는 요인을 결정하라.
    3. useState로 상태를 모델링하라.
    4. 버그와 모순을 피하려면 비필수적인 state를 제거하라.
    5. 이벤트 핸들러를 연결하여 state를 설정하라.

React 공식 문서

https://react.dev/

React 비공식 번역 문서

https://react-ko.dev/

MDN

https://developer.mozilla.org/ko/

Wikipedia

https://ko.wikipedia.org/wiki/

profile
함께 일하고 싶어지는 동료, 프론트엔드 개발자입니다.

0개의 댓글

관련 채용 정보