컴포넌트의 생명주기

김강민·2025년 7월 27일

개발

목록 보기
19/32
post-thumbnail

Life Cycle이란?

  • 컴포넌트의 수명은 페이지에 렌더링 되기 전인 준비과정에서 시작하여, 브라우저에 렌더링 및 업데이트 후 페이지에서 사라질 때 끝난다.
  • 컴포넌트는 생성(mountion) → 업데이트(updating) → 제거(unmountion)의 생명주기를 갖는다.
  • 클래스 컴포넌트는 라이플 사이클 메서드를 사용하고, 함수형 컴포넌트는 Hook을 사용한다.
    (라이프사이클 메소드는 클래스 컴포넌트에서만 사용. 함수형 컴포넌트 → Hooks 사용)
  • 컴포넌트가 처음 렌더링 될 때, 어떤 작업을 처리해야하거나 컴포넌트를 업데이트하기 전후로 어떤 작업을 처리해야 할 수 도 있고, 불필요한 업데이트를 방지해야 할 수도 있다. 이러한 경우에 컴포넌트 라이프사이클 메소드를 사용한다.

Life Cycle의 구성

  • 라이프 사이클은 Mount, Update, Unmount로 총 3가지 카테고리로 구성
  • will 접두사 메소드 → 어떤 작업을 작동하기 전에 실행
  • Did 접두사 메소드 → 어떤 작업을 작동한 후에 실행

클래스 컴포넌트의 Life Cycle

Mount

  • constructor : 컴포넌트의 생성자 메소드. 컴포넌트가 만들어지면 가장 먼저 실행됨.
  • getDerivedStateFromProps : props로 받아온 것을 state에 넣어주고 싶을 때 사용.
  • render : 컴포넌트를 렌더링하는 메소드
  • componentDidMount : 컴포넌트의 첫번째 렌더링이 끝나면 호출되는 메소드. 이 메소드가 호출되는 시점에서 우리가 만든 컴포넌트가 화면에 나타난 상태. (여기서 주로 D3, masonry 처럼 DOM을 사용해야하는 외부 라이브러리 연동을 하거나, 해당 컴포넌트에서 필요로하는 데이터를 요청하기 위해 axios, fetch 등을 이용하여 ajax 요청을 하거나, DOM의 속성을 읽거나 직접 변경하는 작업을 진행)
  • constructor : 컴포넌트의 생성자 메소드. 컴포넌트가 만들어지면 가장 먼저 실행됨.
  • getDerivedStateFromProps : props로 받아온 것을 state에 넣어주고 싶을 때 사용.
  • render : 컴포넌트를 렌더링하는 메소드
  • componentDidMount : 컴포넌트의 첫번째 렌더링이 끝나면 호출되는 메소드. 이 메소드가 호출되는 시점에서 우리가 만든 컴포넌트가 화면에 나타난 상태. (여기서 주로 D3, masonry 처럼 DOM을 사용해야하는 외부 라이브러리 연동을 하거나, 해당 컴포넌트에서 필요로하는 데이터를 요청하기 위해 axios, fetch 등을 이용하여 ajax 요청을 하거나, DOM의 속성을 읽거나 직접 변경하는 작업을 진행)

Update

  • getDerivedStateFromProps : 컴포넌트의 props나 state가 바뀌었을때도 이 메소드가 호출됨.
  • ShouldComponenetUpdate : 컴포넌트가 리렌더링 할지 말지를 결정
  • render : mount와 상동
  • getSnapshotBeforeUpdate : 컴포넌트에 변화가 일어나기 직전의 DOM 상태를 가져와서 특정 값을 반환하면, 그 다음 발생하게 되는 componentDidUpdate 함수에서 받아와서 사용할 수 있음.
  • componentDidUpdate : 리렌더링을 마치고, 화면에 우리가 원하는 변화가 모드 반영되고 난 뒤 호출되는 메소드. 3번째 파라미터로 getSnapshotBeforeUpdate에서 반환 값 조회 가능.

Unmount

  • componentWillUnmount : 컴포넌트가 화면에서 사라지기 직전에 호출

함수 컴포넌트의 Life Cycle


