리액트에서 어떤 값을 선언하고 대응하여 사용할 때에 일반적으로 쓰이는 것은 지난 글에서 다룬 상태(State)값이다. 그런데 상태는 말 그대로 구성요소의 상태에 관계된 값이기 때문에, 상태가 변하면 구성요소 역시 변해야 한다. 즉, 상태의 변화는 구성요소를 다시 로드(렌더)시킨다. 이 동작이 원하는 동작이었다면 관계 없지만, 값이 변하더라도 결합된 구성요소가 바로 다시 렌더링되기를 원하지 않을 수 있다. 이 때 사용할 수 있는 것이 참조(useRef)이다.
useRef의 사용법은 아래와 같다:
import {useRef} from 'react';
const ref = useRef(initialValue);
위를 통해 상수 ref는 initialValue라는 초기값을 current로 갖는 객체가 되는데, 따라서 ref.current를 통해 이 값에 접근할 수 있고 바꿀 수 있다. 이렇게 변화된 값은 상태와는 달리 구성요소를 다시 렌더링하도록 하지는 않는다. 그러면서도 일반적으로 구성요소 내부에 정의된 변수들과는 달리, 리렌더링 시에 값이 초기화되지 않고 최종으로 변경된 참조값을 저장하고 있다가 사용할 수 있도록 하는 것이 useRef의 특징이다.
이 시점에서 그러면 전역변수로 let으로 값을 정의하면 되는데 왜 useRef를 써야할까라는 의문이 드는데, 실제로 전역변수로 let을 지정해 사용하면 useRef와 같이 다시 렌더링하지 않는 업데이트 가능한 변수를 만들수는 있다. 그러나 이러한 방법은 아래의 문제가 있어 useRef가 필요하다.
1. 메모리 효율성
let은 전역변수로 사용되어야 하기에 구성요소 외부에 사용되어야 하고, 이렇게 전역변수를 사용하는 구성요소가 많아질 경우 너무 많은 전역변수가 생기며 계속 값을 저장하고 있어야 해서 메모리 누수 문제와 같은 비효율성 문제가 생긴다. 그러나 useRef는 구성요소 내부에 정의되기 때문에 구성요소가 필요한 경우에만 활성화되고 해제되면 같이 사라지기 때문에 메모리 효율 측면에서 더 유리하다.
2. 값의 조작 안정성
let으로 정의된 전역변수는 어떤 구성요소도 접근이 가능하기 때문에 변수 겹침 문제나 오용으로 인한 오염 문제가 발생할 여지가 있다. useRef는 구성요소와 대응되는 관계를 갖기 때문에, 대응된 구성요소만 값을 변화시킬 수 있어 외부 오염에서 안전하고 보안성이 더 좋다.
function MyComponent() {
// ...
// 🚩 Don't write a ref during rendering
myRef.current = 123;
// ...
// 🚩 Don't read a ref during rendering
return <h1>{myOtherRef.current}</h1>;
}
useRef의 사용법이자 주의점은 값을 동일 렌더링 상에서 변경하는데에 사용하지 않고 렌더가 발생하는 시점에서의 초기값으로 활용한다는 점인데, '참조'라는 이름이 가진 의미와 같이 어디까지나 초기화 시점에서의 참조로 활용해야하며 참조 값을 계속 읽는 일이 없도록 해야한다는 것이다.
즉 위와 같이 중간에 단순히 값을 대입하거나 그 참조값을 지속적으로 읽어 보여주는 것은 참조의 동작원리와는 다르며, 오작동을 일으킬 수 있다. 이러한 동작은 어떤 특정한 이벤트나 트리거에 따라 한번씩 참조를 업데이트하거나 읽는 식으로 쓰여야 한다.
function MyComponent() {
// ...
useEffect(() => {
// ✅ You can read or write refs in effects
myRef.current = 123;
});
// ...
function handleClick() {
// ✅ You can read or write refs in event handlers
doSomething(myOtherRef.current);
}
// ...
}
useEffect와 같은 훅을 사용하거나 특정 기능에 따라 이벤트로 발생하는 것은 괜찮다는 의미이다.
useRef의 개념은 처음 접했을 때에는 쉬운 듯 하면서도 처음에는 왜 이걸 쓰지? 다른 방법이 있지 않나? 라는 생각이 들게 만들고 나중에는 상태(State)와 혼용해 문제를 발생시키는 측면이 있다. 참조(reference)의 의미를 되새기고 훅이 만들어진 배경과 정신을 이해하는 접근이 필요한 이유이다.
'React.Native' 카테고리의 다른 글
[React] 시스템의 공영 방송: Context API (0) | 2024.11.17 |
---|---|
[React] Props는 통신용이 아니다 : Props 진짜 이해하기 (3) | 2024.11.15 |
[React] useEffect와 정리함수(clean up) (10) | 2024.11.10 |
[React] useEffect 이해하기 (1) | 2024.11.09 |
[React] State 이해하기 : useState (2) | 2024.11.08 |