App Check를 붙인 뒤 사이트가 비어 보이고 콘솔에 API_KEY_HTTP_REFERRER_BLOCKED 403이 뜬다면, 원인은 App Check가 아니라 Browser key 웹사이트 목록에 새 도메인이 빠진 경우가 많아요. Google Cloud 사용자 인증 정보에서 Browser key에 내 도메인을 추가하고 5분쯤 기다리세요. AI Logic이 “deactivated” 오류를 내면 App Check 기준 보호를 적용하고, 반영된 뒤 다시 시도하세요.
아래는 App Check를 켜고 다시 배포했더니 사이트가 텅 비어 보이고, 나중에는 AI 생성까지 멈췄던 실제 경험을 순서대로 정리한 기록이에요. 화면을 하나씩 따라 하면 같은 문제를 스스로 풀 수 있습니다.
가이드 정보
- 난이도: 초보자
- 예상 시간: 약 1시간 (설정 반영을 기다리는 시간 약 20분 포함)
- 준비물: 4개
- 확인 날짜: 2026-09-29
- 예시 환경: 프로젝트
내-프로젝트-id(여러분의 Firebase 프로젝트 ID로 바꿔 읽으세요), 사이트bluel.moonlang.com, React + Vite + Firebase
목차
- 증상별 빠른 찾기
- 0. 이 튜토리얼로 할 수 있는 것
- 1. App Check가 뭔가요?
- 2. reCAPTCHA Enterprise 키는 어떻게 만드나요?
- 3. Firebase 콘솔에서 App Check 등록
- 4. 코드에 App Check 연결하기
- 5. 403 API_KEY_HTTP_REFERRER_BLOCKED는 왜 뜨나요?
- 6. Browser key에 도메인은 어떻게 추가하나요?
- 7. 확인하기
- 8. AI Logic “deactivated” 오류는 어떻게 고치나요?
- 9. 적용 뒤 localhost 개발은 어떻게 하나요? (주의할 점)
- 10. 체크리스트, 자주 막히는 곳
- 공식 문서
증상별 빠른 찾기
이미 문제가 생겼다면 여기서 내 증상을 찾고, 오른쪽 링크로 바로 가세요.
| 증상 | 원인 | 바로 가기 |
|---|---|---|
배포 후 공개 목록이 비고 “로그인 필요”만 보임, 콘솔에 API_KEY_HTTP_REFERRER_BLOCKED 403 |
Browser key 웹사이트 제한에 새 도메인이 없음 | 6단계 |
| 키 저장 시 API 제한 제거 경고, UPDATE 입력 요구 | 다른 키(예: Gemini Developer API key)를 고치는 중일 가능성(제 경우) | 6단계 흔한 실수 |
콘솔에 API_KEY_SERVICE_BLOCKED 403 |
Browser key의 API 제한 목록에 필요한 API가 빠짐 | 6단계 API 제한 |
| App Check를 설정했는데 메트릭에 확인된 요청이 0 | 코드 미반영(빌드·배포 안 함) 또는 환경변수 누락 | 4단계 |
| “Firebase AI Logic has been deactivated … you must enforce Firebase App Check” | AI Logic에 App Check 적용이 필수로 바뀌는 중 | 8단계 |
| 적용 후에도 “오래된 클라이언트 요청”만 늘어남 | 옛 캐시 번들, 또는 토큰을 붙이지 않는 코드 | 8단계 저장한 뒤에 |
| 재생 보호 적용 후 AI 요청이 전부 막힘 | limited-use 토큰을 쓰는 코드가 없음 | 8단계 틀리면 |
| 적용 후 localhost 개발이 막힘 | localhost는 유효한 기기로 인정되지 않음. 디버그 제공자가 필요 | 9단계 1번 |
| fetch로 부른 내 함수·백엔드가 토큰 검사에서 거부함 | X-Firebase-AppCheck 헤더를 직접 붙이지 않음 |
9단계 3번 |
0. 이 튜토리얼로 할 수 있는 것
다 읽고 따라 하면 이런 걸 할 수 있어요.
- 내 Firebase 웹앱에 App Check(출입증 확인)를 처음부터 붙이기
- 배포 뒤 사이트가 비어 보이는
API_KEY_HTTP_REFERRER_BLOCKED403 오류 고치기 - “Firebase AI Logic has been deactivated” 오류가 났을 때 AI Logic에 App Check 적용하기
전체 흐름 한눈에 보기

