useState vs useRef 톺아보기

moreas·2023년 11월 28일

react

목록 보기
1/3
post-thumbnail

들어가기 전에

몇 달 전 팀 프로젝트에서 로그인과 관련해 정해진 시간이 지나면 자동으로 로그아웃을 해주는 커스텀 훅을 구현하는 도중, 내부 컴포넌트에서 확장하여 DOM 자체에 영향을 줄 수 있는 로직을 작성하기 위해 useRef를 사용한 경험이 있었다.

그때도 100% 만족스럽게 구현이 되진 않았지만, 제대로 짚어보지 않고 표면적인 개념만 살펴보고 넘어갔더니 이후에 리팩토링이나 강의를 들을 때 뭔가 2퍼센트 부족하고,, 성에 차지 않음(?)을 느꼈다.
그래서 useState와 useRef에 대해서 알아보고 막연하게 알고 있던 둘의 차이점을 정확하게 톺아보기 위해 작성하고자 한다.



useState의 정의에 대해서 알기 위해서는 우선 리액트가 가진 특징을 전제로 알아두어야 한다.

React에서 알아두어야 할 포인트

  • 리액트는 인터페이스를 만들기 위한 자바스크립트 라이브러리로, vue와 같은 프레임워크에 비해 자율성이 높은 라이브러리 형식으로 ui를 중심으로 구현하기 위해 사용된다. UI를 컴포넌트 단위로 보여주고 event에 반응하도록 만들어 나가는 라이브러리이다.

  • 리액트 컴포넌트를 구성하는 동작원리는 크게 3가지로 본다.

  • 컴포넌트에서 반환값을 나타내는 render, 컴포넌트의 내부 상태인 state, 외부에서 받아온 상태를 뜻하는 props.

  • 우리는 그 중 state를 관리하는 useState의 특징에 대해 알아볼 것이다.




🧼 useState

useState는 React Hook의 일종으로, 컴포넌트에 state 변수를 추가할 수 있는 Hook(재사용 가능한 로직)이다.

특징

const [state, setState] = useState(initialState);

1. 배열 구조분해할당을 사용하여 변수명과 같은 set 함수를 설정해주는 것이 규칙

2. 조건문이나 반복문 내부에선 호출할 수 없다.

3. 두 개의 값을 가진 배열을 반환한다.



상태 관리 ?

  • 컴포넌트의 상태를 관리한다...는 문장이 지금에야 익숙해졌지만 처음엔 와닿지 않았다. 그러다가 깨달은 점은 웹 플랫폼은 수많은 상호작용으로 이루어진 결과물이므로 화면에서 아주 작은 상호작용이라도 일어난다면 그 상호작용이 업데이트된 화면을 띄우기 위해서는 상태를 관리해야 한다는 점이다.

  • 컴포넌트 내부에는 그들의 상태를 다루는 state가 있다. 사용자가 입력하는 이벤트가 변경될 때마다 화면에 표시되는 상태를 지속적으로 업데이트 해주어야 한다는 것이다.

  • 리액트에서는 상태값이 업데이트된 컴포넌트를 리렌더링하여 보여준다.

  • 인터페이스가 일어나는 경우에 상태를 업데이트 할 수 있도록 useState를 사용한다.




🧽 useRef

useRef는 렌더링에 필요하지 않은 값을 참조할 수 있는 React Hook

특징

const ref = useRef(initialValue)

1. 단일 프로퍼티를 가진 객체를 반환한다.

{ current: initialValue }

2. current 속성을 사용해서 값을 변경할 수 있다.

3. ref를 변경해도 리렌더링이 발생하지 않는다.

-> 리렌더링 사이에 정보를 저장할 수 있다.
-> 외부 변수와 달리 각각의 컴포넌트에 로컬로 저장된다.

4. Ref로 DOM 조작할 수 있다.

-React는 자동으로 DOM을 변경하고 처리하기 때문에 컴포넌트에서 DOM을 조작해야 할 필요가 없지만 가끔 특정 노드에 포커스를 옮기거나, 스크롤 위치를 옮기거나, 위치와 크기를 측정하기 위해 DOM 요소에 접근해야 할 때가 있다. React는 이런 작업을 수행하는 내장된 기능이 없기 때문에 DOM 노드에 접근하기 위한 ref가 필요하다.

-얼마 전 메뉴 클릭 시 스크롤 이동하는 기능을 구현했는데 이것도 Ref로 DOM을 조작한 예시가 될 수 있다.



  • useState와 useRef는 함수형 컴포넌트에서 상태관리를 위한 hooks라는 점에서는 기본적으로 비슷한 성질을 갖고 있다.



🫧 유의미한 차이점?

렌더링 유무

  • useState는 리렌더링이 일어난다.
  • useRef는 상태가 변경되어도 리렌더링이 일어나지 않는다. ref는 일반 JavaScript 객체라서 React는 사용자가 언제 변경했는지 알지 못하기 때문이다.

반환값

  • useState는 항상 두 개 값을 가진 배열을 반환하고,
  • useRef는 객체를 반환한다.

예시

  • 리액트 공식 문서에서 두 hook의 차이점을 보여준 예시가 있다.

useState 사용

import { useState } from 'react';

export default function Counter() {
  const [count, setCount] = useState(0);

  function handleClick() {
    setCount(count + 1);
  }

  return (
    <button onClick={handleClick}>
      You clicked {count} times
    </button>
  );
}

useRef 사용

import { useRef } from 'react';

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

  function handleClick() {
    // 이것은 컴포넌트의 리렌더를 일으키지 않습니다!
    countRef.current = countRef.current + 1;
  }

  return (
    <button onClick={handleClick}>
      You clicked {countRef.current} times
    </button>
  );
}




어떻게 사용하면 좋을까

  • 간단하게 생각하면.. 리렌더링이 필요한 바로바로 업데이트 상태를 변경해야 한다면(w좀 더 동적인 이벤트라면) useState를, 그게 아니라면 useRef를 사용할 수 있다.

  • '무엇을 변경해야 할 대상인 "상태"로 보는지'가 중요한 관점이 될 수도 있다고 생각했다.

  • 예전 useRef로 작성했던 타이머 작동 로직에 대해서, 타이머는 ui에 적용되지 않으므로 ref를 사용했는데 적절했나? 생각해본다면 대답은 yes다. 페이지의 성격에 따라 달라질 수도 있을 것이다.



마무리

이렇게 리액트 훅에 대해 자세히 들어가다보니.. 자바스크립트를 마스터하는 게 얼마나 얼마나 얼마나 x 1000 중요한지 더 체감하게 되었다.

자바스크립트의 기본 개념에 대해서만 충실히 알고 있다면 그걸 감싼 라이브러리나 프레임워크가 무엇이든 활용과 적용을 더 쉽게 할 수 있다고 확신한다.

프로그래밍이나 코딩을 공부한 지 이제 1년이 조금 되어가는 시점에서, 평생을 문과로 살아온 내가 CS 공부는 어떤 방식으로 해야 더 효율적인지 그 방법론에 대해서도 길을 찾아가고 있다. 그 시간들이 마냥 쉽고 재밌기만 하다면 거짓말일 것이다.

“한 권의 책은 우리 안의 얼어붙은 바다를 깨는 도끼" 라는 카프카의 말처럼 개발자가 되기 위한 공부가 불가능이라고 생각해왔던 나의 또다른 벽을 깨는 무기가 되었으면 한다. (쓸데없이 비장..)

자 이제 해산! 하지말고 공부해.

참고 자료

profile
Everything is connected 🐶 좀 더 나은 개발을 위해

0개의 댓글