React - children props

반응형

리액트에서는 모든 컴포넌트가 props를 받을 수 있지만

children prop은 특별한 역할을 하는데

컴포넌트 태그 내부에 있는 내용을 동적으로 전달할 때 사용하고

레이아웃 컴포넌트, 재사용 가능한 UI 요소 등을 만들 때 매우 유용하다.

 

기본적으로는 props는 부모 -> 자식으로 데이터를 전달하는 역할을 한다고 했을 때,

children prop은 컴포넌트 태그 사이의 내용을 가져오는 역할을 한다.

즉 children을 사용하면 부모 컴포넌트에서 원하는 내용을 동적으로 넣을 수 있다.

 


children prop 기본 사용법

// Card.jsx

function Card({ children }) {
  return (
    <div className='card'>
      {/* children을 통해 태그 내부의 내용을 랜더링 */}
      {children}
    </div>
  )
}

export default Card
// App.jsx

import Card from "./Card"

function App() {
  return (
    <div>
      <Card>
        <h2>카드 컴포넌트 입니다.</h2>
        <p>원하는 내용 입력 가능</p>
      </Card>

      <Card>
        <button>버튼 기능 추가 가능</button>
      </Card>
    </div>
  )
}

export default App

이렇게 children을 활용하여 컴포넌트 내부에 동적인 내용을 넣을 수 있으며

Card 컴포넌트를 어떤 용도로든 재사용이 가능하다. (ex: h2, p, button 등)

etc-image-0


children - 간단한 사용 예제 (Layout, Modal...)

페이지 레이아웃을 만들 때 children을 사용하면 코드가 더 깔끔해지고 관리하기 편하다.

// Layouy.jsx

function Layout({ children }) {
  return (
    <div>
      <header>헤더 부분</header>
      <main>{children}</main> {/* 이 부분에 동적인 콘텐츠가 들어감 */}
      <footer>푸터 부분</footer>
    </div>
  )
}

export default Layout
// App.jsx

import Card from "./Card"
import Layout from "./Layout"

function App() {
  return (
    <div>
      <Layout>

        <Card>
          <h2>카드 컴포넌트 입니다.</h2>
          <p>원하는 내용 입력 가능</p>
        </Card>

        <Card>
          <button>버튼 기능 추가 가능</button>
        </Card>

      </Layout>
    </div>
  )
}

export default App

위와 같이 children 안에 원하는 페이지 내용을 넣어서

레이아웃을 모든 페이지에서 재사용 가능하다.

이 방법은 실제 프로젝트에서 헤더와 푸터가 고정된 레이아웃을 만들 때 자주 사용된다.

etc-image-1

또한 팝업(모달) 창을 만들 때도 children을 활용하여 더 유연한 UI를 구성할 수 있다

(단 useState로 열고 닫는 기능까지 추가해야 하므로 다음 기회에..)


children - 스타일 적용

마찬가지로, 스타일링을 하여 색상이나 폰트 등 유연하게 변경할 수 있다.

// Color.jsx

function Color({ children, backgroundColor }) {
  return (
    <div style={{ backgroundColor, padding: "20px", borderRadius: "10px" }}>
      {children} {/* 안에 어떤 내용이든 들어갈 수 있음 */}
    </div>
  );
}

export default Color;
// App.jsx

import Card from "./Card"
import Layout from "./Layout"
import Color from "./Color"

function App() {
  return (
    <div>
      <Layout>

        <Card>
          <h2>카드 컴포넌트 입니다.</h2>
          <p>원하는 내용 입력 가능</p>
        </Card>

        <Color backgroundColor="lightblue" >
          <p>연한 파란색</p>
        </Color>

        <Color backgroundColor="lightpink" >
          <p>연한 핑크색</p>
        </Color>

        <Card>
          <button>버튼 기능 추가 가능</button>
        </Card>

      </Layout>
    </div>
  )
}

export default App

etc-image-2

Color 컴포넌트를 사용할 때마다 다른 색상을 설정할 수 있다.


children - propTypes

children도 props의 일종이기 때문에

propTypes를 사용하여 유효성 검사를 추가해 주는 것이 좋다.

children을 사용할 경우에도 propTypes를 설정하지 않으면

다른 props와 마찬가지로 ESlint 경고가 발생한다.

// Card.jsx - propTypes 추가

import Proptypes from "prop-types"

function Card({ children }) {
  return (
    <div className='card'>
      {/* children을 통해 태그 내부의 내용을 랜더링 */}
      {children}
    </div>
  )
}
// children을 `node` 타입으로 지정 (React 요소, 문자열, 숫자 등 허용)
Card.propTypes = {
  children: Proptypes.node.isRequired, // children이 필수 값임을 명시
};

export default Card
// Color.jsx - PropTypes 추가

