Skip to main content

Command Palette

Search for a command to run...

React useRef를 사용하는 이유

리액트에서 DOM을 다룰 때 왜 `useRef`를 써야하는지 이유를 정리해봤습니다

Updated
3 min readView as Markdown
React useRef를 사용하는 이유
T

Software engineer for web tech. Interested in sustainable growth as software engineer.

자꾸만 익숙했던 방식대로 querySelector를 사용하려고 하는 스스로를 설득하기 위해 리액트 useRef 훅의 내용을 정리합니다.

간단하게 먼저 결론부터 언급하자면, useRef를 사용하는 주된 이유는 React의 선언적이고 반응형인 특성과 잘 맞기 때문입니다.

선언적 프로그래밍에 잘 맞는다

  • React는 선언적 프로그래밍 패러다임을 따릅니다. UI의 현재 상태를 선언하고, 데이터가 변경될 때마다 React가 UI를 자동으로 업데이트 해줍니다. 이 때 useRef를 사용하면 React의 랜더링 사이클과 일관성을 유지하면서 DOM 요소에 접근할 수 있습니다.

  • document.querySelector등 Element 요소를 반환하는 방식을 사용하면, 명령적인 코드가 되기 때문에 React의 선언적 특성과 어울리지 않습니다.

렌더링 사이클과 통합된다

  • useRef를 사용하면 React의 렌더링 사이클에 통합됩니다. 그래서 컴포넌트가 렌더링될 때 자동으로 참조가 업데이트 됩니다. 결과적으로 DOM요소가 변경될 때마다 안정적으로 참조를 유지할 수 있게 됩니다. 리액트 렌더링 사이클인 마운팅 -> 업데이트 -> 언마운팅의 과정이 있는데, useRef를 통해 참조된 객체는 이 과정과 라이프 사이클이 동기화 됩니다.

  • document.querySelector를 사용하면 리액트 라이프사이클과 동기화가 어긋날 수 있어 문제가 생길 수 있습니다. 만약 라이프사이클을 통한 DOM 업데이트 시점과 실제 React 렌더링 라이프사이클을 통해 업데이트 되는 시점이 다를 경우 dom을 찾을 수 없거나, 제대로 업데이트 되지 않은 DOM 요소를 찾을 수도 있기 때문입니다. 이런 경우 컴포넌트가 업데이트(=리렌더링)될 때마다 수동으로 DOM 요소를 다시 찾아야 할 필요가 생깁니다.

메모리 누수 방지

  • 렌더링 사이클 통합과 이어지는 장점으로, React 컴포넌트가 언마운트될 때, useRef를 통해 생성된 참조도 자동으로 정리가 되기 때문에 메모리 누수에 대해 안전합니다.

  • document.querySelector로 가져온 참조의 경우 더이상 활용하지 않게된 Element 를 변수에 가지고 있거나 계속 참조하여 가지고 있음으로 인해 메모리 낭비가 커지기 쉽습니다.

리액트 16.8 부터 적용된 함수 컴포넌트와의 호환

  • useRef는 React의 훅 중 하나로, 함수 컴포넌트 내에서 상태나 DOM 요소에 대한 참조를 유지하는데 사용됩니다. 클래스 컴포넌트에서는 this.refs를 통해서 사용했던 기능이지만, 16.8버전부터 생겨난 함수 컴포넌트에서는 useRef가 동일한 역할을 해줍니다.

예시를 통해 차이를 알아보기

  • document.querySelector 사용 케이스

      import React, { useEffect } from 'react';
    
      function AutofocusInput() {
        useEffect(() => {
          // 컴포넌트가 마운트된 후 input 요소를 선택하여 포커스를 줌
          const inputElement = document.querySelector('#myInput');
          if (inputElement) {
            inputElement.focus();
          }
        }, []);
    
        return (
          <input id="myInput" type="text" />
        );
      }
    

    이 예시에서 컴포넌트가 마운트 된 후 useEffect 내부에서 document.querySelector를 사용해 DOM요소를 찾고 포커스를 주고 있습니다.
    - 이 방법은 작동하지만, React의 선언전 특성과 잘 어울리지 않습니다.
    - 또한 ID를 기반으로 요소를 찾기 때문에 ID가 중복되거나 변경될 경우 예상 못한 동작이 발생할 수 있습니다.
    - 그리고 리액트 렌더링 사이클과 동기화 되지 않기 때문에 만약 리렌더링이 발생되어 요소에 변화가 생기면 참조가 유효하지 않게 될 가능성도 있습니다.

  • useRef 사용 케이스

      import React, { useEffect } from 'react';
    
      function AutofocusInput() {
        useEffect(() => {
          // 컴포넌트가 마운트된 후 input 요소를 선택하여 포커스를 줌
          const inputElement = document.querySelector('#myInput');
          if (inputElement) {
            inputElement.focus();
          }
        }, []);
    
        return (
          <input id="myInput" type="text" />
        );
      }
    

    이 예시에서 useRef를 사용하면 React의 선언적 패러다임을 유지하면서도 렌더링 사이클과의 통합을 보장합니다.
    또한 컴포넌트의 렌더링 사이클과 자연스럽게 통합되어있기 때문에 컴포넌트의 상태 변화나 리렌더링에 영향을 받지 않고 일관된 참조를 유지할 수 있습니다.

마치며

useRef를 사용해야 하는지 정리하며, 리액트의 프로그래밍 철학, 랜더링 동작원리, 메모리까지 연관 되었으므로 꼭 사용해야 된다는 점을 돌이켜 볼 수 있었습니다. 이 글을 보신 분들에게도 지식을 상기하거나 새롭게 아는데 도움이 되었으면 좋겠습니다.

More from this blog

프론트엔드는 경계를 다루는 직무가 되어간다

프론트엔드는 원래도 복잡했습니다. 브라우저마다 다른 렌더링, 상태 동기화, 성능, 접근성 — 화면 하나 제대로 만드는 데 신경 쓸 게 늘 많았습니다. 다만 그 복잡함은 대체로 한 방향을 향했습니다. 이 UI를 어떻게 만들까, 상태를 어떻게 관리할까, 클릭하면 무엇이 바뀌어야 할까. 그런데 요즘 질문의 축이 하나 더 늘고 있습니다. 이 UI는 서버에서 먼저

Jul 20, 20266 min read

AI가 코드를 짜는 시대, 나는 리뷰를 못 따라가고 있었다

솔직히 말하면, 요즘 PR을 제때 리뷰하지 못하고 있습니다. 개발 속도는 빨라졌는데 리뷰 속도는 그대로입니다. 예전엔 하루 이틀이면 처리하던 게 이제는 며칠씩 밀립니다. 처음엔 제가 게을러진 탓인가 싶었습니다. 돌아보니 그게 아니었습니다. AI 도구를 쓰면서 코드가 쏟아지는 속도가 달라졌습니다. 한 사람이 만들어내는 코드 양이 예전과 비교가 안 됩니다. P

Mar 18, 20263 min read
AI가 코드를 짜는 시대, 나는 리뷰를 못 따라가고 있었다

테드풀의 한 입 지식

78 posts

가볍게 정리하는 기록들입니다.