PHP에서 구글 reCAPTCHA 적용 방법

스팸 방지를 위한 필수 보안 솔루션, 어떻게 구현할까?

게시판에 스팸글이 하루에 3,000개 이상 등록된다는 이야기를 듣고 봇과 자동화 스크립트를 막을 수 있는 방법을 고민하게 되었습니다.

reCAPTCHA는 웹 폼에서 자동화된 스팸을 차단하기 위한 구글의 무료 도구입니다. 특히 회원가입, 로그인, 문의하기 페이지에 적용하면 악의적인 봇의 접근을 효과적으로 방지할 수 있습니다. 이 글에서는 PHP 환경에서 reCAPTCHA v2를 적용하는 단계별 절차를 실제 코드와 함께 알아가 보겠습니다.

reCAPTCHA란 무엇이며 왜 사용해야 할까?

reCAPTCHA는 사용자가 사람인지 컴퓨터인지를 판단하는 구글의 기술입니다. v2는 체크박스 방식이며, v3는 사용자 행동을 기반으로 점수를 산정하는 방식입니다. “봇으로 인한 스팸을 막는 가장 쉬운 방법”으로 전 세계 수많은 사이트에서 채택되고 있습니다. 여기서는 v2 방식(체크박스)으로 진행을 하겠습니다.

구글 reCAPTCHA 사이트 등록하기

먼저 구글 reCAPTCHA 공식 사이트(https://cloud.google.com/security/products/recaptcha) 접속합니다. 그리고 검은색 박스에 내용을 모조리 입력 및 클릭을 해줍니다.

라벨, recaptcha유형, 도메인, 프로젝트 이름과 약관에 동의해줍니다.

사이트 키와 비밀 키를 복사한 뒤에 PHP코드에 저장합니다. 저는 바닐라 PHP를 사용해서 .env대신 common에 difine을 활용하여 상수로 저장을 하였습니다.

reCAPTCHA 위젯 자동 렌더링하기

<html>
  <head>
    <title>reCAPTCHA demo: Simple page</title>
    <script src="https://www.google.com/recaptcha/api.js" async defer></script>
  </head>
  <body>
    <form action="?" method="POST">
      <div class="g-recaptcha" data-sitekey="<?= RECAPTCHA_SITE_KEY ?>"></div>
      <input type="submit" value="Submit">
    </form>
  </body>
</html>

head태그 안에 <script src=”https://www.google.com/recaptcha/api.js” async defer></script> 스크립트를 추가하고 사용한 form 태그 안에 <div class=”g-recaptcha” data-sitekey=”your_site_key”></div>추가해줍니다.

recaptcha이 잘 나옵니다. 적용할 태그의 위치와 CSS는 알맞게 수정을 해줍니다.

JavaScript에서 reCAPTCHA 체크 여부 확인하는 방법

웹사이트에서 봇의 접근을 차단하기 위해 reCAPTCHA를 적용했더라도, 사용자가 실제로 체크했는지 확인하지 않으면 의미가 없습니다. reCAPTCHA를 추가한 것만으로 스팸을 방지했다고 생각할 수 있지만 사용자가 체크박스를 클릭하지 않은 채 폼을 제출할 수도 있기 때문에 JavaScript로 클라이언트 측에서 응답 값을 사전에 검증하는 절차가 필수입니다. 서버 측 검증은 마지막 보루이며, 클라이언트에서는 UX를 위한 사전 확인을 꼭 적용해야 합니다.

function boardSummit() {
    let response = grecaptcha.getResponse();
        if (response.length === 0) {
            alert("reCAPTCHA를 체크해 주세요.");
        return false; // 폼 전송 막기
    }
}

핵심은 response.length === 0은 사용자가 reCAPTCHA를 클릭하지 않았음을 의미합니다.

reCAPTCHA 서버 검증: 클라이언트 확인 후 보안을 완성하는 PHP 로직

reCAPTCHA를 적용했다면, 서버 검증은 선택이 아닌 필수입니다. 사용자가 reCAPTCHA를 통과했다고 해도 그것이 곧 ‘정상 요청’이라는 보장은 없습니다. JavaScript에서의 클라이언트 검증은 사용자 경험 향상용일 뿐, 보안 측면에서는 한계가 있습니다. PHP로 서버에서 reCAPTCHA 응답을 안전하게 검증하는 코드와 로직의 의미를 알아보겠습니다.

클라이언트 검증만으로는 부족한 이유

JavaScript는 사용자의 브라우저에서 동작하기 때문에 누구나 콘솔을 통해 스크립트를 우회하거나 조작할 수 있습니다. 따라서 사용자가 실제로 reCAPTCHA를 통과했는지 구글 서버에 확인하는 절차가 필수입니다.

서버 검증의 전체 흐름

구글이 제공하는 https://www.google.com/recaptcha/api/siteverify 주소로 POST 요청을 보내고, 응답 결과 중 success 값을 확인합니다.

단계설명비고
응답 수집POST로 넘어온 g-recaptcha-response 값 확인클라이언트에서 전송
서버 요청구글 서버에 secret, response, remoteip 포함 전송PHP로 요청
응답 분석JSON 응답에서 success 값 추출true/false 반환

PHP 서버 검증 코드

PHP에서 서버 검증을 수행하는 예시 코드입니다. 여러곳에서 사용하기 때문에 함수형 구조로 작성되어 있습니다.

function verifyRecaptcha($recaptchaResponse) {
    $secretKey = RECAPTCHA_SECRET_KEY;
    $remoteIp = $_SERVER['REMOTE_ADDR'];

    if (!$recaptchaResponse) return false;

    $url = 'https://www.google.com/recaptcha/api/siteverify';

    $postData = [
        'secret'   => $secretKey,
        'response' => $recaptchaResponse,
        'remoteip' => $remoteIp
    ];

    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_TIMEOUT, 10);
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));

    $response = curl_exec($ch);

    if (curl_errno($ch)) {
        error_log('reCAPTCHA cURL error: ' . curl_error($ch));
        curl_close($ch);
        return false;
    }

    curl_close($ch);

    $result = json_decode($response);
    return $result && isset($result->success) && $result->success === true;
}

// 호출해서 사용하는 소스코드
require_once 're_captcha.php';
if (!isset($_POST['g-recaptcha-response']) || !verifyRecaptcha($_POST['g-recaptcha-response'])) {
	echo "<script>alert('reCAPTCHA 인증을 실패하였습니다.')</script>";
	exit;
}

reCAPTCHA 검증, 보안과 신뢰를 위한 마지막 관문

자동화 공격을 막는 진짜 핵심은 ‘서버 검증’입니다. reCAPTCHA는 웹사이트 보안을 위한 강력한 도구입니다. 하지만 단순히 폼에 추가하는 것만 로는 완벽한 방어가 되지 않습니다. 클라이언트 측 JavaScript 검증은 사용자 편의를 위한 1차 필터일 뿐, 궁극적인 신뢰는 서버 측 검증을 통해 완성되어야 합니다.

마지막으로 정리하면 다음 한 줄이 핵심입니다. “보안은 폼에 넣는 순간이 아니라, 서버가 응답을 신뢰하는 순간 완성된다.”