React에서 똑똑하게 Props 관리하기

휴먼스케이프

PropTypes, 혹은 TypeScript로 props의 타입을 정해주는 방법 알아보기

안녕하세요. 휴먼스케이프 Frontend Software Engineer 남현욱입니다. 이번 포스트에서는 Props에 타입을 지정해서 육안만으로 예측이 어려운 Props를 조금 더 똑똑하게 관리하는 방법을 알아보겠습니다.

난 천재라서 상관없어

아무리 천재라도 컴퓨터보다 정확할 수는 없으리라고 생각합니다. 이런 상황들을 마주할 때 말이죠.

최악의 상황

이 코드만 봐도, 2가지의 문제가 발생합니다.

MainPage에서 어떤 props를 필요로 하는 지 모른다.

App에서 MainPageContainer로 어떤 props를 전달해야 하는 지 모른다.

사실 이렇게 코드가 짧으면, 당신은 잠깐 천재로 빙의해서 모든 props를 다 알아맞출 수 있습니다. 그렇지만 depth가 깊어지고,props를 좀 많이 줘야 하는 상황이 온다면 어떨까요?

장풍! ==3

아래부터는 이런 상황들을 방지하기 위해 사용할 수 있는 여러 가지 방법을 알려드리려고 합니다.

그 전에

props가 복잡해지기 전, 먼저 depth와 넘겨주는 값들을 줄여보는 것은 어떨까요?

예를 들자면, react-redux에는 리덕스 안 리듀서의 state와 dispatch를 넘겨받을 수 있도록 고차 컴포넌트를 반환하는 connect() 함수가 있습니다. 그러나, 이 함수를 대신할 새로운 방법으로 useSelector()와 useDispatch() 훅을 사용할 수 있습니다.

이 두 개로 커스텀 훅을 만들면, depth가 하나 줄어들게 되고 받아오는 만큼의 props 개수를 줄일 수 있습니다.

또 권장하는 방법은, props에 Object Destructuring을 사용하여 어떤 이름의 props가 올 것인지라도 유추할 수 있는 방법이 있습니다.

props를 쪼갠 예시

이외에도 Hooks API 사용하기, 고차 컴포넌트 덜 사용하기, 지나친 props drilling 피하기, Context API 사용하기 등의 방법이 있습니다. 글의 주제는 아니니, 궁금한 부분에 대해서는 구글링 실력을 발휘해주세요 :)

useSelector() 및 useDispatch(): https://react-redux.js.org/next/api/hooks

Object Destructuring: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Object_destructuring

PropTypes 사용하기

링크: https://github.com/facebook/prop-types

정말 간단하고, 또 유용하게 사용할 수 있습니다. 별도의 세팅 없이도, 단순히 아래 명령어로 prop-types 패키지를 설치하기만 하면 사용할 수 있습니다.

$ npm i --save prop-types
or
$ yarn add prop-types

예시로 하나의 컴포넌트를 만들 건데, 단순히 이름을 받아서 Hello를 앞에 붙여주는 컴포넌트입니다.

만들고 나면, 브라우저에서는 이렇게 보일 겁니다.

하지만 지금 name의 타입이 어떤 종류라도, 다 받아서 사용할 수 있습니다!

그래서 “name이라는 녀석은 string 타입만 받게 하고 싶어.” 라고 생각하시면, 아래처럼 해주시면 됩니다.

이제 App 컴포넌트에서 문자열이 아닌 다른 값을 넣어보세요. 개발자 콘솔에서 에러가 발생합니다.

1을 넣었을 때의 결과

어느 정도 버그를 잡아낼 수 있다고 생각하지만, 그래도 이 방법으로는 많이 부족한 것 같습니다. 에디터가 먼저 앞장서서 잡아주거나, 에러를 만들어낸다면 조금 더 편하지 않을까요?

TypeScript를 적용해서 Props의 타입 지정하기

TypeScript는 타입이 적용된 JavaScript의 슈퍼셋입니다. 쉽게 말해서, 약타입 언어인 JavaScript에 타입을 지정할 수 있습니다.

아까 알려드린 게 PropTypes인데, TypeScript만 세팅해주면 별다른 세팅 없이 바로 props에 타입을 적용하실 수 있습니다.

이제 prop-types 패키지와 관련 코드를 지우고, TypeScript를 사용할 수 있는 준비를 해줍니다.

$ npm rm --save prop-types
$ npm i --save typescript @types/node @types/react @types/react-dom @types/jest
or
$ yarn remove prop-types
$ yarn add typescript @types/node @types/react @types/react-dom @types/jest

Adding TypeScript: https://create-react-app.dev/docs/adding-typescript/

위 작업이 끝났으면, index.js, App.js, Hello.js 파일의 확장자를 모두 tsx로 변경해줍니다.

이제 앱을 시작하자마자 TypeScript 에러를 보게 됩니다.

“‘name’이라는 element가 묵시적으로 ‘any’ 타입입니다.” 라고 오류가 발생했습니다. 이 오류를 수정하려면, name의 타입이 필요합니다.

interface 부분을 types로 대체할 수 있습니다.

둘의 차이: https://medium.com/@alexsung/typescript-type%EA%B3%BC-interface-%EC%B0%A8%EC%9D%B4-86666e3e90c

type Props = {
  name: string
};

이제 다시 App 컴포넌트에 string 타입이 아닌 것을 넣어보세요.

타입 에러

타입 에러가 발생했습니다! 이제 string을 넣어야 원활하게 작동할 수 있다는 점을 알았습니다.

돌아보기

지금까지 React에서 똑똑하게 Props를 관리하는 방법을 알아보았습니다. 물론 Props를 관리하는 것보다 더욱 재사용 가능한 컴포넌트를 만든다던가, 쓰기 좋은 훅을 작성하는 것이 먼저 우선시되어야 합니다.

물론 Props의 타입을 검증했다고 해도, 꼼꼼하게 테스트 코드를 작성하는 것도 중요합니다. 언젠가는 테스트 코드나 Atomic Design 관련 포스트를 작성해보고 싶은 개인적인 마음이 있네요 :)

이상으로 이번 포스트를 마치겠습니다. 감사합니다.

Get to know us better! Join our official channels below.

Telegram(EN) : t.me/Humanscape KakaoTalk(KR) : open.kakao.com/o/gqbUQEM Website : humanscape.io Medium : medium.com/humanscape-ico Facebook : www.facebook.com/humanscape Twitter : twitter.com/Humanscape_io Reddit : https://www.reddit.com/r/Humanscape_official Bitcointalk announcement : https://bit.ly/2rVsP4T Email : support@humanscape.io

기업문화 엿볼 때, 더팀스

로그인

/