콘텐츠로 이동

리액트 컴포넌트의 핵심: 구성과 데이터 관리

리액트 애플리케이션을 구성하는 가장 작은 단위인 컴포넌트는 크게 클래스형 컴포넌트함수형 컴포넌트로 나뉩니다. 이 글에서는 두 컴포넌트의 특징과 함께, 데이터를 다루는 핵심 개념인 propsstate에 대해 알아보겠습니다.


1. 클래스형 컴포넌트 vs 함수형 컴포넌트

클래스형 컴포넌트

클래스형 컴포넌트는 다음과 같은 특징을 가집니다. - state 기능 및 라이프사이클(Lifecycle) 기능을 사용할 수 있습니다. - 임의의 메서드를 정의하여 로직을 분리할 수 있습니다. - 필수 사항: render() 함수가 반드시 존재해야 하며, 그 안에서 보여주어야 할 JSX를 반환해야 합니다.

함수형 컴포넌트

최근 리액트 개발의 주류가 된 함수형 컴포넌트의 특징입니다. - 장점: - 클래스형 컴포넌트보다 선언하기가 훨씬 편합니다. - 메모리 자원을 덜 사용하며, 빌드 후 배포할 때 파일 크기가 더 작습니다. (다만, 성능과 크기 면에서 클래스형과 극적인 차이는 없습니다.) - 단점: - 초기에는 state와 라이프사이클 API 사용이 불가능했습니다. - 해결: 리액트 v16.8 이후 Hooks(useState, useEffect 등) 기능이 도입되면서 클래스형 컴포넌트의 기능을 대부분 대체할 수 있게 되었습니다.


2. 컴포넌트의 속성: props

props는 'properties'의 줄임말로, 컴포넌트가 부모 컴포넌트로부터 전달받는 속성입니다.

  • 설정: 부모 컴포넌트에서 자식 컴포넌트를 불러와 사용할 때 설정합니다.
  • 사용:
    • 함수형 컴포넌트: 파라미터로 받아와 사용.
    • 클래스형 컴포넌트: this.props를 통해 접근.
  • 기능:
    • defaultProps: props의 기본값을 설정할 수 있습니다.
    • children: 태그 사이의 내용을 보여줄 때 사용합니다.
  • 비구조화 할당: const { name, children } = props;와 같이 내부 값을 직관적으로 추출하여 사용할 수 있습니다.

propTypes를 통한 검증

컴포넌트의 props 타입을 지정하여 예기치 못한 에러를 방지할 수 있습니다.

import PropTypes from 'prop-types';

MyComponent.propTypes = {
  name: PropTypes.string,
  age: PropTypes.number.isRequired // 필수 설정
};

다양한 PropTypes 종류: - array, bool, func, number, object, string, symbol - node: 렌더링할 수 있는 모든 것(숫자, 문자열, JSX, children) - instanceOf(클래스): 특정 클래스의 인스턴스 - oneOf(['dog', 'cat']): 배열 요소 중 하나 - oneOfType([PropTypes.string, PropTypes.number]): 주어진 종류 중 하나 - shape({name: PropTypes.string, num: PropTypes.number}): 특정 스키마를 가진 객체


3. 컴포넌트 내부의 상태: state

state는 컴포넌트 내부에서 바뀔 수 있는 값을 의미합니다. 부모가 결정하는 props와 달리, 컴포넌트 스스로가 관리합니다.

useState (함수형 컴포넌트)

클래스형 컴포넌트의 state가 반드시 객체여야 했던 것과 달리, useState는 어떤 형태의 값(숫자, 문자열, 객체 등)이든 가질 수 있습니다.

  • 사용법: const [value, setValue] = useState(초기값);
  • 반환값: 첫 번째 원소는 현재 상태, 두 번째 원소는 상태를 바꾸어 주는 함수(setter)입니다.
  • 주의사항: 상태를 업데이트할 때는 반드시 세터 함수를 사용해야 합니다. 배열이나 객체를 업데이트할 때는 원본을 직접 수정하지 않고, 사본을 만들어 업데이트한 후 세터 함수로 전달해야 합니다.

4. 정리: props vs state

  • props: 부모 컴포넌트가 설정하며, 자식 컴포넌트 입장에서는 읽기 전용입니다.
  • state: 컴포넌트가 자체적으로 지닌 값으로, 내부에서 업데이트할 수 있습니다.

비록 용도는 다르지만 둘 다 렌더링 결과에 영향을 주는 데이터를 담고 있습니다. 효율적인 아키텍처를 위해 부모의 state를 자식의 props로 전달하거나, 자식의 이벤트가 발생할 때 부모의 메서드를 호출하여 상위 state를 변경하는 방식으로 유동적인 데이터 흐름을 구현할 수 있습니다.