React

React 컴포넌트 개념 정리: UI 재사용 구조 잡기

2025.12.04·수정 2026.05.11·약 12분

이 글에서 정리하는 내용

React 컴포넌트를 어떻게 이해해야 하는지부터, UI를 왜 나누는지, 재사용 가능한 컴포넌트를 어떻게 설계하는지, 그리고 presentational / container 느낌의 역할 분리를 어떻게 받아들이면 좋은지까지 한 흐름으로 정리합니다. 버튼, 카드, 모달, 리스트 같은 익숙한 UI를 기준으로 생각하면 React 컴포넌트가 훨씬 덜 추상적으로 느껴집니다.

React 컴포넌트를 어떻게 이해하면 되는가

React 컴포넌트 쉽게 이해하기: UI 재사용 구조 잡기 핵심 개념을 설명하는 첫 번째 본문 이미지

처음 React를 볼 때는 컴포넌트를 파일 하나나 함수 하나 정도로만 받아들이기 쉽습니다. 하지만 React 공식 문서 기준으로 보면 React 컴포넌트는 마크업을 반환하는 일반 JavaScript 함수로 이해하는 편이 더 정확합니다. 버튼 하나도 컴포넌트가 될 수 있고, 카드 하나도 컴포넌트가 될 수 있으며, 상황에 따라 페이지 전체도 하나의 큰 컴포넌트가 될 수 있습니다.

중요한 점은 크기가 아니라 역할입니다. 화면에서 어떤 부분이 스스로 의미를 가지는지, 반복될 가능성이 있는지, 다른 화면에서도 비슷한 형태로 다시 등장할 수 있는지를 기준으로 보면 컴포넌트라는 개념이 훨씬 선명해집니다. React는 화면을 통째로 만드는 방식보다 작은 UI 조각을 조합하는 방식에 더 가깝고, React 컴포넌트는 바로 그 조각을 표현하는 단위입니다.

버튼도 컴포넌트, 카드도 컴포넌트

type ButtonProps = { label: string;
}; export default function MyButton({ label }: ButtonProps) { // 아주 작은 UI 조각도 컴포넌트가 될 수 있다는 예시 return <button>{label}</button>;
}

이 예시는 단순하지만 핵심을 잘 보여줍니다. React에서는 버튼 하나도 컴포넌트가 될 수 있습니다. 즉, React 컴포넌트는 거창한 단위가 아니라, 화면 안에서 의미 있는 조각이라면 충분합니다. 이 감각이 잡히면 페이지를 볼 때도 한 장짜리 화면이 아니라 여러 컴포넌트가 모인 구조로 보이기 시작합니다.

UI를 왜 컴포넌트로 나누는가

UI를 컴포넌트로 나누는 가장 큰 이유는 재사용성과 유지보수성 때문입니다. 같은 버튼 스타일이 여러 곳에 반복된다면 한 번 정의해 두고 여러 곳에서 쓰는 편이 훨씬 안정적입니다. 나중에 디자인이 바뀌어도 한 군데를 바꾸면 전체 반영이 쉬워집니다.

또한 나누는 과정 자체가 화면 구조를 더 명확하게 만들어 줍니다. 헤더, 상품 카드, 목록, 필터 영역, 모달처럼 역할별로 나누면 어느 부분이 무엇을 담당하는지 읽기 쉬워지고, 수정 범위도 예측하기 좋아집니다. 결국 컴포넌트 분리는 코드 정리를 위한 취향 문제가 아니라, 변경에 덜 흔들리는 구조를 만드는 방법에 가깝습니다.

리스트와 아이템을 분리해서 생각하기

type Product = { id: number; name: string; price: number;
}; function ProductItem({ product }: { product: Product }) { // 목록의 한 줄 또는 한 칸을 담당하는 작은 컴포넌트 return ( <li> <strong>{product.name}</strong> - {product.price}원 </li> );
} export default function ProductList({ products }: { products: Product[] }) { // 리스트는 반복을 담당하고, 실제 모양은 ProductItem이 담당 return ( <ul> {products.map((product) => ( <ProductItem key={product.id} product={product} /> ))} </ul> );
}

이 구조에서는 목록 전체를 렌더링하는 책임과 항목 하나의 모양을 그리는 책임이 분리됩니다. 당장은 한 파일 안에 있어도 괜찮지만, 역할이 분리되어 있다는 점이 중요합니다. 나중에 상품 카드 디자인이 복잡해져도 중심으로 수정하면 되고, 목록 정렬이나 필터링 로직은 쪽에서 고민하면 됩니다. 이런 분해 방식은 React 컴포넌트를 설계할 때 가장 자주 쓰는 사고방식입니다.

