안녕하세요, 개발자 Sean입니다.
“Young man, in mathematics you don't understand things. You just get used to them.”
― John von Neumann
컴퓨터의 아버지로 불리는 폰 노이만 선생님께서 하신 말씀입니다.
일찍부터 알았더라면 어땠을까... 생각하게 되는 명언이죠 ㅎㅎ
최근 리엑트를 매일같이 다루면서 다시 한번 떠올리게 되어 적어보았습니다.
이전에 리엑트를 공부할 때 커스텀 훅과 관련된 내용을 읽어본 기억이 납니다.
그때까지만 해도 커스텀 훅의 필요성을 느끼지 못했기 때문에 뭔가 대단히 어렵고 사용하기 난해한 기술로 여기고 여태까지 단 한 번도 사용하지 않았는데요, 업무를 보면서 그리고 코드에 대해 익숙해지면 질 수록 그 필요성을 느끼고 이번에 관련해서 공부를 깊게 파보기로 했습니다.
본론에 앞서 제가 그간 개발팀에서 업무를 하며 느낀 점은
개발의 목적을 단순히 '동작하는' 어플로 설정한다면 관심사의 분리 혹은 디자인 패턴, 아키텍처 등을 고민할 필요가 없다는 점입니다. (반박 시 그대 말이 맞습니다...)
반면, 개발팀의 개발 목적이 '확장이 가능한' 어플이라면 관심사의 분리 혹은 디자인 패턴, 아키텍처는 매우매우매우 중요하다고 생각합니다.
이렇게 느끼게 된 계기는 현재 개발팀은 스타트업 개발팀이고
스타트업의 특성상 우선 '동작하는' 어플 개발에 있다보니 이전에 작성한 코드를 읽고 이해하는데 너무나도 어려운 점이 많았고
자연스럽게 왜 이해가 어려운지 원인을 분석하다 보니 위와 같은 결론을 내리게 되었습니다.
처음 팀에 합류하고 코드를 리뷰하면서 어떤 자바스크립트 파일에는 비즈니스 로직과 뷰를 담당하는 코드들이 뒤죽박죽 섞여있어 깜짝 놀랐던 기억이 납니다. 해당 코드를 이해하기 위해서 코드의 상단과 하단을 여러 번 왔다 갔다 하며 무엇을 위한 코드인지 이해를 해야 했고(심지어 변수 명도 이해하기 힘들었습니다 ㅠㅠ) props를 전달해주는 부모 컴포넌트에서도 코드를 확인해야 하는... 그런 극악의 코드를 가지고 있었습니다.
하지만, 이게 잘못된 것이라고 생각하지는 않습니다. 확장성이 큰 효율을 발휘하는 경우는 어디까지나 규모가 큰 어플에 한하기 때문에 스타트업과 같이 하루라도 빨리 어플을 만들어 내야하는 상황에서 매번 리펙토링을 하며 패턴을 연구하고 상의하는 방식은 옳지 않다고 생각합니다. 일단은 생존해야 하니까요. (일단은 월급을 벌어야 하니까요 ㅎㅎ)
그러던 중 베타버전 런칭이 2주 앞으로 다가왔고 목표로 했던 기능들은 거의다 구현이 마무리된 상태에서,
대표님께 현재 코드 상황에 대해 상의를 드렸습니다. 대표님은 나의 의도를 단번에 이해하시고는 베타 버전 배포가 끝나면 일정기간 리펙토링을 통해 유지보수 및 확장 가능한 코드로 코드를 정리하는 시간을 가지자고 말씀해 주셨습니다.
따라서 이번에는 커스텀 훅을 활용해 비즈니스 로직과 뷰를 담당하는 코드를 분리하는 커스텀 훅 패턴으로 코드를 재구성해 관심사의 분리를 용이하게 하고자 하는 방법에 대해 알아보려고 합니다.
관련해서 좋은 글이 있어 번역해서 옮겨봅니다.
Creating Custom React Hooks
본 포스팅에서는 간단한 커스텀 리엑트 훅을 만들어보고 커스텀 훅의 생성과 사용 뒤에 숨겨진 구조를 이해해보려고 한다.
커스텀 훅을 이용하는 주요 목적으로는:
- UI와 로직의 분리
- 재사용가능한 로직 블록 생성
- 깔끔하고 확장가능한 코드
- 커스텀 훅을 활용한 다른 훅 이용
훅은 리엑트 개발에 중요한 개념이다. 이미 리엑트에는 특정 업무를 수행하는 useMemo, useEffect와 같은 내장 훅들이 있다.
Creating Simple React Custom Hook
한번 아래와 같은 간단한 커스텀 리엑트 훅을 만들어 보자:
function useCustomHooks() {
let userName = "Mayank";
let userDesignation = "Trainer";
return [userName, userDesignation];
}
위의 코드는 다양한 값을 리턴하는 간단한 커스텀 훅이다. 위 코드에서 아래와 같은 원칙을 지니고 있다:
- 'use'가 커스텀 훅의 함수명 앞에 붙는다.
- 커스텀 훅은 어떤 값을 리턴한다.
- 커스텀 훅은 재사용 가능하다.
위에서 생성한 훅을 어플리케이션의 다른 부분에 어떻게 사용하는지 한 번 살펴보자. 위의 훅에서는 'userName'과 'userDesignation'이라는 두 개의 배열을 반환한다. 위의 훅을 이용하면...
function useCustomHooks() {
let userName = "Mayank";
let userDesignation = "Trainer";
return [userName, userDesignation];
}
function ApplicationComponent() {
const [name, designation] = useCustomHooks();
return (
<div>
<h1>User Name: {name}</h1>
<h2>User Designation: {designation}</h2>
</div>
)
}
위의 코드에서 커스텀훅을 사용했고 이 커스텀 훅은 ApplicationComponent 컴포넌트 내에서 name과 designation 변수명으로 그 안의 값을 추출해 반환하고 있다. 위의 커스텀 훅은 애플리케이션에 그렇게 많은 값을 추가하지는 않지만, 그 안에 데이터를 저장하고 반환하는 재사용 가능한 간단한 커스텀 컴포넌트를 나타내고 있다.
Passing Parameter to React Hooks
이번에는 커스텀 훅이 반환하는 데이터의 초기값을 설정할 수 있는 코드를 넣어보자.
function useCustomHooks(userName, userDesignation) {
let userName = "User Name: " + userName;
let userDesignation = "User Designation: " + userDesignation;
return [userName, userDesignation];
}
function ApplicationComponent() {
const [name, designation] = useCustomHooks("Mayank", "Trainer");
return (
<div>
<h1>{name}</h1>
<h2>{designation}</h2>
</div>
)
}
위 코드에서 useCustomHook 훅에 파라미터를 전달했고 이 파라미터는 컴포넌트 데이터의 초기값을 설정하게 된다.
지금까지 만든 커스텀 훅은 실제 상황에서 사용하기는 현실적이진 않다. 이제 현업에서 맞닥뜨릴만한 상황을 가정하고 리엑트 훅을 생성해 사용해보자.
코드를 한번 살펴보자.
function useCustomTimeHooks() {
function getCurrentTime() {
let date = new Date();
return date.getHours() + ": " + date.getMinutes() + ": " + date.getSeconds();
}
let [time, setTime] = useState(getCurrentTime());
setTimeout(() => {
setTime(getCurrentTime());
}, 1000);
return [time];
}
function ApplicationComponent() {
const [time] = useCustomTimeHooks();
return (
<div>
<h1>Current Time: {time}</h1>
</div>
);
}
위의 코드에서 아래 개념을 이해할 필요가 있다:
- useCustomTimeHooks라는 커스텀 훅을 생성했다.
- 커스텀 훅은 useState 훅을 내부에 사용했다.
- 커스텀 훅은 time이라는 변수를 반환한다.
- time 속성은 컴포넌트 내에서 반환되고 렌더링된다.
- 커스텀 훅은 매초 업데이트 된다.
- 시간 속성은 렌더링된 컴포넌트에서 매초 업데이트된다.
위 코드의 핵십내용은 아래와 같다:
state 데이터를 업데이트하는 새로운 커스텀 훅을 만들었다. state 변수는 애플리케이션에서 반복해서 사용될 수 있다. 그리고 특성의 업데이트는 애플리케이션 컴포넌트가 아닌 커스텀 훅에 의해 이루어진다.
이런 패턴의 이점은:
- time 번수는 컴포넌트에 의해 컨트롤 되지 않는다.
- time 변수의 관리는 훅에 의해 이루어 진다.
- 업데이트 시간 카운터 함수는 재사용 가능하다.
- 주요 어플리케이션을 다수의 서브 파트로 나눌 수 있다.
- 컴포넌트에서 비즈니스 로직을 없앨 수 있다.
Using "useEffect" Hook in React Custom Hooks
커스텀 훅에 또한가지 추가할 수 있는 부분은 "useEffect"의 사용이다.
"useEffect"는 컴포넌트가 초기 렌더링 되거나 리-렌더링 될 때 특정한 코드를 실행하도록 할 수 있다.
아래 컴포넌트에서는 관련된 총 직원 수를 표시하고 비동기적으로 직원 데이터가 추출된다. 우리는 여기서 비동기적으로 직원 데이터를 추출하는 훅을 만들고 회사의 직원수를 카운팅 하는 상태 변수를 업데이트해 볼 것이다.
function useEmployeeCountHooks() {
let [empCount, setEmpCount] = useState(0);
useEffect(() => {
setTimeout(() => {
setEmpCount(employeeData.length);
}, 2000);
});
return [empCount];
}
function ApplicationComponent() {
const [empCount] = useEmployeeCountHooks();
return (
<div>
<h3>"useEmployeeCountHooks" used to maintain App state</h3>
<b>"useEffect" Hook can be used inside Custom Hooks</b><br /><br />
<b>"useEffect" is extracting data asynchronously from the aplication</b><br /><br />
<b>The Custom Component is maintaining the state data as well..</b><br /><br />
<b>View for the application has been simplified to cater rendering logic</b>
<h1>Employee Count: {empCount}</h1>
</div>
);
}
위 코드에서 상태변수는 "empCount"라고 이름 지어졌고 그 값은 "useEmployeeCountHooks"라는 훅에 의해서 변경된다. "ApplicationComponent" 컴포넌트에 표시된 컴포넌트는 useEmployeeCountHook을 사용해 직원수 카운트를 비동기적으로 데이터를 업데이트하고 관리한다.
위 코드의 이점은:
- "ApplicationComponent"는 "empCount"를 관리하지 않는다.
- "ApplicationComponent" 뷰의 복잡성을 감소시킨다.
- 커스텀 훅은 재사용 가능하다.
- 뷰와 비즈니스 로직이 분리된다.
출처: https://medium.com/technofunnel/creating-custom-react-hooks-9d4f382359bb
Creating Custom React Hooks
All you need to know to create Custom Hooks in React…
medium.com
'Front-End > React' 카테고리의 다른 글
[React] 리엑트에 SOLID 원칙 적용시키기 (0) | 2022.10.31 |
---|---|
[React] 선언형과 리엑트 (0) | 2022.10.20 |
[React] Build 후에 CSS 사라짐 현상? (0) | 2022.08.14 |
[React] 리엑트 컴포넌트가 두 번 렌더링 되는 이유? (0) | 2022.07.29 |
[React] 리엑트 디자인 패턴: Return Component From Hooks (0) | 2022.06.30 |