안드로이드 자바
[Java][Android] 버튼 연속 클릭 방지하기
teamnova
2025. 6. 2. 15:58
728x90
왜 버튼 연속 클릭 방지가 필요한가요?
서버 부하 증가: 사용자가 버튼을 빠르게 여러 번 누르면, 각 클릭마다 서버로 API 요청이 중복해서 전송될 수 있습니다. 이는 서버 리소스를 불필요하게 소모시키고, 심한 경우 서비스 장애로 이어질 수 있습니다.
의도치 않은 데이터 중복 생성/수정: 예를 들어 '게시글 작성' 버튼을 연타하면 동일한 내용의 게시글이 여러 개 생성될 수 있습니다.
사용자 경험(UX) 저하: 앱이 반복적인 요청으로 인해 느려지거나, 예기치 않은 동작을 보이면 사용자는 불편함을 느낍니다.
클라이언트 리소스 낭비: 불필요한 네트워크 요청은 사용자의 데이터 소모를 늘리고, 배터리 사용량에도 영향을 줄 수 있습니다.
1.마지막 클릭 시간으로 연속 클릭 방지 (Throttling)
마지막으로 유효한 클릭이 발생한 시간을 기록하고, 다음 클릭이 너무 짧은 시간 내에 발생하면 해당 클릭 이벤트를 무시하는 것입니다. 이를 '쓰로틀링(Throttling)'의 한 형태로 볼 수 있습니다.
2. 버튼 비활성화 활성화로 연속 클릭 방지
사용자가 버튼을 클릭하면 즉시 버튼을 비활성화(disabled) 상태로 만들고, 서버 통신 또는 지정된 작업이 완료되거나 일정 시간이 지난 후 다시 활성화(enabled)하는 방식입니다. 이는 사용자에게 시각적으로 버튼이 현재 동작 중이거나 일시적으로 사용할 수 없음을 알려줍니다.
예제코드
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<Button
android:id="@+id/myThrottlingButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="클릭 (시간 간격 체크)" />
<Button
android:id="@+id/myDisableEnableButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="클릭 (비활성화/활성화)" />
</LinearLayout>
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.SystemClock;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
private Button myThrottlingButton, myDisableEnableButton;
private long lastClickTime = 0; // 마지막으로 유효하게 클릭된 시간
private static final long CLICK_TIME_INTERVAL = 3000; // 3초 (밀리초 단위) - 이 시간 내의 클릭은 무시
private static final long DISABLE_DURATION = 1500; // 1.5초 동안 비활성화
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myThrottlingButton = findViewById(R.id.myThrottlingButton);
myDisableEnableButton = findViewById(R.id.myDisableEnableButton);
myThrottlingButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 현재 시간과 마지막 클릭 시간 비교
if (SystemClock.elapsedRealtime() - lastClickTime < CLICK_TIME_INTERVAL) {
Log.d("ButtonClick", "연타 방지: 너무 빠른 클릭입니다.");
Toast.makeText(MainActivity.this, "너무 빠른 클릭입니다. 잠시후 시도해 주세요", Toast.LENGTH_SHORT).show();
return; // 클릭 이벤트 무시
}
// 유효한 클릭이므로, 마지막 클릭 시간을 현재 시간으로 업데이트
lastClickTime = SystemClock.elapsedRealtime();
// 실제 클릭 처리 로직 (예: 서버 통신)
Log.d("ButtonClick", "버튼 클릭됨! 서버 통신 시작...");
performServerCommunication("시간 간격 체크 방식");
}
});
myDisableEnableButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
myDisableEnableButton.setEnabled(false); // 버튼 즉시 비활성화
// 실제 클릭 처리 로직 (예: 서버 통신)
Log.d("ButtonClick", "비활성화 버튼 클릭됨! 서버 통신 시작...");
performServerCommunication("비활성화/활성화 방식");
// 일정 시간 후 버튼 다시 활성화 (UI 스레드에서 실행)
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
@Override
public void run() {
// Activity가 아직 살아있고 버튼이 존재할 때만 활성화 (선택적이지만 안전)
if (myDisableEnableButton != null && !isFinishing()) {
myDisableEnableButton.setEnabled(true);
}
}
}, DISABLE_DURATION);
}
});
}
private void performServerCommunication(String method) {
// 여기에 실제 서버와 통신하는 코드를 넣습니다.
Toast.makeText(this, method + ": 서버와 통신하거나 다른 작업을 수행합니다.", Toast.LENGTH_SHORT).show();
}
}
시연영상