티스토리 뷰
개발하면서 앱이 커질수록 타입체크는 더욱 잘해야하고 타입 검사를 잘 활용하면 많은 버그를 잡을 수 있다.
React에는 내장된 타입 검사 기능들을 갖고 있다. 컴포넌트간 데이터를 전달하는 prop에 타입체크를 하는 것은 필수적으로 해줘야 미래의 내가 덜 고생하는 길이 될 수 있다.
PropTypes
컴포넌트의 prop에 타입 검사를 하기 위해 prop를 받는 하위컴포넌트에 PropTypes를 선언해준다.
import PropTypes from "prop-types";
prop에 유효하지 않은 값이 전달되면 콘솔에 경고문이 보일 것이다.

타입이 다르면 실행을 아예 안시키는 타입스크립트와 달리 자바스크립트에선 실행은 시켜주는 대신 콘솔에 저런 경고문을 띄워준다. 그리고 저 경고문은 propTypes 성능상의 이유로 개발 모드에서만 확인할 수 있다.
import React from "react";
import PropTypes from "prop-types";
const Board = ({ articles }) => {
return (
<ul>
{articles.map((article) => (
<li key={article.id}>
{article.id} | {article.title}
</li>
))}
</ul>
);
};
Board.propTypes = {
articles: PropTypes.array,
};
export default Board;
자식컴포넌트인 Board에서 prop 타입 체크하는 코드이다.
PropTypes를 사용함으로써 또 하나의 장점은 타입 정의만으로 좋은 코드가 될 수 있다는 점이다.
const User = ({ type, age, male, onChangeName, onChangeTitle }) => {
const onClick1 = () => {
const msg = `type: ${type}, age: ${age ? age : '알 수 없음'}`
log(msg, { color: type === "gold" ? "red" : "black" })
// ...
}
const onClick2 = () => {
if (onChangeName) onChangeName(name)
onChangeTitle(title)
male ? goMalePage() : goFemalePage()
// ...
}
// ...
}
위 코드처럼 코드를 자세히 뜯어보지 않는이상 타입을 한번에 알기가 어렵다.
User.propTypes = {
male: PropTypes.bool.isRequired,
age: PropTypes.number,
type: PropTypes.oneOf(["gold", "silver", "bronze"]),
onChangeName: PropTypes.func,
onChangeTitle: PropTypes.func.isRequired
}
const User = ({ type, age, male, onChangeName, onChangeTitle }) => {
// ...
이렇게 PropTypes로 타입을 명시해주면 코드를 뜯어보지 않고도 타입을 한번에 알 수 있고 협업할때 일의 능률도 올라갈 것이다.
PropTypes를 사용하여 다양한 유효성 검사를 할 수 있다.
예제) 하나의 자식만 요구하기
PropTypes.element를 이용하여 컴포넌트의 자식들에 단 하나의 자식만이 전달될 수 있도록 명시할 수 있다.
// 부모 컴포넌트
...
<PropEx>
<h1>Hello</h1>
<h2>World</h2>
</PropEx>
...
// 자식 컴포넌트
import React from "react";
import PropTypes from "prop-types";
const PropEx = ({ children }) => {
return <div>{children}</div>;
};
PropEx.propTypes = {
children: PropTypes.element.isRequired, // 타입에러
};
export default PropEx;

그 외 PropTypes종류
MyComponent.propTypes = {
// 리액트 요소
// <div>123</div> , <Component />
menu: PropTypes.element,
// 컴포넌트 함수가 반환할 수 있는 모든 것(비추)
// <SomeComponent />, 123
description: PropTypes.node,
// Message 클래스로 생성된 모든 객체
// new Messages() -> 참, new Car() -> 거짓
message: PropTypes.instanceOf(Message),
// 배열에 포함된 값 중에서 하나를 만족
name: PropTypes.oneOf(["jake", "olivia"]),
// 배열에 포함된 타입 중에서 하나를 만족
width: PropTypes.oneOfType([PropTypes.number, PropTypes.string])
// 특정 타입만 포함하는 배열
// [1, 5, 7] -> 참, ['a', 'b'] -> 거짓
ages: PropTypes.arrayOf(PropTypes.number),
// 객체의 속성값 타입을 정의
// {color: 'red', weight: 123} -> 참
info: PropTypes.shape({
color: PropTypes.string,
weight: PropTypes.number
})
// 객체에서 모든 속성값의 타입이 같은 경우
// {prop1: 123, prop2: 456}
infos: PropTypes.objectOf(PropTypes.number)
}
나는 여기서 한가지 의문이 들었다.
타입스크립트에선 PropTypes가 필요없나??
결론부터 얘기하자면 완벽한 휴먼에러 퇴치를 원한다면 PropTypes 사용을 권장한다
이유는,
자바스크립트는 동적인 언어이고 런타임에 타입이 결정된다. 그리고 타입스크립트는 정적인 언어로 컴파일 시에 타입이 결정된다. 그렇기 때문에 타입스크립트 코드를 짤 때 IDE에서 미리 경고를 날려주는게 특징이다.
다만 외부 데이터를 사용할때, 즉 API 호출을 통해 받아온 응답이나 로컬 스토리지 등의 외부 데이터는 컴파일 단계에서 타입 체크를 할 수 없기 때문에 여기에서 타입 불일치가 발생할 가능성이 있다.
그래서 런타임에 타입 체크를 해주는 PropTypes 라이브러리를 사용하는게 좀 더 완벽하게 휴먼 에러를 방지하는 것이라고 볼 수 있다.
타입스크립트 PropTypes의 자세한 내용은 참고
참고
PropTypes와 함께 하는 타입 검사 – React
A JavaScript library for building user interfaces
ko.reactjs.org
[React] PropTypes 쓰는 이유, 방법
작업하는 프로젝트의 규모가 커질 수록 생각지 못한 곳에서 에러가 발생하는 일이 잦아진다. 이를 방지하기 위한 방법으로, PropTypes를 활용하여 타입(type)을 확인하는 것이 대표적이다.
velog.io
'React' 카테고리의 다른 글
[React] React 18버전의 새로운 기능들 (원티드 프리온보딩 사전과제) (8) | 2023.03.27 |
---|---|
[React] 전역상태관리 라이브러리 Recoil (2) | 2023.02.20 |
[React] 라이프 사이클 (0) | 2023.02.11 |
[React] 최적화 (useMemo, React.memo) (0) | 2022.12.17 |
- Total
- Today
- Yesterday
- 프로그래머스 데브코스 FE
- 힙
- 번들러
- 알고리즘
- jwt
- useMemo
- 프로세스 동기화
- JavaScript
- CORS
- 토이 프로젝트
- 회고
- 코딩테스트
- propTypes
- 호이스팅
- 배열의 메서드
- 프로그래머스 데브코스
- 라이프사이클
- 웹 브라우저 객체
- 원티드 프리온보딩 챌린지
- 네트워크
- React.Memo
- 리액트
- 교착상태
- 프로젝트 회고
- 프로그래머스
- 무한스크롤
- 노션 클로닝 프로젝트
- Recoil
- kdt
- 스코프
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |