[React] React에서 key 중복으로 발생한 렌더링 이슈 (Reconciliation 사례)

2025. 5. 27. 14:41·Development/React

한가로이 기존에 개발한 기능을 테스트하다가 찾은 이슈 기록

 

올 초에 리팩토링한 칸반 보드를 테스트하다가 보니 API로 받은 데이터는 분명 1건인데, 화면엔 같은 태스크가 2번씩 표시되는 이상한 현상을 겪었다. (벌써 v3.. 그 이유는 더보기에서)

더보기

1. 최초 기능 개발

2. 라이브러리 교체 (beautiful-dnd -> dnd-kit)

3. 디자인 전환작업으로 인한 리팩토링

 

이번에 전체 검색 기능을 넣으면서, 검색 기능을 전반적으로 테스트하다가 발견했다.

처음에는 계층 구조 때문에 백엔드에서 중복 데이터를 잘못 가져오는 줄 알았지만 실제로는 렌더링 로직의 문제였다.

 

API 응답 자체에는 이상이 없었으며, 실제 원인은 React 내부의 reconciliation 알고리즘과 컴포넌트에 할당한 key 사용 방식에 있었다.

 


현상 요약

  • API에서 수신된 태스크(task.id)는 분명 1건
  • 하지만 UI에는 같은 태스크가 2개 이상 중복 표시됨
  • 콘솔을 찍어보면 task는 1개인데, 컴포넌트는 반복 렌더링됨

 


원인: 중복된 key로 인한 잘못된 재사용

React는 리스트를 렌더링할 때 key 값을 기준으로 컴포넌트의 identity를 판단하고,

같은 key가 있으면 DOM을 재사용한다.

{tasks.map((task) => (
  <KanbanTask key={task.id} ... />
))}

이 구조만 보면 문제가 없어 보이지만, 실제로는:

  • columnTasksList [columnId]로 여러 column에서 같은 task가 포함될 수 있음
  • 그리고 각 column 별로 map()을 돌리기 때문에, 동일한 id가 여러 column의 서로 다른 map 안에서 반복 사용됨

❗ 이때는 React가 중복 key 경고를 출력하지 않지만,

내부적으로는 동일한 컴포넌트로 오인하고 잘못 재사용하여

결과적으로 UI에 중복 렌더링이 발생한다.

중복 key는 주로 콘솔에 에러 찍히는 것만 보고 처리하는 경우가 많았어서, 이 부분을 놓친 것 같다.

 


해결: key를 고유하게 구성하기

React가 올바르게 diffing 하도록 하기 위해, key를 아래처럼 고유하게 조합해 주었다:

<KanbanTask
  key={`${task.id}-${column.knbnSn}-${i}`}
/>

이렇게 column과 index를 함께 조합해서 고유한 key를 만들었더니, 정상적으로 동작하는 것을 확인할 수 있었다.

 


정리

항목내용

문제 동일한 key로 인해 React가 컴포넌트를 잘못 재사용함
원인 서로 다른 리스트(map()) 안에서 동일 key 사용 시 React 경고 없음
증상 데이터는 1건인데, UI에는 중복 표시됨
해결 key={id-columnId} 형태로 고유한 값으로 변경

 


마무리

React의 key는 단순히 반복 렌더링을 위한 인덱스가 아니라,

컴포넌트의 정체성을 보장하는 중요한 기준이다.

특히 리스트가 여러 개(map 여러 번) 존재하거나, 동일한 데이터가 다른 위치에 중복 포함될 수 있다면 key는 반드시 유일하고 의미 있는 값으로 만들어야 한다.

https://ko.legacy.reactjs.org/docs/reconciliation.html

 

재조정 (Reconciliation) – React

A JavaScript library for building user interfaces

ko.legacy.reactjs.org

 

'Development > React' 카테고리의 다른 글

[React] ReactQuery 순환 참조  (1) 2025.06.09
[React] useId()를 사용하다가 삽질한 기록  (4) 2025.05.25
[TypeScript] 고급 타입 활용법: 조건부 타입, 제네릭 심화와 Exclude/Extract 활용  (0) 2025.04.01
[React] 상태 (State)  (0) 2024.02.28
[React] JSX 사용하기  (0) 2024.02.28
'Development/React' 카테고리의 다른 글
  • [React] ReactQuery 순환 참조
  • [React] useId()를 사용하다가 삽질한 기록
  • [TypeScript] 고급 타입 활용법: 조건부 타입, 제네릭 심화와 Exclude/Extract 활용
  • [React] 상태 (State)
곽진돔
곽진돔
Developer
  • 곽진돔
    echo "곽박한 세상";
    곽진돔
  • 전체
    오늘
    어제
    • 분류 전체보기 (184)
      • Development (57)
        • Linux (13)
        • k8s (3)
        • Docker (5)
        • AWS (1)
        • PHP (35)
        • Python (21)
        • Java (1)
        • SpringBoot (4)
        • JavaScript (1)
        • React (8)
        • MySql (19)
        • MongoDB (1)
      • Daily (4)
      • Study (6)
        • TIL (1)
        • license (3)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
    • 글쓰기
    • 설정
  • 링크

    • github
  • 공지사항

  • 인기 글

  • 태그

    date
    CentOS
    Java
    스프링부트
    Shell
    MySQL
    springboot
    db
    php
    정규표현식
    IP
    Python
    JavaScript
    CentOS7
    error
    SQL
    리눅스
    인코딩
    chromedriver
    HTML
    크롤링
    리액트
    Linux
    docker
    UTF8
    Selenium
    ssh
    윈도우
    nodejs
    react
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
곽진돔
[React] React에서 key 중복으로 발생한 렌더링 이슈 (Reconciliation 사례)
상단으로

티스토리툴바