앞선 포스트에서 컴포넌트(component)는 리액트 프로젝트에서 특정 부분이 어떻게 생길지를 결정하는 선언체라고 배웠습니다. 리액트의 컴포넌트는 함수형 컴포넌트와 클래스형 컴포넌트로 두 가지로 선언될 수 있습니다.
클래스형 컴포넌트와 함수형 컴포넌트를 비교하며 컴포넌트를 생성해보겠습니다. 또한 컴포넌트에서 사용하거나 렌더링 하는 데이터를 담는 props와 state의 차이점과 선언 방식을 배우겠습니다.
1. 📌 클래스형 컴포넌트
1.1. 📚 클래스형 컴포넌트
컴포넌트를 선언하는 방식은 클래스 컴포넌트와 함수 컴포넌트로 나뉩니다. 클래스형 컴포넌트와 함수 컴포넌트는 state 기능 및 라이프 사이클 기능, 임의 메서드 정의 등에서 차이가 납니다.
각 방법으로 작성된 코드를 보면서 차이점을 비교해보자.
1.1.1. 📃 클래스 컴포넌트
<javascript />
import {Component} from "react";
class App extends Component {
render() {
const name = 'react';
return <div className='react'> {name} </div>;
}
}
export default App;
1.1.2. 📃 함수 컴포넌트
<javascript />
import './App.css';
function App() {
const name = "리액트";
return <div className='react'> {name} </div>;
}
export default App;
함수 컴포넌트의 특징은 다음과 같습니다.
- 클래스 컴포넌트보다 선언하기 편리
- 클래스 컴포넌트보다 메모리 자원을 덜 사용하고, 실제 배포할 때도 결과물의 파일 크기가 더 작습니다.
- 리액트 v16.8 업데이트로 state와 라이프사이클 API도 사용이 가능해졌습니다.
리액트 v16.8 업데이트로 Hooks가 도입되었고 함수 컴포넌트도 클래스 컴포넌트와 같이 작업을 할 수 있게 되었습니다. 리액트 공식 매뉴얼에서는 함수 컴포넌트와 Hooks를 사용하도록 권장합니다. 그러나 이전의 작성된 코드들의 유지 및 보수를 위하여 클래스 컴포넌트도 반드시 알아두어야합니다.
2. 📌 첫 컴포넌트 생성
2.1. 📚 함수 컴포넌트 작성하기
컴포넌트는 다음의 세 단계를 거쳐서 만들 수 있습니다.
- 파일 만들기
- 코드 작성하기
- 모듈 내보내기 및 불러오기
VS 코드에서 파일을 만드는 방법은 src 디렉터리 - [우클릭] - <파일이름>.js 작성하면 됩니다.

