React 04 - 컴포넌트를 알아보자
예전에 다른 리액트 책을 공부할 때 함수형 컴포넌트와 클래스형 컴포넌트를 공부했었는데 어느덧 반년을 아예 공부하지 않고 생각을 안하다보니 어느덧 머릿속에서 기억이 나질 않는다. 컴포넌트는 정확히 무엇이고, 함수형 컴포넌트(Functional Component)와 클래스형 컴포넌트(Class Component)가 무엇이고 어떤 차이가 있는지 알아보자.
- 컴포넌트가 뭐에요?
쉽게 말하면 리액트를 이루는 최소 단위라고 볼 수 있다.
이렇게 말하면 어려우니까 우리는 그림으로 표현해보자.
위와 같은 페이지가 있다고 생각을 해보자.
아래와 같은 코드 구조를 갖게 될텐데..
<header>
<div style="text-align:center">
<img src="https://user-images.githubusercontent.com/54430432/122516646-fc5bd980-d049-11eb-97bc-81229f4b1ef2.gif" style="width:300px; height:300px;">
</div>
<div>
<a href="/nlog/">
<h1>if(재능이 없으면 시간으로 극복하라){return 성공;}</h1>
</a>
<div class="header-links">
<a href="/nlog/about">
<h2 class="header-link">Profile</h2>
</a>
<a href="/nlog/archive">
<h2 class="header-link">Post</h2>
</a>
<a href="/nlog/career">
<h2 class="header-link">Project</h2>
</a>
</div>
</div>
</header>
<div class="container">
<section id="main_content">
<ul>
<li>
<h2><a href="/nlog/Webpack">Webpack 구조</a></h2>
<time datetime="2022-04-04T00:00:00+00:00">04 Apr 2022</time>
<p>Webpack은 번들링 해주는 프로그램이다. 쉽게 말하자면 다수의 JavaScript를 하나로 만들어 주는 프로그램이다. (물론 JavaScript 외 파일들도 번들링이 가능하다) 그렇다면 왜 다수의 JavaScript를 하나로 만드는 걸까? 과거엔 페이지마다 새로운 html을 호출했지만.. html의 용량이 가벼워서 상관이 없었다. 점점 html에 담는 내용들이 많아지면서 용량이 무거워지고 매 번 호출하는게 버거워졌다. 그래서 SPA(Single Page Appllicaion)를...</p>
</li>
<li>
<h2><a href="/nlog/Whatisprotocol">Network - 프로토콜의 종류와 특징</a></h2>
<time datetime="2022-03-22T00:00:00+00:00">22 Mar 2022</time>
<p>프로토콜(Protocol)이란? 프로토콜은 다른 시스템 및 기기간 데이터 교환을 원활히 하기 위한 표준화된 통신 규약이다. 우리는 인터넷을 통해 많은 나라 사람들과 통신할 수 있다. 이러한 통신을 하기 위해선 일종의 규칙이 지켜져야 서로 통신할 수 있을 것이 아닌가? 예를 들어 미국인 친구와 한국인인 내가 만났다. 근데 우리는 스페인에서 만났는데 어떤 언어를 사용할지...</p>
</li>
</ul>
</section>
</div>
</div>
물론 코드 자체는 어렵지 않지만 컴포넌트화를 하게 되면 말도 안되는 코드로 바뀌게 된다.
<NlogMainHeader/>
<NlogPostList/>
????????? 이 두줄로 다 표현이 사실 가능하다.
물론 위의
html을 하나의 객체로 만든것이 바로 컴포넌트라 생각하면 되겠다. 앞선 포스팅에서 함수로 우리는 html을 반환하였다.
function App(){
return (
<Fragment>
<h1>Test</h1>
<h2>Test</h2>
</Fragment>
)
}
export default App;
이것도 다~~ 컴포넌트가 될 수 있다는 말이다. 기본적으로 컴포넌트가 어떤 느낌인지는 이해가 됐을거라 생각한다. 그렇다면 본격적으로 컴포넌트의 종류가 무엇이 있고 어떻게 사용하는지 자세하게 알아보자.
리액트 포스팅을 시작하면서부터 계속 함수형 컴포넌트로 우리는 사용해왔다. 위에 보면 떡하니 function이라고 시작을 해서 return으로 끝나지 않던가.
그렇다면 위의 문법을 클래스형 컴포넌트로 바꿔보자
import { Component } from 'react';
class App extends Component {
render() {
return (
<Fragment>
<h1>Test</h1>
<h2>Test</h2>
</Fragment>
)
}
}
export default App;
흠.. component를 가져와서 상속 받아서 component의 기능을 App이라는 클래스형 컴포넌트에서 사용하겠다는건데 문법만 보게 된다면 조금 더 복잡해보이기도 하는데 왜 class형 컴포넌트는 존재하는걸까?
바로 state와 lifecycle 기능을 사용할 수 있다는 점이다. 뭐 아직은 state랑 lifecycle에 대해서 분명하게 모르지만 이런걸 사용할 수 있기에 클래스형 컴포넌트를 사용한다는 정도만 알아두자.
- props props는 컴포넌트의 속성을 설정할 때 사용하는 요소다. 이 속성들은 왜 필요하냐..라고 까지도 물어볼 수가 있다. 그렇다면 반대로 물어보고 싶다. 컴포넌트에서 어떤 값을 사용하고 싶으면 어떻게 쓸 것인가? .. props의 존재 이유를 알겠는가?
위에서 사용했던 class컴포넌트를 이용해서 props를 사용해보자.
import { Component } from 'react';
class MyFirstComponent extends Component {
render() {
return (
<>
<h1>{this.props.name}</h1>
<h2>Test</h2>
</>
)
}
}
export default MyFirstComponent;
위 처럼 구성된 컴포넌트를 다른 js에서 사용한다고 쳐보자.
App.js
import MyFirstComponent from './MyFirstComponent';
import { Component } from 'react';
class App extends Component {
render() {
return (
<MyFirstComponent name="^_^" />
)
}
}
export default App;
위 이미지처럼 props에 대한 속성을 가지고 올 수 있다.
만약 props에 대한 속성이 없다면 default값으로 설정할 수 있다.
import { Component } from 'react';
class MyFirstComponent extends Component {
render() {
return (
<>
<h1>{this.props.name}</h1>
<h2>Test</h2>
</>
)
}
}
MyFirstComponent.defaultProps = {
name : '디폴트 값이 설정이 잘 됐나요?'
}
export default MyFirstComponent;
디폴트 값이 잘 설정되었다.
태그 사이의 내용을 가지고 오는 방법도 있다. 태그 사이의 값은 children을 이용해서 하면 되는데,
import MyFirstComponent from './MyFirstComponent';
import { Component } from 'react';
class App extends Component {
render() {
return (
<MyFirstComponent>children 값 가져오기</MyFirstComponent>
)
}
}
export default App;
컴포넌트 사이에 텍스트를 넣어주고,
import { Component } from 'react';
class MyFirstComponent extends Component {
render() {
return (
<>
<h1>{this.props.name}</h1>
<h2>{this.props.children}</h2>
</>
)
}
}
MyFirstComponent.defaultProps = {
name : '디폴트 값이 설정이 잘 됐나요?'
}
export default MyFirstComponent;
props를 통하여 children 값을 가지고 오면,
children값을 잘 가지고 온다.
지금 props의 값을 가지고 올 땐, props.name 이나 props.children 같은 문법을 사용하여 가지고 오고 있는데 훨씬 쉽게 가지고 올 수 있는 방법이 있다.
import { Component } from 'react';
class MyFirstComponent extends Component {
render() {
const {name, children} = this.props;
return (
<>
<h1>{name}</h1>
<h2>{children}</h2>
</>
)
}
}
MyFirstComponent.defaultProps = {
name : '디폴트 값이 설정이 잘 됐네요!'
}
export default MyFirstComponent;
화살표 함수를 통해 문법을 바꾸게 되면..
const MyFirstComponent = props => {
return (
<>
<h1>{props.name}</h1>
<h2>{props.children}</h2>
</>
)
}
MyFirstComponent.defaultProps = {
name : '디폴트 값이 설정이 잘 됐네요!'
}
export default MyFirstComponent;
위와 같은 기본적인 설정들을 잡을 수 있지만, prop의 type을 정할 수 있다.
import { Component } from 'react';
import PropTypes from 'prop-types'; //npm install 해서 따로 받아야 함
class MyFirstComponent extends Component {
render() {
const {name, children} = this.props;
return (
<>
<h1>{name}</h1>
<h2>{children}</h2>
</>
)
}
}
MyFirstComponent.defaultProps = {
name : '디폴트 값이 설정이 잘 됐네요!'
}
MyFirstComponent.propTypes = {
name : PropTypes.string
}
export default MyFirstComponent;
name의 값은 String으로 받는다고 설정을 잡아주고 실제는 숫자로 값을 받아보자.
import MyFirstComponent from './MyFirstComponent';
import { Component } from 'react';
class App extends Component {
render() {
return (
<MyFirstComponent name={3}>children 값 가져오기</MyFirstComponent>
)
}
}
export default App;
import MyFirstComponent from './MyFirstComponent';
import { Component } from 'react';
class App extends Component {
render() {
return (
<MyFirstComponent name="3">children 값 가져오기</MyFirstComponent>
)
}
}
export default App;
String 값으로 다시 받으면
오류 없이 제대로 받을 수 있다.
또한 props의 Type 뿐만 아니라 필수 여부를 정할 수가 있다. 그것은 바로 isRequired이다.
import { Component } from 'react';
import PropTypes from 'prop-types'
class MyFirstComponent extends Component {
render() {
const {name, children, titles} = this.props;
return (
<>
<h1>{name}</h1>
<h2>{children}</h2>
<h3>{titles}</h3>
</>
)
}
}
MyFirstComponent.defaultProps = {
name : '디폴트 값이 설정이 잘 됐네요!'
}
MyFirstComponent.propTypes = {
name : PropTypes.string,
titles : PropTypes.string.isRequired
}
export default MyFirstComponent;
isRequired를 설정하고 값을 넣지 않으면 아래와 같은 오류가 생긴다.
isRequired의 값을 설정해주면
import MyFirstComponent from './MyFirstComponent';
import { Component } from 'react';
class App extends Component {
render() {
return (
<MyFirstComponent name="3" titles="값을 설정하였네요">children 값 가져오기</MyFirstComponent>
)
}
}
export default App;
오류없이 화면이 노출된다.
그 외의 PropTypes의 여러가지 설정들이 존재하니 참고해서 사용할 수 있도록 하자!
다음은 state 관련 포스팅에서 뵙겠습니다.