상자 앞 숫자가 이 글의 단계 번호예요. 위에서 아래로 따라가면 되고, 빨간 점선과 EX 구역은 “막혔을 때” 가는 길이에요. 왼쪽 위 구역 번호(01·02·04)와 범례는 그림 도구가 붙인 분류라 신경 쓰지 않아도 돼요.
준비물
- Firebase 프로젝트와, 거기에 등록된 웹 앱 1개
- Google Cloud 콘솔에 들어갈 수 있는 같은 구글 계정 (Firebase 프로젝트는 Google Cloud 프로젝트이기도 해요)
- React + Vite 같은 웹앱 코드와, 다시 빌드해서 배포할 수 있는 환경
- 내 사이트 주소 (예:
bluel.moonlang.com)
시간은 넉넉히 1시간쯤 잡으세요. 설정이 반영되기를 기다리는 구간(5분, 15분)이 있어요. 403만 고치면 되는 분은 5–7단계만 보면 돼서 훨씬 짧아요.
1. App Check가 뭔가요?
목표: App Check가 무엇을 막아 주는지, 왜 순서가 “키 → 등록 → 코드”인지 설명할 수 있어요.
App Check는 건물 출입증이라고 생각하면 쉬워요. Firebase(데이터베이스, 로그인, AI 같은 서비스)는 건물이고, 내 웹앱은 직원이에요. 출입증이 없던 시절엔 누구든 “저 직원이에요” 하고 들어올 수 있었죠. App Check를 켜면, 요청할 때마다 “진짜 우리 앱에서 온 요청”이라는 출입증(토큰)을 같이 보여줘야 해요.
- 내 웹앱: 사람이 쓰는 진짜 앱
- reCAPTCHA Enterprise: “진짜 내 사이트에서 온 요청 맞아요” 신원 확인만 맡아요
- App Check: 그 확인 결과를 보고 출입증(App Check 토큰, 기본 유효시간 1시간)을 발급해요
- Firebase 서비스: 출입증 확인 후 통과
정리하면 reCAPTCHA Enterprise는 신원을 확인하는 경비원이고, 출입증은 App Check가 발급해요. 그래서 순서가 reCAPTCHA 키 만들기 → App Check에 등록 → 코드에서 출입증 받기가 됩니다.
알아두면 좋은 말 2가지
모니터링(콘솔 표기: 적용되지 않음(모니터링만)): 출입증을 검사만 하고 막지는 않는 상태. 누가 출입증 없이 오는지 숫자로만 봐요.
적용(Enforce): 출입증 없으면 실제로 막는 상태. 이미 사용자가 있는 앱에서 바로 적용하면 옛 버전 앱이 막힐 수 있어서, 보통은 모니터링으로 먼저 지켜봐요.
✅ 이해했다면 “모니터링은 세기만, 적용은 실제로 막기”를 내 말로 말할 수 있어요.
↩️ 헷갈리면 위 목록을 위에서부터 다시 읽고, 2단계로 넘어가도 괜찮아요. 해 보면 더 잘 보여요.
2. reCAPTCHA Enterprise 키는 어떻게 만드나요?
목표: 내 사이트 주소가 들어간 reCAPTCHA 웹 키를 만들고 사이트 키를 복사해 둡니다.
App Check가 “진짜 내 사이트”인지 판정하려면 이 키가 먼저 있어야 해요.
Google Cloud 콘솔에서 reCAPTCHA 메뉴로 가서 키 만들기를 누릅니다. 화면에 “Fraud Defense”라고 보일 수 있는데, 공식 문서에 따르면 reCAPTCHA Enterprise는 Google Cloud Fraud Defense에 포함된 기능이에요. 화면 위쪽 프로젝트 선택기에서 올바른 프로젝트인지 먼저 확인하세요.
- 표시 이름: 알아보기 쉬운 이름을 넣어요. 예:
web-app-check-key - 애플리케이션 유형: 웹을 고릅니다. 화면 안내대로, 만든 뒤에는 바꿀 수 없어요.
- 도메인 목록: 옆의 도메인 확인 사용 중지 토글은 켜지 말고 꺼 둔 채로 둡니다. Google Cloud 문서는 이 토글을 켜면 사이트 제한이 사라져 누구나 키를 쓸 수 있는 보안 위험이 생긴다고 설명해요. 그다음 이 키를 쓸 실제 서비스 주소를 하나씩 추가해요.
- 내 도메인:
bluel.moonlang.com - Firebase 기본 주소(쓰고 있다면):
내-프로젝트-id.web.app,내-프로젝트-id.firebaseapp.com
- 내 도메인:
- 체크박스 문제(Use checkbox challenge)는 선택하지 않고 점수 기반(score-based) 키로 둡니다. App Check는 점수 기반 키만 쓰기 때문에 사용자가 퍼즐을 풀 필요가 없어요. (아래 화면에는 이 칸이 보이지 않아요.)
- Create key를 누르고, 생성된 사이트 키를 복사해 둡니다.
localhost는 reCAPTCHA 키에 넣지 마세요
Firebase 공식 문서는 배포용 reCAPTCHA 키의 도메인에
localhost를 추가하지 말라고 경고해요. 그렇게 하면 누구든 자기 컴퓨터에서 내 앱을 돌려 통과할 수 있기 때문이에요. 내 컴퓨터에서 개발할 때는 9단계의 디버그 토큰을 쓰세요.

