프로그래밍 언어/REACT

prop-types 추가하기

· 코딩마이데이

음식 데이터에 rating 추가하기

import React from "react";

function Food({ name, picture }) {
  return (
    <div>
      <h2>I love {name}</h2>
      <img src={picture} alt={name} />
    </div>
  );
}

const foodILike = [
  {
    id: 1,
    name: "파스타",
    image:
      "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNKuJ29sfo1_gy6jrbo3l0hX8SC8hOJpnqKA&s",
    rating: 5,
  },
  {
    id: 2,
    name: "비빔밥",
    image:
      "https://i.namu.wiki/i/dgjXU86ae29hDSCza-L0GZlFt3T9lRx1Ug9cKtqWSzMzs7Cd0CN2SzyLFEJcHVFviKcxAlIwxcllT9s2sck0RA.jpg",
    rating: 4.9,
  },
  {
    id: 3,
    name: "라면",
    image:
      "https://i.namu.wiki/i/2mrBrfSDXbBJHLjgyycsAhB0qLvjSZbvswmGtVTAupaEfuQ8Xuzp8wJiXyeDTsqz7blqGRYSjW5mbo1Wc4GP_w.webp",
    rating: 4.8,
  },
  {
    id: 4,
    name: "초밥",
    image:
      "https://i.namu.wiki/i/vwbKQLdn5CzWLTdLHKb2rYjLZS6icyFb6b6PdEz_3Y_0gJQqRMuhHGgogptO19gl3NZMnRsTvjYlA-0-JRSrbw.webp",
    rating: 4.9,
  },
  {
    id: 5,
    name: "카레라이스",
    image:
      "https://i.namu.wiki/i/QUSohbmt0G1CuYZKW-skuN5K3HAjf88GgTttXS0EphnSMWN8UkV-nYCb3hCCNNbs2m6pjyNF2MLbdQO8cBy1gA.webp",
    rating: 4.9,
  },
]; // foodLike 변수에 베열을 저장함

function App() {
  return (
    <div>
      {foodILike.map((dish) => (
        <Food key={dish.id} name={dish.name} picture={dish.image} />
      ))}
    </div>
  );
}

export default App;

이제 rating props를 Food 컴포넌트에 전달하면서 이 값을 검사해 볼 것입니다. 그러려면 props의 자료형을 검사할 수 있도록 만들어주는 prop-types라는 도구를 설치해야 합니다.

 

prop-types 설치하기

npm install prop-types

 

package.json 파일을 열어 dependencies 키에 있는 값을 살펴봅시다.

{
  "name": "movie_app_2025",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "6.6.3",
    "@testing-library/react": "16.2.0",
    "@testing-library/user-event": "14.6.0",
    "cra-template": "1.2.0",
    "prop-types": "^15.8.1",
    "react": "^19.0.0",
    "react-dom": "^19.0.0",
    "react-scripts": "5.0.1"
  },
  (생략...)

 

props-types는 컴포넌트가 전달받은 props가 정말 내가 원하는 값인지 확인해줍니다.

 

prop-types 적용하기

import PropTypes from 'prop-types';를 App.js 파일 맨 위에 추가해줍니다.

그리고 rating.props를 Food 컴포넌트에 전달합니다.

import React from "react";
import PropTypes from "prop-types";

function Food({ name, picture, rating }) {
  return (
    <div>
      <h2>I love {name}</h2>
      <h4>{rating}/5.0</h4>
      <img src={picture} alt={name} />
    </div>
  );
}

