본문 바로가기
  • SDXL 1.0 + 한복 LoRA
  • SDXL 1.0 + 한복 LoRA
Study/React

React 살펴보기 #5

by 마즈다 2017. 3. 4.
반응형

Components and Props

component는 UI를 독립적이고 재사용 가능한 부분으로 나누는 개별적인 조각으로 생각할 수 있다.
개념상으로는 component는 JavaScript의 함수와 같다. component는 (“props”라고 불리는)임의의 입력을 
받아서 화면에 그려지는 방식을 기술하는 React elements를 리턴해준다.


Functional and Class Components

가장 간단하게 component를 만드는 방법은 JavaScript 함수를 만드는 것이다.

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

이 함수는 하나의 “props”라는 데이터를 포함한 객체를 인자로 받아서 React elements를 리턴해주므로 유효한
React component라고 할 수 있다. 이러한 component는 말 그대로 JavaScript의 함수(function)와 같은

형태이기에 “functional”이라고 부른다.


물론 ES6 class를 이용해서도 component를 만들 수 있다.

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

React의 관점에서 봤을 때 위의 두 component는 동일하다.


Class들은 우리가 다음 장에서 논의할 추가적인 특징들을 가지고 있다. 그 때까지는 간단하게 functional 
components를 사용할 것이다.


Rendering a Component 

지금까지는 분명 DOM tag를 표현하는React elements들 만을 보아왔다.

const element = <div />;

그러나 elements는 사용자 정의 components를 표현할 수도 있다.

const element = <Welcome name="Sara" />;

React가 elements를 통해 사용자 정의 component가 표현되는 과정을 감지할 때 React는 하나의 객체형태로
JSX 속성을 component에 전달하게 되는데 우리는 이 객체를 “props”라고 부른다.


예를 들어 아래 코드는 화면에 “Hello, Sara”를 표시하게 된다.

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

const element = <Welcome name="Sara" />;
ReactDOM.render(
 element,
 document.getElementById('root')
);

CodePen에서 확인해보자

이 코드에서 무슨 일이 벌어지는 지 되짚어보자.

  1. 우리는 <Welcome name="Sara" />라는 element를 인자로 하여 ReactDOM.render()를 호출한다.
  2. React는 {name: 'Sara'}를 props로 하여 Welcome component를 호출한다.
  3. Welcome component는 그 결과 값으로 <h1>Hello, Sara</h1>라는 element를 리턴한다.
  4. React DOM은 <h1>Hello, Sara</h1>와 일치하도록 효율적으로 DOM을 업데이트 한다.

경고 :
component이름은 항상 대문자로 시작해야 한다.
예를들어 <div />는 DOM tag를 표시하며 <Welcome />는 component를 표시한다 그리고 Welcome
같은 scope 내에 있어야만 한다.

Composing Components

component는 그 자신의 출력에서 다른 component를 참조할 수 있다. 이를 통해서 모든 세부적인 수준에서라도 
공통적으로 이용 가능한 component의 추상화를 사용할 수 있다. React에서는 버튼, form, 다이얼로그, 화면 등이
일반적으로 component로 표현된다.


예를 들면 Welcome을 여러번 렌더링할 수 있는 App이라는 component를 생성할 수 있다.

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

function App() {
 return (
	<div>
	  <Welcome name="Sara" />
	  <Welcome name="Cahal" />
	  <Welcome name="Edite" />
	</div>
 );
}

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

CodePen에서 확인해보자


일반적으로 새로운 React app을 만들 때에는 제일 먼저 App이라는 하나의 component를 만들어 시작한다. 
하지만 만일 기존에 존재하는 app에 React를 통합하는 경우라면 버튼 같은 작은 component로부터 시작하여
점차로 view 계층의 상위 요소로 구성해 나갈 수 있다.


경고 :
Components는 반드시 하나의 root element만을 리턴해야 한다. 이 때문에 모든 <Welcome />element를 포함한 <div />를 추가한 것이다.

Extracting Components

components를 더 작은 components로 나누는 것을 두려워 하지 말라.


예를 들어 아래의 Comment component를 살펴보자

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>
 );
}

CodePen에서 확인해보자


이 component는 props의 author (객체 타입), text (문자열 타입), 그리고 date (날짜 타입)에 접근 할 수
있다. 그리고 소셜 미디어 웹사이트의 comment를 표시한다.


이 component는 모두 중첩된 구조로 되어있어 수정하기가 어렵고 각각을 개별적인 부분으로 재사용하기도 
어렵다. 이 component로부터 몇개의 작은 component를 추출해보자.


우선 Avatar를 추출해보자

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

Avatar는 Commnet안에서 렌더링 될 것을 알 필요가 없다. 즉, 다른 어떤 component에서 렌더링이 될 수도
있는 것이다. 때문에 prop을 author보다 일반적인 user로 이름 붙였다.


props의 이름은 component가 사용되는 맥락보다는 component 자체의 관점에서 지어줄 것을 권장한다.


이제 Comment를 조금 간단하게 할 수 있다.

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 component를 추출해보자

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>
 );
}

CodePen에서 확인해보자


component를 추출하는 작업은 처음에는 귀찮은 작업으로 보일 수도 있다. 그러나 재사용 가능한 components의
모음을 가지고 있으면 더 큰 app에서 발생하는 비용을 줄여줄 것이다. 경험에 비추어보았을 때 UI의 일부가 여러번
반복해서 사용되거나(ButtonPanelAvatar), 그 자체로 충분히 복잡하다면(AppFeedStory
Comment) 이러한 것들은 재사용 가능한 component를 만들기 위한 좋은 후보자들이다.


Props are Read-Only

component가 function으로 선언되었건 Class로 선언되었건 props를 수정할 수는 없다. 아래의 sum 
function을 살펴보자

function sum(a, b) {
 return a + b;
}

이런 함수는 전달받은 입력값을 변경하지도 않고 같은 값이 입력된다면 항상 리턴 값도 동일하기 때문에 “pure”라고 
부른다.


반면에 전달 받는 입력 값을 변경하는 아래 함수는 impure다.

function withdraw(account, amount) {
 account.total -= amount;
}

React는 꽤 유연하지만 하나의 엄격한 규칙이 있다.


모든 React components는 props에 대해서는 반드시 pure로 작동해야 한다.


물론 애플리케이션의 UI들은 유동적이며 시간이 지남에 따라 변한다. 다음 장에서는 “state”라는 새로운 개념에 대해
소개할 것이다. State는 이러한 규칙을 위반하지 않으면서도 사용자의 동작, 네트워크 응답 및 기타 다른 요소들에

대한 응답으로 시간 경과에 따라 출력을 변경할 수 있도록 해준다.

반응형

'Study > React' 카테고리의 다른 글

React 살펴보기 #7  (0) 2017.04.20
React 살펴보기 #6  (0) 2017.03.27
React 살펴보기 #4  (0) 2017.02.17
React 살펴보기 #3  (0) 2017.02.11
React 살펴보기 #2  (0) 2017.02.06