import PropTypes from "prop-types"

function Color({ children, backgroundColor }) {
  return (
    <div style={{ backgroundColor, padding: "20px", borderRadius: "10px" }}>
      {children} {/* 안에 어떤 내용이든 들어갈 수 있음 */}
    </div>
  );
}

Color.propTypes = {
  children: PropTypes.node.isRequired,
  backgroundColor: PropTypes.string // backgroundColor는 css 속성이므로 string
}

export default Color;
// Layouy.jsx - Proptypes 추가

import PropTypes from "prop-types"

function Layout({ children }) {
  return (
    <div>
      <header>헤더 부분</header>
      <main>{children}</main> {/* 이 부분에 동적인 콘텐츠가 들어감 */}
      <footer>푸터 부분</footer>
    </div>
  )
}

Layout.propTypes = {
  children: PropTypes.node.isRequired
}

export default Layout

 

여기서 코드를 보면 PropTypes.node에서 node라는 단어가 나오게되는데,

children은 여러가지 타입을 가질 수 있으며 node, element, string,number등의 타입이 존재한다.

어떤 타입을 지정해야 하는지 방법을 알아보자.

 

▶ children에 사용할 수 있는 propTypes 타입

리액트에서는 children의 타입을 일반적으로 node로 설정하는 것이 적합하다.

타입 설명 사용 예제
PropTypes.node 모든 리액트 랜더링 가능한 요소
(문자열, 숫자, JSX 배열 등)
<Card>텍스트</Card>
<Card><h1>제목</h1></Card>
PropTypes.element 리액트 요소만 가능 (JSX 컴포넌트) <Card><h1>제목</h1></Card>
PropTypes.string 문자열만 가능 <Card>텍스트</Card>
PropTypes.number 숫자만 가능 <Card>{123}</Card>

즉 PropTypes.node를 사용하면 대부분의 경우를 포함할 수 있기 때문에 node를 주로 설정한다.

 

설명을 더해서, Proptyles.node와 PropTypes.element의 차이점은

node는 React에서 렌더링할 수있는 거의 모든 값을 포함하기 때문에 일반적으로 더 유용하며

element는 JSX 요소만 받을 때 사용하기 때문에 node보다 조금 덜 사용된다.

 

그리고 backgroundColor는 CSS 속성으로 사용되기 때문에 PropTypes.string을 사용했으며

node로는 사용할 수 없고 왜 string으로 사용하는지 알아보자

backgroundColor는 CSS에서 색상을 나타내는 문자열 값인데

여기서 중요한 점은 "문자열 값" 이다

backgroundColor: "red" // 문자열
backgroundColor: "#ff0000" // 문자열
backgroundColor: "rgb(255, 0, 0)" // 문자열

위 코드를 보면 전부 문자열로 색상을 지정하고 있다.

그러므로..

PropTypes.node 는 JSX요소 (div,h1)와 관련됨 -> 배경색과 무관함!

PropTypes.element 는 JSX요소 (React.createELement())와 관련됨 -> 역시나 배경색과 무관함

 

▶ children의 isRequired

children이 필수( isRequired )인지 여부는 컴포넌트 사용방식에 따라 다르다.

isRequired를 사용하면 컴포넌트를 사용할 때 children이 반드시 있어야 하므로

children을 빼먹으면 ESLint 경고가 뜰 것이다.

하지만 isRequired가 없으면 children이 없어도 정상적으로 동작할 것이다.

또한 defaultProps를 사용하면 children이 없을 때 기본값을 설정할 수 있다.

// children이 필수일 경우

Card.propTypes = {
  children: PropTypes.node.isRequired,
};
// children이 선택 사항일 경우 (isRequired 없이 기본값 설정)

Card.propTypes = {
  children: PropTypes.node,
};

Card.defaultProps = { // defaultProps를 사용하면 children이 없을 때 기본값을 설정
  children: "기본 내용입니다.", // 기본값 설정
};

정리하면 다음과 같다.

  • children은 리액트에서 태그 내부의 내용을 동적으로 전달하는 props이다.
  • Card, Layout 등 재사용 가능한 컴포넌트를 만들 때 사용된다.
  • children을 활용하면 컴포넌트의 유연성이 증가하고 재사용성이 높아진다.
  • children도 prop의 일부이므로 propTypes로 유효성 검사를 해야한다.
  • isRequired를 추가하면 children을 필수값으로 설정할 수 있다.
반응형

'React' 카테고리의 다른 글

React - React의 렌더링 방식 : State  (0) 2025.02.27
React - State  (0) 2025.02.26
React - props  (0) 2025.02.20
React - 리액트 컴포넌트 (React Component)  (0) 2025.02.19
React - JSX에서 자바스크립트 사용하기  (0) 2025.02.17