리액트에서 Hook은 함수형 컴포넌트에서 React state와 생명주기 기능을 연동 할 수 있게 해주는 함수를 의미한다.

Hook은 class 안에서는 동작하지 않고, class없이 React를 사용할 수 있게 한다.

리액트 훅을 도입한 목적

  • 기존의 라이프사이클 메서드 기반이 아닌 로직 기반으로 나눌 수 있어서 컴포넌트를 함수 단위로 잘게 쪼갤 수 있다는 이점이 있다.
  • 라이프사이클 메서드에는 관련 없는 로직이 자주 섞여 들어가는데, 이로 인해 버그가 쉽게 발생하고, 무결성을 쉽게 해친다.

Hook 사용 규칙 두가지

  • 최상위에서만 Hook을 호출해야 한다.
    • 반복문, 조건문, 중첩된 함수 내에서 Hook을 실행하면 안된다.
    • 이 규칙을 따르면 컴포넌트가 렌더링될 때마다 항상 동일한 순서로 Hook이 호출되는 것이 보장된다.
  • 리액트 함수 컴포넌트에서만 Hook을 호출해야 한다.
    • 일반 JS함수에서는 Hook을 호출해서는 안된다.

Hook의 종류와 정리

🍀 useState

상태를 관리한다. [state이름, setter이름] 순으로 반환 받아서 사용한다.

const [state, setState] = useState(initialState);

🍀 useEffect

화면에 렌더링이 완료된 후에 수행되며 componentDidMount와 componentDidUpdatecomponentWillUnmount 가 합쳐진 것

  • ❗️만약 화면을 다 그리기 이전에 동기화 되어야 하는 경우에는,useLayoutEffect 를 활용하여 컴포넌트 렌더링 - useLayoutEffect 실행 - 화면 업데이트 순으로 effect를 실행시킬 수 있다.
useEffect(() => {}); // 렌더링 결과가 실제 돔에 반영된 후마다 호출
useEffect(() => {}, []); // 컴포넌트가 처음 나타날때 한 번 호출
useEffect(() => {}, [의존성1, 의존성2, ..]); // 조건부 effect 발생, 의존성 중 하나가 변경된다면 effect는 항상 재생성됩니다.

useEffect안에서의 return은 정리 함수(clean-up)를 사용하기위해 쓰여집니다.

  1. 메모리 누수 방지를 위해 UI에서 컴포넌트를 제거하기 전에 수행
  2. 컴포넌트가 여러 번 렌더링 된다면 다음 effect가 수행되기 전에 이전 effect가 정리됩니다.

🍀 useContext

Context API를 통해 만들어진 Context에서 제공하는 Value를 가져올 수 있다.

const value = useContext(MyContext);

컴포넌트에서 가장 가까운 <MyContext.Provider>가 갱신되면 이 Hook은 그 MyContext provider에게 전달된 가장 최신의 context value를 사용하여 렌더러를 트리거한다.

🍀 useReducer

useState의 대체 함수로 컴포넌트 상태 업데이트 로직을 컴포넌트에서 분리시킬 수 있다.

컴포넌트 바깥에 로직을 작성할 수 도 있고, 심지어 다른 파일에 작성한 후 불러와서 사용할 수도 있다.

reducer란 현재 상태와 액션 객체를 파라미터로 받아와서 새로운 상태를 반환해주는 함수를 의미한다.

const [state, dispatch] = useReducer(reducer, initialArg, init);

🍀 useRef

특정 DOM 선택할때 주로 쓰이며 .current 프로퍼티로 전달된 인자로 초기화된 변경 가능한 ref 객체를 반환한다.

반환된 객체는 컴포넌트의 전 생애주기를 통해 유지된다.

const refContainer = useRef(null);

🍀 useMemo

메모이제이션된 값을 반환한다. 이미 연산 된 값을 리렌더링 시 다시 계산하지 않도록 한다.

의존성이 변경되었을 때에만 메모이제이션된 값만 다시 계산한다. 의존성 배열이 없는 경우 매 렌더링 때마다 새 값을 계산한다.

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

