Component
컴포넌트는 UI를 독립적이고 재사용 가능한 단위로 나눈 것이다.
특징
- 독립성: 컴포넌트는 자신만의 상태와 생명주기를 가짐
- 재사용성: 다양한 곳에서 재사용 가능 (
<Button />
,<Card />
등) - 계층적 구조: 부모-자식 관계로 트리를 구성하여 UI를 표현
- 단방향 데이터 흐름:
props
를 통해 부모 → 자식 방향으로만 데이터 전달
클래스 컴포넌트
React.Component
클래스를 상속받아 구현- 생명주기 메서드를 기본적으로 지원
- class의 state로 state 관리
- 생명 주기 메서드 정의
- 함수 컴포넌트를 권장하기에, 현재는 거의 레거시화
web component 패턴 등장보다 React가 빠르다고 한다.
함수 컴포넌트
-
react v16.18 이후로 권장되는 컴포넌트 형식
-
예전에는 함수형 컴포넌트라는 표현이 흔히 사용되었지만, 현재는 함수 컴포넌트(Function Component)가 더 정확한 표현이다.
- React의 Function Component는 단순히 "함수로 정의된 컴포넌트"일 뿐, 함수형 프로그래밍의 모든 원칙을 따르지 않기 때문
- 의미가 혼동될 여지가 있어, React 공식 문서나 커뮤니티에서는 함수 컴포넌트(Function Component)표현 사용
-
클래스 컴포넌트가 클래스로 작성 된 컴포넌트라면, 함수 컴포넌트는 함수로 작성된 컴포넌트다.
-
컴포넌트의 마운팅, 리렌더링은 해당 함수의 실행이다.
상태 관리
- 함수 컴포넌트는 함수인데 어떻게 상태를 가질 수 있을까?
- 함수 컴포넌트는
useState
라는 hook api로 상태를 관리한다. - 리액트 앱은 각 컴포넌트에 대해 Fiber 노드를 만들고, 거기에 hook list를 저장한다.
- 컴포넌트 함수 실행 될 때 훅 호출을 순서대로
hook list
에 담는다. - 함수 실행마다 훅의 호출순서가 같아야 한다 - 훅의 조건부 호출은 제한된다.
- 해당 리스트는 컴포넌트가 마운트될 때 생성, 렌더마다 재사용 또는 업데이트,컴포넌트가 언마운트될 때까지 유지
- 컴포넌트 함수 실행 될 때 훅 호출을 순서대로
- useState hook을 담을 때, 값도 같이 담아 상태를 유지한다.
생애 주기
- 리액트 컴포넌트에는 생성(mount) > 업데이트(update) > 제거(unmount)의 생명주기를 갖는다.
- 클래스 컴포넌트에서는 생애주기 메서드로 로직을 처리했다면, 함수 컴포넌트에서는
useEffect
로 처리한다.
렌더링
- 렌더링은 React가 컴포넌트를 호출하는 것이다.
- 호출한 결과는 virtual DOM(value UI)에 저장
- UI가 화면에 나오기전에, React는 컴포넌트를 렌더링한다.
-
렌더링이 트리거 된다.
- 첫 렌더링 - root.render
- (컴포넌트, 부모 컴포넌트)의 스테이트 변경 -> 자동적으로 렌더링을 트리거 하도록 큐에 삽입
-
컴포넌트를 렌더링한다.
-
DOM에 반영한다(commit).
- 초기에는
appendChild
로 추가하고, 리렌더링에서는 변경된 값만 DOM에 반영한다. - DOM diffing + patching - HTML 엘리먼트가 변경되면 해당 엘리먼트와 자식들은 전부 다시 추가한다.
- 초기에는
상태 업데이트 배치
- 상태 업데이트는 현재 렌더에서의 값을 변경하는게 아닌, 새 렌더링을 트리거
- React는 상태 업데이트를 즉시 처리하지 않고 업데이트 큐에 쌓는다.
- 코드 실행이 완료된 후, 리렌더링 시작 시, 업데이트 큐를 처리하여 최종 상태를 반영하여 한 번만 Vdom을 업데이트
- 기존에는 이벤트 핸들러 내부만 배치처리가 되었지만, 18버전 이후로는 대부분 배치처리가 된다.