[React] 불필요한 DOM 요소를 피하는 방법: React.Fragment

25년 07월 12일 16:00LearningReact, JSX, DOM, Fragment

🤔 JSX의 규칙: 단일 루트 요소

React 컴포넌트에서 여러 엘리먼트를 반환하려면, 반드시 하나의 부모(루트) 요소로 감싸야 한다는 규칙이 있습니다. 이 때문에 종종 불필요한 <div> 태그를 추가하게 됩니다.

// ❌ 잘못된 예: 여러 개의 루트 요소를 반환
function MyComponent() {
  return (
    <h1>제목</h1>
    <p>내용</p>
  );
}

// ✅ 일반적인 해결책: 불필요한 <div>로 감싸기
function MyComponent() {
  return (
    <div>
      <h1>제목</h1>
      <p>내용</p>
    </div>
  );
}

이 방식은 유효하지만, 실제 DOM에 불필요한 <div>가 추가되어 HTML 구조가 복잡해지고, 특정 CSS 스타일(예: Flexbox, Grid) 적용에 문제를 일으킬 수 있습니다.

✨ 해결책: React.Fragment

React.Fragment는 이러한 문제를 해결하기 위해 등장했습니다. Fragment는 DOM에 별도의 노드를 추가하지 않고 여러 자식 엘리먼트를 그룹화할 수 있게 해주는 특별한 컴포넌트입니다.

import React from 'react';

function MyComponent() {
  return (
    <React.Fragment>
      <h1>제목</h1>
      <p>내용</p>
    </React.Fragment>
  );
}

위 코드는 렌더링될 때 <h1><p> 태그만 남기고, <React.Fragment>는 사라집니다. 결과적으로 더 깔끔하고 의미 있는 HTML 구조를 만들 수 있습니다.

단축 문법: <>

React.Fragment를 매번 타이핑하는 것은 번거로울 수 있습니다. 다행히도 React는 이를 위한 단축 문법을 제공합니다.

function MyComponent() {
  return (
    <>
      <h1>제목</h1>
      <p>내용</p>
    </>
  );
}

<></><React.Fragment></React.Fragment>와 거의 동일하게 동작합니다. 단, 한 가지 중요한 차이점이 있습니다.

<> vs React.Fragment

특징<> (단축 문법)<React.Fragment> (명시적 문법)
DOM 추가없음없음
key 속성불가능가능
기타 속성불가능불가능

배열을 렌더링할 때와 같이 key prop을 전달해야 하는 경우에는 반드시 명시적인 <React.Fragment> 문법을 사용해야 합니다.

function Glossary(props) {
  return (
    <dl>
      {props.items.map(item => (
        // `key` prop이 필요하므로, 단축 문법을 사용할 수 없습니다.
        <React.Fragment key={item.id}>
          <dt>{item.term}</dt>
          <dd>{item.description}</dd>
        </React.Fragment>
      ))}
    </dl>
  );
}

React.createElement와의 관계

JSX는 내부적으로 React.createElement(component, props, ...children) 함수 호출로 변환됩니다. React.Fragment도 마찬가지입니다.

// 이 JSX 코드는
const jsx = (
  <>
    <td>Hello</td>
    <td>World</td>
  </>
);

// 아래의 `React.createElement` 호출로 변환됩니다.
const element = React.createElement(
  React.Fragment,
  null,
  React.createElement('td', null, 'Hello'),
  React.createElement('td', null, 'World')
);

결론적으로, 불필요한 <div> 래퍼(wrapper)를 피하고 싶을 때 React.Fragment 또는 단축 문법 <>를 사용하는 것은 React 개발의 기본적이면서도 중요한 패턴입니다. 이를 통해 더 깔끔하고 효율적인 컴포넌트를 작성할 수 있습니다.