웹 사이트를 이용하다 보면 '로봇이 아닙니다' 하는 문구와 함께
신호등을 선택한다거나 문자를 입력하는 절차를 종종 거치게 된다.
이러한 부분은 웹사이트를 공격하는 봇으로 부터 내 웹사이트를 보호하고자 하는 절차인데
비밀번호를 유출하거, 스팸을 작성하는 등의 공격을 당할 수 있기 때문에
유저의 정보가 관리되는 서비스라고 한다면 이러한 안전장치는 반드시 필요할 것 같다.
그래서 이번에 우리 서비스에서는 google에서 제공하는 reCAPTCHA를 적용하기로 했다.
Init Setting
아래 참고자료 링크를 통해 접근하게 되면 새 프로젝트를 만들어야 하는데
이 프로젝트를 만들 두 개의 key를 발급 받을 수 있다.
기존 v2는 우리가 봤던 것 처럼 유저가 직접 봇인지 아닌지를 판단하도록 문제를 내는데
v3에서는 그런 과정없이 자체적으로 점수를 세분화해 평가하는 방식인 것 같다.
// .env
NEXT_PUBLIC_RECAPTCHA_KEY=
NEXT_PUBLIC_SECRET_RECAPTCHA_KEY=
발급받은 키는 환경변수에 이런 식으로 지정해 놓고 사용하자
만약 next 환경이 아닌 다른 환경이라면 그 프레임워크에 맞는 방식으로 적용해야한다.
npm install react-google-recaptcha-v3
공식 문서에서는 자바스크립트 코드를 이용해서 적용하도록 하고 있는데
이것도 라이브러리가 있어서 냉큼 설치했다 ㅋㅋㅋ
아래 참고 자료의 링크를 통해서 들어가면 해당 라이브러리에 대한 사용 정보를 볼 수 있는데
이것도 provider를 만들고 사용하고자 하는 컴포넌트를 감싸주면 적용할 수 있겠다.
"use client";
import React, { ReactNode } from "react";
import { GoogleReCaptchaProvider } from "react-google-recaptcha-v3";
const GoogleCaptchaWrapper = ({ children }: { children: ReactNode }) => {
const recaptchaKey = process.env.NEXT_PUBLIC_RECAPTCHA_KEY as string;
return (
<GoogleReCaptchaProvider reCaptchaKey={recaptchaKey}>
{children}
</GoogleReCaptchaProvider>
);
};
export default GoogleCaptchaWrapper;
이번 provider는 구성이 매우 간단했다.
recaptchaKey만 잘 넣어주면 될 것 같다.
// layout.tsx
<html lang="en">
<head>
<Script
async
src={`https://www.google.com/recaptcha/enterprise.js?render=${process.env.NEXT_PUBLIC_RECAPTCHA_KEY}`}
/>
</head>
...
</html>
그렇게 하고 끝이 아니라 layout 파일에 script 하나를 추가해 줘야 하는데
이런식으로 적용해 주면 되겠다.
Route Setting
그럼 그렇지 잘 될리가 없지, 그냥 되는줄 알았잖아
근데 이번에 글을 쓰면서 찾아보니 완전 혼종으로 구현해 놔버렸다..!
라이브러리는 react를 쓰면서 적용한 route.ts는 next 버전으로 구현했는데 돌아간다...?
아무튼 route.ts를 적용한 방법을 정리해 보려고 한다...ㅋㅋ
// app/api/recaptchaSubmit/route.ts
import { NextResponse } from "next/server";
import axios from "axios";
export async function POST(request: Request, response: Response) {
const postData = await request.json();
let res: any;
const formData = `secret=${process.env.NEXT_PUBLIC_SECRET_RECAPTCHA_KEY}&response=${postData}`;
try {
res = await axios.post(
"https://www.google.com/recaptcha/api/siteverify",
formData,
{
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
}
);
} catch (e) {
console.log("recaptcha error:", e);
}
if (res && res.data?.success && res.data?.score > 0.5) {
return NextResponse.json({
success: true,
score: res.data?.score,
});
} else {
return NextResponse.json({ success: false, score: res.data?.score });
}
}
위의 코드는 아래 참고 자료에 있는 Demo 페이지에서 가져온 코드다.
구글에서 계속 자료들을 찾고 있었는데, 아무리 자료가 나오지 않아서 고민하다가
구글 리캡챠를 next.js에 적용한 것을 데모로 공개한 분의 github이 있어서 한참 코드를 보면서
내 프로젝트에서 필요한 부분만 가져왔다.
여기 코드 중 score에 대한 부분이 있는데 이 score가 1에 가까울수록 인간의 행동과 유사하다고 판단이 된다고 한다
그래서 0.5는 기준을 좀 러프하게 잡은 편인데 가장 무난한 점수가 아닐까 싶다.
실제 적용
이렇게 route.ts까지 설정해주고 이제 reCAPTCHA가 일 할 수 있도록 해줘야 한다.
실제 적용에 대한 가이드는 위의 영상에서 확인할 수 있는데 설치부터 적용까지 깔끔하게 잘 정리가 되어있었다.
import { useGoogleReCaptcha } from "react-google-recaptcha-v3";
...
const { executeRecaptcha } = useGoogleReCaptcha();
const checkRecaptcha = async () => {
if (!executeRecaptcha) {
return;
}
const gRecaptchaToken = await executeRecaptcha("inquiryVote");
const response: any = await axios.post(
"/api/recaptchaSubmit",
gRecaptchaToken,
{
headers: {
Accept: "application/json, text/plain, */*",
"Content-type": "application/json",
},
}
);
};
...
실제 내 프로젝트에서는 위와 같이 적용했다.
적용할 때 하나 문제가 있었는데 Next app router에서 fetch를 써도 캐시를 이용할 수 있다고 해서
대부분의 통신은 fetch로 진행했었는데, 해당 부분도 fetch로 하면 되겠지 했다가
계속 리캡챠를 인식하지 못하는 에러가 있었는데, 이 부분을 axios로 적용하니까 바로 됐다..
아이콘 안보이게 하기
리캡챠를 적용하면 실제 페이지에 이런 아이콘이 나오게 되는데,
UI를 가리는 형태로 나오게 되는 경우가 있어서 해당 아이콘을 가리는 방법도 있는데 이건 css로 설정할 수 있다
.grecaptcha-badge {
visibility: hidden;
}
이것처럼 hidden을 주면 안보이도록 설정할 수 있다 ㅎㅎ
참고 자료
'Develop > librarys' 카테고리의 다른 글
[Saida Lab] Amplitude 적용하기 (0) | 2024.03.18 |
---|---|
[Saida Lab] Framer-motion 적용하기 (3) | 2024.03.14 |