미친 React key

발행: (2026년 2월 15일 오후 11:42 GMT+9)
4 분 소요
원문: Dev.to

Source: Dev.to

map을 통한 렌더링

예시 1

export function Parent() {
  const [array, setArray] = useState([1, 2, 3, 4, 5]);

  useEffect(() => {
    setTimeout(() => {
      setArray((prev) => [6, 7, 8, 9, 10, ...prev]);
    }, 3000);
  }, []);

  return (
    <>
      {array.map((item) => (
        
      ))}
    
  );
}

export function Child({ item }: { item: number }) {
  console.log(item);
  return <>{item};
}

실험 결과: 1 2 3 4 5

예시 2

export function Parent() {
  const [array, setArray] = useState([1, 2, 3, 4, 5]);

  useEffect(() => {
    setTimeout(() => {
      setArray((prev) => [6, 7, 8, 9, 10, ...prev]);
    }, 3000);
  }, []);

  return (
    <>
      {array.map((_, index) => (
        
      ))}
    
  );
}

실험 결과: 6, 7, 8, 9, 10, 1, 2, 3, 4, 5

예시 3

export function Parent() {
  const [array, setArray] = useState([1, 2, 3, 4, 5]);

  useEffect(() => {
    setTimeout(() => {
      setArray((prev) => [
        ...prev.slice(0, 2),
        10,
        ...prev.slice(3, prev.length),
      ]);
    }, 3000);
  }, []);

  return (
    <>
      {array.map((item) => (
        
      ))}
    
  );
}

export function Child({ item }: { item: number }) {
  return <>{item};
}

실험 결과: 10

실험 1

  • 초기 상태: [1, 2, 3, 4, 5] → [6, 7, 8, 9, 10, 1, 2, 3, 4, 5]
memo 사용 여부key렌더링 결과
사용 안 함item6, 7, 8, 9, 10, 1, 2, 3, 4, 5
사용 안 함index6, 7, 8, 9, 10, 1, 2, 3, 4, 5
사용 (React.memo)item6, 7, 8, 9, 10
사용 (React.memo)index6, 7, 8, 9, 10, 1, 2, 3, 4, 5

실험 2 (값 교체)

  • 초기 상태: [1, 2, 3, 4, 5] → [1, 2, 10, 4, 5]
memo 사용 여부key렌더링 결과
사용 안 함item1, 2, 10, 4, 5
사용 안 함index1, 2, 10, 4, 5
사용 (React.memo)item10
사용 (React.memo)index1, 2, 10, 4, 5

결론 (실험 1·2)

  • React.memo를 사용하면 같은 key에 대해 props가 변하지 않으면 자식 컴포넌트는 재렌더링되지 않는다.
  • React.memo를 사용하지 않으면 부모가 리렌더링될 때마다 자식도 항상 리렌더링된다.

실험 3 (배열 순서 변경과 상태 유지)

export function Parent() {
  const [array, setArray] = useState([1, 2, 3]);

  useEffect(() => {
    setTimeout(() => {
      setArray((prev) => prev.toReversed());
    }, 3000);
  }, []);

  return (
    <>
      {array.map((item) => (
        
      ))}
    
  );
}

export function Child({ item }: { item: number }) {
  const [text, setText] = useState("");

  return (
    <>
      {item}th textfield:
       setText(e.target.value)} />
    
  );
}

결과

  • key={item} 사용 시: 배열 순서가 뒤바뀌어도 각 컴포넌트의 상태가 올바르게 매핑되어 순서가 바뀐 값과 함께 유지된다.
  • key={index} 사용 시: 순서가 바뀌어도 state가 index와 매핑되므로 입력값이 잘못된 위치에 남아 순서 변경이 정상적으로 반영되지 않는다.

최종 결론

  • index를 key로 사용하는 것은 가능하지만, 배열 순서가 변할 가능성이 있는 경우에는 사용하면 안 된다.
  • key는 컴포넌트 인스턴스와 상태를 연결하는 역할을 하므로, 고유하고 변하지 않는 값(item 등)을 사용해야 상태가 올바르게 유지된다.
0 조회
Back to Blog

관련 글

더 보기 »

📦Redux란 무엇인가?

프론트엔드 개발을 배우고 있다면, 특히 React와 함께라면 Redux에 대해 들어봤을 것입니다. 처음에는 혼란스러워 보일 수 있지만, 핵심 아이디어는 간단합니다....