Form ID

Gatsby

하이드레이션 전에도 정적 HTML에서 이미 작동하고, 이후에는 fetch로 향상되는 Gatsby 폼. 시크릿 키로 POST하는 Gatsby Function도 함께 다룹니다.

Gatsby는 빌드 시점에 모든 페이지를 HTML로 렌더링합니다. 폼에 실제 action을 지정하면 React가 하이드레이션되기 전이나 번들 로드에 실패한 경우에도 POST되고, 하이드레이션된 뒤에는 컴포넌트가 fetch로 POST하고 결과를 그 자리에 보여 줍니다.

브라우저에서 POST하기

  1. 폼 ID 추가하기

    .env.production
    GATSBY_IKIFORM_FORM_ID=frm_xxxxxxxxxxxxxxxx

    Gatsby는 GATSBY_로 시작하는 변수만 브라우저 코드에 노출하며, 빌드 시점에 인라인합니다. gatsby develop용으로 .env.development에도 같은 줄을 추가하세요.

  2. 컴포넌트 추가하기

    src/components/contact-form.js
    import * as React from "react";
    
    const endpoint = `https://ikiform.com/f/${process.env.GATSBY_IKIFORM_FORM_ID}`;
    
    export default function ContactForm() {
      const [status, setStatus] = React.useState("idle");
      const [message, setMessage] = React.useState("");
    
      async function onSubmit(event) {
        event.preventDefault();
        setStatus("sending");
        try {
          const response = await fetch(endpoint, {
            method: "POST",
            headers: { Accept: "application/json" },
            body: new FormData(event.currentTarget),
          });
          const result = await response.json();
          if (result.ok) return setStatus("sent");
          setMessage(result.error.message);
        } catch {
          setMessage("Couldn't reach the server. Try again.");
        }
        setStatus("error");
      }
    
      if (status === "sent") return <p>Thanks, we got it.</p>;
    
      return (
        <form action={endpoint} method="post" onSubmit={onSubmit}>
          <label>
            Email
            <input name="email" type="email" autoComplete="email" required />
          </label>
          <label>
            Message
            <textarea name="message" rows={5} />
          </label>
          <input type="hidden" name="_redirect" value="https://example.com/thanks/" />
          <input name="_gotcha" type="text" tabIndex={-1} autoComplete="off" hidden />
          {status === "error" ? <p role="alert">{message}</p> : null}
          <button disabled={status === "sending"}>Send</button>
        </form>
      );
    }

    src/pages/contact.js 같은 아무 페이지에서 렌더링하고, JavaScript 없는 경우의 리디렉션용으로 src/pages/thanks.js를 추가하세요. 필드 오류와 SDK의 사람 확인은 React 가이드처럼 확장하세요.

Gatsby Function에서 POST하기

Gatsby Function은 시크릿 키와 함께 POST를 전달할 수 있으며, 이 경우 허용 도메인과 사람 확인을 건너뜁니다. Gatsby 어댑터를 쓰는 Netlify처럼 Gatsby Functions를 지원하는 호스트에서만 실행되며, GitHub Pages 같은 순수 정적 호스트에서는 실행할 수 없습니다. IKIFORM_FORM_ID와 submissions:write 스코프의 시크릿 키를 IKIFORM_SECRET_KEY로 저장하되, 브라우저에 닿지 않도록 GATSBY_ 접두사 없이 저장하세요.

src/api/contact.js
export default async function handler(req, res) {
  if (req.method !== "POST") return res.status(405).end();
  const response = await fetch(`https://ikiform.com/f/${process.env.IKIFORM_FORM_ID}`, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Accept: "application/json",
      Authorization: `Bearer ${process.env.IKIFORM_SECRET_KEY}`,
    },
    body: JSON.stringify(req.body),
  });
  res.status(response.status).json(await response.json());
}

Gatsby는 JSON과 폼 인코딩 본문을 req.body로 파싱하므로, 페이지는 어느 형식으로든 /api/contact에 POST할 수 있습니다. 이 경우 모든 POST가 레이트 리밋에서 함수의 IP 주소를 공유합니다. 서버에서 보내기를 참고하세요.

Allowed domains

브라우저 POST에 적용됩니다. Gatsby Function에서 보내는 POST는 시크릿 키를 사용하므로 이 검사를 건너뜁니다.

폼이 실행되는 곳Allowed domains에 추가할 값
gatsby develop과 gatsby servelocalhost. http://localhost:8000과 http://localhost:9000에 일치합니다. Ikiform은 포트가 아니라 호스트 이름만 비교합니다.
여러분의 도메인example.com, www.example.com도 포함
Netlifyyour-site.netlify.app. 배포 미리보기(deploy-preview-12--your-site.netlify.app)와 브랜치 배포(branch--your-site.netlify.app)는 하위 도메인이 아니므로, 테스트하는 동안 정확한 미리보기 호스트를 추가하세요.
Cloudflare Pagesyour-project.pages.dev. abc123.your-project.pages.dev 같은 미리보기 URL은 하위 도메인이므로 이미 일치합니다.
  • netlify.app이나 pages.dev만 단독으로 추가하지 마세요. 다른 사람의 사이트를 포함해 그 호스트의 모든 사이트가 일치하게 됩니다.

테스트 체크리스트

  1. gatsby build를 실행하고 public/contact/index.html을 여세요. 폼의 action이 undefined가 아니라 여러분의 폼 ID로 끝나야 합니다.
  2. 허용 도메인에 localhost를 넣고 gatsby serve를 실행해 제출하세요. 감사 메시지가 폼을 대체해야 합니다.
  3. JavaScript를 끄고 새로 고친 뒤 제출하세요. 로컬에서는 Ikiform의 감사 페이지가, https: 도메인에서는 /thanks/가 보여야 합니다.
  4. 함수를 쓴다면 배포 미리보기에서 /api/contact로 POST하고 Ikiform에 제출이 나타나는지 확인하세요.

문제 해결

증상원인해결
404 not_found, action이 /f/undefined로 끝남변수에 GATSBY_ 접두사가 없거나, 빌드 시점에 설정되지 않음GATSBY_IKIFORM_FORM_ID로 이름을 바꾸고 다시 빌드하세요.
함수가 403 forbidden으로 응답함시크릿 키가 다른 워크스페이스의 키이거나, 폐기되었거나, submissions:write가 없음해당 스코프로 시크릿 키를 만드세요.
배포 후 /api/contact가 404를 반환함호스트가 정적 파일만 제공함Gatsby Functions를 지원하는 호스트에 배포하거나 브라우저 버전을 사용하세요.
제출이 origin_mismatch와 함께 스팸 필터에 들어감POST한 페이지가 폼의 허용 도메인에 없음위 표의 호스트를 추가하세요. Reject를 골랐다면 같은 POST가 대신 403 origin_not_allowed를 받습니다.