useRef를 왜 사용할까?

들어가며

React Hooks에는 다양한 것들이 있는데, 그중에 자주쓰는 useState(), useEffect() 말고 useRef()에 대해서 왜 사용하고 어떠한 문제를 해결해주는지 알아보려고합니다.


useRef()?


공식 문서에서는 useRef를 이렇게 설명하고 있다.
useRef는 current 프로퍼티로 전달된 인자(initialValue)로 초기화된 변경 가능한 ref 객체를 반환합니다. 반환된 객체는 컴포넌트의 전 생애 주기를 통해 유지될 것입니다. 본질적으로 useRef는 current 프로퍼티에 변경 가능한 값을 담고 있는 상자와 같습니다. useRef는 내용이 변경될 때 그것을 알려주지는 않는다는 것을 유념하세요. current 프로퍼티를 변형하는 것이 리렌더링을 발생시키지는 않습니다.

다시 정리하자면

1.useRef() 는 일반적인 자바스크립트 객체입니다.

2.매번 렌더링할 때 동일한 객체를 제공합니다.

3.값이 변경되어도 리렌더링이 되지않습니다.

즉 heap에 저장되어 있기 때문에 애플리케이션이 종료되거나 가비지 컬렉팅될 때까지, 참조할 때마다 같은 메모리 값을 가지고 있습니다. 그렇기 때문에 자바스크립트의 === 연산이 항상 true를 반환하기 때문에, 즉 변경사항을 감지할 수 없기 때문에 리렌더링을 하지 않는다는 뜻입니다.



내가 useRef()를 사용한 이유

기본적으로 React 컴포넌트는 내부 상태가 변경될 때마다 해당 컴포넌트를 재 렌더링 합니다.

그러면 게시글이나 form을 사용할 때 입력값 상태를 useState()를 사용한다면, 게시글을 입력할 때마다 불필요한 렌더링을 하게 됩니다.

아래 코드를 실행하면 input을 입력할 때마다 컴포넌트가 재실행이 되어서 리렌더링이 출력되는 것을 확인할 수 있습니다.

import './App.css'
import { useState } from 'react'

function App() {
  const [user, setUser] = useState('')

  const handleChange = e => {
    setUser(e.target.value)
  }

  console.log('리렌더링')

  return (
    <div>
      <input type="text" onChange={handleChange} />
      {user}
    </div>
  )
}

export default App

컴포넌트 함수가 다시 호출이 된다는 것은 함수 내부의 변수들이 모두 다시 초기화되고 함수의 모든 로직이 다시 실행된다는 것을 의미합니다.

이러한 상황에서 input 값을 입력해 줄 때마다 해당 컴포넌트 함수를 다시 호출하게 된다면 메모리나 성능면에서 상당히 비효율적일 것입니다.


어떻게 사용할 수 있을까?

useRef 함수는 current 속성을 가지고 있는 동일한 메모리의 객체를 반환하기 때문에 값을 변경하여도 React 컴포넌트가 리렌더링 되지 않고, 또한 React 컴포넌트가 리렌더링 된다고 해도 current의 속성값이 유실되지 않습니다. 이러한 특징을 이용하면 다음과 같이 사용할 수 있습니다.

import React, { useState, useRef } from 'react'

function App() {
  const inputRef = useRef()
  const [user, setUser] = useState()

  const clickSetUser = () => {
    setUser(inputRef.current.value)
  }

  console.log('리렌더링')

  return (
    <div>
      <input type="email" ref={inputRef} />
      <button onClick={clickSetUser}>set user</button>
      <div>{user}</div>
    </div>
  )
}

export default App

위 코드를 실행하면 input 값을 입력해도 리렌더링 콘솔이 출력되지 않는 것을 확인할 수 있습니다.


마무리

useRef Hook은 자주 사용하지는 않지만, 어떻게 사용하느냐에 따라 좋은 결과를 얻을 수 있다고 생각합니다. 위에 설명한 것들 말고도 useRef의 다른 사용 경우가 있는데, DOM 노드나 React 엘리먼트에 직접 접근하기 위해서입니다. 이것은 추후에 포스팅하겠습니다.



참고

useRef()가 순수 자바스크립트 객체라는 의미를 곱씹어보기

공식문서

daleseo