const foodILike = [
  {
    id: 1,
    name: "파스타",
    image:
      "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNKuJ29sfo1_gy6jrbo3l0hX8SC8hOJpnqKA&s",
    rating: 5,
  },
  {
    id: 2,
    name: "비빔밥",
    image:
      "https://i.namu.wiki/i/dgjXU86ae29hDSCza-L0GZlFt3T9lRx1Ug9cKtqWSzMzs7Cd0CN2SzyLFEJcHVFviKcxAlIwxcllT9s2sck0RA.jpg",
    rating: 4.9,
  },
  {
    id: 3,
    name: "라면",
    image:
      "https://i.namu.wiki/i/2mrBrfSDXbBJHLjgyycsAhB0qLvjSZbvswmGtVTAupaEfuQ8Xuzp8wJiXyeDTsqz7blqGRYSjW5mbo1Wc4GP_w.webp",
    rating: 4.8,
  },
  {
    id: 4,
    name: "초밥",
    image:
      "https://i.namu.wiki/i/vwbKQLdn5CzWLTdLHKb2rYjLZS6icyFb6b6PdEz_3Y_0gJQqRMuhHGgogptO19gl3NZMnRsTvjYlA-0-JRSrbw.webp",
    rating: 4.9,
  },
  {
    id: 5,
    name: "카레라이스",
    image:
      "https://i.namu.wiki/i/QUSohbmt0G1CuYZKW-skuN5K3HAjf88GgTttXS0EphnSMWN8UkV-nYCb3hCCNNbs2m6pjyNF2MLbdQO8cBy1gA.webp",
    rating: 4.9,
  },
]; // foodLike 변수에 베열을 저장함

function App() {
  return (
    <div>
      {foodILike.map((dish) => (
        <Food
          key={dish.id}
          name={dish.name}
          picture={dish.image}
          rating={dish.rating}
        />
      ))}
    </div>
  );
}

Food.propTypes = {
  name: PropTypes.string.isRequired,
  picture: PropTypes.string.isRequired,
  rating: PropTypes.number.isRequired,
};

export default App;

 

 

이제 props를 적용해봅니다.

import React from "react";
import PropTypes from "prop-types";

function Food({ name, picture, rating }) {
  return (
    <div>
      <h2>I love {name}</h2>
      <h4>{rating}/5.0</h4>
      <img src={picture} alt={name} />
    </div>
  );
}

const foodILike = [
  {
    id: 1,
    name: "파스타",
    image:
      "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNKuJ29sfo1_gy6jrbo3l0hX8SC8hOJpnqKA&s",
    rating: 5,
  },
  {
    id: 2,
    name: "비빔밥",
    image:
      "https://i.namu.wiki/i/dgjXU86ae29hDSCza-L0GZlFt3T9lRx1Ug9cKtqWSzMzs7Cd0CN2SzyLFEJcHVFviKcxAlIwxcllT9s2sck0RA.jpg",
    rating: 4.9,
  },
  {
    id: 3,
    name: "라면",
    image:
      "https://i.namu.wiki/i/2mrBrfSDXbBJHLjgyycsAhB0qLvjSZbvswmGtVTAupaEfuQ8Xuzp8wJiXyeDTsqz7blqGRYSjW5mbo1Wc4GP_w.webp",
    rating: 4.8,
  },
  {
    id: 4,
    name: "초밥",
    image:
      "https://i.namu.wiki/i/vwbKQLdn5CzWLTdLHKb2rYjLZS6icyFb6b6PdEz_3Y_0gJQqRMuhHGgogptO19gl3NZMnRsTvjYlA-0-JRSrbw.webp",
    rating: 4.9,
  },
  {
    id: 5,
    name: "카레라이스",
    image:
      "https://i.namu.wiki/i/QUSohbmt0G1CuYZKW-skuN5K3HAjf88GgTttXS0EphnSMWN8UkV-nYCb3hCCNNbs2m6pjyNF2MLbdQO8cBy1gA.webp",
    rating: 4.9,
  },
]; // foodLike 변수에 베열을 저장함

function App() {
  return (
    <div>
      {foodILike.map((dish) => (
        <Food
          key={dish.id}
          name={dish.name}
          picture={dish.image}
          rating={dish.rating}
        />
      ))}
    </div>
  );
}

Food.propTypes = {
  name: PropTypes.string.isRequired,
  picture: PropTypes.string.isRequired,
  rating: PropTypes.string.isRequired,
};

export default App;

 

