profile image

L o a d i n g . . .

리액트 컴포넌트

리액트 컴포넌트에서의 입력은 `props`, 출력은 리액트 엘리먼트.

역할: `어떠한 속성들을 입력으로 받아서 그에 맞는 리액트 엘리먼트를 생성하여 리턴해주는 것

컴포넌트의 이름은 항상 대문자로 시작해야 한다.

 

Props

리액트 컴포넌트의 속성

컴포넌트에 전달할 다양한 정보를 담고 있는 자바스크립트 객체

 


Props를 사용하지 않는다면?

데이터 흐름의 혼란

props는 부모 컴포넌트 -> 자식 컴포넌트로 데이터를 전달하는 기본적인 방식이므로, props를 사용하지 않으면 데이터가 어디서 오는지, 어디로 가는지 명확하지 않기 때문에 코드의 가독성이 떨어지고 유지보수가 어려워짐

 

Props를 사용하지 않은 경우

import React, { useState } from 'react';

const ParentComponent = () => {
  const [data, setData] = useState('Hello');

  return (
    <div>
      <ChildComponent />
    </div>
  );
};

const ChildComponent = () => {
  const data = 'Hello'; // 데이터가 어디서 오는지 명확하지 않음
  return <div>{data}</div>;
};

export default ParentComponent;

 

Props를 사용한 경우

import React, { useState } from 'react';

const ParentComponent = () => {
  const [data, setData] = useState('Hello'); // 상태 정의

  return (
    <div>
    /* ChildComponent에 props로 data를 전달 */
      <ChildComponent data={data} />
    </div>
  );
};

// ChildComponent는 props로 data를 받음
const ChildComponent = ({ data }) => { 
// 받은 props(data)를 렌더링
  return <div>{data}</div>;
};

export default ParentComponent;

 

컴포넌트의 재사용성 감소

특정 데이터나 기능에 종속된 컴포넌트를 만들게 되고, 다른 상황에서 재사용 하기 어려워짐

 

Props를 사용하지 않은 경우

import React from 'react';

// 이 Button 컴포넌트는 고정된 텍스트 "Click Me"를 버튼 안에 표시
const Button = () => {
  return <button>Click Me</button>;
};

export default Button;

// 이 상태에서는 다른 텍스트를 가진 버튼을 만들려면 컴포넌트를 수정하거나 새로운 컴포넌트를 만들어야 함

 

Props를 사용한 경우

import React from 'react';

// Button 컴포넌트는 label 이라는 props를 받음
const Button = ({ label }) => {

// 받은 label props를 버튼 안에 표시
  return <button>{label}</button>;
};

export default Button;

// 이 Button 컴포넌트는 여러 곳에서 다양한 label로 재사용 가능
import React from 'react';
import Button from './Button';

const App = () => {
  return (
    <div>
      {/* 서로 다른 label을 가진 Button 컴포넌트를 여러 번 사용 가능 */}
      <Button label="Submit" />
      <Button label="Cancel" />
      <Button label="Click Me" />
    </div>
  );
};

export default App;

 

상태 관리의 복잡성

상태(state)는 컴포넌트 내부에서 관리되고, props는 외부에서 전달되는 데이터이다.

props를 사용하지 않으면 상태 관리가 복잡해지고, 상태 간의 의존성이 높아져 코드가 복잡해질 수 있다.

 

Props를 사용하지 않은 경우

import React, { useState } from 'react';

const ParentComponent = () => {
  const [count, setCount] = useState(0); // 상태를 정의

  return (
    <div>
      {/* ChildComponent에 상태(count)를 props로 전달하지 않음 */}
      <ChildComponent /> 
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
};

const ChildComponent = () => {
  const count = 0; // 상수로 설정된 값, 부모의 상태와 무관
  return <div>Count: {count}</div>;
};

export default ParentComponent;

/*
	`ParentComponent`는 `count` 라는 상태를 갖고 있지만, `ChildComponent`를 렌더링 할 때
   	이 상태를 `ChildComponent`에 props로 전달하지 않았다.
    `ChildComponent`는 자신의 내부에서 상수로 `count` 값을 설정하고 있다.
    그래서 `ParentComponent`의 상태 변화가 `ChildComponent`에 반영되지 않는다.
 */

 

Props를 사용한 경우

import React, { useState } from 'react';

const ParentComponent = () => {
  const [count, setCount] = useState(0); // 상태를 정의

  return (
    <div>
      {/* ChildComponent에 상태(count)를 props로 전달 */}
      <ChildComponent count={count} />
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
};

// ChildComponent는 props로 count를 받음
const ChildComponent = ({ count }) => {
  // 받은 props(count)를 렌더링
  return <div>Count: {count}</div>;
};

export default ParentComponent;

/*
	`ParentComponent`가 `ChildComponent`를 받아서 렌더링 할 때 `count` 상태를 props로 전달하고
    `ChildComponent`는 이 props를 받아서 화면에 표시한다.
    `ParentComponent`의 상태 변화가 `ChildComponent`에도 반영되어 
    상태 관리가 명확해지고 일관성이 생긴다.
*/

 

테스트의 어려움

props를 사용하지 않으면 외부 데이터에 의존하는 컴포넌트를 테스트 하는 것이 어려워질수 있다. 따라서 코드의 안정성을 떨어뜨릴 수 있다.

 

props를 사용하지 않은 경우

import React from 'react';

const Greeting = () => {
  // 'World'라는 고정된 값을 사용
  const name = 'World'; 
  
  // 고정된 'World' 값을 사용하여 인사말을 표시
  return <div>Hello, {name}!</div>; 
};

export default Greeting;

// 컴포넌트가 고정된 값을 사용중이므로 다른 이름으로 인사말을 표시할 때마다 코드를 수정해야 함

 

 

props를 사용한 경우

import React from 'react';

// Greeting 컴포넌트는 props로 name을 받음
const Greeting = ({ name }) => {
  // 받은 name props를 사용하여 인사말을 표시
  return <div>Hello, {name}!</div>;
};

export default Greeting;
import React from 'react';
import Greeting from './Greeting';

const App = () => {
  return (
    <div>
      <Greeting name="World" />
      <Greeting name="Alice" />
      <Greeting name="Bob" />
    </div>
  );
};

export default App;

코드의 일관성 부족

props를 사용하면 컴포넌트 간의 데이터 전달 방식이 일관성을 가지게 되지만, props를 사용하지 않으면 각 컴포넌트가 서로 다른 방식으로 데이터를 주고 받게 되어 코드 전체의 일관성이 떨어진다.

 

props를 사용하지 않은 경우

import React from 'react';

// Header 컴포넌트는 고정된 제목을 사용
const Header = () => {
  const title = 'My App'; // 'My App'이라는 고정된 제목을 사용
  return <h1>{title}</h1>; // 고정된 제목을 h1 요소로 렌더링
};

// Footer 컴포넌트는 고정된 푸터 텍스트를 사용
const Footer = () => {
  const footerText = '© 2024 Namani'; // '© 2024 Namani'라는 고정된 텍스트를 사용
  return <footer>{footerText}</footer>; // 고정된 텍스트를 footer 요소로 렌더링
};

// Header와 Footer 컴포넌트를 내보냄
export { Header, Footer };

 

props를 사용한 경우

import React from 'react';

// Header 컴포넌트는 props로 title을 받음
const Header = ({ title }) => {
  return <h1>{title}</h1>; // 받은 title props를 h1 요소로 렌더링
};

// Footer 컴포넌트는 props로 footerText를 받음
const Footer = ({ footerText }) => {
  return <footer>{footerText}</footer>; // 받은 footerText props를 footer 요소로 렌더링
};

// Header와 Footer 컴포넌트를 내보냄
export { Header, Footer };
import React from 'react';
import { Header, Footer } from './HeaderFooterComponents';

const App = () => {
  return (
    <div>
      {/* 서로 다른 title과 footerText를 props로 전달 */}
      <Header title="My App" />
      <Footer footerText="© 2024 My Company" />
      <Header title="Another App" />
      <Footer footerText="© 2024 Another Company" />
    </div>
  );
};

export default App;

컴포넌트 추출

큰 컴포넌트에서 일부를 추출해서 새로운 컴포넌트를 만드는 것

 

<img> 태그를 추출해서 `Avatar` 라는 별도의 컴포넌트를 생성할 것임

 

Avatar 컴포넌트 추출

 

 

Comment에 Avartar 컴포넌트 적용

 

UserInfo 컴포넌트 추출, Avatar 컴포넌트도 함께 추출 됨
추출한 UserInfo를 반영함
추출된 컴포넌트 구조

 

컴포넌트는 기능 단위로 구분하는 것이 좋고, 나중에 곧바로 재사용이 가능한 형태로 추출하는 것이 좋다.

 

복사했습니다!