기술 포스트

컴포넌트 — 레고 블록처럼 UI를 조립합니다


Article

React에서 가장 중요한 개념을 하나만 고르라면, 단연 컴포넌트입니다. React로 만드는 모든 화면은 컴포넌트의 조합으로 이루어져 있습니다.

퍼블리셔에게 익숙한 개념으로 시작하면 이해가 빠릅니다.

퍼블리셔가 이미 아는 개념입니다

퍼블리셔라면 이런 경험이 있을 겁니다.

  • 모든 페이지에 들어가는 header.html을 따로 만들어서 include 하기
  • 반복되는 카드 UI를 하나 만들어놓고 복사해서 쓰기
  • 공통 모듈을 별도 파일로 분리해서 관리하기

컴포넌트도 본질은 같습니다. 반복되는 UI를 독립적인 조각으로 분리한 것입니다. 다만 HTML의 include보다 훨씬 더 강력합니다.

컴포넌트는 함수입니다

React의 컴포넌트는 JSX를 반환하는 함수입니다. 이게 전부입니다.

function Greeting() {
  return <h1>안녕하세요!</h1>;
}

이게 하나의 컴포넌트입니다. 이 컴포넌트를 쓸 때는 HTML 태그처럼 씁니다.

function App() {
  return (
    <div>
      <Greeting />
      <Greeting />
      <Greeting />
    </div>
  );
}

<Greeting />을 세 번 쓰면 "안녕하세요!"가 세 번 나옵니다. 한 번 만들고 여러 번 쓸 수 있습니다.

규칙이 하나 있습니다. 컴포넌트 이름은 반드시 대문자로 시작해야 합니다. greeting이 아니라 Greeting. 소문자로 시작하면 React가 HTML 태그로 인식합니다.

props — 같은 틀, 다른 내용

레고 블록 비유를 계속해보겠습니다. 같은 모양의 블록이라도 색깔이 다를 수 있습니다. 컴포넌트도 마찬가지입니다. 같은 구조인데 내용만 다르게 넣을 수 있습니다. 이걸 props라고 부릅니다.

function PostCard({ title, date, description }) {
  return (
    <article>
      <h2>{title}</h2>
      <p>{date}</p>
      <p>{description}</p>
    </article>
  );
}

이 컴포넌트를 쓸 때 다른 데이터를 넣어줄 수 있습니다.

<PostCard
  title="브라우저 렌더링 과정"
  date="2026-03-08"
  description="DOM 트리부터 페인트까지"
/>
<PostCard
  title="자바스크립트 엔진 이해하기"
  date="2026-03-08"
  description="콜 스택과 이벤트 루프"
/>

같은 컴포넌트인데 전달하는 props에 따라 다른 내용이 보입니다. HTML의 include에서는 불가능한 일입니다. include는 파일 내용을 그대로 가져올 뿐, 데이터를 넘겨줄 수 없으니까요.

왜 쪼개야 하나?

"그냥 한 파일에 전부 쓰면 안 되나요?"

됩니다. 작은 프로젝트에서는 그래도 괜찮습니다. 하지만 화면이 복잡해지면 문제가 생깁니다.

1. 재사용

버튼 하나를 예로 들어보겠습니다. 사이트 전체에서 같은 스타일의 버튼이 20군데에 쓰인다고 해봅시다.

컴포넌트 없이는 같은 HTML을 20번 복사합니다. 나중에 버튼 스타일을 바꿔야 하면? 20군데를 전부 찾아서 수정해야 합니다.

컴포넌트로 만들어놓으면 한 곳만 고치면 20군데가 전부 바뀝니다.

2. 유지보수

한 파일에 1000줄짜리 마크업이 있다고 상상해보세요. 헤더, 사이드바, 메인 콘텐츠, 모달, 푸터가 전부 한 파일에 들어있습니다. 여기서 사이드바의 메뉴 순서를 바꾸려면? 1000줄 중에서 해당 부분을 찾아야 합니다.

컴포넌트로 나누면 Sidebar.jsx 파일만 열면 됩니다. 어디를 수정해야 하는지 즉시 알 수 있습니다.

3. 팀 협업

프로젝트에 3명이 동시에 작업한다고 해봅시다. 한 파일에 모든 UI가 있으면 충돌이 끊임없이 일어납니다. 컴포넌트로 나눠져 있으면 각자 다른 파일에서 작업할 수 있습니다.

실제 페이지를 컴포넌트로 분해하면

블로그 메인 페이지를 예로 들어보겠습니다.

function BlogPage() {
  return (
    <div>
      <Header />
      <main>
        <PostList />
        <Sidebar />
      </main>
      <Footer />
    </div>
  );
}

이 한 줄 한 줄이 독립적인 컴포넌트입니다. Header 안에는 로고와 네비게이션이, PostList 안에는 여러 개의 PostCard가, Sidebar 안에는 카테고리 목록과 태그 클라우드가 들어있을 수 있습니다.

BlogPage
 ├── Header
 │    ├── Logo
 │    └── Navigation
 ├── PostList
 │    ├── PostCard
 │    ├── PostCard
 │    └── PostCard
 ├── Sidebar
 │    ├── CategoryList
 │    └── TagCloud
 └── Footer

이런 구조를 컴포넌트 트리라고 부릅니다. 첫 번째 글에서 본 DOM 트리와 비슷한 모양입니다.

include와 컴포넌트의 차이

HTML include React 컴포넌트
데이터 전달 불가능 props로 전달 가능
조건부 표시 서버 측 로직 필요 JSX 안에서 바로 처리
상태 관리 없음 컴포넌트 자체 상태 보유 가능
이벤트 처리 별도 JS 필요 컴포넌트 안에 포함
재사용 파일 통째로 다른 데이터로 여러 번 사용

컴포넌트는 마크업 + 스타일 + 로직이 하나로 묶인 독립적인 UI 단위입니다. include는 마크업만 분리하는 것이라서, 비교하면 컴포넌트가 훨씬 강력합니다.

정리

컴포넌트는 어렵게 생각할 필요가 없습니다.

  • JSX를 반환하는 함수입니다.
  • props로 데이터를 받아서 다른 내용을 보여줄 수 있습니다.
  • UI를 독립적인 조각으로 나눈 것입니다.
  • 재사용, 유지보수, 협업 전부에서 이점이 있습니다.

퍼블리셔가 이미 해왔던 "공통 부분 분리하기"의 진화된 버전이라고 생각하면 됩니다.

이 시리즈에서 다룬 5가지 — 브라우저 렌더링, 자바스크립트 엔진, 선언적 UI, JSX, 컴포넌트 — 는 React를 시작하기 전에 알아두면 좋은 기초 체력 같은 것입니다. 이 기초가 있으면 React 공부가 훨씬 수월해집니다.