prop-types 경고 해결하기

Food 컴포넌트에 전달하는 picture props의 이름을 image로 바꿔봅니다.

import React from "react";
import PropTypes from "prop-types";

function Food({ name, picture, rating }) {
  return (
    <div>
      <h2>I love {name}</h2>
      <h4>{rating}/5.0</h4>
      <img src={picture} alt={name} />
    </div>
  );
}

const foodILike = [
  {
    id: 1,
    name: "파스타",
    image:
      "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNKuJ29sfo1_gy6jrbo3l0hX8SC8hOJpnqKA&s",
    rating: 5,
  },
  {
    id: 2,
    name: "비빔밥",
    image:
      "https://i.namu.wiki/i/dgjXU86ae29hDSCza-L0GZlFt3T9lRx1Ug9cKtqWSzMzs7Cd0CN2SzyLFEJcHVFviKcxAlIwxcllT9s2sck0RA.jpg",
    rating: 4.9,
  },
  {
    id: 3,
    name: "라면",
    image:
      "https://i.namu.wiki/i/2mrBrfSDXbBJHLjgyycsAhB0qLvjSZbvswmGtVTAupaEfuQ8Xuzp8wJiXyeDTsqz7blqGRYSjW5mbo1Wc4GP_w.webp",
    rating: 4.8,
  },
  {
    id: 4,
    name: "초밥",
    image:
      "https://i.namu.wiki/i/vwbKQLdn5CzWLTdLHKb2rYjLZS6icyFb6b6PdEz_3Y_0gJQqRMuhHGgogptO19gl3NZMnRsTvjYlA-0-JRSrbw.webp",
    rating: 4.9,
  },
  {
    id: 5,
    name: "카레라이스",
    image:
      "https://i.namu.wiki/i/QUSohbmt0G1CuYZKW-skuN5K3HAjf88GgTttXS0EphnSMWN8UkV-nYCb3hCCNNbs2m6pjyNF2MLbdQO8cBy1gA.webp",
    rating: 4.9,
  },
]; // foodLike 변수에 베열을 저장함

function App() {
  return (
    <div>
      {foodILike.map((dish) => (
        <Food
          key={dish.id}
          name={dish.name}
          image={dish.image}
          rating={dish.rating}
        />
      ))}
    </div>
  );
}

Food.propTypes = {
  name: PropTypes.string.isRequired,
  picture: PropTypes.string.isRequired,
  rating: PropTypes.number.isRequired,
};

export default App;

 

위 앱을 실행해보면 사진이 나오지 않습니다. 

 

[Console] tab에 경고 메시지가 나오는데, 경고 메시지를 읽어보면 "Food 컴포넌트에 picture라는 이름의 props가 필요한데, 그 값이 undefined다"라고 말하고 있습니다.

Food 컴포넌트에 picture props가 아니라 inage props를 전달했기 때문입니다.

이제 코드를 원래대로 돌려놓습니다.

import React from "react";
import PropTypes from "prop-types";

function Food({ name, picture, rating }) {
  return (
    <div>
      <h2>I love {name}</h2>
      <h4>{rating}/5.0</h4>
      <img src={picture} alt={name} />
    </div>
  );
}

