본문 바로가기
programming_kr/react

컴포넌트와 props

by JSsunday 2021. 1. 13.
728x90

 

React의 기본 구조는 컴포넌트의 집합입니다. 컴포넌트란 UI를 재사용 가능하게끔 만들어 놓은 여러 조각입니다.

 

함수 컴포넌트와 클래스 컴포넌트

 

컴포넌트를 정의하는 간단한 방법은 javascript 함수를 만드는 것입니다.

 

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

 

이 함수는 데이터를 가진 하나의 props 파라미터를 받은 후 React 엘리먼트로 반환합니다. 이러한 컴포넌트는 javascript 함수이기 때문에 함수 컴포넌트라고 합니다.

 

또한 ES6의 클래스를 통해 컴포넌트를 정의할 수 있습니다.

 

class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

 

React의 관점에서는 두 가지 유형의 컴포넌트는 동일합니다. class의 컴포넌트는 추가기능이 있는데 다음에 알아보도록 합니다.

 

컴포넌트 렌더링

 

React 엘리먼트는 DOM 태그로 나타낼수도 있짐나 사용자 정의 컴포넌트로도 나타낼 수 있습니다.

 

const element = <Welcome name="브니" />;

 

React가 사용자 정의 컴포넌트로 작성한 엘리먼트를 발견하게 되면 JSX 속성과 자식을 해당 컴포넌트에 단일 객체로 전달합니다. 이 것을 props라고 합니다. 자식 컴포넌트에서는 부모컴포넌트에서 보낸 속성들을 props로 받는 것 입니다.

 

function Test(props) {
  return <h1>안녕, {props.name}</h1>;
}

const element = <Test name="브니" />;
ReactDOM.render(
  element,
  document.getElementById('root')
);

 

위의 코드를 실행하게 되면 아래와 같은 일이 발생합니다.

 

  1. <Test name="브니"/> 엘리먼트로 ReactDOM.render()를 호출합니다.
  2. React는 {name : "브니"}를 props로 하여 Test 컴포넌트를 호출합니다.
  3. Test 컴포넌트는 결과적으로 <h1>안녕, 브니</h1>엘리먼트를 반환합니다.
  4. ReactDOM은 <h1>안녕, 브니</h1>엘리먼트와 일치하도록 DOM을 효율적으로 업데이트(변경된 부분이 있으면 가상의 DOM과 비교해서 달라진 부분만 업데이트) 합니다.

 

컴포넌트의 이름은 항상 대문자로 시작해야 합니다.
<div/>는 HTML의 태그지만 <Test/>는 컴포넌트를 나타냅니다.

 

컴포넌트 합성

 

컴포넌트는 다른 컴포넌트를 참조할 수 있으므로 동일한 추상 컴포넌트를 사용할 수 있습니다. React 앱에서는 Button, Form, dialog, 화면 등의 모든 것들의 하나의 컴포넌트로 표현됩니다.

 

function Test(props) {
  return <h1>안녕, {props.name}</h1>;
}

function App() {
  return (
    <div>
      <Test name="브니" />
      <Test name="바니" />
      <Test name="보니" />
    </div>
  );
}

ReactDOM.render(
  <App />,
  document.getElementById('root')
);

 

일반적으로 React 프로젝트는 만들게 되면 최상위로 App 컴포넌트를 가지고 있고 이 App 컴포넌트는 메인 페이지의 태그의 id가 root인 태그에 렌더링됩니다. 기존 앱에서 React를 통합하게 되는 경우 Button처럼 작은 컴포넌트부터 상단으로 올라가면서 작업해야 합니다.

 

컴포넌트 추출

 

function Comment(props) {
  return (
    <div className="Comment">
      <div className="UserInfo">
        <img className="Avatar"
          src={props.author.avatarUrl}
          alt={props.author.name}
        />
        <div className="UserInfo-name">
          {props.author.name}
        </div>
      </div>
      <div className="Comment-text">
        {props.text}
      </div>
      <div className="Comment-date">
        {formatDate(props.date)}
      </div>
    </div>
  );
}

 