나누지 않았을 때 나눴을 때
반복, 레이아웃, 항목 모양이 한곳에 섞임 리스트와 아이템의 책임이 구분됨
수정 범위를 한 번에 파악하기 어려움 어디를 수정해야 할지 비교적 명확함

재사용 가능한 컴포넌트는 어떻게 설계하는가

재사용 가능한 컴포넌트를 만든다는 것은 비슷해 보이는 UI를 억지로 하나로 합친다는 뜻이 아닙니다. 핵심은 공통 구조와 변경 포인트를 구분하는 것입니다. 버튼이라면 공통 뼈대는 버튼이고, 달라지는 부분은 텍스트, 색상, 클릭 동작일 수 있습니다. 카드라면 카드 틀은 같지만 제목, 설명이미지, 버튼 유무가 바뀔 수 있습니다. 재사용 가능한 React 컴포넌트를 설계할 때는 무엇을 고정하고 무엇을 바깥에서 받는지 먼저 구분하는 편이 좋습니다.

이때 는 바뀌는 값을 밖에서 주입받는 통로입니다. 다만 재사용을 욕심내다 보면 가 너무 많아져서 오히려 쓰기 어려운 컴포넌트가 되기도 합니다. 그런 경우에는 정말 같은 컴포넌트가 맞는지 다시 보는 것이 좋습니다. 겉모양만 비슷하고 역할이 다르면 분리하는 편이 더 낫습니다.

공통 구조와 변경 포인트를 분리한 카드 예시

type UserCardProps = { name: string; description: string; buttonLabel?: string;
}; export default function UserCard({ name, description, buttonLabel = '자세히 보기'}: UserCardProps) { // 카드의 공통 레이아웃은 고정하고, 텍스트만 바뀌게 설계한 예시 return ( <article> <h4>{name}</h4> <p>{description}</p> <button>{buttonLabel}</button> </article> );
}

이런 형태는 여러 화면에서 반복하기 좋습니다. 중요한 것은 처음부터 모든 상황을 다 커버하려 하지 않는 것입니다. 우선 실제로 반복되는 부분만 공통화하고이후에 반복 패턴이 명확해질 때 범위를 넓히는 편이 훨씬 안전합니다. 재사용 가능한 컴포넌트는 많이 받는 컴포넌트보다, 읽기 쉽고 쓰기 쉬운 컴포넌트가 더 좋은 경우가 많습니다.

모달처럼 상태는 밖에서, UI는 안에서 받는 구조

type ModalProps = { isOpen: boolean; title: string; onClose: () => void;
}; export default function Modal({ isOpen, title, onClose }: ModalProps) { // 열림 여부는 부모가 관리하고, 모달은 보여주는 역할에 집중 if (!isOpen) return null; return ( <div> <h3>{title}</h3> <button onClick={onClose}>닫기</button> </div> );
}

모달은 재사용 설계를 이해하기 좋은 예시입니다. 모달이 스스로 모든 상태를 다 들고 있으려고 하면 다른 화면에서 제어하기 어려워집니다. 반대로 열림 여부와 닫기 동작을 바깥에서 받고, 모달 내부는 보여주는 역할에 집중하면 다양한 곳에서 재사용하기 쉬워집니다. 여러 컴포넌트가 같은 열림 상태를 함께 써야 할 때는 가장 가까운 공통 부모로 상태를 올리고 로 내려주는 방식이 자연스럽습니다.

presentational / container 느낌으로 역할을 나누는 방법

React 컴포넌트 쉽게 이해하기: UI 재사용 구조 잡기 적용 흐름을 설명하는 두 번째 본문 이미지

React를 공부하다 보면 presentational 컴포넌트와 container 컴포넌트라는 표현을 자주 보게 됩니다. 지금은 이 패턴을 엄격하게 그대로 따르기보다, React 컴포넌트의 관심사를 분리하는 힌트 정도로 받아들이면 충분합니다. 쉽게 말해 presentational 쪽은 화면을 어떻게 보여줄지에 집중하고, container 쪽은 어떤 데이터를 가져오고 어떤 상태를 관리할지에 집중합니다.

