[TIL] React - Hooks

jeongjwon·2023년 12월 6일
1

이론

목록 보기
17/19

Hooks

등장 배경

2018년 React 컨퍼런스에서 처음 소개되고 도입된 기술이다.

기존의 React 는 클래스 컴포넌트를 기반으로 작업했다. 하지만 클래스 컴포넌트를 사용하면 this 키워드 사용의 문제와 재사용성이 떨어져 낮은 가독성과 성능을 지닌다.


this 키워드 문제

이때 클래스 컴포넌트에서는 자기 자신을 가리키는 this 키워드를 사용했다.
this 키워드는 변경될 수 있어서 다음과 같은 문제가 발생한다.

export default ProfileFollowButton() {
	handleClick = () => {
      setTimeout(() => {
        alert(`${this.props.name}를 팔로우 했습니다.`);
      }, 3000);
    };
  
  render(){
    return <button onClick={handleClick}>팔로우</button>
  }
}

이 코드는 팔로우 버튼 컴포넌트로, 클릭시 해당 속성으로 가지고 있는 this.props.name 을 3초후 알림창이 뜨게 하는 기능을 가진다.

this.props.name 이 룩소일 때 팔로우 버튼을 클릭하면 알림창으로 '룩소를 팔로우 했습니다' 라고 3초 후 떠야한다.
그렇지만, select 박스로 이미 this.props.name 을 우테코로 변경했기 때문에 3초 사이에 컴포넌트가 리렌더링 되면서 this가 가리키는 값이 변경되어 버리고 만다. 이처럼 고정되지 않은 this의 사용법이 어렵기도 하고 버그가 잘 발생한다.


재사용성

클래스형 컴포넌트에서는 재사용성의 문제점이 있었다. 이는 함수형 컴포넌트의 HOC 패턴을 이용해서 해결 가능하다.

HOC (Higher Order Component) 패턴이란?
화면에서 재사용 가능한 로직을 분리해서 컴포넌트로 만들고, 재사용 불가능한 부분은 parameter 로 받아서 처리하는 방법이다.

다음은 클래스형 컴포넌트에서 사용될 수 있는 두가지 컴포넌트 예시이다.

사용자의 나이 정보 페이지사용자의 직업 정보 페이지

코드를 잘 살펴보면 중복되는 로직이 사용되는 것을 볼 수 있다.
함수형 컴포넌트에서는 HOC 패턴을 가지는 다음 코드로 변경할 수 있다.

function usersHoc(Componennt){
  return class usersHOC extends React.Component{
    state = {
       users: [],
    }
 
   componentDidMount() {
     fetchUsers().then((users) => {
       this.setState({ users });
      });
   }
   
   render() {
     return <Component {...this.props} {...this.state} />;
   }
}

사용할 컴포넌트를 인자(parameter)로 전달하고, 인자로 받은 컴포넌트를 render 의 props 에 넣어 전달할 수 있다.

사용자의 나이 정보 페이지사용자의 직업 정보 페이지

그렇게 되면 위에서 길었던 각 페이지 컴포넌트들의 코드는 usersHOC를 감싸서 사용할 수 있었다.
이렇게 Hook이 도입되기전에는 HOC 패턴을 활용한 코드가 추천되어졌다. 그렇지만 이는 계속해서 감싸지다보면 깊어지는 Wrapper Hell 이라는 또다른 문제를 도출했다.


사실 이런 문제가 발생하는 시기에도 함수형 컴포넌트 또한 존재하였지만, 제한적 기능을 가지고 있어서 사용을 지양했었다.
오히려 클래스 컴포넌트가 상태관리 기능, 생명 주기 기능, 렌더링 기능을 지녀 더 많이 쓰였다.

하지만 Hooks의 등장으로 클래스 컴포넌트가 지녔던 장점들을 흡수하며 함수의 장점을 이용하는 함수형 컴포넌트를 더 많이 사용하기 시작했다.







Hooks 이점

더 깔끔하고 간단한 코드 ➡️ 높은 가독성

클래스형 컴포넌트함수형 컴포넌트

생성자를 따로 만들어주어야했던 클래스형 컴포넌트는 단순히 useState hook 을 사용하면서 가독성을 높일 수 있다.

React 의 생명 주기(Life Cycle)을 살펴보면,
처음 컴포넌트가 새성되고 렌더링을 거치는 과정인 Mount가 끝나면 클래스 컴포넌트는 componentDidMount() 메서드를 실행한다.
props 나 state 가 변경되거나 forceUpdate() 메서드가 실행되면 리렌더링 과정을 거치는 Update 가 끝이 나면 componentDidUpdate() 메서드를 실행한다.
컴포넌트가 종료되는 Unmount 에서는 componentWillUnmount() 메서드를 실행한다.

방금의 과정과 같이 클래스 컴포넌트에서의 Life Cycle 함수인 componentDidMount(), componenetDidUpdate(), componentWillUnmount() 세 가지 함수는 hooks 를 사용한 함수형 컴포넌트에서는 useEffect() 훅 하나로 대체될 수 있다.

componentDidMount(){
  this.updateList(this.props.id);
}

componentDidUpdate(prevProps){
  if(prevProps.id === this.props.id) return;
  this.updateList(this.props.id);
}

예를 들면 클래스형 컴포넌트에서 Life Cycle 을 활용한 코드로 컴포넌트가 Mount 될 때 (componentDidMount), id라는 props 가 변경될 때 (componetDidUdpate)의 함수이다.

useEffect(() => {
  update(id);
},[id]);

하지만, useEffect hooks 를 사용하면 단순한 코드로 사용할 수 있다.



재사용성

앞서 언급한 HOC 패턴을 사용한 것은 함수형 컴포넌트를 기반으로 한 코드였다.
이는 더 나아가 Custom Hook(use___)으로 발전할 수 있었다.

const useFetchUser = () => {
  const [users, setUsers] = useState([]);
  
  useEffect(() => {
    fetchUsers().then((users) => {
      setUsers(users);
    });
  }, []);
  
  return users;
}

위 userHOC 파일을 useFetchUser 커스텀 훅을 생성하여

const UserAgePage = () => {
  const users = useFetchUser();
  return{
    //...
  }
}

사용할 페이지 컴포넌트에서 useFetchUser 를 호출하여 state 를 설정해 사용해줄 수 있다.




정리

React Hooks 란?

  • 함수형 컴포넌트에서 Life Cycle 과 state 상태를 관리할 수 있는 기술
  • 클래스형 컴포넌트의 한계점을 극복한 재사용성을 높이고, 더 간단한 코드로 가독성 있는 코드로 완성시킬 수 있다.



마치며

hooks 들을 공부하고 활용할 생각만 했었는데, 어떻게 생성되었는지 origin 을 알게 되어서 react 의 초기 기반이었던 클래스형 컴포넌트와 지금 잘 쓰이는 함수형 컴포넌트의 차이도 잘 알게 되어서 이해하기 쉬웠다.
그리고 우테콕 강의를 이제부터 하루에 최소 하나 이상을 듣고 내 것으로 이해하는 작업을 할 예정이다. 이렇게 해서 CS 를 조금씩이나마 자신감있게 익히고 싶다.


참고 : https://www.youtube.com/watch?v=qjEcsNYFWYg

0개의 댓글