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

Syoee·2023년 12월 2일
0

React

목록 보기
23/30
post-thumbnail

Chapter 4. Escape Hatches

#1 ref로 값 참조하기

학습 목차

1. 컴포넌트에 ref 추가하기
2. ref와 state의 차이점
3. ref를 사용해야 하는 경우
4. ref 모범 사례
5. Ref와 DOM


1. 컴포넌트에 ref 추가하기

  • React에서 useRef 훅을 가져와서 컴포넌트에 ref를 추가할 수 있습니다:

    import { useRef } from 'react';

  • 컴포넌트 내부에서 useRef 훅을 호출하고 참조할 초기값을 인자로 전달하십시오. 예를 들어, 값 0은 ref에 대한 초기값이다.

    const ref = useRef(0);

  • useRef는 다음과 같은 객체를 반환한다.

{ 
  current: 0 // The value you passed to useRef
}


Illustrated by Rachel Lee Nabors

  • ref.current 속성을 통해 해당 ref의 현재 값에 액세스할 수 있다.
    이 값은 의도적으로 변이 가능하므로 읽기와 쓰기가 모두 가능하다.

  • React가 추적하지 않는 컴포넌트의 비밀 주머니와 같다.
    (이것이 바로 React의 단방향 데이터 흐름에서 “탈출구”가 되는 이유이다.)

  • 여기서 버튼은 클릭할 때마다 ref.current를 증가시킨다.

import { useRef } from 'react';

export default function Counter() {
  let ref = useRef(0);

  function handleClick() {
    ref.current = ref.current + 1;
    alert('You clicked ' + ref.current + ' times!');
  }

  return (
    <button onClick={handleClick}>
      Click me!
    </button>
  );
}
  • 여기서의 ref는 숫자를 가리키고 있지만, state와 마찬가지로 문자열, 객체, 함수 등 무엇이든 가리킬 수 있다.
    state와 달리 ref는 current 속성을 읽고 수정할 수 있는 일반 JavaScript 객체이다.
  • 컴포넌트는 ref가 증가할 때마다 리렌더링되지 않는다는 점에 유의하라.
    state와 마찬가지로 ref는 리렌더링 사이에 React에 의해 유지된다.
    state를 설정하면 컴포넌트가 다시 렌더링된다.
    반면 ref를 변경하면 그렇지 않다.

2. ref와 state의 차이점

  • 어쩌면 ref가 state보다 덜 “엄격”해 보인다고 생각할 수도 있다.
    항상 state 설정자 함수를 사용하지 않고도 변이할 수 있기 때문이다.
    하지만 대부분의 경우 state를 사용하고 싶을 것이다.
    ref는 자주 사용하지 않는 “탈출구”이다.
    state와 ref를 비교하면 아래와 같다.
refsstate
useRef(initialValue){ current: initialValue }을 반환useState(initialValue)는 state 변수의 현재값과 state 설정자함수([value, setValue])를 반환
변경 시 리렌더링을 촉발하지 않음변경 시 리렌더링을 촉발함
Mutable— 렌더링 프로세스 외부에서 current 값을 수정하고 업데이트할 수 있음“Immutable”— state setting 함수를 사용하여 state 변수를 수정해 리렌더링을 대기열에 추가해야함
렌더링 중에는 current 값을 읽거나 쓰지 않아야 함언제든지 state를 읽을 수 있음. 각 렌더링에는 변경되지 않는 자체 state snapshot이 있음

DEEP DIVE
ref는 내부에서 어떻게 작동하는가?

  • useStateuseRef는 모두 React에서 제공하지만, 원칙적으로 useRefuseState 위에 구현될 수 있다.
    React 내부에서 useRef는 다음과 같이 구현된다고 상상할 수 있다.
// Inside of React
function useRef(initialValue) {
  const [ref, unused] = useState({ current: initialValue });
  return ref;
}
  • 첫 번째 렌더링 중에 useRef{ current: initialValue }를 반환한다.
    이 객체는 React에 의해 저장되므로 다음 렌더링 중에 동일한 객체가 반환된다.
    이 예제에서 state setter가 어떻게 사용되지 않는지 주목하라.
    useRef는 항상 동일한 객체를 반환해야 하기 때문에 불필요하다.
  • React는 충분히 일반적인 상황이라 판단하고 빌트인 버전의 useRef를 제공한다.
    ref를 설정자가 없는 일반 state 변수라고 생각하면 된다.
    객체지향 프로그래밍에 익숙하다면 인스턴스 필드를 떠올릴 수 있는데, this.something 대신 somethingRef.current를 사용하면 된다.

