React 공부 (15) State 끌어올리기

seon·2024년 3월 4일

Web

목록 보기
29/33
post-thumbnail
  • 출처: 소플의 처음 만난 리액트
    리액트의 컴포넌트 사이에서 state를 공유하는 방법에 대해 배워 보도록 하겠습니다. 리액트로 개발을 하다 보면 하나의 데이터를 여러 개의 컴포넌트에서 표현해야 하는 경우가 종종 생깁니다. 이러한 경우에 각 컴포넌트의 state에 대해서 데이터를 각각 보관하는 것이 아니라 가장 가까운 공통된 부모 컴포넌트의 state를 공유해서 사용하는 것이 더 효율적입니다.

Shared State

공유된 state

자식 컴포넌트들이 가장 가까운 공통된 부모 컴포넌트의 state를 공유해서 사용하는 것이죠. shared state는

어떤 컴포넌트의 state에 있는 데이터를 여러 개의 하위 컴포넌트에서 공통적으로 사용하는 경우

를 말합니다.

  • 위의 그림에는 총 세 개의 컴포넌트가 있습니다. 가장 위에 있는 컴포넌트는 부모 컴포넌트이고 아래에 화살표롤 연결된 두 개의 컴포넌트는 자식 컴포넌트입니다. 부모 컴포넌트는 값을 가지고 있습니다.
  • 왼쪽 아래에 있는 컴포넌트 A는 값에 2를 곱해서 표시하는 컴포넌트이고,
    오른쪽 아래에 있는 컴포넌트 B는 값에 3을 곱해서 표시하는 컴포넌트입니다.
  • 이러한 경우 자식 컴포넌트들이 각각 값을 갖고 있을 필요가 없습니다. 그냥 부모 컴포넌트의 state에 있는 값에 각각 2와 3을 곱해서 표시해 주면 되기 때문입니다.


위 그림도 마찬가지로 총 세 개의 컴포넌트가 있습니다.

  • 부모 컴포넌트는 degree라는 이름의 섭씨온도 값을 갖고 있으며
  • 왼쪽 아래에 있는 컴포넌트는 온도를 섭씨로 표현하는 컴포넌트이고,
    오른쪽 아래에 있는 컴포넌트는 온도를 화씨로 표현하는 컴포넌트입니다.
  • 이 경우에도 자식 컴포넌트들이 각각 온도 값을 가지고 있을 필요 없이, 그냥 컴포넌트의 state에 있는 섭씨온도 값을 변환해서 표시해 주면 됩니다.

지금까지 살펴 본 것처럼 하위 컴포넌트가 공통된 부모 컴포넌트의 state를 공유하여 사용하는 것을 shared state라고 합니다.


# 하위 컴포넌트에서 State 공유하기

지금부터 사용자로부터 온도를 입력받아서 각각 섭씨온도와 화씨온도로 표현해주고 해당 온도에서 물이 끓는지 안 끓는지를 출력해 주는 컴포넌트를 만들어 보면서 state를 공유하는 방법에 대해 자세히 살펴보도록 하겠습니다.

먼저 섭씨온도 값을 props로 받아서 물이 끓는지 안 끓는지를 문자열로 출력해 주는 컴포넌트를 만들어 보도록 하겠습니다.

물의 끓음 여부를 알려주는 컴포넌트

위 코드는 BoilingVerdict라는 이름을 가진 굉장히 간단한 컴포넌트입니다. 섭씨온도 값을 props로 받아서 100도씨 이상이면 물이 끓는다는 문자열을 출력하고 그 외에는 물이 끓지 않는다는 문자열을 출력합니다. 이제 이 컴포넌트를 실제로 사용하는 부모 컴포넌트를 만들어 보겠습니다.

  • 위의 코드에 나온 Calculator라는 컴포넌트는 state로 온도 값을 하나 갖고 있습니다.
  • 또한 사용자로부터 입력을 받기 위해서 <input> 태그를 사용하여 앞에서 배운 제어 컴포넌트 형태로 구현되어 있습니다.
  • 사용자가 온도 값을 변경할 때마다 handleChange() 함수가 호출되고,
    setTemperature() 함수를 통해 온도 값을 갖고 있는 temperature라는 이름의 state를 업데이트합니다.
  • 그리고 state에 있는 온도 값은 앞에서 만든 BoilingVerdict 컴포넌트에 celsius라는 이름의 props로 전달됩니다.

입력 컴포넌트 추출하기

다음은 Calculator 컴포넌트 안에 온도를 입력하는 부분을 별도의 컴포넌트로 추출해 보겠습니다. 이렇게 하는 이유는 섭씨온도와 화씨온도를 각각 따로 입력받을 수 있도록 하여 재사용이 가능한 형태로 컴포넌트를 만들어 사용하는 것이 효율적이기 때문입니다.

  • 위의 코드는 온도를 입력받기 위한 TemperatureInput 컴포넌트입니다.
  • Calculator 컴포넌트에서 온도를 입력받는 부분을 추출하여 별도의 컴포넌트로 만든 것입니다.
  • 추가적으로 props에 단위를 나타내는 scale을 추가하여 온도의 단위를 섭씨 또는 화씨로 입력 가능하도록 만들었습니다.

