PropTypes로 React 입력 타입 체크하기
PropTypes는 React에서 타입 체크를 위해서 사용되는 라이브러리입니다. 이 번 포스팅에서는 PropTypes를 이용해서 React 컴포넌트의 prop에 대한 타입 정의와 기본값 설정을 하는 방법에 대해서 알아보겠습니다.
패키지 설치
PropTypes 라이브러리는 prop-types
이라는 패키지 이름을 가지고 있는데요.
기본적으로 react
패키지에 내장이 되어 있기 때문에, React만 설치되어 있다면 별도로 설치할 필요가 없습니다.
예제 컴포넌트
PropTypes를 어떻게 사용하는지 보여드리기 위해서 먼저 예제 컴포넌트를 작성하도록 하겠습니다.
아래 코드는 prop으로 path
와 chidren
, blank
, size
를 받아서, <a/>
엘리먼트를 랜더링해주는 간단한 React 함수 컴포넌트입니다.
import React from "react";
const BASE_URL = "https://www.daleseo.com";
function Anchor({ path, children, blank, size }) {
return (
<a
href={`${BASE_URL}${path}`}
target={blank ? "_blank" : "_self"}
style={{ fontSize: size }}
>
{children}
</a>
);
}
예를 들어, 위 Anchor
컴포넌트는 다음과 같이 사용할 수 있습니다.
<Anchor path="/react-prop-types" blank size={20}>
PropTypes
</Anchor>
그러면 실제로 브라우저에서는 다음과 같이 랜더링됩니다.
<a
href="https://www.daleseo.com/react-prop-types"
target="_blank"
style="font-size: 20px;"
>PropTypes</a
>
타입 체크 부재로 인한 문제점
만약에 Anchor
컴포넌트를 사용하는 사람이 아래와 같은 실수를 한다고 가정해보겠습니다.
children
prop을 누락시킨다면?
<Anchor path="/react-prop-types" blank size={20} />
size
prop에 숫자가 아닌 문자열을 넘긴다면?
<Anchor path="/react-prop-types" blank size="20">
PropTypes
</Anchor>
이런 경우, Anchor
컴포넌트는 원치않는 방식으로 랜더링되게 됩니다.
이렇게 React에서 흔히 발생하는 버그는 컴포넌트의 prop에 대한 명시적인 타입 체크를 통해 해결을 할 수 있으며, 이를 도와주는 라이브러리가 PropTypes
입니다.
prop 타입 정의
PropTypes를 이용해서 React 컴포넌트에 prop으로 넘어오는 입력값들이 어떤 타입을 가져야하는지 정의할 수 있습니다.
우선, prop-types
패키지에서 PropTypes
객체를 임포트해야 합니다.
import PropTypes from "prop-types";
이 PropTypes
객체는 타입을 정의할 때 필요한 다양한 타입 검증자(validator)들을 제공합니다.
그리고 React 컴포넌트의 PropTypes
을 이용해 정의된 타입 정보를 할당받기 위한 propTypes
속성을 가지고 있습니다.
예를 들어, 위에서 작성한 Anchor
컴포넌트는 타입 정의는 다음과 같이 할 수 있습니다.
Anchor.propTypes = {
path: PropTypes.string,
children: PropTypes.string.isRequired,
blank: PropTypes.bool,
size: PropTypes.number,
};
path
와 children
prop은 문자열, blank
prop은 불리언, size
porp은 숫자로 타입을 정의하였습니다.
그리고 children
prop은 맨 뒤에 isRequired
를 붙임으로써 반드시 입력되어야 하는 필수 prop으로 정의하였습니다.
이렇게 타입 명시적으로 컴포넌트에 넘어올 prop에 대한 타입 정의를 해주면, React는 타입 정의 위반 시 경고 메시지를 콘솔에 출력해줍니다.
예를 들어, size
prop에 숫자가 아닌 문자열을 넘기면, 다음과 같은 경고 메시지를 확인하실 수 있으실 겁니다.
<Anchor path="/react-prop-types" blank size="20" />
Warning: Failed prop type: Invalid prop `size` of type `string` supplied to `Anchor`, expected `number`.
이러한 경고 메시지는 개발 모드에서만 출력되기 때문에, 실제 사용자에게 아무 영향을 주지 않으면서, 오직 개발자들만 확인할 수 있습니다.
prop 기본값 설정
추가로 타입 정의와 더불어 많이 사용되는 prop의 기본값을 설정하는 방법을 알아보겠습니다.
타입 정의를 할 때와 비슷한 방식으로 React 컴포넌트는 defaultProps
속성을 가지고 있고, 여기에 기본값을 정의하는 객체를 할당해주면 됩니다.
예를 들어, 위에서 작성한 Anchor
컴포넌트는 기본값 설정은 다음과 같이 할 수 있습니다.
Anchor.defaultProps = {
path: "/#",
blank: false,
size: 16,
};
위와 같이 각 prop에 대한 기본값을 설정해주면, 해당 prop에 입력값이 넘어오지 않은 경우, 이 기본값이 사용됩니다.
그리고 children
prop의 경우 위에서 타입을 정의할 때 필수 prop으로 정의하였기 때문에 기본값을 설정해줄 필요가 없습니다.
이제, 다음과 같이 Anchor
컴포넌트에 children
prop만을 넘기게 되면,
<Anchor>Home</Anchor>
아래와 같이 prop에 기본값이 설정된 상태로 랜더링이 되게 됩니다.
<a href="https://www.daleseo.com/#" target="_self" style="font-size: 16px;"
>Home</a
>
전체 코드는 아래에 올려두었으니 참고바라겠습니다.
복잡한 타입 정의
위 예제처럼 단순한 타입이 아닌 복잡한 구조를 가진 객체를 prop으로 받는 컴포넌트들은 어떻게 타입 정의를 할 수 있을까요?
PropTypes
객체는 복잡한 타입 정의를 위한 shape()
, arrayOf()
, oneOf()
, instanceOf()
와 같은 고급 검증자들도 제공하고 있습니다.
예를 들어, 아래의 UserProfie
컴포넌트의 경우, 필수 prop인 user
와 선택 prop인 friends
를 갖도록 정의되어 있습니다.
user
prop의 경우, 숫자 타입인 id
속성과 문자열 타입인 name
속성을 반드시 갖는 객체로 타입이 정의되어 있습니다.
avatar
는 선택적으로 필요한 속성인데, 필수인 theme
속성은 black
과 white
중 하나의 값이 될 수 있는 Enum 타입이며, 선택인 image
속성은 Image
클래스의 인스턴스여야 합니다.
friends
prop의 경우 선택 사항이며, user
와 유사한 구조를 가진 객체를 원소로 갖는 배열의 형태로 입력되도록 정의되어 있습니다.
UserProfie.propTypes = {
user: PropTypes.shape({
id: PropTypes.number.isRequired,
name: PropTypes.string.isRequired,
preference: PropTypes.shape({
theme: PropTypes.oneOf(["black", "white"]).isRequired,
image: PropTypes.instanceOf(Image),
}),
}).isRequired,
friends: PropTypes.arrayOf(
PropTypes.shape({
id: PropTypes.number.isRequired,
name: PropTypes.string.isRequired,
}).isRequired
),
};
마치면서
지금까지 PropTypes 라이브러리를 사용해서 React 컴포넌트의 타입 체크를 하는 아주 기본적인 방법에 대해서 알아보았습니다. 왠만한 프로젝트에서는 이 정도 수준의 타입 체크만 해줘도 많은 버그를 예방할 수 있을 것이라고 생각합니다. PropTypes 라이브러리에 대한 세부적인 사항들은 아래 사이트를 참고바라겠습니다.