3. ref를 사용해야 하는 경우

  • 일반적으로 ref는 컴포넌트가 React로부터 “외부로 나가서” 외부 API,
    즉,컴포넌트의 형상에 영향을 주지 않는 브라우저 API 등과 통신해야 할 때 사용한다.
    다음은 이러한 드문 상황 중 몇가지이다.
    • timeout ID 저장
    • 다음 페이지에서 다룰 DOM elements 저장 및 조작
    • JSX를 계산하는 데 필요하지 않은 다른 객체 저장
  • 컴포넌트에 일부 값을 저장해야 하지만 렌더링 로직에는 영향을 미치지 않는 경우 ref를 선택하자.

4. ref 모범 사례

  • 다음 원칙을 따르면 컴포넌트의 예측 가능성을 높일 수 있다.
    • ref를 탈출구로 취급하라.
      ref는 외부 시스템이나 브라우저 API로 작업할 때 유용하다.
      애플리케이션 로직과 데이터 흐름의 대부분이 ref에 의존하는 경우 접근 방식을 재고해봐야 할 수도 있다.
    • 렌더링 중에는 ref.current를 읽거나 쓰지 말자.
      렌더링 중에 일부 정보가 필요한 경우, 대신 state를 사용하자.
      React는 ref.current가 언제 변경되는지 알지 못하기 때문에, 렌더링 중에 읽어도 컴포넌트의 동작을 예측하기 어렵다.
      (유일한 예외는 첫 번째 렌더링 중에 ref를 한 번만 설정하는 if (!ref.current) ref.current = new Thing()과 같은 코드이다).
  • state의 제한은 ref에는 적용되지 않는다.
    예를 들어, state는 모든 렌더링에 대해 스냅샷처럼 작동하며 동기적으로 업데이트되지 않는다.
    하지만 ref의 현재 값을 변이하면 즉시 변경된다.
ref.current = 5;
console.log(ref.current); // 5
  • 이는 ref 자체가 일반 JavaScript 객체이므로 JavaScript 객체처럼 동작하기 때문이다.
  • 또한 ref로 작업할 때 변이를 피하고자 조심할 필요가 없다.
    변이하는 객체가 렌더링에 사용되지 않는 한, React는 ref나 그 콘텐츠로 무엇을 하든 상관하지 않는다.

5. Ref와 DOM

  • ref는 모든 값을 가리킬 수 있다.
    그러나 ref의 가장 일반적인 사용 사례는 DOM 요소에 액세스하는 것이다.
    예를 들어, 프로그래밍 방식으로 input에 focus를 맞추고자 할 때 유용하다.
    <div ref={myRef}>와 같이 JSX의 ref 어트리뷰트에 ref를 전달하면 React는 해당 DOM 엘리먼트를 myRef.current에 넣는다.
    이에 대한 자세한 내용은 ref로 DOM 조작하기에서 확인할 수 있습니다.

요약

  • ref는 렌더링에 사용되지 않는 값을 유지하기 위한 탈출구입니다.
    자주 필요하지 않다.
  • ref는 current라는 단일 프로퍼티를 가진 일반 JavaScript 객체로, 읽거나 설정할 수 있다.
  • useRef 훅을 호출하여 React에 ref를 제공하도록 요청할 수 있다.
  • state와 마찬가지로 ref를 사용하면 컴포넌트의 리렌더링 사이에 정보를 유지할 수 있다.
  • state와 달리 ref의 current 값을 설정해도 리렌더링이 트리거되지 않는다.
  • 렌더링 중에는 ref.current를 읽거나 쓰지 마세요. 이렇게 하면 컴포넌트를 예측하기 어렵다.

React 공식 문서

https://react.dev/

React 비공식 번역 문서

https://react-ko.dev/

MDN

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

Wikipedia

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

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

0개의 댓글