서버 없이 정적 사이트에 문의 폼 만들기

글: beautifulwind · · 기능 추가

정적 사이트에는 폼 데이터를 받아 줄 서버가 없습니다. 하지만 폼 백엔드 서비스를 이용하면 HTML 몇 줄로 이메일로 전달되는 문의 폼을 만들 수 있습니다. Formspree를 예로 들어 설정 방법과, 실제로 운영하면서 챙겨야 할 부분을 정리했습니다.

동작 원리

HTML 폼은 action 속성에 적힌 주소로 입력값을 전송합니다. 보통은 이 주소가 내 서버지만, 폼 백엔드 서비스를 쓰면 그 서비스가 대신 데이터를 받아 저장하고 등록된 이메일로 알려 줍니다. 즉 내 사이트는 여전히 정적 파일뿐이고, "받는 쪽"만 외부에 맡기는 구조입니다.

Formspree 외에도 비슷한 서비스가 여럿 있으며, 무료 요금제의 월간 제출 횟수 한도와 스팸 필터 기능이 서비스마다 다릅니다. 예상 문의량에 맞춰 고르면 됩니다.

가장 단순한 폼

Formspree에 가입해 새 폼을 만들면 https://formspree.io/f/고유ID 형태의 주소를 받습니다. 이 주소를 action에 넣으면 끝입니다.

<form action="https://formspree.io/f/고유ID" method="POST">
            <label for="email">이메일</label>
            <input id="email" name="email" type="email" required>

            <label for="message">문의 내용</label>
            <textarea id="message" name="message" required></textarea>

            <button type="submit">보내기</button>
        </form>

몇 가지를 지키면 사용성이 크게 좋아집니다.

페이지 이동 없이 보내기

기본 방식은 전송 후 Formspree의 감사 페이지로 이동합니다. 내 사이트 안에서 결과를 보여 주고 싶다면 fetch로 보내고 Accept: application/json 헤더를 붙이면 됩니다.

form.addEventListener('submit', function (e) {
            e.preventDefault();
            button.disabled = true;
            status.textContent = '보내는 중...';

            fetch(form.action, {
                method: 'POST',
                body: new FormData(form),
                headers: { 'Accept': 'application/json' }
            }).then(function (res) {
                if (!res.ok) throw new Error();
                form.reset();
                status.textContent = '문의가 접수되었습니다.';
            }).catch(function () {
                status.textContent = '전송에 실패했습니다. 잠시 후 다시 시도해 주세요.';
            }).finally(function () {
                button.disabled = false;
            });
        });

여기서 중요한 점은 두 가지입니다. 첫째, 전송 중에는 버튼을 비활성화해 중복 제출을 막습니다. 둘째, 결과 메시지를 담는 요소에 role="status"를 지정하면 화면 낭독기가 내용이 바뀔 때 자동으로 읽어 줍니다. 자바스크립트가 꺼져 있어도 action 덕분에 폼은 기본 방식으로 여전히 동작합니다.

스팸 막기

공개된 폼에는 언젠가 반드시 스팸이 들어옵니다. 가장 간단한 방법은 사람에게는 보이지 않는 미끼 입력란(허니팟)을 두는 것입니다. 자동화된 봇은 모든 입력란을 채우는 경향이 있어서, 이 칸이 채워진 제출은 스팸으로 걸러낼 수 있습니다. Formspree는 _gotcha라는 이름의 필드를 이 용도로 인식합니다. 이것으로 부족하면 서비스가 제공하는 reCAPTCHA 같은 추가 검증을 켜면 됩니다.

개인정보 고지

이름과 이메일을 받는 순간 개인정보를 수집하는 것입니다. 무엇을, 어떤 목적으로, 얼마나 보관하는지, 그리고 데이터가 외부 서비스(이 경우 Formspree)를 거친다는 사실을 개인정보처리방침에 적어 두세요. 필요한 항목만 받는 것도 중요합니다. 답장에 전화번호가 필요 없다면 입력란을 만들지 않는 것이 가장 좋은 보호 방법입니다.

정리

정적 사이트의 문의 폼은 action 주소 하나로 시작할 수 있습니다. 여기에 레이블 연결, 중복 제출 방지, 스팸 필터, 개인정보 고지까지 더하면 운영하면서 문제가 생길 일이 거의 없습니다. 이 사이트의 문의 페이지도 같은 구성으로 만들어져 있습니다.

댓글