이번 시간엔 앞서서 미리 봤었던, React hook에 대해서 살펴보자.
해당 문서는 전반적으로 React 공식 문서를 정리한 글이다.
Hook이란?
Hook은 함수 컴포넌트에서 React state와 생명주기 기능(lifecycle features)을 “연동(hook into)“할 수 있게 해주는 함수다.
Hook은 class 안에서는 동작하지 않고 기존에 Class component에서 class 없이 React를 사용할 수 있게 해준다.
React에서 제공하는 내장 hook은 단순히 "use"로 시작하는 모든 함수를 말한다.
Motivation of Hook
React에서 Hook이 나오게 된 계기는 다음과 같다.
- Component 사이에서 state 로직을 재사용하기 어렵다.
- 복잡한 component들은 이해하기 어렵다.
- Class은 개발자와 React를 혼동시킨다.
React 16.8.0 버전[2019년도 2월 6일]이 나오기 전까지 React에는 Hook이라는 것이 없었다.
때문에, React로 component를 작성하고 유지하는 동안 수 많은 문제들에 부딪혔다고 한다.
It’s hard to reuse stateful logic between components
- Component 사이에서 state 로직을 재사용하기 어렵다.
React는 Hook이 나오기 전에는, component 간에 재사용 가능한 로직을 붙이는 방법을 제공하지 않았다.
필자는 이전부터 React를 사용해보지는 않았지만 JavaScript의 class를 바탕으로 제작이 되었던 것으로 생각된다.
그러나 이런 패턴의 사용은 component의 재구성을 강요하며, 코드의 추적을 어렵게 만드는 경향이 있다.
따라서, React는 state 관련 로직을 공유하기 위해 좀 더 좋은 기초 요소가 필요했다고 한다.
앞서서 배운 useReducer()과 같이 Hook을 사용하면 component로부터 state 관련 로직을 추상화할 수 있는데,
이를 이용해 독립적인 테스트와 재사용이 가능해졌다.
Hook은 계층의 변화 없이 state 관련 로직을 재사용할 수 있도록 도와준다.
이것은 많은 컴포넌트 혹은 커뮤니티 사이에서 Hook을 공유하기 쉽게 만들어준다는 장점이 있다.
Complex components become hard to understand
- 복잡한 component들은 이해하기 어렵다.
State 관련 로직들과 side effect가 있는 component들은 관리하기가 힘들어서 추가적인 수정이 있다면 유지보수해야한다.
앞에서 side effect에서 다뤘듯이 component를 구성하는 데에는 자주 관련 없는 로직이 섞여들어간다.
특정 상황에 맞게 화면이 변경되는 경우라면, UI를 구성하는 state 관련 코드는 분리되지만,
연관 없는 코드들은 단일 메서드로 결합하기 때문이다. 이로 인해 버그가 쉽게 발생하고 무결성을 너무나 쉽게 해친다는 문제가 있다.
특히, React에서 state 관련 로직은 한 공간안에 묶여 있어서, component들을 작게 분리하는 것은 사실상 불가능하며 테스트하기도 어렵다.
때문에 많은 개발자들은 그동안 React를 별도의 state 관리 library를 추가해서 사용해왔다.
그러나, 이런 state 관리 library는 종종 너무 많은 추상화를 하기도 하고,
서로 다른 파일들 사이에서 건너뛰기를 요구하며 component 재사용을 더욱 더 어렵게 만들었다.
이같은 문제를 해결하기위해, state 관련 로직과 같은 생명주기 메서드를 기반으로 쪼개는 것보다는, Hook을 사용할 수 있다.
Hook을 통해 서로 비슷한 것을 하는 작은 함수의 묶음으로 component를 나누는 방법을 사용할 수 있다.
또한, 이러한 로직의 추적을 쉽게 할 수 있도록 reducer를 활용해 컴포넌트의 지역 상태 값을 관리하도록 할 수 있다.
Classes confuse both people and machines
- Class은 개발자와 React를 혼동시킨다.
React에서의 Class 사용을 위해서는 JavaScript의 this 키워드가 어떻게 작동하는지 알아야 사용 가능하다.
JavaScript의 this키워드는 대부분의 다른 언어에서와는 다르게 작동함으로 큰 혼란을 주었다.
또한, 코드의 재사용성과 구성을 매우 어렵게 만들었다.
Class의 사용을 위해 event handler가 등록되는 방법을 정확히 파악해야 한다.
이는 ES2022 public class fields가 없을 때, 코드를 매우 장황하게 만들다.
개발자들은 props, state, 그리고 top-down 데이터 흐름을 완벽하게 이해하고도 하고도, Class에는 어려움을 겪었다.
React 내의 함수와 Class component의 구별, 각 요소의 사용 타이밍 등은 숙련된 React 개발자 사이에서도 의견이 일치하지 않았다.
그간 React가 component를 미리 컴파일해놓는 방식에는 높은 잠재력이 있다는 것을 많이 봐왔지만,
Class의 사용이 지속된다면, 최적화가 더디게 작용할 것이다.
Class는 의도하지 않더라도 최근 사용되는 도구에서도 많은 문제를 일으킨다.
예를 들어 Class는 코드의 최소화를 힘들게 만들며,
Hot-reloading(사이트의 변화가 즉각 반영되는 것)을 깨지기 쉽고, 신뢰할 수 없게 만든다.
이러한 문제를 해결하기 위해, Hook은 Class없이 React 기능들을 사용하는 방법을 제시한다.
Hook은 명령형 코드로 해결책을 찾을 수 있게 해주며 복잡한 함수형 또는 반응형 프로그래밍 기술을 배우도록 요구하지 않는다.
Rules of Hook
여러 이점이 많은 Hook을 제대로 사용하기 위해서는 규칙을 알고 있어야 할 것이다.
따라서, Hook을 사용할 때 지켜야하는 규칙들에 대해서 살펴보자.
✅ 반복문, 조건문 혹은 중첩된 함수 내에서가 아닌, 오직 최상위(at the Top Level)에서만 Hook을 호출해야 한다
- 이 규칙을 따르면 component가 렌더링될 때마다, 항상 동일한 순서로 Hook이 호출되는 것이 보장된다.
- 이러한 점은 React가
useState()
와useEffect()
가 여러 번 호출되는 중에도 Hook의 상태를 올바르게 유지해준다.
✅ React component 함수 혹은 custom Hook에서만 호출해야 한다.
- 규칙을 지키면 컴포넌트의 모든 state 관련 로직을 소스코드에서 명확하게 보이도록 할 수 있다.
여기까지가 React 공식 문서에서 규정한 규칙이다.
여기에 강의에서는 useEffect()
Hook에 대한 추가 규칙을 언급한다.
항상, 참조하는 모든 항목을 의존성으로 useEffect()
내부에 추가해야 해줘야한다는 것이다.
물론, 그 조건에 예외사항이 존재한다. 그에 대한 추가적인 설명은 게시글을 참고바란다.
참조
React 공식 문서 - Hook 개요 | 근데 Hook이 뭔가요?