예전에는 이 분리를 컴포넌트 단위로 많이 했지만, 요즘은 커스텀 훅을 이용해 로직을 분리하는 방식도 자주 사용합니다. 다만 커스텀 훅은 상태 자체를 여러 컴포넌트가 함께 쓰게 만드는 도구가 아니라, 상태를 다루는 로직을 재사용하는 도구로 이해하는 편이 정확합니다. 결국 이름보다 중요한 것은 UI를 그리는 코드와 데이터 처리 코드를 뒤섞지 않는 감각입니다.

UI 전용 컴포넌트와 로직 분리 예시

type ProfileCardProps = { name: string; email: string;
}; function ProfileCard({ name, email }: ProfileCardProps) { // 화면 표시만 담당하는 presentational 느낌의 컴포넌트 return ( <section> <h4>{name}</h4> <p>{email}</p> </section> );
} function useProfile() { // 실제 프로젝트에서는 fetch, query, 상태 관리가 들어갈 수 있는 자리 return { name: '김리액트', email: 'react@example.com'};
} export default function ProfileCardContainer() { // 데이터 준비를 담당하고, 화면은 ProfileCard에 전달 const profile = useProfile(); return <ProfileCard name={profile.name} email={profile.email} />;
}

이 예시에서는 가 화면을 그리고, 또는 이 데이터를 준비합니다. 이렇게 나누면 디자인을 수정할 때는 UI 쪽만 보면 되고, 데이터 출처가 바뀔 때는 로직 쪽만 보면 됩니다. 컴포넌트를 잘게 나누는 목적도 결국 이런 식으로 책임을 선명하게 만드는 데 있습니다.

결론

React에서 컴포넌트를 공부할 때 가장 먼저 잡아야 하는 감각은 화면을 작은 UI 조각으로 본다는 점입니다. 그리고 그 조각을 나누는 기준은 파일 개수나 크기가 아니라 역할입니다. 버튼, 카드, 모달, 리스트처럼 의미 있는 단위로 쪼개고, 공통 구조와 변경 포인트를 구분하면 재사용 가능한 React 컴포넌트를 훨씬 안정적으로 설계할 수 있습니다.

또한 presentational / container 느낌의 역할 분리는 오래된 패턴 이름을 외우는 데 목적이 있지 않습니다. UI를 그리는 책임과 상태·데이터를 다루는 책임을 적절히 분리하는 연습이 핵심입니다. 이 흐름이 익숙해지면 이후, 상태 끌어올리기, 커스텀 훅 같은 주제도 훨씬 자연스럽게 이어집니다.

컴포넌트를 나눈 뒤 데이터 전달은 React props 데이터 전달, 컴포넌트 내부 상태 기준은 React useState 상태 관리 기본에서 이어서 정리할 수 있습니다.

많이 받는 질문

Q. 컴포넌트는 무조건 잘게 나눌수록 좋은가요?
아닙니다. 너무 잘게 나누면 오히려 파일만 많아지고 흐름이 끊길 수 있습니다. 중요한 기준은 역할 분리와 읽기 쉬움입니다. 한 컴포넌트가 여러 책임을 동시에 가지기 시작할 때 나누는 쪽이 더 자연스럽습니다.

Q. 재사용하려다 props가 너무 많아지면 어떻게 해야 하나요?
먼저 정말 같은 컴포넌트인지 다시 확인하는 것이 좋습니다. 겉모양만 비슷하고 실제 역할이 다르면 분리하는 편이 더 낫습니다. 공통화는 많이 받는 것보다, 실제로 반복되는 패턴만 정확히 묶는 것이 더 중요합니다.

Q. presentational / container 패턴은 지금도 꼭 써야 하나요?
엄격하게 따를 필요는 없습니다. 다만 화면 표시와 데이터 처리의 책임을 나눈다는 생각은 지금도 유효합니다. 요즘은 container 컴포넌트 대신 커스텀 훅으로 로직을 분리하는 방식도 많이 사용합니다.

Q. 커스텀 훅을 쓰면 여러 컴포넌트가 같은 상태를 자동으로 공유하나요?
아닙니다. 커스텀 훅은 상태를 다루는 로직을 재사용하게 해주지만, 각 호출은 서로 독립적입니다. 여러 컴포넌트가 같은 상태를 함께 써야 한다면 공통 부모로 상태를 올리거나, 상황에 따라 Context 같은 다른 공유 방식이 필요합니다.

이 글이 마음에 드세요?

RSS 피드를 구독하세요!

“React 컴포넌트 개념 정리: UI 재사용 구조 잡기”에 대한 4개의 생각

댓글 남기기