임베드 전용 접근 설정하기
설문 링크를 통한 직접 접속을 제한하고, 웹사이트에 임베드된 설문에서만 응답을 받는 방법을 안내합니다.
설정 방법
임베드 전용 접근 켜기
임베드 전용 접근을 켜면 세 가지 모드 중 하나를 고를 수 있습니다.
| 모드 | 막아주는 것 | 준비해야 할 것 | 플랜 |
|---|---|---|---|
| 허용한 사이트에서만 | 허용 목록 밖 사이트의 임베드, 링크 직접 접속 | 허용 origin | Pro |
| 호스트 서명 토큰 | 위 + 브라우저가 아닌 요청 | 허용 origin, 서명 시크릿, 호스트 서버 연동 | Enterprise |
| 호스트 서명 토큰 + 회원 식별 | 위 + 회원 단위 중복 응답 | 위 + 토큰에 회원 ID 포함 | Enterprise |
1. 허용한 사이트에서만
브라우저에서 허용 외 사이트 임베드와 직접 접속을 막습니다. 설정이 가장 간단합니다. 다만 서버 간 요청은 같은 헤더를 흉내 낼 수 있습니다. 응답자가 누구인지 확인해야 한다면 아래 서명 모드를 사용하세요.

2. 호스트 서명 토큰
서버가 서명한 토큰이 있어야만 폼이 열립니다. 브라우저가 아니어도 마찬가지입니다. 헤더를 흉내 내는 방식으로는 통과할 수 없어요.

3. 호스트 서명 토큰 + 회원 식별
토큰에 담긴 회원 ID까지 사용해 중복 응답을 회원 단위로 막습니다.
이 모드를 사용하면 응답자 탭의 중복 응답 요약에 "외부 회원 ID"가 기준으로 함께 표시됩니다. 응답자에게 별도의 이메일·전화번호 인증을 요구하지 않고도 한 회원당 한 번만 응답받을 수 있습니다.

허용 origin 입력하기
설문을 임베드할 사이트의 주소를 입력합니다.

- 스킴과 호스트만 입력하세요.
https://your-site.com - 끝 슬래시나 경로는 넣지 않습니다.
https://your-site.com/survey는 잘못된 입력이에요.
주의사항
허용한 사이트에서만 모드는 origin을 하나 이상 추가해야 게이트가 적용됩니다. 비어 있으면 제한이 걸리지 않으니 반드시 확인하세요.
서명 시크릿 발급하기
서명 모드를 고르면 서명 시크릿 영역이 나타납니다. 호스트 서버가 토큰에 서명할 때 사용하는 값입니다.

