React 공부 (7) 컴포넌트와 Props

seon·2024년 1월 26일

Web

목록 보기
13/33
post-thumbnail

# Component 합성

컴포넌트 합성은 여러 개의 컴포넌트를 합쳐서 하나의 컴포넌트를 만드는 것입니다.
리액트에서는 컴포넌트 안에 또 다른 컴포넌틀르 사용할 수 있기 때문에 복잡한 화면을 여러개의 컴포넌트로 나눠서 구현할 수 있습니다. Welcome 컴폰넌트를 사용해서 컴포넌트 합성을 하는 예제 코드를 보겠겠습니다.

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

function App(props) {
  return (
    <div>
    	<Welcome name="Mike" />
    	<Welcome name="Steve" />
    	<Welcome name="Jane" />
    </div>
  )
}

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

이 코드를 보면 props 의 값을 다르게 해서 Welcome 컴포넌트를 여러번 사용하는 것을 볼 수 있습니다. 이렇게 하면 App 이라는 컴포넌트는 Welcome 컴포넌트 세개를 포함하고 있는 컴포넌트가 되는 것이죠. 이렇게 여러 개의 컴포넌트를 합쳐서 또다른 컴포넌트를 만드는 것을 컴포넌트 합성이라고 합니다. 여기에 나온 App 컴포넌트를 좀 더 이해하기 쉽게 그림으로 표현해 보겠습니다. App 컴포넌트 안에 3개의 Welcome 컴포넌트가 있고 각각의 Welcome 컴포넌트는 각기 다른 props를 가지고 있습니다.

이렇게 App 컴포넌트를 root로 해서 하위 컴포넌트들이 존재하는 형태가 리액트로만 구성된 앱의 기본적인 구조입니다.

만약 기존에 있던 웹페이지에 리액트를 연동한다면 root 노드가 하나가 아닐 수도 있기 때문에 이런 구조가 되지 않을 수도 있습니다.


# Component 추출

컴포넌트 합성과 반대로 복잡한 컴포넌트를 쪼개서 여러 개의 컴포넌트로 나눌 수도 있습니다. 이러한 과정을 우리는 컴포넌트 추출이라고 부릅니다.

큰 컴포넌트를 산산조각내자!

큰 컴포넌트에서 일부를 추출해서 새로운 컴포넌트를 만든다는 뜻이죠. 컴포넌트 추출을 잘 활용하게 되면 컴포넌트의 재사용성이 올라가게 됩니다.

재사용성 ⇑

왜냐하면 컴포넌트가 작아질수록 해당 컴포넌트의 기능과 목적이 명확해지고 props 도 단순해지기 때문에 다른 곳에서 사용할 수 있을 확률이 높아지기 때문입니다.

재사용성이 올라감으로써 동시에 개발 속도도 향상됩니다.

개발 속도 ⇑

지금부터 예제코드를 통해서 컴포넌트를 추출하는 과정을 하나하나씩 살펴보도록 하겠습니다.
먼저 여기에 Comment라는 컴포넌트가 하나 있습니다. 이 컴포넌트는 댓글을 표시하기 위한 컴포넌트로,

function Comment(props) {
  return (
    <div className="comment">
    	<div className="user-info">
    		<img className="avatar"
    			src={props.author.avatarUrl}
				alt={props.author.name}
			/>
            <div className="user-info-name">
              {props.author.name}
			</div>
		</div>

			<div className="comment=text">
              {props.text}
			</div>

			<div className="comment-date">
              {formatDate(props.date)}
            </div>
	</div>
  );
}

내부의 작성자의 프로필 이미지와 이름 그리고 댓글 내용과 작성일을 포함하고 있습니다.
그리고 이 컴포넌트의 props는 아래와 같은 형태일 것입니다.

props = {
  author: {
    name: "소플",
    avatarUrl: "https://...",
  }
  text: '댓글입니다.",
  dae: Date.now(),
}

이제 이 컴포넌트에서 하나씩 컴포넌트를 추출해보도록 하겠습니다.

1. Avatar 추출하기

Comment 컴포넌트에서는 img 태그를 사용하여 사용자의 프로필 이미지를 표시하고 있습니다.