useMemo는 오로지 성능 향상을 위한 용도로만 사용하라고 공식문서에 언급되어있으며 리액트는 메모리 확보를 위해 이전 메모이제이션 데이터를 삭제할 수 있다. 따라서 useMemo가 없어도 올바르게 작동되도록 코드를 작성한 뒤 성능개선을 목표로 useMemo를 추가하는 것이 적절한 접근 방식이다.

🍀 useCallback

메모이제이션 된 콜백을 반환한다. useMemo와 유사하게 이용되며 '함수'에 적용해준다.

의존성이 변경되었을때만 변경된다. 때문에 특정 함수를 새로 만들지 않고 재사용가능하게 한다.

const memoizedCallback = useCallback(
  () => {
    doSomething(a, b);
  },
  [a, b],
);

생명주기 순서 요약

  1. 컴포넌트가 호출되어 로드된다.

  2. 컴포넌트 내부 함수 수행

  • 데이터의 초기화를 수행합니다.
  1. return() 함수 실행
  • 화면의 렌더링을 수행합니다
  1. useEffect() 실행

- 조건부 수행 -

5-1. useEffect() 실행

  • 컴포넌트의 '변화'가 발생하는 경우 수행합니다.

5-2. useEffect() 실행

  • 컴포넌트의 '소멸'이 발생하는 경우 수행합니다.

생명주기 상세 설명

1. [Mounting] 컴포넌트 내부

컴포넌트 내부

  • 컴포넌트가 호출이 되었을 때 가장 먼저 호출이 되는 것은 컴포넌트 내부이다.
  • 라이프 사이클 메서드라고 할 수는 없지만 클래스 컴포넌트의 contructor()을 이해하기 위한 설명이다.
  • 동일하게 State를 정의하거나 사용될 함수들에 대해 미리 정의를 하는 공간이다.

2. [Mounting] return()

return()

  • 미리 구현된 HTML을 화면상에 그려지는 과정(렌더링)을 수행하는 함수를 의미한다.
  • 해당 메서드 안에서는 부모 컴포넌트로 전달받은 'props’값의 접근이 가능하다.
  • 컴포넌트 내부에서 정의한 'state'값의 접근이 가능하다.

3. [Mounting / Updating / Unmounting] useEffect()

useEffect()

  • 해당 메서드를 통하여서 Mounting/Updating/Unmounting 처리가 가능합니다.
  • useEffect()는 한개 또는 여러개 선언이 가능합니다.

3.1 [Mouting] useEffect()

useEffect(() => {}, [])

  • 컴포넌트 내에서 렌더링이 수행된 이후에 단 한번만 실행이 되는 메서드이다.
  • deps 파라미터를 빈 배열로 수행하면 렌더링이 수행된 이후 최초 한번 수행이 된다.

3.2 [Updating] useEffect()

useEffect(() => {}, [값])

  • 컴포넌트 내에서 '변화'가 발생된 이후 호출되는 메서드를 의미합니다.
  • 변화라 함은 부모 컴포넌트로부터 전달받은 props 값의 변화가 발생하거나 부모 컴포넌트가 리 렌더링이 발생을 하는 경우 수행됩니다.
  • 해당 컴포넌트 내에서state의 값이 변하는 경우 수행됩니다.

3.3 [Unmounting] useEffect()

useEffect(() => { return {//}}, [값])

  • 컴포넌트가 DOM에서 제거되기 직전에 호출되는 메서드입니다.
  • 컴포넌트의 DOM이 제거될 때 수행이 됩니다. 예를 들어 A라는 컴포넌트 내에서 B라는 컴포넌트를 부르고 있을 전제라고 할 때, B 컴포넌트를 조건부에 따라서 소멸을 시킬 경우 해당 라이프사이클 메서드가 수행이 됩니다.

Life Cycle에 대한 클래스∙함수 컴포넌트 비교

분류클래스형 컴포넌트함수형 컴포넌트
Mountingconstructor()함수형 컴포넌트 내부
Mountingrender()return()
MountingcomponentDidMount()useEffect()
UpdatingcomponentDidUpdate()useEffect()
UnMountingcomponentWillUnmount()useEffect()
profile
인생은 프레임워크처럼, 공부는 라이브러리처럼

0개의 댓글