[React] 함수형 컴포넌트 vs 클래스형 컴포넌트

배고픈메꾸리·2021년 6월 6일
0

React

목록 보기
1/6


React에서 컴포넌트를 작성하는 방법은 두 가지가 있다. 하나는 함수형 컴포넌트이고 다른 하나는 클래스형 컴포넌트 이다. 책이나 강의를 보더라도 예전에는 전부 클래스형 컴포넌트로 작성했지만 Hook의 출현과 비슷한 시기부터 함수형 컴포넌트를 많이 사용하는 것을 알 수 있다. 무슨 차이가 있는 것일까? 알아보자


1. JSX를 렌더링하는 방식


가장 명확하면서도 확실한 차이는 구문의 차이이다. 이름에서도 알 수 있듯 함수형 컴포넌트는 일반적인 자바스크립트의 함수의 형태이다 ( JSX를 리턴하는 ) 이에 비해 클래스형 컴포넌트는 render 메서드를 갖고 있는 React.Component 를 상속받아 사용하고 있다.

함수형 컴포넌트

import React from "react";

const FunctionalComponent = () = >{
  return <h1> Hi There! </h1>;
};

혹은

function FunctionalComponent(){
  return <h1> Hi There ! </h1>;
};

위의 코드에서 알 수 있듯 함수형 컴포넌트는 JSX를 반환하는 자바스크립트 함수이다.

클래스형 컴포넌트

import React , { Component } from "react";

class ClassComponent extends Component{
  render(){
    return <h1> Hi There! </h1>;
  }
}

혹은

class ClassComponent extends React.Component{
  render(){
      return <h1> Hi There! </h1>;
    }
  }

클래스형 컴포넌트의 경우React.Component 를 불러와서 상속받아서 사용해야 한다. JSX는 render 메서드 내부에서 반환된다.


2. props를 전달하는 방법


아래와 같이 하위 컴포넌트에 name : "wook" 이라는 props를 전달해 보자.

<Component name ="wook" />

함수형 컴포넌트

const FunctionalComponent = (props) =>{
  return <h1> Hello, {props.name} </h1>;
};

혹은

const FunctionalComponent = ({name}) =>{
  return <h1> Hello, {name} </h1>;
};

함수형 컴포넌트의 경우 함수의 인자로 props를 전달받는 방식을 사용한다.

클래스형 컴포넌트

class ClassComponent extends React.Component{
  render() {
    const { name } = this.props;
    return <h1>Hello, { name } </h1>;
  }
}

클래스형 컴포넌트의 경우 this 키워드를 사용하여 props를 조회할 수 있다. ( this.props.name 으로도 접근이 가능하다. )


3. 상태 관리


아마도 가장 중요한 이유가 아닐까 한다. 비교적 최근 까지 (라고 해도 약 2019년) 클래스형 컴포넌트에서만 상태(state)를 관리할 수 있었다. 그러나 React 16.8부터 React Hook 이 도입되었고 개발자들은 stateful 한 함수형 컴포넌트를 작성할 수 있게 되었다.

함수형 컴포넌트

const FunctionalComponent = () => {
  const [count , setCount] = React.useState(0);
  
  return (
    <div>
   	<p> count : {count} </p>
	<button onClick = {() => setCount(count+1)}>Click</button>
    </div>
  );
};

함수형 컴포넌트에서 상태 변수를 사용하기 위해서는 useState라는 Hook을 사용해야 한다.
위의 예제는 버튼을 클릭할 때 마다 count라는 상태에 1을 더해주는 함수형 컴포넌트이다.
(위의 예제에서 인자로 0을 넣어주었기 때문에 초기값이 0이 된다.)

클래스형 컴포넌트

class ClassComponent extends React.Component{
  constructor(props){
    super(props);
    this.state = {
      count : 0
    };
  }
  
  render(){
    return(
       <div>
   	 <p> count : {count} </p>
	 <button onClick={() => this.setState({ count: this.state.count + 1 })}>
         Click
       </button>
       </div>
    );
  }//end of render
}//end of class

클래스형 컴포넌트의 경우 함수형 컴포넌트와 기본적으로 아이디어는 같지만 , 조금의 차이가 있다. 먼저 constructor 에 대해 알아보자.

“The constructor for a React component is called before it is mounted. When implementing the constructor for a React.Component subclass, you should call super(props) before any other statement. Otherwise, this.props will be undefined in the constructor, which can lead to bugs.”

기본적으로 생성자에서 super(props) 를 호출하지 않으면 모든 상태 변수들은 전부 undefined가 된다. 그렇기 때문에 개발자는 생성자를 먼저 선언하고 생성자 내부에 key 와 value로 이루어진 상태 객체를 생성해야 한다.
그래야만 JSX 구문 내부에서 this.state.count 와 같은 형식으로 상태 변수에 접근이 가능하다.


4. 생명 주기 함수


생명주기는 컴포넌트의 렌더링 시기와 관련하여 중요한 역할을 한다.
클래스형 컴포넌트에서 함수형 컴포넌트로 이사하는 과정에서 componentDidMount() 같은 메서드가 어떻게 대체되는지 알아보자.

4-1) componentDidMount

componentDidMount() 메서드는 첫 번째 렌더링이 완료된 직후에 호출된다.

<< 클래스형 컴포넌트 >>
  
class ClassComponent extends React.Component {
 componentDidMount() {
   console.log("Hello");
 }

 render() {
   return <h1>Hello, World</h1>;
 }
}

위의 클래스형 컴포넌트를 Hook을 사용한 함수형 컴포넌트로 바꿔보자

<< 함수형 컴포넌트 >>
  
const FunctionalComponent = () => {
  React.useEffect(()=>{
    console.log("Hello");
  }, []);
  return <h1>Hello , World</h1>;
};

함수형 컴포넌트에서 componentDidMount 를 대체하기 위해서는 useEffect 라는 hook을 사용하면 된다. useEffect두 번째 인자에 있는 배열은 해당 배열에 있는 state의 값이 변경될때 useEffect를 실행해라 라는 용도로 사용되는데, 이렇게 빈 배열을 두면 컴포넌트가 마운트 될 때 한번만 호출된다.

4-2) componentWillUnmount

만약 어떠한 사유로 인해 컴포넌트가 unmounting 된다면 해당 컴포넌트에 달려있는 이벤트도 전부 지워야 한다. 그렇지 않으면 큰 프로젝트의 경우 메모리 누수를 야기할 수 있다.

<< 클래스형 컴포넌트 >>
  
class ClassComponent extends React.Component {
 componentWillUnmount() {
   console.log("Bye");
 }

 render() {
   return <h1>Bye, World</h1>;
 }
}

위의 코드를 hook을 사용한 함수형 컴포넌트로 변경해 보자.

<< 함수형 컴포넌트 >>
  
const FunctionalComponent = () => {
 React.useEffect(() => {
   return () => {
     console.log("Bye");
   };
 }, []);
 return <h1>Bye, World</h1>;
};

이렇게 useEffect를 사용하여 관리하면 한 가지 좋은점이 있는데 바로 mounting 과 unmounting 되는 경우를 한 곳에서 처리할 수 있게 된다.

(+ 이외의 다른 생명주기 함수들도 hook으로 처리가 가능하다.)

출처 에 있는 글을 직접 번역
잘못된 지식이나 오타 , 수정사항 있으면 알려주시면 감사하겠습니다.

profile
FE 개발자가 되자

0개의 댓글