function Comment(props) {
  return (
    <div className="comment">
    	<div className="user-info">
    		<img className="avatar" //---추출할 img 부분 ------ㄱ
    			src={props.author.avatarUrl} //                | 
				alt={props.author.name}//                      |
			/> //_____________________________________________⌟
			<div className="user-info-name">
              {props.author.name}
			</div>
		</div>
// ... ...
	</div>
  );
}

이 부분을 추출해서 Avatar라는 별도의 컴포넌트로 만들어 보겠습니다.
추출된 Avatar 컴포넌트는 이런 모습이 될 것입니다.

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

그리고 props의, 기존에 사용하던 author 대신 조금 더 보편적인 의미를 갖고 있는 user를 사용하였습니다. 보편적인 단어를 사용하는 것은 재사용성 측면을 고려하는 것이라고 보면 됩니다. 다른 곳에서 이 컴포넌트를 사용할 때도 props에 들어갈 속성들이 의미상 큰 차이없이 사용할 수 있게 하기 위함이죠.

자, 이제 이렇게 추출된 Avatar 컴포넌트를 실제로 Comment 컴포넌트에 반영해야 되겠죠? 추출된 Avatar 컴포넌트가 적용된 모습입니다.

function Comment(props) {
  return (
    <div className="comment">
    	<div className="user-info">
    		<Avatar user={props.author} />//추출후,Avatar컴포넌트 적용된부분
  			<div className="user-info-name">
              {props.author.name}
			</div>
		</div>
// ... ...
	</div>
  );
}

Avatar 라는 이름의 컴포넌트로 교체되고 나니 좀 더 코드의 가독성이 높아진 것 같죠.


2. UserInfo 추출하기

이제 다음 단계로 사용자 정보를 담고 있는 부분을 추출해보도록 하겠습니다.

function Comment(props) {
  return (
    <div className="comment">
    	<div className="user-info"> //----사용자의 정보를 담고 있는 부분-----ㄱ
    		<Avatar user={props.author} /> //							  |
  			<div className="user-info-name">//							  |
              {props.author.name}//										  |
			</div>//													  |
		</div>//_________________________________________________________⌟
// ... ...
	</div>
  );
}

이 부분을 추출해서 별도의 컴포넌트로 만들어 보겠습니다.

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

이 코드는 사용자 정보를 담고 있는 부분을 UserInfo 라는 컴포넌트로 추출한 것입니다. 아까 처음에 추출했던 Avatar 컴포넌트도 여기에 함께 추출된 것을 볼 수 있습니다. 그리고 역시 props의 author 대신 좀 더 보편적인 의미를 갖고 있는 user 를 사용하였습니다.
그럼 이제 추출된 UserInfo 컴포넌트를 Comment 컴포넌트에 반영해보겠습니다.

UserInfo 컴포넌트를 반영하면 이렇게 됩니다.

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

코드가 처음에 비해서 훨씬 더 단순해진 것을 볼 수 있습니다.

지금까지 추출한 컴포넌트들의 구조를 그림으로 나타내면 다음과 같습니다. Comment 컴포넌트가 UserInfo 컴포넌트를 포함하고 있고 UserInfo 컴포넌트가 Avatar 컴포넌트를 포함하고 있는 구조입니다.
지금까지 추출한 것 이외에도 추가적으로 Comment의 글과 작성일이 나오는 부분도 별도의 컴포넌트로 추출이 가능합니다. 컴포넌트를 어느정도 수준까지 추출하는 것이 좋은지에 대해 정해진 기준은 없습니다. 하지만 기능 단위로 구분하는 것이 좋고, 나중에 곧바로 재사용이 가능한 형태로 추출하는 것이 좋습니다.

지금까지 살펴본 예제에서 추출한 Avatar 컴포넌트나 UserInfo 컴포넌트는 다른 웹사이트를 만들 때에도 충분히 재사용이 가능할 것입니다. 그리고 앞에서 말씀드린 것처럼 재사용이 가능한 컴포넌트를 많이 갖고 있을수록 개발 속도가 굉장히 빨라지게 됩니다.


📍정리

컴포넌트와 Props (2)

  • 컴포넌트 합성 : 여러 개의 컴포넌트를 합쳐서 하나의 컴포넌트를 만드는 과정
    => 리액트로만 구성된 앱의 기본적인 구조이다!
  • 컴포넌트 추출 : 복잡한 컴포넌트를 쪼개서 여러 개의 컴포넌트로 나누는 과정
    => 재사용성과 개발 속도가 높아진다!



profile
🌻

0개의 댓글