화면에서 볼 곳: 맨 위 표시 이름 → 애플리케이션 유형 “웹” → “도메인 확인 사용 중지” 토글은 꺼진 상태 그대로 → 도메인 목록에 도메인 추가 → 맨 아래 Create key. 오른쪽 요약에서 자물쇠 표시된 값은 나중에 못 바꿔요.
비용 참고
Firebase 문서에 따르면 reCAPTCHA Enterprise는 매월 평가 1만 건까지 무료이고, 그 뒤로는 비용이 나와요. App Check 라이브러리는 토큰 유효시간(TTL)의 절반쯤마다 토큰을 새로 받으니, 기본 TTL 1시간이면 사용자 한 명이 사이트를 계속 쓰는 동안 시간당 2번쯤 갱신해요. 무료 Spark 요금제에서는 쓸 수 있는 reCAPTCHA 점수 단계가 일부로 제한돼요.
사이트 키는 공개돼도 괜찮아요
reCAPTCHA 사이트 키는 원래 브라우저 코드에 들어가는 값이에요. 다만 서버용 비밀 키나 서비스 계정 파일은 절대 프런트엔드 코드에 넣으면 안 됩니다.
✅ 이렇게 보이면 성공 키 목록에 새 키가 생기고, 사이트 키를 복사해 뒀어요.
↩️ 아니면 유형을 “웹”으로 골랐는지 보세요. 잘못 만들었다면 새로 만드는 게 빨라요.
3. Firebase 콘솔에서 App Check에 웹 앱 등록
목표: 내 웹 앱의 App Check 상태를 “등록됨”으로 만들어요.
Firebase가 2단계에서 만든 키를 알아야 출입증을 확인할 수 있어요.
- Firebase 콘솔에서 보안(Security) → App Check로 들어가 앱 탭을 엽니다.
- 내 웹 앱 줄을 펼쳐서 증명 제공업체로 reCAPTCHA Enterprise(화면에는 “Fraud Defense(이전 명칭: reCAPTCHA Enterprise)”)를 고릅니다.
- 2단계에서 복사한 사이트 키를 붙여넣어요.
- 토큰 TTL(출입증 유효시간)은 기본값 1시간 그대로 둡니다. 공식 문서는 30분에서 7일 사이로 바꿀 수 있지만 대부분의 앱에는 1시간이 적당하다고 안내해요.
- 저장하면 상태가 “등록됨”으로 바뀝니다.

화면에서 볼 곳: 앱 탭 → 증명 제공업체(Fraud Defense) → 사이트 키 입력칸 → 토큰 TTL 1시간 → 오른쪽 상태. 등록 전이라 상태가 “등록되지 않음”으로 보여요. (프로젝트 이름은 가렸어요.)
처음엔 적용(Enforce)을 서두르지 마세요
등록만 하고 API 탭의 각 서비스(Firestore, Authentication 등)는 모니터링 상태로 둡니다. 코드가 출입증을 제대로 붙이는지 숫자로 확인한 다음에 적용해도 늦지 않아요. 단, 아직 출시하지 않은 앱이라면 공식 문서는 바로 적용하는 것을 권해요(막힐 옛 버전 사용자가 없으니까요).
✅ 이렇게 보이면 성공 웹 앱 줄의 상태가 “등록됨”이에요.
↩️ 아니면 사이트 키 칸의 빨간 안내를 보세요. 키를 앞뒤 공백 없이 다시 붙여넣어요.
4. 코드에 App Check 연결하기
목표: 앱이 실제로 출입증을 받아 오도록 코드와 환경변수를 넣고, 다시 빌드·배포해요.
콘솔 설정만으로는 아무 일도 안 일어나요. 앱이 실제로 출입증을 받아 오도록 코드에 몇 줄 넣어야 합니다. Firebase를 초기화하는 파일(예: src/firebase.ts)에 추가해요.
1 | import { initializeApp } from "firebase/app"; |
공식 문서도 App Check 초기화 코드를 다른 Firebase 서비스에 접근하기 전에 실행하라고 안내하고, 토큰 자동 갱신은 isTokenAutoRefreshEnabled: true로 직접 켜야 한다고 적고 있어요. 사이트 키는 코드에 직접 쓰지 않고 환경변수로 넣어요.
1 | # 내 컴퓨터: 프로젝트 폴더의 .env.local |
- Vite는 이름이
VITE_로 시작하는 변수만 브라우저 코드에 넣어 줘요. - GitHub Actions 같은 CI로 배포한다면 저장소 Secret에
VITE_RECAPTCHA_SITE_KEY를 추가하고, 빌드 단계에서 환경변수로 넘겨주세요.
반영 순서는 코드 수정(initializeAppCheck) → 환경변수(.env.local / CI Secret) → 다시 빌드(npm run build) → 다시 배포예요.
빌드와 배포를 꼭 다시 하세요
Vite는 빌드할 때
import.meta.env값을 코드에 그대로 바꿔 넣어요. 그래서 키를 바꾸거나 새로 넣었다면 반드시 다시 빌드하고 배포해야 사이트에 반영됩니다.
✅ 이렇게 보이면 성공 배포 뒤 App Check API 탭 메트릭에 확인된 요청이 생기기 시작해요.
↩️ 아니면 확인된 요청이 0이면 환경변수 이름과 재빌드·재배포를 다시 보세요. 사이트가 비어 보이면 5단계로.
5. 403 API_KEY_HTTP_REFERRER_BLOCKED는 왜 뜨나요?
목표: 내 문제가 “API 키 웹사이트 제한” 때문인지 콘솔 오류로 확인해요.
원인을 잘못 짚으면 App Check를 끄는 것처럼 엉뚱한 곳을 고치게 돼요.
App Check를 붙여 새 도메인으로 배포했더니, 로그아웃 상태에서 공개 강의 목록이 안 나오고 “로그인이 필요해요”만 보였어요. 강의 페이지도 자물쇠만 떴습니다.

