해당 글에서는 버튼의 중복 호출을 막기 위해 lodash 라이브러리의 Debounce 모듈을 활용하는 방법에 대해 알아봅니다.
1) 문제점 파악
💡 문제점 파악
- SetState()로 버튼을 누르면 즉각적으로 버튼에 대해 disabled = true 처리를 하면 해결이 되지만, 부모와 자식 구조간에 관계에서 빠르게 처리가 되지 않아서 중복으로 함수 처리가 되는 문제가 발생하였습니다.
- 이에 따라서 버튼을 여러 번 빠르게 눌러도 한 번의 처리인 것과 같은 기능을 구현하고 싶어서 찾아보는 중 lodash 라이브러리의 Debounce 모듈을 알게 되어 이를 적용하였습니다.
2) lodash
💡 lodash - JavaScript에서 사용할 수 있는 유틸리티 라이브러리입니다. - 배열, 객체, 함수, 언어 유틸, 숫자, 문자열, 날짜, 논리 등과 같은 다양한 데이터 타입을 처리하는 데 도움이 되는 수많은 메서드를 제공합니다. - 이 라이브러리를 사용하면 코드를 보다 명확하고 간결하게 작성할 수 있습니다. 또한 Lodash는 모듈화가 되어 있어 필요한 기능만 선택적으로 사용할 수 있으므로, 애플리케이션의 성능 향상에도 기여할 수 있습니다.
1. lodash 주요 모듈
모듈명
설명
_.chunk
배열을 지정된 크기의 여러 부분으로 나눕니다.
_.compact
배열에서 거짓 값(false, null, 0, "", undefined, NaN)을 제거합니다.
_.concat
배열 또는 값들을 연결하여 새 배열을 만듭니다.
_.difference
첫 번째 배열에는 있지만 두 번째 배열에는 없는 값을 반환합니다.
_.drop
배열의 첫 번째 요소를 제거하고 나머지 요소를 반환합니다.
_.debounce
연속적으로 호출되는 함수의 실행을 일정 시간 동안 ‘지연’시킵니다.
2. lodash Debounce
💡 lodash Debounce - 연속적으로 호출되는 함수의 실행을 일정 시간 동안 ‘지연’시키는 역할을 합니다. 이는 사용자에게서 이벤트가 여러 번 발생할 경우, 이벤트 핸들러가 과도하게 호출되는 것을 방지하고, 성능을 향상하는 데 도움이 됩니다.
- 예를 들어, 버튼을 누르면 DB INSERT를 수행하는 API를 호출하는 함수가 있다고 가정합니다. - 그리고 해당 함수는 lodash Debounce로 감싸져 있고, 시간을 5000으로 지정했습니다. - 그래서 사용자는 연속으로 해당 버튼을 연타를 누릅니다. 누르게 되면 5초(5000) 동안에 발생하는 이벤트 중 제일 마지막에 누른 1번만 수행을 합니다. 단 5초가 지날 때까지 감싸진 함수는 수행되지 않습니다.
- TestScreen로 컴포넌트 화면을 구성하였습니다. ‘버튼 테스트를 수행합니다.’라는 버튼을 누르면 onPressTest() 함수가 수행되는 구조입니다. - onPressTest() 함수는 lodash의 debounce 함수로 감싸져 있어서 버튼을 누르면 5초 뒤에 수행이 됩니다. - 이 5초가 수행되는 과정에 여러번 버튼을 터치한 경우에 5초가 지나기 전 제일 마지막에 누른 이벤트만 수행을 합니다.
- useCallback을 사용하여 onPressTest 함수를 메모이제이션하였습니다. 이로써, 컴포넌트가 리렌더링 되더라도 onPressTest 함수는 새롭게 생성되지 않고 메모리에 저장된 이전 함수가 반환됩니다. - 이를 통해서 디바운스 효과를 유지하는 데 필요한 조건을 충족시킵니다.
- 아래와 같은 코드 내에서 버튼을 터치하면 “[+] 버튼을 반복 터치합니다.”이라는 콘솔을 출력하는 한편 onPressTest() 함수를 호출합니다. - 실제 터치를 했을 때는 콘솔이 나오지만, onPressTest() 함수는 1초간 한 번만 호출되는 처리를 확인할 수 있었습니다.
import React, { useCallback } from "react";
import { Text, TouchableOpacity } from "react-native";
import { View } from "react-native";
import _ from "lodash";
const TestScreen = () => {
const onPressTest = useCallback(_.debounce(() => {
console.log("[+] 실제 함수의 호출")
}, 1000), [])
return (
<>
<View>
<TouchableOpacity onPress={() => {
console.log("[+] 버튼을 반복 터치합니다.")
onPressTest()
}}
style={{ backgroundColor: "red", height: 200 }}>
<Text>버튼 테스트를 수행합니다.</Text>
</TouchableOpacity>
</View>
</>
)
}
export default TestScreen