- 리액트 훅(react hook)에 대해2022년 05월 07일
- 루루개발자
- 작성자
- 2022.05.07.:01
반응형안녕하세요. 루루개발자 입니다.
이번 글에서는 react 의 hook에 대해 한번 알아보도록 하겠습니다.
리액트 훅 (react hook) 이란?
[ 정리해보기 ]
리액트의 훅은 16.8 버전부터 새로 추가된 기능이라고 합니다. Hook은 함수형 컴포넌트에서 React state와 생명주기 기능(lifecycle features)을 “연동(hook into)“할 수 있게 해주는 함수라고 합니다. Hook은 class 안에서는 동작하지 않으며, 대신 class 없이 React를 사용할 수 있게 해주는 것이라고 합니다.
[ 생각해보기 ]
즉, 기존 클래스의 생명주기 메서드를 함수형 방식에서 함수로 사용할 수 있도록 한 것이 훅인 것 같습니다. 상태 값을 초기화 하거나, 변경이 발생했을 때 등의 상황에서 리액트의 훅함수가 호출되는 방식인 듯 합니다.
리액트 훅의 규칙
[ 정리해보기 ]
리액트 훅은 반복문, 조건문, 중첩된 함수내에서 호출하면 안된다고 합니다. 이 규칙을 지키면 컴포넌트가 렌더링 될 때마다 항상 동일한 순서로 훅이 호출되는 것이 보장된다고 합니다.
리액트 훅은 일반적인 javascript 함수에서 호출하면 안된다고 합니다. 이 규칙을 지키면 컴포넌트의 모든 상태 관련 로직을 소스코드에서 명확하게 보이도록 할 수 있다고 합니다.
이러한 리액트 훅의 규칙을 강제하도록 하는 ESLint 플러그인이 있다고 합니다.
npm install eslint-plugin-react-hooks --save-dev
위 명령어를 통해 설정 가능하다고 합니다.
리액트 훅은 한 컴포넌트내에서 여러번 사용될 수 있다고 합니다. 다만 조건문 등을 통해 리액트 훅 함수가 호출 될 수도 있고 아닐수도 있는 구조로 작성하게 되면 동일한 순서로 훅이 호출되는 것이 보장되지 않기 때문에 예상치 못한 버그가 발생할 수 있다고 합니다.
[ 생각해보기 ]
위 내용을 통해 알 수 있는 사실은 리액트 훅 함수는 컴포넌트 내에서 최초 호출된 순서가 보장되도록 코드를 작성해야 하고 element.addEventListener('click', function() { ... }); 와 같은 일반적인 javascript 함수 내에서 호출하면 안된다는 것을 알 수 있었습니다. 이러한 규칙을 강제하도록 하는 eslint 플러그인도 있다고 하니 사용하지 않을 이유는 없겠네요! (create-react-app 을 통해 리액트 프로젝트를 생성하면 이러한 eslint 플러그인이 포함되어 있다고 하네요.)
useState
[ 정리해보기 ]
리액트의 훅중 하나이며 현재의 state 값과 state 값을 업데이트하는 함수를 반환하는 함수라고 합니다. 일반적으로 함수 내의 변수는 함수가 종료되면 사라지지만, useState 를 사용해 변수의 상태를 초기화하면 리액트에 의해 해당 변수는 사라지지 않고 계속 관리된다고 합니다.
useState 함수는 배열을 반환하며, 첫번째 요소는 useState 함수의 인자로 넘겼던 초기 state 값이 반환되며 두번째 요소는 해당 state 값을 변경하는 함수가 반환됩니다. 이렇게 배열로 반환되기 때문에 보통 배열 구조 분해 할당 문법을 활용한다고 합니다. 이렇게 배열로 반환하는 이유는 개발자가 구조 분해 할당을 통해 상태값 변수명과 상태를 변경하는 함수명을 쉽게 지정할 수 있기 때문이라고 합니다.
[ 생각해보기 ]
변수의 상태를 초기화하는 것에 있어서 useState 훅은 class 의 constructor 와 비슷한 포지션이라고 볼 수 있을 것 같습니다. 다만 차이점은 class 의 constructor 는 한번만 호출되지만 useState 는 여러번 호출 될 수 있다는 점이네요.
useEffect
[ 정리해보기 ]
리액트의 훅중 하나이며 DOM이 렌더링된 이후에 어떤 일을 수행해야 하는지를 명시할 때 사용하는 훅이라고 합니다. useEffect 함수를 컴포넌트 함수 내에서 호출하게 되면 해당 함수내에 정의된 변수를 감지하는 것이 가능하며, 이 때문에 useEffect 함수를 컴포넌트 함수 내에서 사용하는 것이라고 합니다.
useEffect 는 화면이 렌더링 된 이후에 최초 한번 실행되고 이후 상태가 변경될 때마다 계속 실행됩니다. React는 effect가 수행되는 시점에 이미 DOM이 업데이트되었음을 보장한다고 합니다.
useEffect 함수에 첫번째 인자로 전달하는 함수를 Effect 라고 합니다. 그리고 두번째 인자애 전달하는 값은 상태를 감지할 대상인 변수가 나열된 배열이며 해당 값을 전달하지 않으면 모든 상태 변화때마다 effect 가 실행되고 해당 값을 전달하면 해당 상태 값들이 변경되었을 때만 effect 가 실행되게 할 수도 있다고 합니다. useEffect 가 컴포넌트가 마운트 될 때, 그리고 마운트가 해제 될 때만 호출되게 하고 싶다면 두번째 인자에 빈 배열을 넘겨주면 된다고 합니다.
만약 clean-up(정리)를 이용하는 Effect 가 필요하다면 useEffect 에서 정리될 내용이 작성된 cleanup 함수를 반환하면 된다고 합니다. (꼭 함수명을 cleanup 으로 해야할 필요는 없다고 합니다.) useEffect 에서 반환한 함수는 리액트에서 해당 컴포넌트가 마운트 해제될 때 호출한다고 합니다. 당연하겠지만 clean-up(정리)가 필요없는 effect 는 아무것도 반환하지 않게 작성하면 된다고 합니다.
useEffect 는 여러번 호출 될 수 있는 만큼 관심사별로 내용을 분리할 수도 있다고 합니다. 코드가 무엇을 하는지에 따라 나눌 수가 있으며, React는 컴포넌트에 사용된 모든 effect를 지정된 순서에 맞춰 적용한다고 합니다.
[ 생각해보기 ]
useEffect 함수가 언제 호출되는지에 대해 알 수 있었고, 컴포넌트가 파괴(마운트 해제)될 때 실행되어야 할 내용은 useEffect 함수에서 cleanup 함수를 반환하면 된다는 사실을 알 수 있었습니다. 위에서 언급된 clean-up (정리) 라는 용어는 컴포넌트가 마운트 해제되기 전에 구독된 것을 해제하는 등의 정리를 말하는 걸로 보입니다.
또한 기존 클래스들의 생명주기 메서드들은 동시에 여러 함수로 존재할 수 없었지만 useEffect 는 여러개로 존재 할 수 있기 때문에 effect 별로 코드의 관심사를 분리 할 수 있다는 것도 기존 class 방식과의 차이점으로 다가왔습니다.
custom hook (커스텀 훅)
[ 정리해보기 ]
리액트에 내장된 이러한 훅 함수들을 활용해 직접 필요한 훅을 만들 수도 있다고 합니다. 커스텀 훅을 활용하면 중복되는 코드를 줄일 수 있고 이전 클래스형 React 컴포넌트에서는 불가능했던 로직 공유의 유연성을 제공한다고 합니다.
[ 생각해보기 ]
일반적으로 코딩을 할 때도 중복되는 부분은 함수로 만들어 해당 함수를 호출하는 식으로 작성을 많이 하곤 합니다. 리액트 훅도 결국엔 함수이기 때문에 중복된 로직을 하나의 커스텀 훅이란 함수로서 처리할 수 있다는 걸로 이해하면 될 것 같습니다.
마치며
이 외에도 다른 훅들도 존재합니다. 해당 훅들은 사용해야 될 상황에 직면하게 되었을 때 따로 다뤄보는 시간을 가져보도록 하겠습니다. 읽어주셔서 감사합니다. :)
<참고>
https://ko.reactjs.org/docs/hooks-intro.html
https://ko.reactjs.org/docs/hooks-state.html
https://ko.reactjs.org/docs/hooks-rules.html
https://ko.reactjs.org/docs/hooks-effect.html
https://ko.reactjs.org/docs/hooks-custom.html
반응형'react & next.js' 카테고리의 다른 글
Next.js 에서 local, development, production 환경 셋팅하기 (0) 2022.10.13 자식 컴포넌트에 전달하는 props 관련 테스트 (0) 2022.05.29 리액트 렌더링 시점 및 훅 호출 순서 확인해보기 (1) 2022.05.16 react 에서 useEffect 가 2번 호출되는 현상 (두 번 렌더링 되는 현상) (0) 2022.05.15 리액트에 style 적용하는 방법 2가지 (0) 2022.05.08 다음글이전글이전 글이 없습니다.댓글