이렇게 추출한 컴포넌트를 사용하도록 Calculator 컴포넌트를 변경하면 아래 코드와 같이 됩니다.

  • 총 두 개의 입력을 받을 수 있도록 되어 있으며 하나는 섭씨온도를 입력받고 다른 하나는 화씨 온도를 입력받습니다.

그런데 여기에서 한 가지 문제가 발생합니다.

사용자가 입력하는 온도값이 TemperatureInput의 state에 저장되기 때문에 섭씨온도와 화씨온도 값을 따로 입력받으면 두 개의 값이 다를 수 있습니다. 이를 해결하기 위해 값을 동기화시켜줘야 합니다.


온도 변환 함수 작성하기

먼저 섭씨온도와 화씨온도 값을 동기화시키기 위해서 각각 변환하는 함수를 작성해야 합니다. 아래 함수는 화씨온도를 섭씨온도로 변환하는 함수와 섭씨온도를 화씨온도로 변환하는 함수입니다. 이렇게 만든 함수를 호출하는 함수를 작성해 보겠습니다.

  • tryConver() 함수는 온도 값과 변환하는 함수를 파라미터로 받아서 값을 변환시켜 리턴해 주는 함수입니다.
  • 만약 숫자가 아닌 값을 입력하면 empty string을 리턴하도록 예외 처리를 했습니다. 이 함수를 실제로 사용하는 방법은 아래와 같습니다.

Shared State 적용하기

다음은 하위 컴포넌트의 state를 공통된 부모 컴포넌트로 올려서 shared state를 적용해야 합니다.

State 끌어올리기

state를 상위 컴포넌트로 올린다는 것을 'State 끌어올리기'라고 표현

영단어 'Lifting'은 '들어 올리다'라는 뜻을 갖고 있는데 말 그대로 state를 위로 끌어올린다는 의미입니다. 이를 위해 먼저 TemperatureInput 컴포넌트에서 온도 값을 가져오는 부분을 아래와 같이 수정해야 합니다. 이렇게 하면 온도 값을 state에서 가져오는 것이 아닌 props를 통해서 가져오게 됩니다. 또한 컴포넌트의 state를 사용하지 않게 되기 때문에 입력값이 변경되었을 때 상위 컴포넌트로 변경된 값을 전달해 주어야 합니다. 이를 위해서 handleChange() 함수를 다음과 같이 변경합니다.이제 사용자가 온도 값을 변경할 때마다 props에 있는 onTemperatureChange() 함수를 통해 변경된 온도 값이 상위 컴포넌트로 전달됩니다. 최종적으로 완성된 TemperatureInput 컴포넌트의 모습은 아래와 같습니다. state는 제거되었고 오로지 상위 컴포넌트에서 전달받은 값만을 사용하고 있습니다.


Calculator 컴포넌트 변경하기

마지막으로 변경된 TemperatureInput 컴포넌트에 맞춰서 Calculator 컴포넌트를 변경해 주어야 합니다. 다음 코드는 변경된 Calculator 컴포넌트의 모습입니다.

  • 우선 state로 temperature와 scale을 선언하여 온도 값과 단위를 각각 저장하도록 하였습니다. 이 온도와 단위를 이용하여 변환 함수를 통해 섭씨온도와 화씨온도를 구해서 사용합니다.
  • TemperatureInput 컴포넌트를 사용하는 부분에서는 각 단위로 변환된 온도 값과 단위를 props로 넣어 주었고, 값이 변경되었을 때 업데이트하기 위한 함수를 onTemperatureChange에 넣어 주었습니다. 따라서 섭씨온도가 변경되면 단위가 'c'로 변경되고, 화씨온도가 변경되면 단위가 'f'로 변경됩니다.

이렇게 최종적으로 완성된 구조를 그림으로 나타내면 아래와 같습니다.

  • 상위 컴포넌트인 Calculator에서 온도 값과 단위를 각각의 state로 가지고 있으며, 두 개의 하위 컴포넌트는 각각 섭씨와 화씨로 변환된 온도 값과 단위 그리고 온도를 업데이트하기 위한 함수를 props로 갖고 있습니다.

이처럼 각 컴포넌트가 state에 값을 갖고 있는 것이 아니라 공통된 상위 컴포넌트로 올려서 공유하는 방법을 사용하면 리액트에서 더욱 간결하고 효율적인 개발을 할 수 있습니다.


정리

  • Shared state : 하위 컴포넌트가 공통된 부모 컴포넌트의 state를 공유하여 사용하는 것
  • state 끌어올리기 : 하위 컴포넌트의 state를 공통된 부모 컴포넌트로 끌어올려서 공유하는 방식

profile
🌻

0개의 댓글