Comment 컴포넌트는 부모 컴포넌트로 부터 author, text, date를 받고 있습니다. 이 컴포넌트는 모두 중첩 구조로 되어 있어 변경하기 어렵기 때문에 재사용도 힘듭니다. 이 컴포넌트를 작은 단위의 컴포넌트로 추출해보겠습니다.

 

className인 Avatar를 컴포넌트로 추출해보겠습니다.

 

function Avatar(props) {
  return (
    <img className="Avatar"
      src={props.user.avatarUrl}
      alt={props.user.name}
    />
  );
}

 

Avatar는 자신이 Comment 내에서 렌더링 된다는 것을 알 필요 없습니다. 따라서 props의 이름을 author에서 일반화된 user로 변경했습니다. props의 이름은 사용될 context가 아닌 컴포넌트 자체의 관점에서 짓는 것을 권장합니다.

 

Avatar를 컴포넌트로 추출한 코드는 아래와 같습니다.

 

function Comment(props) {
  return (
    <div className="Comment">
      <div className="UserInfo">
        <Avatar user={props.author} />
        <div className="UserInfo-name">
          {props.author.name}
        </div>
      </div>
      <div className="Comment-text">
        {props.text}
      </div>
      <div className="Comment-date">
        {formatDate(props.date)}
      </div>
    </div>
  );
}

 

다음으로 Avatar 아래에 있는 사용자의 이름을 렌더링하는 UserInfo 컴포넌트를 추출하겠습니다.

 

function UserInfo(props) {
  return (
    <div className="UserInfo">
      <Avatar user={props.user} />
      <div className="UserInfo-name">
        {props.user.name}
      </div>
    </div>
  );
}

 

Comment가 더욱 단순해졌습니다.

 

function Comment(props) {
  return (
    <div className="Comment">
      <UserInfo user={props.author} />
      <div className="Comment-text">
        {props.text}
      </div>
      <div className="Comment-date">
        {formatDate(props.date)}
      </div>
    </div>
  );
}

 

컴포넌트를 추출하는 작업이 번거로울 수도 있지만 재사용이 가능한 컴포넌트를 만들어 놓는 것은 큰 앱을 작업할 때 효과를 발휘하고 리액트가 가장 지향하는 방식입니다. UI의 일부가 여러 번 사용되거나(Button, Form, Panel 등), UI 일부가 자체적으로 복잡한 (App, FeedStory, Comment) 경우에는 별도의 컴포넌트로 만드는 게 좋습니다.

 

props는 읽기 전용입니다.

 

컴포넌트를 함수나 클래스로 선언했을 때 props를 수정할 수 없습니다.

 

//이 함수는 파라미터의 값이 변경되지 않습니다.
//순수한 함수입니다.
function sum(a,b){
	return a + b;
}

//이 함수는 파라미터인 a의 객체 프로퍼티 값이 변경됩니다.
//순수한 함수가 아닙니다.
function add(a,b){
	return a.sum + b;
}

 

모든 React 컴포넌트에서는 props와 관련한 동작을 할 때 순수 함수처럼 동작해야 하는 엄격한 규칙이 있습니다.

그럼 규칙을 어기지 않고 유저 액션, 네트워크 응답, 기타 등등에 대한 응답으로 시간 경과에 따라 출력을 변경을 할 때는 어떻게 해야 하나요?

다음 섹션에서 배워봅니다.

 

컴포넌트와 props
728x90

'programming_kr > react' 카테고리의 다른 글

이벤트 제어  (0) 2021.01.19
state와 lifecycle  (0) 2021.01.16
요소의 렌더링  (0) 2021.01.10
JSX란?  (0) 2021.01.08
React.js란?  (0) 2021.01.03

댓글