사용자가 폼 제출 후 새로고침을 누르면 데이터가 중복 전송되는 문제는 웹 개발에서 자주 발생합니다. 이를 효과적으로 해결하는 방법들을 알아보겠습니다.
문제: POST 후 새로고침 시 폼이 재전송됨
해결책: POST 처리 후 GET 페이지로 리다이렉트
if ($_POST) {
// 폼 데이터 처리
$name = $_POST['name'];
$email = $_POST['email'];
// 데이터베이스에 저장
saveUser($name, $email);
// 리다이렉트로 재전송 방지
header('Location: success.php');
exit;
}
문제: 의도적인 중복 제출 방지 필요
해결책: CSRF 토큰을 활용한 일회성 토큰 시스템
session_start();
// 폼 표시 시 토큰 생성
if (!isset($_SESSION['form_token'])) {
$_SESSION['form_token'] = bin2hex(random_bytes(32));
}
// 폼 처리
if ($_POST && isset($_POST['token'])) {
if ($_POST['token'] === $_SESSION['form_token']) {
// 정상 처리
processForm($_POST);
// 토큰 삭제로 재사용 방지
unset($_SESSION['form_token']);
header('Location: success.php');
exit;
}
}
<form method="POST">
<input type="hidden" name="token" value="<?= $_SESSION['form_token'] ?>">
<input type="text" name="name" required>
<button type="submit">전송</button>
</form>
문제: 같은 데이터의 연속 제출 방지
해결책: 마지막 제출 데이터를 세션에 저장하여 비교
session_start();
if ($_POST) {
$current_data = serialize($_POST);
// 이전 제출과 동일한지 확인
if (isset($_SESSION['last_submit']) && $_SESSION['last_submit'] === $current_data) {
// 중복 제출 감지
header('Location: already_submitted.php');
exit;
}
// 데이터 처리
processForm($_POST);
// 현재 제출 데이터 저장
$_SESSION['last_submit'] = $current_data;
header('Location: success.php');
exit;
}
문제: 사용자가 여러 번 클릭하는 경우
해결책: 제출 후 버튼 비활성화
<form method="POST" onsubmit="disableSubmit()">
<input type="text" name="name" required>
<button type="submit" id="submitBtn">전송</button>
</form>
<script>
function disableSubmit() {
document.getElementById('submitBtn').disabled = true;
document.getElementById('submitBtn').value = '처리중...';
return true;
}
</script>
문제: 중복 데이터가 DB에 저장되는 경우
해결책: 유니크 키와 예외 처리 조합
try {
$stmt = $pdo->prepare("INSERT INTO users (email, name) VALUES (?, ?)");
$stmt->execute([$email, $name]);
header('Location: success.php');
exit;
} catch (PDOException $e) {
if ($e->getCode() == 23000) { // 중복 키 에러
header('Location: duplicate_error.php');
exit;
}
throw $e;
}