Custom hook이란?
React의 커스텀 훅(custom hook)은 리액트의 함수형 컴포넌트에서 상태 또는 사이드 이펙트가 있는 로직을 재사용하기 위해 캡슐화할 수 있는 특정 네이밍 규칙을 따르는 함수이다.
커스텀훅을 사용하면 복잡한 로직을 재사용가능한 함수로 만들어버릴 수 있는데, 이렇게 할 경우 코드가 깰끔해지고 컴포넌트 내 관심사 분리를 유지하기 쉬워진다.
일반 함수 vs. 커스텀훅
커스텀훅 또한 함수라고 했는데, 그렇다면 일반 함수와 커스텀 훅의 차이는 무엇일까?
1. 네이밍 규칙
커스텀훅들은 "use"라는 이름으로 시작해야 한다(예: useFetchData). 이를 통해 리액트가 이 친구가 커스텀훅이라는걸 알 수 있게 되고, 리액트 내부에서 진행되는 특정 최적화 작업의 대상이 될 수 있다.
2. 재사용성
커스텀훅은 컴포넌트간 존재할 수 있는 복잡한 로직을 캡슐화하여 재사용하는 방법이다. 이를 통해 코드 재사용성을 올리고 유지보수를 용이하게 할 수 있다.
3. 관심사 분리
커스텀훅은 상태가 있거나 사이드 이펙트가 있는 로직을 컴포넌트의 랜더링 로직과 분리할 수 있게 해준다.
4. 상태 분리
커스텀 훅을 사용하는 사용하는 각 컴포넌트는 각자 'isolated'된 상태를 갖게 된다. 같은 커스텀훅을 여러 컴포넌트에서 사용하는 경우, 한 컴포넌트 내에서 사용하는 요 커스텀훅의 상태는 같은 커스텀훅을 사용하는 다른 컴포넌트의 상태와 겹치지 않는다.
5. 훅 조합
커스텀훅은 더 복잡한 행동을 만들기 위해 서로 함께 뭉칠 수 있다. 이를 통해 이미 만들어진 로직 위에 새로운 기능을 추가하는 것이 가능해진다.
Custom hook을 사용했을 때 vs. 안썼을 때
데이터를 받아오는 fetching logic은 여러 컴포넌트에서 사용 가능한 친구이기 때문에 커스텀훅으로 만들면 재사용성에 이점을 얻을 수 있는 기능이다. 만약이 이와 같이 데이터를 받아오는 로직을 날 것 그대로 컴포넌트에 작성하게 된다면 아래와 같이 될 것이다:
import React, { useState, useEffect } from 'react';
function AppWithoutCustomHook() {
const [movies, setMovies] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch('https://api.example.com/movies')
.then(response => response.json())
.then(data => {
setMovies(data);
setLoading(false);
})
.catch(error => console.error('에러가 발생해부렀어유:', error));
}, []);
return (
<div>
<h2>Movies</h2>
{loading ? (
<p>Loading...</p>
) : (
<ul>
{movies.map((movie, index) => (
<li key={index}>
<strong>{movie.title}</strong> - Rating: {movie.rating}
</li>
))}
</ul>
)}
</div>
);
}
export default AppWithoutCustomHook;
그러나, 위 예시 같은 경우엔 데이터를 가져오는 기능과 컴포넌트를 랜더링하는 기능이 한 컴포넌트에 복잡하게 얽히면서 관심사 분리가 명확히 되지 않는다. 뿐만 아니라, 동일한 데이터 fetching 기능을 다른 컴포넌트에서 사용하려면 동일한 코드를 그 컴포넌트에 또 써야된다는 문제가 발생하게 된다. 커스텀훅은 바로 이런 경우에 사용할 수 있는 수단이다.
위와 같이 작성하지 않고 fetching 기능을 별도로 쏙 뽑아내서 아래와 같이 만들 수 있다:
import { useState, useEffect } from 'react';
function useFetchData(url) {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch(url)
.then(response => response.json())
.then(data => {
setData(data);
setLoading(false);
})
.catch(error => console.error('에러가 발생해부렀어유:', error));
}, [url]);
return { data, loading };
}
export default useFetchData;
이렇게 쏙 뽑아내서 별도로 만든 커스텀훅을 아래와 같이 사용하면, 관심사 분리가 명확하면서도, 데이터 fetching 커스텀훅을 다른 곳에서도 재사용할 수 있게 된다:
import React from 'react';
import useFetchData from './useFetchData';
function AppWithCustomHook() {
const movies = useFetchData('https://api.example.com/movies');
return (
<div>
<h2>Movies</h2>
{movies.loading ? (
<p>Loading...</p>
) : (
<ul>
{movies.data.map((movie, index) => (
<li key={index}>
<strong>{movie.title}</strong> - Rating: {movie.rating}
</li>
))}
</ul>
)}
</div>
);
}
export default AppWithCustomHook;
'Learn to Code' 카테고리의 다른 글
[Next.js] 브라우저 캐싱 문제 해결 방법 (0) | 2023.10.20 |
---|---|
[Next.js] 버전 13+으로 업데이트하기 (0) | 2023.10.07 |
TCP와 UDP (0) | 2023.08.15 |
클라이언트 사이드 렌더링 vs. 서버 사이드 렌더링 (CSR vs. SSR) (0) | 2023.08.03 |
이벤트 버블링(Event Bubbling)이란? (0) | 2023.07.27 |
댓글