안녕하세요 메이토입니다 🍅 요즘 리액트 공식 문서 스터디에서 Hook을 주에 2개씩 뿌셔보고 있는데, 마침 이름도 길고, 써본적 없는 생소한 훅이 있어 이번 기회에 소개해보려고 합니다 !
한번도 사용해본적 없는 훅이라 정의부터 사용법, 중간 중간 리액트 공식 문서에서 들었던 의문을 같이 녹여내었습니다 :)
useImperativeHandle 이란?
정의
useImperativeHandle은 ref로 노출되는 핸들을 사용자가 직접 정의할 수 있게 해주는 훅
React Hook that lets you customize the handle exposed as a ref
사용법
useImperativeHandle(ref,createHandle, dependencies?)
❓ 노출과 핸들, 각 단어는 어떤걸 의미하는가?
노출 (expose) : 부모 컴포넌트가 자식 컴포넌트 내부의 어떤 것에 접근할 수 있게 해주는 것
React의 기본 데이터 흐름은 부모에서 자식으로 데이터를 내려주는 단방향 흐름이 기본인데, 반대로 부모가 자식의 내부 메서드 내지 값에 접근하고 싶을 때 이 훅을 사용하게 됩니다.
핸들(handle) : 사용자 정의 메서드를 담은 객체
import { useImperativeHandle } from 'react';
function MyInput({ ref }) {
useImperativeHandle(ref, () => {
return {
// ... 메서드를 여기에 입력하세요 ...
};
}, []);
// ...
ref - props로 받은 ref
createHandle - 인수가 없고 노출하려는 ref 핸들을 반환하는 함수
dependencies - createHandle 내부에서 참조된 모든 반응형 값들 (props, state, 모든 변수와 함수)
💡 React 19 부터는 ref가 prop으로 가능해졌어요 !
❓ 이전에는 어떻게 썼나?
forwardRef로 감싸서 ref를 가져왔어야 했어요 !
forwardRef 란 '부모 컴포넌트가 자식 함수형 컴포넌트의 ref 에 접근할 수 있게 하는 고차함수'입니다 !
ref 는 원래 DOM 요소에만 붙을 수 있는데 함수형 컴포넌트는 DOM 요소가 아니기 때문에 직접 ref를 붙일 수는 없었습니다 🤔
부모 요소에 DOM 노드를 노출 시키고 싶다면 ref를 prop으로 넘겨라
function MyInput({ ref }) {
return <input ref={ref} />;
};
위 방법대로 하면 단순히 ref 만 props로 전달하는거니까, input DOM 자체가 부모에 노출됩니다
import { useImperativeHandle } from 'react';
function MyInput({ ref }) {
useImperativeHandle(ref, () => {
return {
// ... 메서드를 여기에 입력하세요 ...
};
}, []);
return <input />;
};
이 때 DOM 자체를 전달하지 않고 커스텀한 메서드 등을 전달하고 싶을 경우에 useImperativeHandle 훅을 사용해볼 수 있는데, 공식 문서에 다음과 같은 말이 있습니다.
Note that in the code above, the ref is no longer passed to the <input>.
ref는 더이상 <input>에 전달이 되지 않는다는 의미인데, 이 말이 뭘 의미할까요? 부모가 MyInput 이라는 컴포넌트에 ref를 주더라도, useImperativeHandle의 콜백을 통해 반환하는 커스텀 핸들을 가리키게 될 뿐, 내부 input DOM 자체는 가리키지 않습니다.
즉, 부모 컴포넌트가 MyInput에 대한 ref를 가져온다고 하더라도 input DOM 자체를 가리키지 않으므로 Input DOM 노드에 대한 전체 액세스 권한은 없고, 콜백에 넘겨져있는 메서드만 호출할 수 있다는 얘기가 되겠죠
The methods you expose via an imperative handle don’t have to match the DOM methods exactly.
이 떄, useImperativeHandle을 통해 노출하는 메서드는 DOM 메서드와 정확하게 일치할 필요가 없습니다. 이 훅을 썼을 때의 ref.current 는 커스텀 객체가 될 수 있고 DOM 의 실제 메서드와 이름이 같을 필요가 없어요. 이러한 이유는 이 훅 자체의 목적이 DOM 자체를 부모가 만지지 않도록 인터페이스를 제어하기 위함이에요!
❓ 그래서 왜 DOM 노드에 대한 전체 액세스를 막고 일부 커스텀 메서드에 대해서만 허용하게 되었을까?
이 이유를 알기 위해서는 DOM 에 대한 전체 액세스를 허용할 경우 발생할 수 있는 문제부터 살펴봐야겠죠? 단순합니다만, 부모가 자식 DOM 을 무제한으로 조작하게 된다는 문제가 발생하게 되기 때문이에요 ,, 그렇다면 DOM 노드를 무제한으로 조작하는건 왜 문제일까요?
- 자식 컴포넌트의 캡슐화 깨짐
- 자식이 내부에서 어떤 구조를 갖든 상관없이 외부에서 직접 접근 가능해진다.
- 예: <input>을 <textarea>로 바꿨더니 부모에서 ref.current.value 하던 코드가 터진다.
- 부모 - 자식 간 강한 결합도 발생
- 1.2와 유사한 결로, 자식의 요소가 바뀌면 부모도 바뀌어야 한다.
ref를 과도하게 사용하지 말 것
열심히 훅에 대해 설명해놓고 이게 무슨 말이냐구요? 그치만 공식 문서에서 이렇게 이야기 합니다 ..
즉, ref는 React 컴포넌트가 직접 접근할 수 없는 DOM 요소나 자식 컴포넌트 인스턴스에 대한 참조를 제공하는 도구인데,
ref를 너무 남용하게 되면 어쨌든 데이터를 받을 수는 있겠지만, 유지보수가 어려워지고, 컴포넌트 간 책임이 불명확해진다는 단점이 있습니다.
즉, props로 전달할 수 있는 값은 props로, 명시적으로 전달하자는 이야기 입니다!
마무리
부모가 자식 컴포넌트의 ref를 통해 접근할 수 있는 메서드나 값을 자식이 직접 선택적으로 노출하도록 도와주는 훅 이라고 한줄 요약할 수 있겠네요 !
'리액트 톺아보기' 카테고리의 다른 글
| Memoization, 최적화 (0) | 2025.05.22 |
|---|---|
| [React] 제어 컴포넌트 vs. 비제어 컴포넌트 (0) | 2025.05.08 |
| [React] React의 렌더링 트리🌳 (0) | 2025.04.24 |
