안녕하세요, React 개발자 여러분! React의 세계에서 UI를 선언적으로 관리하는 매력을 즐기고 계신가요? 하지만 가끔은 가상 DOM의 편리함을 넘어 직접적인 DOM 조작이 필요할 때가 있죠. 바로 이때 React Refs가 등장합니다. Refs는 컴포넌트 내에서 DOM 요소나 다른 React 컴포넌트에 직접 접근할 수 있는 강력한 도구로, 상태(state)만으로는 해결하기 어려운 문제를 유연하게 풀어줍니다.
이 가이드에서는 Refs의 기본 개념부터 실전 사용법까지, 함수형 컴포넌트 중심으로 깊이 파헤쳐 보겠습니다. 특히 useRef 훅과 콜백 Refs 두 가지 방법을 중점적으로 다루며, 왜 이들이 React 개발의 필수 스킬인지 알아보죠. 준비되셨나요? 함께 Refs를 마스터해 보아요!
왜 Refs를 사용해야 할까?
React는 상태와 props를 통해 UI를 효율적으로 업데이트하지만, 모든 것을 상태로 관리하려다 보면 복잡해지고 성능이 떨어질 수 있습니다. Refs는 이런 한계를 보완하는 '명령형 도구'로, 다음 세 가지 이유로 필수적입니다.
1. 직접 접근과 DOM 조작의 자유로움
Refs의 핵심 매력은 DOM 노드나 클래스 컴포넌트 인스턴스에 직접 접근할 수 있다는 점입니다. React의 가상 DOM을 우회해 실시간으로 조작할 수 있어요. 주요 사용 사례:
- 입력 필드에 포커스를 주거나, 텍스트를 선택/관리할 때
- 오디오/비디오 미디어 재생을 제어할 때 (예: play(), pause())
- 애니메이션 트리거나 요소의 위치/크기 측정 (getBoundingClientRect() 활용)
예를 들어, 사용자가 입력 필드를 클릭하지 않아도 자동으로 포커스를 주는 기능을 상상해 보세요. Refs 없이는 불가능하죠!
2. 성능 최적화: 불필요한 렌더링 줄이기
상태를 업데이트할 때마다 컴포넌트가 재렌더링되는데, 이는 빈번한 변화(스크롤 위치, 실시간 입력 값)에서 비효율적입니다. Refs는 이런 '가벼운' 업데이트를 DOM 직접 조작으로 처리해 렌더링 주기를 최소화합니다. 결과적으로 앱의 반응성이 높아지고, 특히 모바일 환경에서 배터리와 CPU를 절약할 수 있어요.
3. 서드파티 라이브러리 연동의 다리 역할
D3.js나 Chart.js처럼 DOM을 직접 다루는 라이브러리를 React에 통합할 때, Refs가 '브릿지' 역할을 합니다. React의 가상 DOM과 라이브러리의 명령형 스타일을 연결해 충돌 없이 활용할 수 있죠. 예를 들어, 차트 라이브러리를 컴포넌트에 렌더링할 때 Refs로 컨테이너 요소를 전달하면 됩니다.
이제 이론은 그만! 실제로 Refs를 어떻게 생성하고 사용하는지 보겠습니다.
Refs 생성하기: useRef 훅 (표준 Refs)
함수형 컴포넌트에서 Refs를 다루는 가장 쉽고 표준적인 방법은 useRef 훅입니다. 이 훅은 초기값을 설정하고, 컴포넌트의 생명주기 동안 안정적으로 Refs를 유지합니다. (클래스 컴포넌트에서는 createRef()를 사용하지만, 요즘은 함수형이 주류죠.)
useRef 사용법 예제
간단한 텍스트 입력 필드에 포커스를 주는 예제를 보죠. 버튼 클릭 시 입력 필드가 자동 포커스됩니다.
import React, { useRef } from 'react';
const TextInput = () => {
// 1. useRef 훅으로 Ref 생성: 초기값은 null (마운트 전에는 아무것도 참조하지 않음)
const inputRef = useRef(null);
// 2. 포커스 함수: current 속성을 통해 DOM 요소 접근
const focusInput = () => {
if (inputRef.current) {
inputRef.current.focus();
}
};
return (
<div>
{/* 3. ref 속성으로 요소에 Refs 연결 */}
<input ref={inputRef} type="text" placeholder="여기에 입력하세요..." />
<button onClick={focusInput}>Focus Input</button>
</div>
);
};
export default TextInput;
핵심 포인트:
inputRef.current는 마운트된 DOM 요소(HTMLInputElement)를 가리킵니다. 언마운트되면 자동으로null이 됩니다.- 이 방법은 직관적이고, 대부분의 시나리오(포커스, 스크롤 등)에 딱 맞아요. 추가로, Refs는 렌더링 중에 변경되지 않아 무한 루프를 피할 수 있습니다.
콜백 Refs: 더 많은 제어를 위한 선택
useRef가 훌륭하지만, 때로는 콜백 Refs가 필요합니다. 이는 ref 속성에 함수를 전달하는 방식으로, 요소가 마운트/언마운트될 때마다 콜백이 호출됩니다. 동적 요소나 세밀한 생명주기 관리가 필요할 때 빛을 발합니다.
콜백 Refs의 장점
- 세밀한 제어: 마운트 직후 초기화 로직(예: 이벤트 리스너 추가)을 실행할 수 있습니다.
- 동적 요소에 강력: 조건부 렌더링이나 포털 같은 복잡한 UI에서 Refs가 자주 변경될 때 유연합니다.
- 여러 Refs 체이닝: 콜백 내에서 이전 Refs를 업데이트하며 체인을 만들 수 있어요.
콜백 Ref 예제
위 useRef 예제와 비슷하지만, 콜백으로 처리해 보죠. 여기서는 마운트 시 콘솔 로그를 추가해 생명주기를 관찰합니다.
import React from 'react';
const CallbackRefsExample = () => {
let inputElement; // Refs를 저장할 변수 (useRef 없이도 가능)
// 1. 콜백 Ref 함수: element는 마운트 시 DOM 노드, 언마운트 시 null
const setInputElement = (element) => {
inputElement = element;
if (element) {
console.log('Input 마운트됨:', element); // 초기화 로직 예시
} else {
console.log('Input 언마운트됨'); // 정리 로직 예시
}
};
const focusOnInput = () => {
if (inputElement) {
inputElement.focus();
}
};
return (
<div>
{/* 2. ref에 콜백 함수 전달 */}
<input ref={setInputElement} type="text" placeholder="콜백 Refs 테스트" />
<button onClick={focusOnInput}>Focus Input</button>
</div>
);
};
export default CallbackRefsExample;
주의할 점: 콜백 Refs는 함수형 컴포넌트에서 자주 재생성되므로, useCallback으로 메모이제이션하는 게 좋습니다. 클래스 컴포넌트에서는 인스턴스 메서드로 구현할 수 있어요.
Refs의 고급 팁: 주의할 점과 베스트 프랙티스
- 부모-자식 Refs: 자식 컴포넌트에 Refs를 전달할 때는
forwardRef를 사용하세요. (예:React.forwardRef((props, ref) => <Child ref={ref} />)) - 성능 고려: Refs를 남용하지 말고, 상태로 대체 가능한 부분은 상태를 우선하세요.
- 테스트 팁:
ref.current를 스냅샷 테스트할 때는toBeInTheDocument()같은 DOM 쿼리를 활용하세요. - 대안 탐구: 최근에는
useImperativeHandle로 커스텀 Refs를 노출할 수 있어요. 더 깊이 파고들고 싶다면 다음 포스트에서 다루죠!
결론: Refs로 더 강력한 React 앱 만들기
Refs는 React의 선언적 철학과 명령형 필요를 조화롭게 연결하는 마법 같은 도구입니다. useRef는 일상적인 DOM 조작에, 콜백 Refs는 복잡한 생명주기 관리에 적합하죠. 이 두 방법을 마스터하면 불필요한 재렌더링을 줄이고, 서드파티 통합을 쉽게 하며, 사용자 경험을 한층 업그레이드할 수 있습니다.
오늘 가이드가 Refs에 대한 두려움을 날려버렸기를 바래요! 실제 프로젝트에서 써보시고, 궁금한 점이나 팁이 있으면 댓글로 공유해 주세요. 다음 포스트에서는 Hooks 심화편으로 만나요. Happy coding! 🚀
'프로그래밍 > ReactJS' 카테고리의 다른 글
| React 프래그먼트: 깔끔한 DOM 구조와 최적화된 성능을 위한 필수 패턴 (0) | 2025.10.11 |
|---|---|
| React 개발의 숨은 조력자: useRef 훅 완전 정복! (0) | 2025.10.11 |
| React Refs 완벽 가이드: DOM 직접 조작, 과연 필요할까요? (0) | 2025.10.11 |
| React 폼 완벽 가이드: 제어/비제어 컴포넌트부터 유효성 검사까지 (1) | 2025.10.11 |
| React 폼 다루기: 비제어 컴포넌트의 이해와 활용 (0) | 2025.10.11 |