generated from jwson-automation/blueberry_template
-
Notifications
You must be signed in to change notification settings - Fork 0
리버팟을 활용해 Debouncing 적용해보기
AlphanoJack edited this page Sep 29, 2024
·
2 revisions
디바운싱은 이벤트가 발생한 후 일정 시간 동안 추가적인 이벤트가 하지 않을때 마지막 이벤트만 처리하도록 하기위해 사용합니다. 보통 키보드입력, 버튼 클릭, 스크롤이벤트에서 자주 사용됩니다.
- 이벤트 조절: 여러번 발생할 수 있는 이벤트를 제한하여, 불필요한 처리 비용이나 통신횟수를 감소 시킵니다.
- 성능개선: 반복적인 작업을 줄여 성능을 개선하고, 서버와 통신 횟수를 줄여 비용을 절감할 수 있습니다.
예제 그림을 보시면 첫 클릭이벤트가 어떤 상태가 반영되던 마지막에 받은 이벤트만 반영됩니다.
- 클라이언트가 서버를 터트리는 행위를 방지할 수 있습니다. (예를 들어서 클릭마다 서버와 통신을 한다고 했을때 디바운싱 처리를 하지 않으면 클라이언트가 악의적인 행위로 버튼을 연속적으로 클릭하게 되었을때 무수히 많은 통신 처리를 하게되고 서버에 트래픽 과다 현상이 발생하여 앱을 사용중인 다른 유저에게까지 악영향을 주게 됩니다. )
- 대규모의 형식의 개발이 아닌 경우 비용절감이 핵심입니다. (통신 횟수는 직접적인 서버 사용 비용으로 반영되기 때문에 현저하게 줄일수 있습니다.)
리버팟의 StateNotifier을 활용해서 상태를 임시 저장하여 처리를 하겠습니다.
먼저 상태를 관리하기 위한 2개의 State를 선언합니다
class NotificationState {
final bool uiState;
final bool actualState;
NotificationState(this.uiState, this.actualState);
NotificationState copyWith({bool? uiState, bool? actualState}) {
return NotificationState(
uiState ?? this.uiState,
actualState ?? this.actualState
);
}
}
두개의 State를 선언하게 된 이유는 최초에 한개의 State로 선언해서 처리 해봤습니다. 하지만 디바운싱을 처리 하는 동안에 클라이언트단에서 UI의 동작 감지도 안되기때문에 두개의 State를 선언해서 한개는 UI상태를 추적하기 위해 두개를 선언했습니다.
class NotificationStateNotifier extends StateNotifier<NotificationState> {
NotificationStateNotifier() : super(NotificationState(true, true)) {
loadInitialState();
}
Timer? debounceTimer;
void toggleNotificationState() {
state = state.copyWith(uiState: !state.uiState);
// UI상태를 즉시 변경
debounceTimer?.cancel();
// 타이머가 다 진행되기 전에 연속적으로 클릭하게 되면 리셋
debounceTimer = Timer(const Duration(seconds: 2),() async {
await updateActualState();
// 타이머가 시간이 지나면 현재 uiState의 상태를 actualState로 반환
});
}
Future<void> updateActualState() async {
final newActualState = state.uiState;
final previousState = state.actualState;
state = state.copyWith(actualState: newActualState);
... 서버 통신 로직
}
Future<void> loadInitialState() async {
..서버에서 최초 상태를 반환하는 로직
}
final notificationStateProvider = StateNotifierProvider<NotificationStateNotifier, NotificationState> ((ref) {
return NotificationStateNotifier();
});
이렇게 하면 기본적인 구성은 끝입니다.
IconButton (
onPressed: (){
ref.read(notificationStateProvider.notifier)
.toggleNotificationState();
}
icon ? const Icon(Icons.notifications_active)
: const Icon(Icons.notifications_off),
)
최초 불러오는 로직이나 서버 통신 로직인 개개인의 편차가 존재한다고 생각하여 넣지 않았습니다.
이외 추가로 궁금하신 사항이 있다면 언제든지 댓글 및 연락주세요