1. 컴포넌트 구조화의 필요성
리액트의 가장 큰 장점 중 하나는 **컴포넌트 기반 구조(Component-Based Architecture)**입니다.
즉, 화면을 여러 개의 작은 조각으로 나누어 각각 독립적으로 관리할 수 있다는 뜻입니다.
예를 들어, 블로그 게시글 화면을 생각해봅시다.
하나의 페이지 안에는 다음과 같은 구성 요소가 있을 수 있습니다.
- 헤더(Header)
- 게시글 내용(PostContent)
- 댓글 목록(CommentList)
- 댓글 입력창(CommentForm)
이 모든 것을 하나의 파일에서 관리한다면 코드가 길어지고 복잡해집니다.
하지만 리액트에서는 이 각각을 독립된 컴포넌트로 분리할 수 있습니다.
function Header() {
return <h1>블로그 제목</h1>;
}
function PostContent() {
return <p>이것은 게시글 내용입니다.</p>;
}
function App() {
return (
<div>
<Header />
<PostContent />
</div>
);
}
이처럼 리액트는 UI를 작은 단위로 쪼개서 재사용할 수 있게 하는 구조를 제공합니다.
2. 불필요한 <div> 문제
컴포넌트를 구성하다 보면 종종 “불필요한 <div> 태그”가 너무 많이 생기는 경우가 있습니다.
리액트는 컴포넌트가 여러 요소를 반환할 때 반드시 하나의 부모 태그로 감싸야 하기 때문입니다.
예를 들어, 아래 코드는 오류가 발생합니다.
function Post() {
return (
<h1>제목</h1>
<p>내용입니다.</p>
);
}
리액트는 여러 요소를 직접 반환하는 것을 허용하지 않기 때문에,
보통 이렇게 감싸서 해결합니다.
function Post() {
return (
<div>
<h1>제목</h1>
<p>내용입니다.</p>
</div>
);
}
문제는 이런 <div>가 여러 단계 중첩되면
DOM 구조가 불필요하게 복잡해진다는 점입니다.
3. React Fragments의 등장
이 문제를 해결하기 위해 리액트는 Fragments라는 개념을 제공합니다.
Fragment는 눈에 보이지 않는 가상의 래퍼(wrapper)로,
실제 DOM에 아무것도 추가하지 않고 여러 요소를 묶을 수 있습니다.
즉, <div>를 쓰지 않고도 여러 자식 요소를 반환할 수 있습니다.
function Post() {
return (
<>
<h1>제목</h1>
<p>내용입니다.</p>
</>
);
}
이렇게 <>와 </>로 감싸면,
React는 이를 내부적으로 <React.Fragment>로 변환해줍니다.
이 태그는 실제 HTML에 표시되지 않기 때문에
불필요한 <div>가 생기지 않습니다.
4. Fragment를 사용하는 이유
① DOM 구조 단순화
불필요한 중첩을 방지해 HTML 트리 구조를 깔끔하게 유지할 수 있습니다.
② CSS 충돌 방지
의미 없는 <div>가 많으면 스타일 적용 범위가 꼬일 수 있습니다.
Fragment를 사용하면 이런 문제를 최소화할 수 있습니다.
③ 성능 최적화
DOM 노드가 줄어들면 브라우저가 렌더링해야 하는 요소도 줄어듭니다.
작은 차이처럼 보이지만 대규모 컴포넌트 트리에서는 성능에 영향을 줍니다.
5. Fragment에 key 속성 사용하기
리액트에서 리스트를 렌더링할 때는 key가 필요하죠.
Fragment도 예외는 아닙니다.
단, key를 넣고 싶을 때는 **짧은 문법(<>) 대신 <React.Fragment>**를 써야 합니다.
function List() {
const items = ['React', 'Vue', 'Svelte'];
return (
<>
{items.map((item, index) => (
<React.Fragment key={index}>
<h4>{item}</h4>
<hr />
</React.Fragment>
))}
</>
);
}
이렇게 하면 각 항목이 고유한 key를 가지면서
불필요한 div 없이 리스트를 표현할 수 있습니다.
6. 컴포넌트 구조 설계 시 팁
리액트를 잘 다루려면
**“컴포넌트를 얼마나 잘 나누는가”**가 중요합니다.
다음은 컴포넌트를 설계할 때 도움이 되는 기준입니다.
- UI 단위로 쪼개라.
하나의 기능(버튼, 카드, 댓글 등)은 하나의 컴포넌트로 만든다. - 상위-하위 관계를 명확히 하라.
부모는 데이터와 이벤트를 관리하고,
자식은 그 데이터를 화면에 표시하는 역할만 맡는다. - 불필요한 div를 지양하라.
Fragment를 적극적으로 활용해 DOM을 깨끗하게 유지한다. - 컴포넌트의 재사용성을 고려하라.
비슷한 UI 구조가 반복되면 하나의 컴포넌트로 추출한다.
7. 마무리 정리
이번 글에서는 React에서 컴포넌트를 깔끔하게 관리하는 방법,
그리고 그 과정에서 자주 등장하는 React Fragment의 개념을 다뤘습니다.
- 여러 요소를 반환할 때 <div> 대신 Fragment 사용
- Fragment는 실제 DOM에 렌더링되지 않음
- key가 필요할 때는 <React.Fragment key={...}> 형태로 사용
- 컴포넌트는 가능한 작고 명확하게 분리
이 원칙만 지켜도 코드의 가독성과 유지보수성이 눈에 띄게 좋아집니다.
다음 글에서는 **React 컴포넌트의 생명주기(Lifecycle)**를 자세히 살펴보겠습니다.
'frontend > react' 카테고리의 다른 글
| [React] React.js 강좌 10. 상태 끌어올리기 (Lifting State Up)와 Context API 기초 (0) | 2025.11.10 |
|---|---|
| [React] React.js 강좌 9. Hooks 기본 – useState와 useEffect 완벽 이해 (0) | 2025.11.10 |
| [React] React.js 강좌 2. Props와 State 완벽 정리 (0) | 2025.11.10 |
| [React] React.js 강좌 1. 리액트 기초 개념 정리 (0) | 2025.11.10 |
| ⚛️ React란? 초보도 이해하는 리액트 개념 정리 (0) | 2025.11.04 |