const foodILike = [
  {
    id: 1,
    name: "파스타",
    image:
      "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNKuJ29sfo1_gy6jrbo3l0hX8SC8hOJpnqKA&s",
    rating: 5,
  },
  {
    id: 2,
    name: "비빔밥",
    image:
      "https://i.namu.wiki/i/dgjXU86ae29hDSCza-L0GZlFt3T9lRx1Ug9cKtqWSzMzs7Cd0CN2SzyLFEJcHVFviKcxAlIwxcllT9s2sck0RA.jpg",
    rating: 4.9,
  },
  {
    id: 3,
    name: "라면",
    image:
      "https://i.namu.wiki/i/2mrBrfSDXbBJHLjgyycsAhB0qLvjSZbvswmGtVTAupaEfuQ8Xuzp8wJiXyeDTsqz7blqGRYSjW5mbo1Wc4GP_w.webp",
    rating: 4.8,
  },
  {
    id: 4,
    name: "초밥",
    image:
      "https://i.namu.wiki/i/vwbKQLdn5CzWLTdLHKb2rYjLZS6icyFb6b6PdEz_3Y_0gJQqRMuhHGgogptO19gl3NZMnRsTvjYlA-0-JRSrbw.webp",
    rating: 4.9,
  },
  {
    id: 5,
    name: "카레라이스",
    image:
      "https://i.namu.wiki/i/QUSohbmt0G1CuYZKW-skuN5K3HAjf88GgTttXS0EphnSMWN8UkV-nYCb3hCCNNbs2m6pjyNF2MLbdQO8cBy1gA.webp",
    rating: 4.9,
  },
]; // foodLike 변수에 베열을 저장함

function App() {
  return (
    <div>
      {foodILike.map((dish) => (
        <Food
          key={dish.id}
          name={dish.name}
          picture={dish.image}
          rating={dish.rating}
        />
      ))}
    </div>
  );
}

Food.propTypes = {
  name: PropTypes.string.isRequired,
  picture: PropTypes.string.isRequired,
  rating: PropTypes.number.isRequired,
};

export default App;

 

prop-types는 이런 식으로 props를 검사합니다.

자료형과 그 이름의 값이 전달되었는지도 검사해줍니다.

 

isRequired의 뜻 살펴보기

import React from "react";
import PropTypes from "prop-types";

function Food({ name, picture, rating }) {
  return (
    <div>
      <h2>I love {name}</h2>
      <h4>{rating}/5.0</h4>
      <img src={picture} alt={name} />
    </div>
  );
}

const foodILike = [
  {
    id: 1,
    name: "파스타",
    image:
      "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNKuJ29sfo1_gy6jrbo3l0hX8SC8hOJpnqKA&s",
    rating: 5,
  },
  {
    id: 2,
    name: "비빔밥",
    image:
      "https://i.namu.wiki/i/dgjXU86ae29hDSCza-L0GZlFt3T9lRx1Ug9cKtqWSzMzs7Cd0CN2SzyLFEJcHVFviKcxAlIwxcllT9s2sck0RA.jpg",
    rating: 4.9,
  },
  {
    id: 3,
    name: "라면",
    image:
      "https://i.namu.wiki/i/2mrBrfSDXbBJHLjgyycsAhB0qLvjSZbvswmGtVTAupaEfuQ8Xuzp8wJiXyeDTsqz7blqGRYSjW5mbo1Wc4GP_w.webp",
    rating: 4.8,
  },
  {
    id: 4,
    name: "초밥",
    image:
      "https://i.namu.wiki/i/vwbKQLdn5CzWLTdLHKb2rYjLZS6icyFb6b6PdEz_3Y_0gJQqRMuhHGgogptO19gl3NZMnRsTvjYlA-0-JRSrbw.webp",
    rating: 4.9,
  },
  {
    id: 5,
    name: "카레라이스",
    image:
      "https://i.namu.wiki/i/QUSohbmt0G1CuYZKW-skuN5K3HAjf88GgTttXS0EphnSMWN8UkV-nYCb3hCCNNbs2m6pjyNF2MLbdQO8cBy1gA.webp",
    rating: 4.9,
  },
]; // foodLike 변수에 베열을 저장함

function App() {
  return (
    <div>
      {foodILike.map((dish) => (
        <Food
          key={dish.id}
          name={dish.name}
          picture={dish.image}
          rating={dish.rating}
        />
      ))}
    </div>
  );
}

Food.propTypes = {
  name: PropTypes.string.isRequired,
  picture: PropTypes.string.isRequired,
  rating: PropTypes.number,
};

export default App;

rating: PropTypes.number라고 작성하면, 이제 rating props는 필수가 아니여도 되는 항목이 됩니다. 하지만, 값이 전달되는 경우 자료형이 number이긴 해야 합니다.