1. 처음 발급할 때
시크릿 발급을 누르면 시크릿 값이 화면에 한 번 표시됩니다. 바로 복사를 눌러 호스트 서버의 환경변수 등 안전한 곳에 보관하세요.
주의하세요
이 값은 다시 표시되지 않습니다. 복사하지 못했다면 재발급해야 하며, 재발급 시 기존 토큰은 즉시 사용할 수 없게 됩니다.
2. 재발급할 때
시크릿이 이미 있는 경우 버튼이 시크릿 재발급으로 바뀝니다. 누르면 확인 창이 나타납니다.
재발급하면 다음과 같이 동작합니다.
- 현재 시크릿으로 서명한 토큰이 즉시 거부됩니다.
- 임베드 토큰을 서명하는 모든 호스트를 새 시크릿으로 교체해야 합니다.
- 이미 열린 세션은 만료(최대 2시간)까지 유지됩니다.
호스트 서버 배포 준비를 마친 뒤 재발급하세요. 순서가 어긋나면 그 사이에 응답자가 폼을 열지 못합니다.
호스트 서버 연동
서명 모드에서는 호스트 서버가 방문자마다 짧은 수명의 JWT 토큰을 만들어 임베드에 전달해야 합니다.
| 용어 | 뜻 |
|---|---|
| 서명 시크릿 | 폼마다 하나씩 발급되는 값입니다. 호스트 서버가 이 값으로 토큰을 서명합니다. |
| 토큰 | 호스트 서버가 방문자마다 서명해서 만드는 짧은 수명의 JWT입니다. |
서명 시크릿 보관하기
복사한 시크릿을 호스트 서버의 환경변수에 저장합니다.
WALLA_EMBED_SECRET=여기에_복사한_값주의사항
서명 시크릿을 브라우저 번들, 프론트엔드 코드 또는 저장소에 넣지 마세요. 값이 노출되면 누구나 토큰을 위조할 수 있습니다. 시크릿은 폼마다 다르므로 여러 폼을 임베드한다면 폼별로 따로 보관해야 합니다.
토큰 서명하기
방문자가 페이지를 열 때마다 서버에서 토큰을 새로 서명합니다. 아래는 jose를 사용한 예시입니다.
import { SignJWT } from 'jose';
const secret = new TextEncoder().encode(process.env.WALLA_EMBED_SECRET);
const token = await new SignJWT({ email: user.email })
.setProtectedHeader({ alg: 'HS256' })
.setSubject(user.id) // 회원 식별 모드에서 필수
.setAudience('{formId}') // 왈라 폼 ID
.setExpirationTime('5m')
.sign(secret);호스트 서명 토큰 모드에서는 .setSubject(...)가 필요하지 않습니다. 호스트 서명 토큰 + 회원 식별 모드에서는 회원 ID를 sub에 반드시 넣어야 합니다.
토큰 규칙
| 항목 | 요구 사항 |
|---|---|
alg | HS256만 사용할 수 있습니다. |
| 서명 키 | 서명 시크릿 문자열의 UTF-8 바이트를 사용합니다. |
aud | 폼 ID와 같아야 합니다. 배열이라면 폼 ID를 포함해야 합니다. |
exp | 필수이며, 최대 10분 뒤까지만 허용됩니다. 권장 수명은 5분입니다. |
sub | 회원 식별 모드에서 필수이며 255자 이하여야 합니다. |
email | 선택 사항입니다. |
| 인코딩 | base64url 문자(A-Za-z0-9_-)를 사용합니다. |
iframe에 토큰 전달하기
대시보드의 공유 → 코드 임베드에서 기본 임베드 코드를 복사할 수 있습니다.
서명 모드
토큰은 URL fragment(#)로 전달합니다.
<iframe
src="https://폼주소/f/{formId}#embedToken=서명한_토큰"
width="100%"
height="500"
style="border:0"
loading="lazy">
</iframe>주의사항
토큰을 쿼리스트링(?embedToken=)으로 보내지 마세요. 쿼리스트링은 서버 접근 로그와 Referer 헤더에 남을 수 있습니다. 반드시 fragment(#embedToken=)를 사용하세요.
허용한 사이트에서만 모드
이 모드에는 토큰이 필요하지 않습니다.
<iframe
src="https://폼주소/f/{formId}"
width="100%"
height="500"
style="border:0"
loading="lazy">
</iframe>허용 origin에는 https://your-site.com처럼 스킴과 호스트만 입력합니다. 끝 슬래시나 경로는 넣지 마세요.
통과 후 세션
게이트를 한 번 통과하면 결과가 2시간 동안 유지됩니다. 이 시간에는 응답자가 새 토큰 없이 화면을 새로고침할 수 있습니다.
연동 흐름
서명 모드에서는 다음 순서로 폼이 열립니다.
- 사용자가 우리 서비스에 로그인했는지 확인합니다.
- 발급받은 서명 시크릿으로 토큰을 서명합니다. 회원 식별 모드라면 토큰에 회원 ID를 함께 담습니다.
- 서명한 토큰을 URL fragment에 실어 폼을 엽니다.
- 왈라가 토큰의 서명과 origin을 검증한 뒤 폼을 표시합니다.
문제 해결
배포 전 체크리스트
- 사용하려는 모드가 현재 플랜에서 지원되는지 확인했습니다.
- 허용 origin에 스킴과 호스트만 입력했습니다.
- 서명 시크릿을 호스트 서버 환경변수에만 저장했습니다.
- 토큰을 요청마다 새로 만들고 수명을 5분으로 설정했습니다.
-
aud에 올바른 폼 ID를 넣었습니다. - 회원 식별 모드의 토큰에
sub를 넣었습니다. - iframe이 토큰을 fragment(
#embedToken=)로 전달합니다. - 실제 임베드 페이지에서 폼이 정상적으로 열리고 제출되는지 확인했습니다.
이런 경우에 사용해요
- 사내 포털이나 회원 페이지에 설문을 임베드했는데, 링크가 외부로 새는 것을 막고 싶을 때
- 우리 서비스 회원만 응답할 수 있어야 할 때
- 회원 한 명당 한 번만 응답하게 하고 싶은데, 이메일 인증을 따로 시키기는 번거로울 때
