React Refs를 심층적으로 탐구하고 useRef와 createRef에 초점을 맞춘 종합 가이드입니다. 전역 애플리케이션에서 효율적인 컴포넌트 관리 및 DOM 접근을 위해 각각을 언제, 어떻게 사용해야 하는지 알아보세요.
React Refs: useRef vs. createRef 심층 분석
React 개발의 역동적인 세계에서 컴포넌트 상태를 효율적으로 관리하고 문서 객체 모델(DOM)과 상호작용하는 것은 매우 중요합니다. React Refs는 DOM 요소나 React 컴포넌트에 직접 접근하고 조작할 수 있는 메커니즘을 제공합니다. Ref를 생성하는 두 가지 주요 방법은 useRef
와 createRef
입니다. 둘 다 Ref를 생성하는 목적은 같지만, 구현 방식과 사용 사례에서 차이가 있습니다. 이 가이드는 이 두 가지 접근 방식을 명확히 설명하고, 특히 전역 사용자를 대상으로 개발할 때 React 프로젝트에서 각각을 언제, 어떻게 효과적으로 활용할 수 있는지에 대한 명확성을 제공하는 것을 목표로 합니다.
React Refs 이해하기
Ref(참조의 약어)는 DOM 노드 또는 React 컴포넌트에 직접 접근할 수 있도록 해주는 React 기능입니다. 이는 다음과 같은 경우에 특히 유용합니다:
- 입력 필드에 포커스를 맞추는 등 DOM 요소를 직접 조작해야 할 때.
- 자식 컴포넌트의 메서드 또는 속성에 접근해야 할 때.
- 리렌더링을 유발하지 않고 렌더링 전반에 걸쳐 지속되는 값을 관리할 때 (클래스 컴포넌트의 인스턴스 변수와 유사).
React는 UI가 상태와 props를 통해 관리되는 선언적 접근 방식을 권장하지만, 직접적인 조작이 필요한 상황도 있습니다. Refs는 React의 선언적 특성과 명령형 DOM 작업 사이의 간극을 메울 수 있는 방법을 제공합니다.
createRef
: 클래스 컴포넌트 접근 방식
createRef
는 React에서 제공하는 메서드입니다. 주로 클래스 컴포넌트 내에서 Ref를 생성하는 데 사용됩니다. 클래스 컴포넌트가 인스턴스화될 때마다 createRef
는 새로운 Ref 객체를 생성합니다. 이는 컴포넌트의 각 인스턴스가 고유한 Ref를 갖도록 보장합니다.
구문 및 사용법
createRef
를 사용하려면 먼저 클래스 컴포넌트, 일반적으로 생성자에서 Ref를 선언합니다. 그런 다음 ref
속성을 사용하여 Ref를 DOM 요소 또는 컴포넌트에 연결합니다.
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
}
componentDidMount() {
// 컴포넌트가 마운트된 후 DOM 요소에 접근
this.myRef.current.focus();
}
render() {
return ;
}
}
이 예시에서 this.myRef
는 React.createRef()
를 사용하여 생성됩니다. 그런 다음 input 요소의 ref
속성에 할당됩니다. 컴포넌트가 마운트된 후(componentDidMount
에서) this.myRef.current
를 사용하여 실제 DOM 노드에 접근하고 작업을 수행할 수 있습니다(이 경우 input에 포커스).
예시: 입력 필드에 포커스하기
컴포넌트가 마운트될 때 입력 필드에 자동으로 포커스를 맞추고 싶은 시나리오를 생각해 봅시다. 이는 Ref의 일반적인 사용 사례이며, 특히 양식이나 대화형 요소에서 그렇습니다.
class FocusInput extends React.Component {
constructor(props) {
super(props);
this.inputRef = React.createRef();
}
componentDidMount() {
this.inputRef.current.focus();
}
render() {
return (
);
}
}
이 예시에서 FocusInput
은 마운트된 직후 입력 필드에 포커스를 맞춥니다. 이는 컴포넌트가 렌더링되자마자 사용자의 주의를 입력 요소로 유도하여 사용자 경험을 개선할 수 있습니다.
Important Considerations with createRef
- 클래스 컴포넌트 전용:
createRef
는 클래스 컴포넌트에서 사용하도록 설계되었습니다. 기술적으로 함수형 컴포넌트에서도 작동할 수 있지만, 의도된 사용법이 아니며 예기치 않은 동작으로 이어질 수 있습니다. - 각 인스턴스에 대한 새 Ref: 클래스 컴포넌트의 각 인스턴스는 자체
createRef
를 얻습니다. 이는 컴포넌트 인스턴스 간의 격리를 유지하는 데 중요합니다.
useRef
: 함수형 컴포넌트 Hook
useRef
는 React 16.8에서 도입된 Hook입니다. 함수형 컴포넌트 내에서 변경 가능한 Ref 객체를 생성하는 방법을 제공합니다. createRef
와 달리 useRef
는 컴포넌트가 렌더링될 때마다 동일한 Ref 객체를 반환합니다. 이로 인해 리렌더링을 유발하지 않고 렌더링 전반에 걸쳐 값을 유지하는 데 이상적입니다.
구문 및 사용법
useRef
를 사용하는 것은 간단합니다. 초기 값을 전달하여 useRef
Hook을 호출합니다. Hook은 .current
속성을 가진 객체를 반환하며, 이를 사용하여 값에 접근하고 수정할 수 있습니다.
import React, { useRef, useEffect } from 'react';
function MyFunctionalComponent() {
const myRef = useRef(null);
useEffect(() => {
// 컴포넌트가 마운트된 후 DOM 요소에 접근
if (myRef.current) {
myRef.current.focus();
}
}, []);
return ;
}
이 예시에서 useRef(null)
은 초기 값이 null
인 Ref를 생성합니다. useEffect
Hook은 컴포넌트가 마운트된 후 DOM 요소에 접근하는 데 사용됩니다. myRef.current
속성은 input 요소에 대한 참조를 보유하여 포커스를 맞출 수 있도록 합니다.
예시: 이전 prop 값 추적하기
useRef
의 강력한 사용 사례 중 하나는 prop의 이전 값을 추적하는 것입니다. Ref 변경은 리렌더링을 유발하지 않으므로, UI에 영향을 미치지 않고 렌더링 전반에 걸쳐 유지하려는 값을 저장하는 데 사용할 수 있습니다.
import React, { useRef, useEffect } from 'react';
function PreviousValueComponent({ value }) {
const previousValue = useRef();
useEffect(() => {
previousValue.current = value;
}, [value]);
return (
Current Value: {value}
Previous Value: {previousValue.current}
);
}
이 예시에서 previousValue.current
는 value
prop의 이전 값을 저장합니다. useEffect
Hook은 value
prop이 변경될 때마다 Ref를 업데이트합니다. 이를 통해 현재 값과 이전 값을 비교할 수 있으며, 이는 변경 사항을 감지하거나 애니메이션을 구현하는 데 유용할 수 있습니다.
Important Considerations with useRef
- 함수형 컴포넌트 전용:
useRef
는 Hook이며 함수형 컴포넌트 또는 사용자 정의 Hook 내에서만 사용할 수 있습니다. - 렌더링 전반에 걸쳐 지속:
useRef
Hook은 모든 렌더링에서 동일한 Ref 객체를 반환합니다. 이는 리렌더링을 유발하지 않고 값을 유지하는 능력의 핵심입니다. - 변경 가능한
.current
속성: Ref 객체의.current
속성을 직접 수정할 수 있습니다. - 초기 값:
useRef
에 초기 값을 제공할 수 있습니다. 이 값은 컴포넌트가 처음 렌더링될 때.current
속성에 할당됩니다. - 리렌더링 없음: Ref의
.current
속성을 수정해도 컴포넌트 리렌더링이 발생하지 않습니다.
useRef
vs. createRef
: 상세 비교
이제 useRef
와 createRef
를 각각 살펴보았으므로, 주요 차이점과 언제 어떤 것을 선택해야 하는지를 강조하기 위해 나란히 비교해 보겠습니다.
기능 | useRef |
createRef |
---|---|---|
컴포넌트 유형 | 함수형 컴포넌트 | 클래스 컴포넌트 |
Hook 또는 메서드 | Hook | 메서드 |
Ref 인스턴스 | 모든 렌더링에서 동일한 Ref 객체 반환 | 컴포넌트의 각 인스턴스에서 새로운 Ref 객체 생성 |
사용 사례 |
|
|
올바른 Ref 선택하기: 결정 가이드
useRef
와 createRef
중에서 선택하는 데 도움이 되는 간단한 가이드입니다:
- 함수형 컴포넌트로 작업 중이신가요?
useRef
를 사용하세요. - 클래스 컴포넌트로 작업 중이신가요?
createRef
를 사용하세요. - 리렌더링을 유발하지 않고 렌더링 전반에 걸쳐 값을 유지해야 하나요?
useRef
를 사용하세요. - prop의 이전 값을 추적해야 하나요?
useRef
를 사용하세요.
DOM 조작을 넘어: Ref의 고급 사용 사례
DOM 요소에 접근하고 조작하는 것이 Ref의 주요 사용 사례이지만, 이러한 핵심 기능 이상으로 다양한 가능성을 제공합니다. Ref가 특히 유용할 수 있는 몇 가지 고급 시나리오를 살펴보겠습니다.
1. 자식 컴포넌트 메서드 접근
Ref는 자식 컴포넌트에 정의된 메서드에 접근하는 데 사용될 수 있습니다. 이를 통해 부모 컴포넌트가 자식으로부터 직접 작업을 트리거하거나 데이터를 검색할 수 있습니다. 이 접근 방식은 자식 컴포넌트에 대한 세밀한 제어가 필요할 때 특히 유용합니다.
class ParentComponent extends React.Component {
constructor(props) {
super(props);
this.childRef = React.createRef();
}
handleClick = () => {
// 자식 컴포넌트의 메서드 호출
this.childRef.current.doSomething();
};
render() {
return (
);
}
}
class ChildComponent extends React.Component {
doSomething = () => {
console.log('자식 컴포넌트 액션이 트리거되었습니다!');
};
render() {
return 이것은 자식 컴포넌트입니다.;
}
}
이 예시에서 ParentComponent
는 Ref를 사용하여 ChildComponent
에 접근하고 doSomething
메서드를 호출합니다.
2. 포커스 및 선택 관리
Ref는 입력 필드 및 기타 대화형 요소 내에서 포커스와 선택을 관리하는 데 매우 유용합니다. 이는 접근성 높고 사용자 친화적인 인터페이스를 만드는 데 중요합니다.
import React, { useRef, useEffect } from 'react';
function FocusOnMount() {
const inputRef = useRef(null);
useEffect(() => {
if (inputRef.current) {
inputRef.current.focus();
inputRef.current.select(); // 입력 필드의 텍스트 선택
}
}, []);
return ;
}
이 예시는 컴포넌트가 마운트되자마자 입력 필드에 포커스를 맞추고 텍스트를 선택합니다.
3. 요소 애니메이션
Ref는 애니메이션 라이브러리(예: GreenSock 또는 Framer Motion)와 함께 사용하여 DOM을 직접 조작하고 복잡한 애니메이션을 만들 수 있습니다. 이를 통해 애니메이션 시퀀스를 세밀하게 제어할 수 있습니다.
단순화를 위한 일반 JavaScript 예시:
import React, { useRef, useEffect } from 'react';
function AnimatedBox() {
const boxRef = useRef(null);
useEffect(() => {
const box = boxRef.current;
if (box) {
// 간단한 애니메이션: 상자를 오른쪽으로 이동
box.animate(
[
{ transform: 'translateX(0)' },
{ transform: 'translateX(100px)' },
],
{
duration: 1000, // 1초
iterations: Infinity, // 무한 반복
direction: 'alternate',
}
);
}
}, []);
return ;
}
이 예시는 웹 애니메이션 API를 사용하여 간단한 상자를 수평으로 앞뒤로 움직이는 애니메이션을 만듭니다.
전역 애플리케이션에서 React Refs 사용을 위한 모범 사례
전역 사용자를 대상으로 React 애플리케이션을 개발할 때, Ref가 국제화(i18n) 및 지역화(l10n)와 어떻게 상호작용하는지 고려하는 것이 중요합니다. 다음은 몇 가지 모범 사례입니다:
1. 접근성 (A11y)
Ref 사용이 접근성에 부정적인 영향을 미치지 않도록 하십시오. 예를 들어, 프로그래밍 방식으로 요소에 포커스를 맞출 때 사용자의 포커스 순서와 포커스 변경이 스크린 리더 및 키보드 사용자에게 적절한지 고려하십시오.
import React, { useRef, useEffect } from 'react';
function AccessibleFocus() {
const buttonRef = useRef(null);
useEffect(() => {
const button = buttonRef.current;
if (button) {
// 버튼이 사용자에게 이미 포커스되어 있지 않은 경우에만 포커스
if (document.activeElement !== button) {
button.focus();
}
}
}, []);
return ;
}
2. 국제화된 입력 필드
입력 필드로 작업할 때, 다른 언어에서 사용되는 다양한 입력 방식과 문자 세트에 유의하십시오. Ref 기반 조작(예: 선택, 커서 위치)이 다양한 입력 유형과 로케일에서 올바르게 작동하는지 확인하십시오. 다른 언어와 입력 방식으로 컴포넌트를 철저히 테스트하십시오.
3. 오른쪽에서 왼쪽(RTL) 레이아웃
애플리케이션이 RTL 언어(예: 아랍어, 히브리어)를 지원하는 경우, Ref를 사용하는 DOM 조작이 반전된 레이아웃을 고려하는지 확인하십시오. 예를 들어, 요소를 애니메이션할 때 RTL 언어의 애니메이션 방향을 반전시키는 것을 고려하십시오.
4. 성능 고려 사항
Ref는 DOM과 상호작용하는 강력한 방법을 제공하지만, 과도하게 사용하면 성능 문제를 일으킬 수 있습니다. 직접적인 DOM 조작은 React의 가상 DOM 및 재조정 프로세스를 우회하여 불일치 및 느린 업데이트로 이어질 수 있습니다. Ref는 신중하게 그리고 필요할 때만 사용하십시오.
결론
React Refs, 특히 useRef
와 createRef
는 React 개발자에게 필수적인 도구입니다. 각 접근 방식의 뉘앙스를 이해하고 언제 효과적으로 적용해야 하는지 아는 것은 견고하고 성능 좋은 애플리케이션을 구축하는 데 중요합니다. createRef
는 클래스 컴포넌트 내에서 Ref를 관리하는 표준으로 남아 있으며, 각 인스턴스가 고유한 Ref를 갖도록 보장합니다. 렌더링 전반에 걸쳐 지속되는 특성을 가진 useRef
는 함수형 컴포넌트에 이상적이며, DOM 요소를 관리하고 불필요한 리렌더링을 유발하지 않고 값을 유지하는 방법을 제공합니다. 이러한 도구를 현명하게 활용함으로써, 접근성 높고 성능 좋은 인터페이스로 전 세계 사용자를 만족시키는 React 애플리케이션의 기능과 사용자 경험을 향상시킬 수 있습니다.
React가 계속 발전함에 따라, 이러한 기본 개념을 숙달하면 지리적, 문화적 경계를 초월하는 혁신적이고 사용자 친화적인 웹 경험을 만들 수 있습니다. 진정으로 전 세계적인 애플리케이션을 제공하기 위해 접근성, 국제화 및 성능을 우선시하는 것을 기억하십시오.