학습 공간 개념 · 판단 · 실험

Frontend Performance Lab

React

Key·Ref·폼과 트리의 정체성

트리 위치·타입·key는 상태의 정체성을 결정하고, ref는 리렌더링을 유발하지 않는 값을 보관합니다.

이럴 때 필요해요

목록 순서가 바뀔 때 입력창 상태가 엉키는 문제를 막고 폼 데이터 소유권과 DOM 접근 경계를 명확히 다룹니다.

어떻게 동작하나요?

할 일 목록에서 맨 위 항목을 삭제했는데 아래 항목의 입력창 글자가 엉뚱하게 남아 있던 적이 있나요? React는 컴포넌트가 트리에서 차지하는 위치, 타입, 그리고 key를 보고 '이 컴포넌트가 아까 그 컴포넌트인지' 정체성을 판단합니다. 따라서 순서가 바뀌거나 추가·삭제되는 목록에서는 배열 index 대신 데이터의 고유 ID를 key로 주어야 상태가 올바른 항목을 따라갑니다. 반대로 선택된 사용자가 바뀔 때 폼에 남아 있던 이전 입력 상태를 깨끗이 비우고 싶다면, 폼 컴포넌트의 key를 user.id로 바꿔 새 컴포넌트로 다시 마운트시킬 수 있습니다.

렌더 사이에 값은 유지하고 싶지만 값이 바뀔 때마다 화면을 다시 그릴 필요는 없다면 useRef를 사용합니다. ref.current는 타이머 ID를 저장하거나 마운트된 실제 input DOM 노드에 포커스를 줄 때 유용합니다. 반대로 화면에 보여야 하는 데이터를 ref에만 담아 바꾸면 React가 변경을 알지 못해 화면이 갱신되지 않습니다.

폼 입력은 현재 값을 React state가 관리하는 제어 입력(value + onChange)과 DOM 자체가 값을 들고 있게 하는 비제어 입력(defaultValue + ref/FormData)으로 나눕니다. 또한 여러 요소를 추가 DOM 태그 없이 묶을 때는 Fragment를 쓰고, 모달처럼 부모의 overflow 제약을 피해 다른 DOM 위치에 그려야 할 때는 Portal을 쓰되 React 이벤트 전파와 Context는 기존 React 트리를 그대로 따른다는 점을 함께 챙깁니다.

코드 예제

동작을 설명하는 읽기 전용 예제입니다.

example.jsx
items.map(item => (
  <Row key={item.id} item={item} />
));
// 사용자가 바뀌면 폼 상태를 의도적으로 초기화
<ProfileForm key={user.id} user={user} />;
jsx · 읽기 전용5줄

안정적인 item.id를 key로 주면 목록 순서가 바뀌어도 각 행의 상태가 유지되고, ProfileForm에 user.id를 key로 주면 사용자가 바뀔 때 폼 내부 상태를 의도적으로 초기화할 수 있습니다.

자주 헷갈리는 포인트

  • 렌더링할 때마다 Math.random() 등으로 매번 새로운 key를 만들어 컴포넌트 상태와 DOM을 불필요하게 초기화하지 않습니다.
  • Portal로 모달을 body 아래에 그렸다고 해서 키보드 포커스 트랩과 스크린 리더 접근성이 자동으로 완성된다고 생각하지 않습니다.

내 말로 설명해 보기

같은 위치에 렌더링되는 프로필 수정 폼에서 대상 사용자가 바뀔 때 내부 입력 상태를 가장 간단히 초기화하려면 어떻게 할까요?

실전 시나리오에 적용해 보기

함께 읽으면 좋은 개념

관련 면접 질문 7개

React의 이벤트 처리는 HTML 이벤트 속성과 어떻게 다른가요?

HTML에서는 onclick 속성에 실행할 코드 문자열을 적지만, React JSX에서는 onClick처럼 camelCase 속성에 함수 참조를 직접 전달합니다. React는 브라우저별 차이를 정규화한 합성 이벤트(SyntheticEvent) 객체를 핸들러에 넘겨주며, 루트 컨테이너 수준에서 이벤트를 위임받아 효율적으로 처리합니다. 또한 기본 동작을 막을 때는 return false를 쓰는 대신 event.preventDefault()를 명시적으로 호출해야 하고, 전파 중단이 필요할 때는 event.stopPropagation()을 구분해 사용합니다.

꼬리질문과 참고자료 →

목록을 렌더링할 때 key가 필요한 이유는 무엇인가요?

key는 배열 목록의 형제 엘리먼트 사이에서 각 항목의 고유한 정체성을 식별해, 항목이 추가·삭제·재정렬될 때 React가 이전 상태와 DOM 노드를 정확한 대상에 연결하도록 돕는 표식입니다. 따라서 데이터베이스 ID처럼 항목이 이동해도 변하지 않는 안정적이고 유일한 값을 key로 지정해야 합니다. 반대로 선택된 사용자나 탭이 바뀔 때 하위 폼의 내부 state를 깨끗이 초기화하고 싶다면 컴포넌트의 key를 의도적으로 바꿔 새 인스턴스로 마운트시키는 패턴도 자주 활용합니다.

꼬리질문과 참고자료 →

ref는 언제 사용하고 state와 어떻게 다른가요?

ref는 렌더 사이에 값을 유지하지만, ref.current 값을 바꿔도 재렌더를 일으키지 않는 변경 가능한 컨테이너입니다. 반면 state는 값이 바뀌면 다음 화면 계산을 요청하므로 화면에 표시되는 데이터에 사용합니다. 따라서 포커스 이동·스크롤 제어·크기 측정처럼 실제 DOM 노드에 명령형으로 접근해야 하거나, 타이머 ID·이전 값 기록처럼 화면 출력과 무관한 내부 값을 보관할 때 ref를 사용합니다.

꼬리질문과 참고자료 →
나머지 질문 4개

공식 참고 자료

← React