2.2. 📚 코드 작성하기
앞으로는 NewComponent.js 파일을 새로 만들어 코드 작업을 진행하도록 하겠습니다.
<javascript />
// NewComponent.js
const NewComponent = () => {
return <div> 화살표 함수를 이용한 컴포넌트 </div>
};
export default NewComponent;
위 코드는 화살표 함수를 이용하여 만든 함수 컴포넌트입니다. JavaScript ES6 문법에서 function 키워드 외에도 화살표 함수로 함수를 선언하여 사용할 수 있습니다. 화살표 함수는 값을 연산하여 바로 반환해야할 때 사용하면 가독성을 높일 수 있습니다.
2.3. 📚 모듈 내보내기 및 불러오기
2.3.1. 📃 모듈 내보내기
<javascript />
export default NewComponent;
이 코드는 다른 파일에서 이 파일을 import 할 때, 위 클래스를 불러오도록 합니다
2.3.2. 📃 모듈 불러오기
<javascript />
// App.js
import NewComponent from "./NewComponent";
const App = () => {
return <NewComponent />
}
export default App;
import 키워드를 통해 NewComponent 컴포넌트를 불러 새로 렌더링할 수 있습니다.
3. 📌 props
3.1. 📚 props 값 사용
props는 properties의 줄임말로 컴포넌트의 속성을 설정할 수 있습니다. 이 props 값은 해당 컴포넌트를 불러와 사용하는 부모 컴포넌트에서 설정할 수 있습니다.
3.1.1. 📃 JSX 내부에서 props 렌더링
NewComponent.js에 다음의 내용을 작성합니다.
<javascript />
// NewComponent.js
const NewComponent = props => {
return <div> {props.prog}에서 컴포넌트를 만듭니다. </div>
};
export default NewComponent;
- 해당 컴포넌트에서 program이라는 props를 렌더링하도록 하는 코드
- props 값은 매개변수(파라미터)로 사용
3.1.2. 📃 컴포넌트를 사용할 때 props 값 지정하기
NewComponent를 불러오는 부모 컴포넌트(App.js)에 다음의 내용을 작성합니다.
<javascript />
// App.js
import NewComponent from "./NewComponent";
const App = () => {
return <NewComponent prog="리액트" />;
};
export default App;
- 부모 컴포넌트에서 props의 값을 지정
3.2. 📚 props 기본값 설정: defaultProps
위의 부모 컴포넌트의 prog 값을 지우면 prog 자리에 아무 내용도 출력되지 않습니다. props 값을 따로 지정하지 않았을 때 보여줄 기본값은 defaultProps로 설정할 수 있습니다. .
<javascript />
// NewComponent.js
const NewComponent = props => {
return <div> {props.prog}에서 컴포넌트를 만듭니다. </div>;
};
NewComponent.defaultProps = {
prog : "REACT"
}
export default NewComponent;
NewComponent.js 파일에 defaultProps을 이용해 기본 값을 설정해줄 수 있습니다.
3.3. 📚 태그 사이의 내용을 보여주는 children
리액트에서는 컴포넌트 태그 사이의 내용을 보여주는 props도 있습니다. children이라는 값을 통해 태그 사이에 작성한 내용을 자식 컴포넌트 내부에서 보여줄 수 있습니다. 자식 노드에서는 props.children을 통해 접근할 수 있습니다.
(코드 내의 (...) 은 새로 작성된 부분 외의 코드는 이전에 작성한 코드와 동일함을 의미합니다.)
<javascript />
// NewComponent.js
const NewComponent = props => {
return (
<div>
{props.prog}에서 컴포넌트를 만듭니다. <br/>
children의 값은 {props.children}입니다.
</div>
);
};
(...)
export default NewComponent;
<javascript />
// App.js
import NewComponent from "./NewComponent";
const App = () => {
return <NewComponent> ~태그 사이~ </NewComponent>
}
export default App;
3.4. 📚 비구조화 할당 문법을 통해 props 내부 값 추출하기
props 값을 조회할 때마다 props.prog, props.children 같이 prog. 이라는 키워드가 필요합니다. ES6의 비구조화 할당 문법을 사용하여 내부 값을 더 편히 추출할 수 있습니다.
<javascript />
// NewComponent.js
const NewComponent = props => {
const {prog, children} = props;
return (
<div>
{prog}에서 컴포넌트를 만듭니다. <br/>
children의 값은 {children}입니다.
</div>
);
};
(...)
export default NewComponent;
- 객체에서 값을 추출하는 문법을 비구조화 할당(destructing assignment)라고 부름
- 구조 분해 문법이라고도 불림
함수의 파라미터 부분에서도 사용 가능합니다. 함수의 파라미터가 객체라면 값을 바로 비구조화하여 다음과 같이 코드를 작성할 수 있습니다.
<javascript />
// NewComponent.js
const NewComponent = ({prog, children}) => {
return (
<div>
{prog}에서 컴포넌트를 만듭니다. <br/>
children의 값은 {children}입니다.
</div>
);
};
(...)
export default NewComponent;
3.5. 📚 propTypes를 통한 props 검증
컴포넌트의 필수 props를 지정하거나 타입을 지정할 때는 propTypes를 사용합니다. propTypes를 지정하는 방법은 defaultProp을 설정하는 것과 비슷합니다. propTypes을 사용하기 위해 코드 상단에 import를 해야합니다.
<javascript />
import PropTypes from 'prop-types';
3.5.1. 📃 타입 설정하기
<javascript />
// NewComponent.js
import PropTypes from 'prop-types';
(...)
NewComponent.propTypes = {
prog: PropTypes.string
};
export default NewComponent;
- prog의 내용은 반드시 String으로 지정되어야 함
- 잘못된 타입으로 값을 지정한 뒤 개발자 도구의 Console 탭을 열면 오류 창이 뜸
3.5.2. 📃 isRequired를 사용하여 필수 propTypes 설정
propTypes을 지정할 때 경고 메세지를 발생시킬 수 있습니다.
<javascript />
// NewComponent.js
import { PropTypes } from "prop-types";
const NewComponent = ({prog, children, age}) => {
return (
<div>
{prog}에서 컴포넌트를 만듭니다. <br/>
children의 값은 {children}입니다. <br/>
저의 나이는 {age}세 입니다.
</div>
);
};
NewComponent.defaultProps = {
prog : "리액트"
}
NewComponent.propTypes = {
prog: PropTypes.string,
age: PropTypes.number.isRequired
};
export default NewComponent;
부모 컴포넌트인 App.js에서 age의 값이 설정되지 않는 다면 콘솔창에서 오류 메시지를 보여줄 것 입니다.
<javascript />
// App.js
import NewComponent from "./NewComponent";
const App = () => {
return(
<NewComponent prog = "React" age = {100} >
~ children 값 ~
</NewComponent>
)
}
export default App;
3.5.3. 📃 PropTypes의 종류
https://github.com/facebook/prop-types 에서 PropTypes에 대한 내용을 볼 수 있습니다.
3.6. 📚 클래스형 컴포넌트에서 props 사용하기
클래스형 컴포넌트에서 props를 사용할 때는 render 함수에서 this.props를 조회하면 됩니다. defaultProps와 propTypes는 똑같은 방식으로 설정할 수 있습니다. 클래스형 컴포넌트에서 props 값을 조회하는 코드입니다.
<javascript />
// NewComponent.js
import { Component } from "react";
import PropTypes from "prop-types";
class NewComponent extends Component {
render() {
const {prog, children, age} = this.props; //비구조화 할당
return (
<div>
{prog}에서 컴포넌트를 만듭니다. <br/>
children의 값은 {children}입니다. <br/>
저의 나이는 {age}세 입니다.
</div>
)
}
}
NewComponent.defaultProps = {
prog : "리액트"
}
NewComponent.propTypes = {
prog: PropTypes.string,
age: PropTypes.number.isRequired
};
export default NewComponent;
defaultProps와 propTypes는 class 내부에서도 지정 가능합니다.
<javascript />
// NewComponent.js
import { Component } from "react";
import PropTypes from "prop-types";
class NewComponent extends Component {
static defaultProps = {
prog : "리액트"
};
static propTypes = {
prog: PropTypes.string,
age: PropTypes.number.isRequired
}
render() {
( ... )
}
}
export default NewComponent;
4. 📌 state
4.1. 📚 state
- state는 컴포넌트 내부에서 바뀔 수 있는 값을 의미
- props는 컴포넌트가 사용되는 과정에서 부모 컴포넌트가 설정하며 자신은 해당 props를 읽기 전용으로만 사용
- state는 컴포넌트 자체적으로 지닌 값으로 컴포넌트 내부에서 값을 업데이트 할 수 있음
- 일반 변수는 값이 변경될 때 html에 자동 변경되지 않지만, state는 값이 변경되면 html에 재랜더링 해줌
=> 값의 변화가 자주 있을 때 state를 사용 - 클래스형 컴포넌트는 state, 함수 컴포넌트에서는 useState를 사용
4.2. 📚 클래스형 컴포넌트의 state
클릭으로 숫자를 늘이는 Counter.js를 만들어 봅시다.
<javascript />
// Counter.js
import { Component } from "react";
class Counter extends Component {
constructor(props) {
super(props);
this.state = {
number: 0 // state 초깃값 설정하기
};
}
render() {
const {number} = this.state; // state 조회시 this.state를 조회
return (
<div>
<h1> {number} </h1>
<button
/* onClick 함수를 사용하여 클릭 시 숫자를 늘려주는 버튼 만들기 */
onClick = {() => {
/* this.setState를 사용하여 state에 새로운 값을 지정 */
this.setState( {number: number +1 } );
}}
>
+1
</button>
</div>
);
}
}
export default Counter;
4.3. 📚 함수 컴포넌트에서 useState 사용하기
4.3.1. 📃 배열 비구조화 할당
- 배열 비구조화 할당은 객체 비구조화 할당과 비슷함
- 배열 안에 들어있는 값을 쉽게 추출하도록 하는 문법
- Destructing 문법을 통해 형태를 맞추어 값을 쉽게 할당
<javascript />
const array = [1, 2];
const one = array[0];
const two = array[1];
위 코드는 배열 비구조화 할당을 통해 더 간단히 표현될 수 있습니다.
<javascript />
const array = [1, 2];
const [one, two] = array;
4.3.2. 📃 useState 사용하기
리액트 16.8 이전 버전에서는 함수 컴포넌트에서 state를 사용할 수 없었습니다. 그러나 업데이트 이후, Hooks가 생기면서 useState 함수를 사용하여 함수 컴포넌트에서도 state를 사용할 수 있습니다. Hooks의 종류 중 하나인 useState를 먼저 배우겠습니다.

