프로그래밍/React

클래스 컴포넌트와 함수 컴포넌트에 대한 간단한 비교 정리.

콘파냐 2020. 5. 6. 14:57

예전처럼 공들여 블로그 글을 쓰기가 귀찮다. 그래서 대략적으로만 정리하려 한다.

리액트의 고전적인 클래스 컴포넌트와,  훅의 등장으로 새롭게 관심 받는 함수형 컴포넌트를 비교하기 위해 글을 쓴다. 보통 함수형 컴포넌트로 페이지를 만들지만 많은 문서와 라이브러리가 클래스형 컴포넌트를 지원한다. 따라서 이 둘을 모두 알아야할 필요가 있다.

기본적으로 두 차이를 이해하려면 적어도 전통적인 함수와 클래스의 차이점을 알아야할 것이다.


우선 리액트에서 페이지를 렌더링하는 방법은 클래스의 경우 render 메소드를 사용한다. 반면에 함수형 컴포넌트는 함수 자체가 render를 담당한다고 보면 된다.

둘 다 리턴 값으로 페이지의 모습을 표현하게 된다.

함수형 컴포넌트

function FuncComp() {
    return (

        <div> Hello FuncComp </div>

    );

}

클래스형 컴포넌트

class ClassComp extends React.Component {

    render() {

        return (

            <div> Hello ClassComp

        );

    }

}


두 형식의 차이점

return 형식은 동일하지만 다음과 같은 차이점이 존재한다.

1. props은 함수형은 인자로 전달되고, 클래스형은 this.props로 접근할 수 있다.

2. state의 값은 함수형은 const [state, setState] useSttate()를 사용하여 정의하고, 클래스형은 state={key:value}로 정의하고 this.state로 접근 한다. 그리고 state값을 갱신하려면 함수는 useState가 반환하는 두번째 요소(함수)를 사용, 클래스형은 this.setState({  key : value})를 사용한다.

3. 라이프 사이클

함수형 훅의 등장으로 클래스에서만 사용하던 라이프 사이클을 함수형 컴포넌트에서도 사용할 수 있게 되었다. 바로 useEffect라는 훅을 사용하여 가능하다. 익숙해지면 간단하지만 처음 훅을 사용하여 라이프 사이클을 구현하려면 매우 어렵게 느껴진다. 처음이라면 클래스형 라이프 사이클이 명료해 보일 것이다.

Props 가져옴 -> State 초기화 -> 컴포넌트 마운트 전 -> 렌더링 -> 컴포넌트 마운트 완료

이렇게가 최초 사이클이다. 이 순서는 외우기 보다는 코드의 실행 순서를 떠올리면 쉽게 이해가 된다. 

여기 렌더링 부분을 주목해 보길 바란다. 렌더링되는 부분은 클래스형에서는 render 메소드의 리턴, 함수형에서는 컴포넌트의 리턴 부분다. 

그런데 렌더링 전후로 여러가지 작업이 필요하다. 예를들어 props를 가져온다던지,  state를 초기화 한다던지, 그리고 렌더링 전에 사용자가 정의할 작업도 있겠다. 이런 작업들은 클래스형 컴포넌트의 경우 미리 정의된 메소드(위 그림)에 정의하면 된다.

반면에 함수형 컴포넌트의 경우는 훅으로 실행시킬 수 있다. 이 때 사용하는 훅이 useEffect라는 훅이다.

useEffect

이 훅이 동작하는 방법은 직관적이지는 않지만 간결하다. 그리고 사용하다보면 쉽게 이해가 되어 편리하다.

간단히 useEffect 내부에 함수를 정의하여 렌더링 작업 후에 동작할 기능을 정의하고, 이 함수가 리턴하는 함수를 정의하여 컴포넌트가 언마운트 될 때 동작할 기능을 정의한다.

useEffect로 표현할 수 있는 라이프 사이클은 다음과 같다

- componentDidMount

- componentDidUpdate

- componentwilUnmout

왜 componentWillMount 등은 없는가? 묻는다면 componentWillMount가 왜 사용되는지 알아야 할 것이다.

https://reactjs.org/docs/react-component.html#unsafe_componentwillmount

공식 문서에서도 이 메소드를 사용하지 말라고 한다.(componentWillUpdate나 기타 다른 메소드들도 Unsafe 되어 있다.) 그래서 리엑트 훅에서도 위 세가지 라이프 사이클만을 사용하도록 하는 것 같다. 만약 렌더링 전에 수행하려는 내용은 constructor()에서 하라고 한다.

물론 특정 라이브러리에서 componentWillMount가 필요할 수도 있다.(기억은 잘 안나는데 next.js에서 본 것 같다.)

위 세가지 메소드들을 useEffect에서 흉내내는 방법은 간단하다. 

간단히, 

componentDidMount 와 componentDidUpdate- useEffect 첫번째 인자로 전달된 함수 

componentWillUnmount - useEffect에 첫번째 인자로 전달된 함수가 반환하는 함수

componentDidMount만 적용 - useEffect 첫번째 인자로 함수 전달, 두번째 인자로 [] 전달

렌더링 Optimization - useEffect 두 번째 인자로 [ 비교할 변수, ..] 전달

반응형