ref와 forwardRef, 언제 왜 써야 할까?

린린린·2026년 1월 16일
post-thumbnail

프로젝트에서 스크롤 이동을 구현하다가
ref는 되는데 컴포넌트에 ref를 붙이니 에러 발생
이 글에서는
ref와 forwardRef의 차이를 “왜 필요한지” 중심으로 풀이

1. 개요

리액트에서 ref를 쓰다가 막힘

div에 ref → 잘 됨
내가 만든 컴포넌트에 ref → 에러

알고보니 차이점
직접 전달 or 배달원 거쳐서 전달


2. 그냥 ref (직접 전달)

  • HTML 태그(div, button, input 등)에 직접 ref를 붙이는 방식
<div ref={myRef}>안녕</div>

대상

  • 실제 DOM 요소 (HTML 태그)

동작 방식

  • 리액트가 해당 DOM을 직접 참조
  • ref는 곧바로 실제 요소를 가리킨다

비유로 설명하면 -> 편의점(HTML 태그)에 직접 가는 것

  • 점원과 바로 대화 가능
  • 중간 전달자 없음
  • ref가 DOM을 바로 붙잡음

따라서 이런 작업 가능

  • 높이 / 위치 측정
  • focus()
  • scrollIntoView()

3. forwardRef (전달 대행)

<Project ref={projectRef} />
  • 내가 만든 Project는 HTML이 아니라 함수형 컴포넌트
    따라서 그냥 ref 붙이면 에러남

해결 방법: forwardRef

const Project = forwardRef((props, ref) => {
  return <div ref={ref}>Project 영역</div>;
});

대상

  • 사용자 정의 컴포넌트 (Intro, Project 등)

동작 방식

  • 부모가 준 ref를
  • 자식 내부의 특정 HTML 태그로 전달(forward)

비유로 설명하면 -> 배달 앱(컴포넌트)을 통해 주문하는 상황

  • 나는 앱에 주문(ref)을 넣는다
  • 실제 음식은 식당(자식 내부 div)에서 나온다
  • forwardRef는 “이 주문을 이 식당으로 전달하세요”라고 연결해 주는 역할

4. 왜 forwardRef??

App.js (부모)

Project 컴포넌트 위치로 스크롤 -> ref 하나 던질게!

Project.js (자식, forwardRef 없음)

나는 함수인데… 이 ref를 어디에?? -> 에러 발생

forwardRef 적용 후

const Project = forwardRef((props, ref) => {
 return <div className="container" ref={ref}>...</div>;
});

그러면 부모에서 이렇게 사용

projectRef.current.scrollIntoView();

4. 한눈에 비교

구분일반 refforwardRef
사용 대상HTML 태그사용자 컴포넌트
접근 대상실제 DOM자식 내부 DOM
주요 목적포커스, 크기, 위치 제어내부 DOM을 부모에 노출
사용 방식ref={myRef}forwardRef((props, ref) => {})

ref와 forwardRef의 차이에 대해 공부하고 기록합니다

  • 리액트 스크롤 기능 구현!

이 글과 코드를 보시고 개선할 부분이나 궁금한 점이 있으면 편하게 댓글이나 메시지로 알려주세요.💪
여러분의 피드백 덕분에 더 나은 콘텐츠를 만들 수 있습니다.
함께 성장해 나가요!

profile
개발은모르겠고일단기록

0개의 댓글