useState는 배열 비구조화 할당 문법과 같습니다. useState를 활용한 코드를 Say.js에 작성해봅시다.
<javascript />
// Say.js
import { useState } from "react";
const Say = () => {
const [message, setMessage] = useState('');
const onClickEnter = () => setMessage("안녕하세요!");
const onClickLeave = () => setMessage("안녕히가세요!");
return (
<div>
<button onClick={onClickEnter}>입장</button>
<button onClick={onClickLeave}>퇴장</button>
<h1> {message} </h1>
</div>
);
};
export default Say;
- useState 함수 인자에는 상태의 초깃값을 지정, 객체가 아니어도 괜찮음
- 함수를 호출하면 배열이 반환
* 배열의 첫 번째 원소는 현재 상태
* 배열의 두 번째 원소는 상태를 바꾸어주는 함수, setter 함수
<javascript />
// App.js
import Say from "./Say";
const App = () => {
return <Say />
}
export default App;
4.4. 📚 한 컴포넌트에서 useState 여러 번 사용하기
<javascript />
// Say.js
import { useState } from "react";
const Say = () => {
const [message, setMessage] = useState('');
const onClickEnter = () => setMessage("안녕하세요!");
const onClickLeave = () => setMessage("안녕히가세요!");
const [color, setColor] = useState('black');
return (
<div>
<button onClick={onClickEnter}>입장</button>
<button onClick={onClickLeave}>퇴장</button>
<h1 style = {{ color }}> {message} </h1>
<button style={{ color: 'red'}} onClick={() => setColor('red')}>
빨간색
</button>
<button style={{ color: 'green'}} onClick={() => setColor('green')}>
초록색
</button>
<button style={{ color: 'blue'}} onClick={() => setColor('blue')}>
파란색
</button>
</div>
);
};
export default Say;
4.5. 📚 state 사용 시 주의 사항
- state 값을 바꿀때는 setState 혹은 useState를 통해 전달받은 세터(setter) 함수를 사용
- 배열이나 객체를 업데이트 할 때는 사본에 값을 업데이트하고 그 사본의 상태를 setState나 세터 함수로 업데이트
- 사본은 spread 연산자를 사용하고 배열의 사본은 내장 함수를 활용
'프레임워크 > REACT' 카테고리의 다른 글
[React] 04. 이벤트 핸들링 (0) | 2022.10.23 |
---|---|
[React] # 클래스형 컴포넌트 VS 함수형 컴포넌트 (0) | 2022.10.21 |
[React] 02. JSX (0) | 2022.10.09 |
[React] # 리액트 프로젝트 만들기 (1) | 2022.10.07 |
[React] 01. 리액트 시작 (2) | 2022.10.06 |