막힌 상태 1: 공개 강의 자리에 “익명 접속에 실패했습니다” 안내만 보여요.

막힌 상태 2: 강의 페이지가 자물쇠 화면으로만 나와요.
브라우저에서 F12를 눌러 개발자도구 Console 탭을 보면 이런 오류가 있었어요.
1 | 403 PERMISSION_DENIED |
원인
App Check 문제가 아니었어요. Firebase 웹앱이 쓰는 API 키에 “이 웹사이트에서만 쓸 수 있음” 제한(웹사이트 제한)이 걸려 있는데, 그 목록에 새 도메인이 없었던 거예요. 그래서 익명 로그인이 403으로 막혀서, 로그인이 필요한 데이터도 못 불러왔어요.
이 API 키는 Google Cloud 콘솔 API 및 서비스 → 사용자 인증 정보(Credentials)에 있어요. Firebase 공식 문서에 따르면 웹앱용 키는 보통 Browser key (auto created by Firebase)라는 이름으로 자동 생성됩니다.

고칠 키는 아래쪽 Browser key이고, 위쪽 Gemini Developer API key는 이번 문제와 상관없어요. (개인정보 보호를 위해 프로젝트 이름, 클라이언트 ID, 계정 정보는 검게 가렸어요.)
✅ 같은 증상이면 Console에
API_KEY_HTTP_REFERRER_BLOCKED가 보여요. 6단계로 가세요.↩️ 다른 오류라면 증상별 빠른 찾기 표에서 비슷한 줄을 찾아보세요.
6. Browser key에 도메인은 어떻게 추가하나요?
목표: Browser key의 웹사이트 제한 목록에 내 도메인과 개발 주소를 넣고 저장해요.
이 목록에 없는 주소에서 오는 요청은 전부 403으로 막혀요.
- Credentials 화면에서 Browser key (auto created by Firebase) 이름을 눌러요.
- Application restrictions가 Websites로 되어 있는지 봅니다.
- Website restrictions에서 원래 있던 항목은 지우지 말고 새 주소만 추가하세요. Add를 눌러 아래 주소를 넣어요.
- 내 도메인:
bluel.moonlang.com과bluel.moonlang.com/*두 줄 (Google Cloud 문서가 한 도메인의 모든 주소를 허용할 때 권하는 형태예요. 제 스크린샷에는 당시 넣은https://bluel.moonlang.com/*한 줄이 보여요.) http://localhost:5173/*(Vite 개발 서버)
- 내 도메인:
- Firebase Auth 로그인 팝업이나 리디렉션을 쓰면 authDomain(기본값
내-프로젝트-id.firebaseapp.com/*)을, Firebase Hosting 기본 주소를 쓰면내-프로젝트-id.web.app/*도 목록에 남겨 두세요. Firebase 문서에 따르면 authDomain에는 로그인 도우미 코드가 올라가 있어요. - 아래 API restrictions는 건드리지 않고 그대로 둔 채 Save를 누릅니다.
- 화면 안내대로 반영까지 최대 5분쯤 걸릴 수 있어요. 잠깐 기다려요.
참고로 Google Cloud 문서는 웹사이트 제한에서 와일드카드(*)를 하위 도메인이나 경로 자리에만 쓸 수 있고 주소 중간에는 쓸 수 없다고 설명해요.
사이트를 새 도메인으로 옮겼고 구글 로그인을 쓴다면
Firebase 콘솔 Authentication → 설정 → 승인된 도메인에도 새 도메인을 추가하세요. Browser key 웹사이트 목록과는 별개의 설정이에요.
API 제한 목록: 할 것과 하지 말 것
같은 키 화면 아래쪽 API restrictions는 이번 문제에서는 건드리지 않아요. 나중에 정리하더라도 아래를 지키세요.
- 빼지 말 것: Firebase 문서의 필수 API 표에 따르면 Authentication에는 Identity Toolkit API와 Token Service API, App Check에는 Firebase App Check API가 필요해요. 이런 항목을 빼면 로그인과 App Check가 깨질 수 있어요.
- 들어 있으면 안 되는 것: Firebase 문서는 Browser key의 API 제한 목록에 Generative Language API가 있으면 안 된다고 안내해요.
- 콘솔에
API_KEY_SERVICE_BLOCKED403이 보이면, 문서 안내대로 필요한 API가 모두 목록에 있는지 확인하세요.

Add를 누르면 주소 입력칸이 열려요. 한 줄에 주소 하나씩 넣고 Done.

화면에서 볼 곳: Websites 선택 → Add와 두 주소 → 아래 Save → “최대 5분” 안내. (프로젝트 이름은 가렸어요.)
흔한 실수: 다른 키를 고치기
Credentials에는 Gemini Developer API key (auto created by Firebase) 같은 다른 키도 있어요. 이름이 비슷해서 이 키를 고치기 쉬운데, 사이트가 막힌 건 이 키 때문이 아니에요.
- Browser key (auto created by Firebase): 웹사이트가 쓰는 키. 여기에 도메인 추가
- Gemini Developer API key (auto created by Firebase): 예전에 AI Logic용으로 자동 생성된 키예요. 2026년 중반부터 AI Logic은 이 키를 쓰지 않아요. 앱 코드나 .env에 절대 넣지 마세요. 이번 문제와는 상관없어요.
틀리면 이렇게 보여요: 다른 키를 고치는 중
제 경우에는 저장하려는데 “API 제한이 제거됩니다” 같은 경고와 함께 UPDATE를 직접 입력하라고 했을 때, 잘못된 키를 고치고 있었어요. 취소하고 화면 맨 위의 키 이름이 Browser key인지 다시 확인하세요.
틀리면 이렇게 보여요: 주소 모양이 다름
저장하고 5분이 지나도 같은 403이 난다면, 넣은 주소를 다시 보세요.
https와http가 바뀌었거나, 끝의/*가 빠졌거나, 도메인 철자가 다르면 목록과 맞지 않아 계속 막힐 수 있어요.
어떤 키인지 확인하는 법
내 앱 코드의
firebaseConfig.apiKey앞 몇 글자와 Credentials의 Show key로 본 앞부분을 비교하면 확실해요. 다만 키 전체를 채팅이나 스크린샷으로 공유하지는 마세요.
✅ 이렇게 보이면 성공 목록에 두 주소가 들어가고 Save 뒤 5분 안내가 보여요. 7단계로 확인하러 가요.
↩️ 아니면 UPDATE 입력을 요구하면 다른 키예요. 그대로면 자주 막히는 곳: 도메인을 추가했는데도 그대로예요를 보세요.
7. 확인하기
목표: 로그아웃 상태에서도 사이트가 정상으로 보이는지 눈으로 확인해요.
로그인한 상태로 보면 막힌 걸 놓칠 수 있어요. 처음 온 방문자 입장에서 봐야 해요.
- 로그아웃한 상태에서 사이트를 엽니다. (시크릿 창을 쓰면 편해요.)
- 새로고침한 뒤 공개 강의 목록이 보이는지 확인해요.
- 강의 하나를 눌러서 커리큘럼이 나오는지 봅니다.
- F12 → Console에 403이나
API_KEY_HTTP_REFERRER_BLOCKED가 더 이상 없는지 확인해요.

고친 뒤: 로그아웃 상태에서도 공개 강의 목록이 보여요.

고친 뒤: 강의 페이지에 커리큘럼이 정상으로 나와요.
✅ 이렇게 보이면 성공 공개 강의 목록과 커리큘럼이 보이고, Console에 403이 없어요.
↩️ 아니면 5분 더 기다린 뒤 강력 새로고침. 그래도 같으면 6단계의 “틀리면 이렇게 보여요”를 다시 보세요.
8. AI Logic “deactivated” 오류는 어떻게 고치나요?
목표: AI Logic의 App Check를 “기본 - 적용됨 / 재생 - 모니터링”으로 저장해요.
사이트는 살아났는데, 이번엔 AI로 강의를 만드는 기능이 이런 오류를 냈어요(실제로 본 오류 문구의 일부).
1 | Firebase AI Logic has been deactivated ... you must enforce Firebase App Check |
Firebase 공식 문서에 따르면 2026년 11월 2일부터 Firebase AI Logic을 쓰려면 App Check 적용(Enforce)이 필수이고, 그날부터는 자동으로 적용되며 끌 수 없어요. 콘솔 배너에도 같은 날짜가 나와요. 우리 앱은 “등록됨(적용되지 않음)” 상태였습니다. (공식 문서는 2026년 7월 초 이후 콘솔에서 AI Logic을 새로 설정하면 App Check가 자동으로 적용된다고 설명해요. 그 전에 설정한 프로젝트라면 직접 적용해야 합니다.)

AI Logic 화면의 노란 배너와 “등록됨(적용되지 않음)” 표시. (프로젝트 이름은 가렸어요.)
메트릭을 보면 요청 100%가 “확인되지 않음: 오래된 클라이언트 요청”이었고 상태는 “기본 - 모니터링”이었어요. 공식 문서에서 “오래된 클라이언트 요청”은 App Check 토큰이 빠진 요청을 뜻해요.
먼저 확인: 앱이 토큰을 붙이고 있나요?
메트릭에 ‘오래된 클라이언트 요청 100%’로 나오면 앱이 아직 토큰을 붙이지 않는 상태라서, 적용하면 AI 요청은 계속 막혀요. 4단계 코드가 들어간 버전을 먼저 배포하세요. 2026년 11월 2일부터는 자동으로 적용되고 끌 수 없어요.

적용 전: 확인된 요청 0, 오래된 클라이언트 요청 100%.
설정 순서
- Firebase 콘솔 보안(Security) → App Check → API 탭에서 Firebase AI Logic 줄의 설정 메뉴(점 3개 ⋮ 또는 그래프 아래 설정 버튼)를 엽니다.
- 1단계 기준 보호: “적용되지 않음(모니터링만)”과 “적용됨” 중 적용됨을 고르고 계속.
- 2단계 재생 보호: 모니터링만을 고르고 계속.
- 3단계 확인에서 저장합니다.

1단계 기준 보호 “적용됨”: 유효한 App Check 토큰이 없는 요청은 막혀요. 고른 뒤 계속.

2단계 재생 보호 “모니터링만”. 고른 뒤 계속, 그다음 확인 화면에서 저장.
재생 보호는 “적용됨”을 고르지 마세요 (지금은)
재생 보호를 “적용됨”으로 하면 요청마다 새로 발급한 한 번용(limited-use) 토큰만 통과해요. 앱 코드에서 limited-use 토큰 사용을 켜 두지 않았다면 내 앱 요청까지 막혀요. 공식 AI Logic 안내는 limited-use 토큰을 켜기 전까지 재생 보호를 “중지됨”으로 두라고 하고, 콘솔 화면은 “모니터링만”도 고를 수 있게 해 줘요. 저는 차단될 요청을 미리 보려고 “모니터링만”을 골랐어요.
틀리면 이렇게 보여요: 재생 보호까지 적용함
저장 뒤 AI 요청이 전부 막힌다면 재생 보호를 “적용됨”으로 저장했을 가능성이 커요. 같은 메뉴로 들어가 재생 보호를 모니터링만(또는 중지됨)으로 되돌리세요.

저장 후: “기본 - 적용됨 / 재생 - 모니터링”.
저장한 뒤에
- 공식 문서 기준으로 적용이 반영되기까지 최대 15분이 걸릴 수 있어요. 조금 기다립니다.
- 사이트에서 강력 새로고침(Windows
Ctrl+Shift+R, MacCmd+Shift+R)을 해서 옛 코드 캐시를 비워요. - 반영된 뒤에 AI 생성을 다시 시도해 보세요.
- App Check 메트릭에서 확인된 요청이 늘어나면 정상 신호예요.
- 계속 오래된 클라이언트 요청만 쌓인다면, 브라우저가 옛 번들을 쓰고 있거나 배포된 코드가 아직 출입증을 붙이지 않는 거예요. 4단계 코드가 들어간 버전으로 다시 빌드·배포됐는지 확인하세요.
솔직한 현재 상태
이 글을 쓰는 시점에는 적용 설정을 저장한 직후라, AI 생성이 다시 되는 것까지는 아직 확인하지 못했어요. 반영될 때까지 기다린 뒤 다시 시도해서 메트릭과 함께 확인해 주세요.
✅ 이렇게 보이면 설정 완료 AI Logic 상태가 “기본 - 적용됨 / 재생 - 모니터링”이에요. 반영된 뒤 AI 생성을 다시 시도하고, 확인된 요청이 늘어나는지 보세요.
↩️ 아니면 AI 요청이 전부 막히면 위 “재생 보호까지 적용함”을, 오래된 요청만 쌓이면 4단계 재빌드·재배포를 보세요.
9. 적용 뒤 localhost 개발은 어떻게 하나요? (주의할 점)
목표: 적용 뒤에 생기기 쉬운 문제 3가지를 미리 알고 대비해요.
적용은 “출입증 없으면 막기”라서, 내 개발 환경이나 직접 부르는 백엔드도 막힐 수 있어요.
1. 내 컴퓨터(localhost) 개발은 디버그 토큰이 필요해요
공식 문서에 따르면 App Check를 적용한 서비스는 localhost나 CI 환경에서 돌리는 앱을 유효한 기기로 인정하지 않아요. 이럴 땐 디버그 제공자(디버그 토큰)를 써요.
- 개발용 빌드에서만, App Check를 초기화하기 전에 디버그 모드를 켭니다.
- 로컬에서 앱을 열고 브라우저 개발자도구 콘솔에 출력된 디버그 토큰을 복사해요.
- Firebase 콘솔 보안 → App Check → 앱 탭에서 내 앱의 ⋮ 메뉴 → 디버그 토큰 관리에 그 토큰을 등록해요.
- 이제 localhost에서도 통과해요.
1 | // 개발용 빌드에서만! 배포용 코드에는 절대 넣지 마세요 |
디버그 토큰은 비밀번호처럼
디버그 토큰이 있으면 검증되지 않은 기기에서도 백엔드에 접근할 수 있어요. 공개 저장소에 커밋하지 말고, 배포용 빌드에 디버그 모드가 켜지지 않게 하세요. 토큰이 유출되면 콘솔에서 바로 삭제하세요.
2. Firestore와 Authentication 적용은 메트릭을 보고
AI Logic은 필수라서 먼저 켰지만, 이미 사용자가 있는 앱이라면 Firestore와 Authentication은 서두르지 않아도 돼요. 공식 문서는 API 탭 메트릭에서 최근 요청이 거의 모두 확인된 요청일 때 적용을 고려하고, 오래된 클라이언트 요청이 많으면 사용자들이 업데이트할 때까지 기다리라고 안내해요. 저는 하루쯤 지켜본 뒤 켜는 편을 권해요. 확인 안 된 요청이 많은데 켜면 실제 사용자가 막혀요.
3. 내 함수·백엔드를 fetch로 직접 부른다면
공식 문서에 따르면 Cloud Functions 클라이언트 SDK로 호출 가능 함수(httpsCallable)를 부르면 App Check 토큰이 자동으로 붙어요. 하지만 fetch로 내 백엔드 주소를 직접 부른다면 토큰을 직접 받아서 X-Firebase-AppCheck 헤더에 넣어야 해요. 토큰은 URL이나 쿼리 문자열에 넣지 말라고 문서가 강조해요.
1 | import { getToken } from "firebase/app-check"; |
이때 받는 쪽(내 백엔드)도 이 헤더의 토큰을 검증하도록 만들어 둬야 실제 보호가 돼요. 방법은 아래 공식 문서의 “커스텀 백엔드에서 토큰 확인”을 참고하세요.
✅ 준비됐다면 디버그 토큰 등록 방법을 알고, Firestore·Authentication은 메트릭을 본 뒤 켜기로 했어요.
↩️ 막혔다면 localhost는 1번, fetch로 부른 백엔드가 거부하면 3번을 다시 보세요.
10. 체크리스트, 자주 막히는 곳
체크리스트
- reCAPTCHA Enterprise 웹 키를 만들고 실제 서비스 도메인(내 도메인, 쓰고 있다면 .web.app·.firebaseapp.com)을 넣었다 (localhost는 넣지 않음)
- App Check 앱 탭에서 웹 앱을 reCAPTCHA Enterprise로 등록했다 (TTL 기본 1시간)
- 코드에
initializeAppCheck를 넣고VITE_RECAPTCHA_SITE_KEY를 .env.local과 CI Secret에 넣었다 - 다시 빌드하고 배포했다
- Credentials의 Browser key에서 원래 항목은 지우지 않고, 내 도메인(
내도메인,내도메인/*)과http://localhost:5173/*를 추가했다 - 구글 로그인을 쓰면 authDomain(
내-프로젝트-id.firebaseapp.com/*), 기본 호스팅을 쓰면내-프로젝트-id.web.app/*가 목록에 남아 있다 - 새 도메인으로 옮겼다면 Authentication 승인된 도메인에도 추가했다
- Browser key의 API 제한 목록에서 필요한 API를 빼지 않았고, Generative Language API는 들어 있지 않다
- 로그아웃 상태에서 공개 강의가 보이고, 콘솔에 403이 없다
- AI Logic: 기준 보호 “적용됨”, 재생 보호 “모니터링만”으로 저장했다
- 15분쯤 뒤 강력 새로고침하고 AI 생성을 다시 시도했다
- 메트릭에서 확인된 요청이 늘어나는지 봤다
자주 막히는 곳
Q. 403이 났는데 App Check를 끄면 되나요?
API_KEY_HTTP_REFERRER_BLOCKED라면 App Check와는 상관없어요. Browser key 웹사이트 목록에 도메인을 추가하세요. 6단계
Q. reCAPTCHA v3와 Enterprise 중 뭘 써야 하나요?
새로 붙인다면 Enterprise예요(공식 권장).
Q. localhost를 reCAPTCHA 키에 넣어도 되나요?
안 돼요. 디버그 토큰을 쓰세요. 9단계 1번
Q. 코드에 API 키가 보여도 괜찮나요?
Firebase용으로 제한된 Browser key라면 괜찮아요. Gemini 키, 비밀 키, 서비스 계정 파일은 절대 코드에 넣으면 안 돼요.
Q. 11월 2일 이후 AI Logic은 어떻게 되나요?
App Check가 자동으로 적용되고 끌 수 없어요.
Q. 도메인을 추가했는데도 그대로예요.
5분쯤 기다린 뒤 강력 새로고침을 해 보세요. 그래도 안 되면 주소 모양(/*, https와 http 구분), 그리고 고친 키가 정말 Browser key인지 다시 확인하세요. 6단계 흔한 실수
Q. 재생 보호도 적용하는 게 더 안전하지 않나요?
보호 수준은 더 높지만, 앱 코드에서 limited-use 토큰을 쓰도록 바꾼 뒤에 켜야 해요. 준비 없이 켜면 내 앱도 막혀요. 공식 문서는 요청마다 새 토큰을 만들어서 지연 시간과 비용이 늘 수 있다는 점도 알려 줘요. 8단계
이것만 기억하세요
- 403
API_KEY_HTTP_REFERRER_BLOCKED는 App Check가 아니라 Browser key 웹사이트 제한 목록 문제예요.- App Check는 끄지 말고 키 → 등록 → 코드 → 다시 빌드·배포 순서로 붙여요.
- AI Logic은 기준 보호만 적용, 재생 보호는 limited-use 토큰 준비 전까지 모니터링만(또는 중지됨). 반영된 뒤 다시 시도해요.
확인 날짜: 2026-09-29. 스크린샷은 실제 작업 화면이며, 개인정보(프로젝트 이름, 계정 이메일, 클라이언트 ID 등)는 가림 처리했어요. 콘솔 메뉴 이름과 배치는 Google이 바꿀 수 있으니, 화면이 조금 달라도 같은 이름의 메뉴를 찾아 주세요.
공식 문서
- Firebase: 웹 앱에서 reCAPTCHA Enterprise로 App Check 시작하기
- Firebase: 웹 앱에서 App Check 디버그 제공자 사용하기
- Firebase: App Check 요청 메트릭 모니터링
- Firebase: App Check 적용 사용 설정(재생 보호 포함)
- Firebase: Firebase AI Logic과 App Check
- Firebase: 커스텀 백엔드 요청에 App Check 토큰 보내기(웹)
- Firebase: 커스텀 백엔드에서 App Check 토큰 확인
- Firebase: Cloud Functions 호출 가능 함수에 App Check 적용
- Firebase: Firebase API 키 사용 및 관리
- Google Cloud: API 키 관리(웹사이트 제한)
- Google Cloud: 웹사이트용 reCAPTCHA 키 만들기(도메인 확인)
- Firebase: AI Logic FAQ(11월 2일 적용, Gemini API 키 변경)
- Firebase: App Check 개요(할당량과 비용)
- Firebase: reCAPTCHA v3 제공자(Enterprise 권장 안내)
- Firebase: signInWithRedirect 권장사항(authDomain)
- Firebase: 웹에서 Google 로그인(승인된 도메인)
- Vite: 환경변수와 모드
댓글
GitHub 계정으로 의견을 남길 수 있습니다. 댓글은 GitHub Discussions에 저장됩니다.