③ 데이터·AI 연결해누리중 조승재
00:00/ –분
바이브코딩 연수 · 모듈 ③ 데이터·AI

학생 데이터와 AI를 내 앱에 연결하기

내 앱에 Supabase를 붙여 학생 제출을 모으고, AI를 키를 숨긴 채 연결하는 방법과 학생에게 내놓기 전에 꼭 볼 것을 정리해보겠습니다!

말 익히기→Supabase 준비→API 연결→제출 받기→교사 대시보드→AI 연결→다섯 가지 점검

연수가 끝난 뒤에도 다시 과정을 살펴보며 따라하실 수 있도록 이 페이지에 순서대로 정리해두었습니다^^

⏱ 60분 💻 만들어 둔 앱 하나 (배포까지 했으면 더 좋습니다) 🔑 GitHub 계정

먼저 쓰시는 도구를 골라 주세요. 고르신 도구에 맞는 부탁문이 나옵니다.

폴더에서 일하는 앱 · 유료 계정
웹 채팅 · 무료 계정도 됩니다
1

딱 여기까지만 알면 되는 말

6분

AI를 연결한 웹 앱을 만들 때 만나는 말들을, 앱 하나를 뜯어 보며 익혀보겠습니다!

「실험 결과 제출함」 하나로 봅니다

모둠이 측정값과 결론을 내면 교사 화면에 모이고, AI가 결론에 피드백 초안을 붙이는 앱입니다. 이 매뉴얼에서 만드는 앱이기도 합니다. 다른 교과라면 「감상문 제출함」이나 「탐구 보고서 제출함」으로 바꿔 읽으셔도 부품은 같습니다.

Supabase · 서버24시간 켜져 있는 남의 컴퓨터
배포GitHub Pages앱 파일이 있는 주소
프론트엔드학생 화면index.html sb_publishable_…
백엔드받아서 확인규칙대로 넣고 꺼냄RLS · 학생은 넣기만
데이터베이스submissions 표
모둠부피결론
145…
342…
프론트엔드교사 대시보드로그인한 교사만
Edge Function대신 묻는 함수금고 속 AI 키CORS · 내 앱 주소만
AI 키를 붙여 대신 물음
AI 회사AI의 API답만 돌려줌

「실험 결과 제출함」 한 벌아래 단계를 누르거나 [차례로 보기]를 누르면, 그 말에 해당하는 부품이 켜집니다.

프론트엔드학생 기기에 보이는 화면입니다. 이 앱에서는 모둠 번호, 부피, 결론을 적고 [제출]을 누르는 index.html 한 파일입니다. 이 파일은 학생 기기의 브라우저로 내려가서 실행되므로, 파일에 적힌 글자는 누구나 F12로 볼 수 있습니다.

서버24시간 켜져 있는 남의 컴퓨터입니다. 학생 기기가 꺼져도 제출을 받아 둘 곳이 있어야 해서 필요합니다. 이 앱에서는 Supabase가 서버를 빌려줍니다.

백엔드서버에서 돌아가는 프로그램입니다. 들어온 제출을 규칙대로 확인해 표에 넣고, 볼 수 있는 사람에게만 꺼내 줍니다. 학생 눈에는 보이지 않습니다.

데이터베이스제출이 한 줄씩 쌓이는 표입니다. 이 앱에서는 submissions 표에 모둠 번호, 부피, 결론, 낸 시각이 한 줄로 들어갑니다. 로그인한 교사의 대시보드가 이 표를 읽어 보여 줍니다(5단계).

API앱이 백엔드에게 부탁하는 약속된 주소와 양식입니다. [제출]을 누르면 앱이 프로젝트 주소 뒤의 /rest/v1/submissions 로 "이 줄을 넣어 줘"라는 요청을 보냅니다.

API 키요청에 붙이는 출입증입니다. 앱에 넣는 publishable 키는 누구나 볼 수 있다고 보고 쓰고, 표를 지키는 일은 규칙(RLS)이 합니다. AI 회사의 키는 쓴 만큼 결제되므로 앱에 넣지 않고 함수의 금고에 넣습니다.

RLS표마다 거는 규칙입니다. 이 앱은 "학생은 넣기만, 읽기는 교사만"입니다. SQL로 만든 표는 RLS를 따로 켜야 하고, 켜지 않으면 publishable 키를 가진 누구나 모든 줄을 읽고 고칠 수 있습니다.

Edge Function · 환경변수서버에서 도는 작은 함수입니다. 금고(Secrets)에 넣은 AI 키를 이름으로 꺼내 AI에게 대신 묻고, 답만 앱으로 돌려줍니다. 이렇게 코드 밖 금고에 넣고 이름으로 꺼내 쓰는 값을 환경변수라고 합니다.

CORS함수가 브라우저에게 "이 주소의 페이지만 내 답을 읽어도 된다"고 알려 주는 허락입니다. 이 앱의 함수는 내 앱 주소만 허락합니다. 브라우저만 지키는 규칙이라 호출 횟수 제한을 함께 겁니다.

GitHub · 배포앱 파일을 보관하고, 누구나 여는 주소로 걸어 주는 곳입니다. GitHub Pages는 파일만 걸어 주고 서버 코드는 돌리지 못해서, 서버 일은 Supabase가 맡습니다.

말 뜻을 한 번에 보면 이렇습니다.

프론트엔드이 앱에서는 학생 화면 index.html

학생 기기에 보이는 화면입니다. 브라우저로 내려가 실행되므로 누구나 코드를 볼 수 있습니다.

GitHub Pages에 올린 앱
백엔드이 앱에서는 제출을 받아 확인하는 쪽

보이지 않는 곳에서 저장하고, 확인하고, 대신 부탁하는 쪽입니다.

Supabase
서버이 앱에서는 Supabase가 빌려준 컴퓨터

24시간 켜져 있는 남의 컴퓨터입니다. 백엔드가 여기서 돌아갑니다.

Supabase, Render
데이터베이스 (DB)이 앱에서는 submissions 표

표 모양으로 기록이 쌓이는 곳입니다. 줄 하나가 제출 하나입니다.

Supabase의 표
API이 앱에서는 /rest/v1/submissions 주소

정해진 주소와 양식으로 부탁하면 정해진 모양으로 답이 오는 약속입니다.

Supabase API, AI 회사의 API
API 키이 앱에서는 publishable 키와 AI 키

요청에 붙이는 출입증입니다. publishable 키는 앱에 넣어도 되고, secret 키와 AI 회사의 키는 앱에 넣지 않습니다.

3단계, 6단계
환경변수이 앱에서는 금고 속 OPENAI_API_KEY

비밀 키를 코드에 적지 않고 서버의 금고에 넣은 뒤, 이름으로만 꺼내 씁니다.

Edge Function의 Secrets
RLS이 앱에서는 학생은 넣기만, 읽기는 교사만

표마다 누가 넣고, 읽고, 고칠 수 있는지 정하는 규칙입니다.

3단계
교사 대시보드이 앱에서는 teacher.html

로그인한 교사만 표를 읽고 메모를 다는 화면입니다. 학생 화면과 같은 표를 씁니다.

5단계
Edge Function이 앱에서는 AI에게 대신 묻는 함수

서버에서 돌아가는 작은 함수입니다. 금고의 키로 AI에게 묻고, 답만 돌려줍니다.

6단계
CORS이 앱에서는 내 앱 주소만 허락

어느 주소의 페이지가 답을 읽어도 되는지 브라우저에게 알려 주는 규칙입니다. 브라우저만 지키는 규칙이라 자물쇠는 아닙니다.

6단계
GitHub · GitHub Pages이 앱에서는 index.html을 보관하고 주소로 걸어 줌

코드를 보관하고, 누구나 여는 주소로 걸어 줍니다. 서버 코드는 돌리지 못합니다.

② 배포
Netlify · Vercel이 앱에서는 쓰지 않습니다

페이지를 걸어 주면서 작은 함수도 돌려 줍니다. 비밀 키는 환경변수로 넣습니다.

Supabase 대신 쓸 때
Render이 앱에서는 쓰지 않습니다

서버 프로그램을 계속 켜 두는 곳입니다. 무료는 15분 동안 아무도 안 부르면 잠들고, 깨어나는 데 1분쯤 걸립니다.

Supabase 대신 쓸 때

오늘 만드는 두 길

학생 제출을 모으는 길 · 3~5단계
프론트엔드학생 화면index.html
API · publishable 키SupabaseRLS가 문지기
데이터베이스표교사만 봅니다
AI에게 묻는 길 · 6단계
프론트엔드화면키가 없습니다
백엔드 · 금고에 AI 키Edge Function횟수를 셉니다
AI 회사의 APIAI답만 돌아옵니다

이 매뉴얼에 나오는 말은 이 정도면 충분합니다. 저도 이 말들을 순서대로 공부한 것이 아니라, 오류를 만날 때마다 하나씩 알게 됐습니다.

2

Supabase 프로젝트 만들기

6분

Supabase에 가입하고, 데이터를 담을 프로젝트를 하나 만들어보겠습니다!

왜 Firebase나 Apps Script가 아니라 Supabase인가요

모인 기록이 표로 보이고, AI 키를 숨기는 함수를 카드 등록 없이 쓰고, 한 반이 한꺼번에 제출해도 버팁니다.

SupabaseFirebase (무료 Spark)Apps Script + 구글 시트
기록 모양표 (줄과 칸)문서 묶음 (표가 아님)시트 (표)
교사가 보는 화면Table Editor에서 표로 보고 CSV로 받음콘솔에서 문서를 하나씩 봄, CSV로 내보내는 단추는 없음시트 그대로
AI 키 숨기기Edge Function의 금고, 카드 없이 무료Cloud Functions, 카드를 등록하는 Blaze 요금제부터스크립트 속성, 카드 없이
한 반이 한꺼번에요청 수 제한 없음하루 쓰기 2만 번, 읽기 5만 번까지한 계정에서 동시에 30개까지 실행
누가 무엇을 하나표마다 RLS 규칙보안 규칙 (Security Rules)웹 앱 공개 범위와 스크립트 안의 확인
조심할 점7일 동안 거의 안 쓰면 멈춤, 1년 안에 다시 켬파일 저장소(Storage)도 Blaze 요금제부터한 번 실행은 6분까지, 여러 명이 한 시트에 쓰면 차례를 지키게 하는 코드가 필요

표에 나온 말

문서 묶음

Firebase는 기록을 엑셀 같은 표가 아니라, 학생마다 따로 적힌 쪽지를 상자에 모으듯 둡니다. 쪽지마다 칸이 달라도 되는 대신, 한 표로 훑어보거나 CSV로 바로 받기가 어렵습니다.

Blaze 요금제

카드를 등록하고 쓴 만큼 내는 Firebase 요금제입니다. 무료 한도 안에서는 0원이지만, 넘으면 카드로 나가고 예산 알림이 와도 저절로 멈추지 않습니다.

동시에 30개까지 실행

Apps Script가 같은 순간에 30건까지 일을 받는다는 뜻입니다. 한 반이 [제출]을 한꺼번에 누르는 순간에 걸릴 수 있습니다.

RLS · 보안 규칙

표(또는 쪽지 상자)마다 누가 넣고 읽을 수 있는지 정하는 규칙입니다. 이름만 다르고 하는 일은 같습니다.

저는 세 가지 때문에 Supabase를 씁니다. 첫째, 모인 기록이 엑셀처럼 표로 보여서 Table Editor에서 바로 확인되고, CSV로 받아 평가나 기록의 근거로 옮기기 쉽습니다. 5단계의 교사 대시보드도 이 표를 그대로 읽습니다. 둘째, AI 키를 숨기는 함수(Edge Function)를 카드 등록 없이 씁니다. Firebase에서 같은 일을 하려면 카드를 등록하는 Blaze 요금제로 바꿔야 하고, 예산 알림을 걸어도 요금이 저절로 멈추지는 않습니다. 셋째, 한 반이 한꺼번에 제출해도 버팁니다. Apps Script 웹 앱은 한 계정에서 동시에 30개까지 실행되는데, 「나로 실행」으로 두면 학생들의 요청이 모두 제 계정으로 돌아갑니다.

구글 시트가 더 편한 때도 있습니다. 이미 시트로 일하고 계시고, 학생들이 한꺼번에 몰리지 않는 설문 같은 수합이라면 Apps Script로 충분합니다. 표의 숫자는 2026년 9월 각 회사의 안내 기준입니다.

「Edge Function의 금고」가 뭔가요

학교 카드로 물건을 살 때를 떠올리면 됩니다. 선생님은 품의만 올리고, 카드는 행정실 금고에 있고, 결제는 행정실이 대신 합니다.

학생 화면 · 프론트엔드교실품의서만 올립니다
"이 결론에 피드백 주세요"
부탁
Edge Function행정실금고 속 학교 카드로 대신 결제,
오늘 몇 건인지 셉니다
금고 = Secrets
카드 결제
AI 회사가게결제를 받고
물건(답)을 내줍니다

교실은 카드를 한 번도 보지 못하고, 행정실을 거쳐 답만 돌려받습니다.

카드 번호를 칠판에 적으면

AI 키를 앱 파일에 넣는 것입니다. 앱 파일은 학생 기기로 내려가서 누구나 F12로 번호를 보고 베껴 갈 수 있고, 쓴 만큼 제 카드로 결제됩니다.

카드를 행정실 금고에 두면

AI 키를 Supabase의 금고(Edge Functions 메뉴의 Secrets)에 넣는 것입니다. 금고는 행정실 역할을 하는 함수(Edge Function)만 열 수 있고, 학생 기기로는 키가 내려가지 않습니다.

Edge Function은 Supabase의 서버에서 돌아가는 작은 프로그램입니다. 학생 화면이 부르면 대신 일을 하고 결과만 돌려줍니다. 금고(Secrets)에 넣은 값은 이 함수 코드에서만 이름으로 꺼내 쓸 수 있습니다.

비유가 맞지 않는 곳도 있습니다. 행정실 주무관님은 이상한 품의를 보면 되물을 줄 알지만, 함수는 코드에 적힌 규칙대로만 움직입니다. 그래서 하루에 몇 번까지 부를지, 어느 주소에서 온 부탁만 받을지를 함수 코드 안에 미리 적습니다. 6단계의 부탁문 빌더가 이 규칙을 넣어 줍니다.

Supabase는 이 행정실을 카드 등록 없이 무료로 빌려줍니다(한 달 50만 번까지). Firebase에도 같은 일을 하는 Cloud Functions가 있지만, 쓰려면 Blaze 요금제로 바꾸고 카드를 등록해야 합니다. Apps Script에도 스크립트 속성이라는 금고가 있어 카드 없이 쓸 수 있지만, 한 계정에서 동시에 30건까지만 일합니다.

GitHub 계정으로 들어갑니다

배포에서 쓴 GitHub 계정으로 가입하면 비밀번호를 따로 만들 필요가 없습니다.

  1. supabase.com 에서 [Start your project]오른쪽 위 [Sign in]이 보이면 그것을 눌러도 됩니다
  2. [Continue with GitHub]로 로그인GitHub 권한을 묻는 화면에서 [Authorize]배포할 때 GitHub을 어차피 쓰니, 계정을 하나로 묶으면 외울 비밀번호가 하나 줄어듭니다.
  3. [New project]에서 이름, 데이터베이스 비밀번호, 지역 정하기비밀번호는 [Generate a password] 후 메모장에 저장. 지역(Region)은 Northeast Asia (Seoul)데이터베이스 비밀번호는 대시보드에서 다시 보여 주지 않고 새로 바꾸는 것만 됩니다. 지역을 서울로 고르는 것은 서버가 가까울수록 학생 화면에 답이 빨리 오기 때문입니다.
  4. [Create new project]를 누르고 1~2분 기다리기프로젝트 화면이 뜨면 준비 끝
Supabase 첫 화면
supabase.com첫 화면의 초록 [Start your project]를 누릅니다.
Supabase 로그인 화면
로그인[Continue with GitHub]로 들어갑니다.
GitHub 로그인 화면
GitHubGitHub에 로그인돼 있지 않으면 GitHub 아이디로 먼저 로그인합니다.
무료 프로젝트는 두 개까지

수업용 하나, 연습용 하나로 쓰면 알맞습니다.

일주일 쉬면 멈춥니다

일주일 동안 쓰지 않으면 메일로 알려 준 뒤 멈춥니다. 1년 안에는 대시보드에서 다시 켤 수 있습니다.

Edge Function은 한 달 50만 번

무료에서는 넘으면 더 쓸 수 없습니다. 한 반이 수업에서 쓰기에는 넉넉합니다.

무료 프로젝트 한도 안내
무료 한도무료 프로젝트 두 개를 다 쓰면 셋째는 이렇게 막힙니다. 안 쓰는 프로젝트를 멈추거나 지워야 새로 만들 수 있습니다.

학기 중에 매주 쓰는 앱이라면 멈출 일이 거의 없고, 방학이 지나면 한 번 다시 켜면 됩니다. 저는 수업에 쓰는 앱 여러 개의 표를 프로젝트 하나에 함께 둡니다. 무료 프로젝트가 두 개뿐이라 앱마다 프로젝트를 만들 수는 없기 때문입니다. 이 숫자들은 2026년 9월 Supabase 안내 기준입니다.

3

주소와 키로 API 연결하기

9분

프로젝트 주소와 키를 찾아, 내 앱이 Supabase와 이야기하게 해보겠습니다!

주소 하나, 키 하나

Project URL과 Publishable key 두 가지만 앱에 넣습니다.

  1. 프로젝트 화면 위쪽의 [Connect] 누르기Project URL과 Publishable key가 함께 보입니다. [Settings] → [API Keys]에서도 찾을 수 있습니다주소는 어느 프로젝트로 보낼지, 키는 어느 앱에서 온 요청인지 알려 줍니다. 둘이 맞아야 Supabase가 요청을 받아 줍니다.
  2. Project URL 복사하기https://영문자.supabase.co 모양
  3. Publishable key 복사하기sb_publishable_ 로 시작하는 키앱 파일은 학생 기기로 내려가 누구나 열어 볼 수 있어서, 보여도 괜찮은 키만 앱에 넣습니다.
프로젝트 첫 화면
프로젝트 첫 화면위쪽 가운데 [Connect], 프로젝트 이름 아래에 Project URL과 [Copy]가 있습니다.
Connect 창
Connect 창아래쪽 .env 칸에 주소(SUPABASE_URL)와 공개 키(PUBLISHABLE_KEY)가 함께 적혀 있습니다.
Settings의 API Keys 화면
Settings · API Keys위쪽 두 번째 탭(Legacy anon, service_role)은 예전 방식의 키입니다.
Publishable key · sb_publishable_

앱에 넣어도 되는 키입니다. 누구나 볼 수 있다는 전제로 쓰고, 표를 지켜 주는 것은 표마다 거는 규칙(RLS)입니다.

Secret key · sb_secret_

모든 규칙을 건너뛰는 열쇠입니다. 앱에도 GitHub에도 넣지 않습니다. AI가 넣으라고 해도 넣지 않습니다.

학생 화면"이 줄을 넣어 줘"sb_publishable_
규칙 (RLS)넣기는 허락
표에 한 줄모둠 3 · 42 mL
누군가"다 보여 줘"sb_publishable_
규칙 (RLS)읽기는 교사만
돌아온 답빈 목록
누군가앱에서 찾은 키로sb_secret_
규칙 (RLS)건너뜀
모든 줄읽고, 고치고, 지움

publishable 키로 온 부탁은 규칙이 허락한 것만 들어갑니다. 이 앱의 규칙은 "학생은 넣기만"입니다.

Publishable key와 Secret keys
두 키위가 앱에 넣어도 되는 publishable 키, 아래가 가려진 secret 키입니다. secret 키 옆 눈 모양은 누르지 않습니다.

예전 설명서나 AI가 eyJ로 시작하는 긴 키(anon, service_role)를 복사하라고 하면 예전 방식입니다. Supabase는 2026년 말까지 예전 키를 없애 가는 중이라, 새로 만드는 앱은 sb_publishable_ 키로 합니다.

빌더연결 부탁문

복사한 주소와 키, 모을 내용을 적으면 부탁문이 완성됩니다.

연결 부탁문
  1. 부탁문을 보내 표를 만드는 SQL 받기되묻는 질문에는 짧게 답합니다표를 마우스로 만들 수도 있지만, 규칙(RLS)까지 한 번에 빠짐없이 걸려면 SQL이 낫습니다. 저도 SQL을 직접 쓰지 않고, AI가 쓴 것을 읽어 본 뒤 실행합니다.
  2. SQL Editor에 붙여 실행하기왼쪽 메뉴 [SQL Editor] → [+ New query] → 붙여넣기 → [Run]SQL로 만든 표는 RLS를 따로 켜야 합니다. 켜지 않으면 publishable 키를 가진 누구나 모든 줄을 읽고 고칠 수 있어서, 부탁문에 RLS를 꼭 넣었습니다.
  3. Table Editor에서 표가 생겼는지 보기왼쪽 메뉴 [Table Editor] → 표 이름SQL이 제대로 돌았는지 눈으로 봅니다. 표 위쪽에 RLS가 꺼져 있다고 나오거나 규칙 수가 0이면 AI에게 다시 부탁합니다.
SQL Editor 새 쿼리
SQL Editor빈 칸에 받은 SQL을 붙여넣고 오른쪽 위 초록 [Run]을 누릅니다.
Table Editor의 표
Table Editor왼쪽에서 표를 누르면 줄이 보입니다. 위쪽 RLS policy 옆 숫자가 걸어 둔 규칙 개수입니다.

주소와 키 칸에 넣은 값은 이 페이지 안에서 부탁문을 만드는 데만 쓰이고, 어디에도 저장하거나 보내지 않습니다.

막혔을 때

SQL을 실행하려니 경고 창이 뜹니다. 표를 만들거나 규칙을 바꾸는 SQL이면 Supabase가 한 번 더 묻습니다. 경고를 읽고, 이미 있는 표를 지우는(drop) 내용이 아니면 실행합니다.

secret 키를 앱에 넣어 버렸습니다. [Settings]의 [API Keys]에서 그 secret 키를 바로 지우고 새로 만듭니다. 앱에서도 지웁니다.

4

학생 제출 받아 보기

8분

학생처럼 제출해 보고, 모인 기록을 교사가 내려받는 데까지 해보겠습니다!

두 갈래 가운데 하나

A · 만들어 둔 도구 설치하기

칭찬 도장판, 질문나무, 진도 트래커를 내 Supabase에 설치해 쓰는 판입니다. 설치 가이드를 따라갑니다.

우리 반 도구 꾸러미 설치 가이드 ↗

B · 내 앱에 제출 붙이기

3단계의 연결 부탁문으로 내 앱에 [제출] 버튼을 붙이고, 아래 순서로 확인합니다.

  1. 휴대폰으로 앱 열기배포한 주소가 있으면 휴대폰으로. 아직이면 내 컴퓨터에서 index.html학생은 휴대폰이나 크롬북으로 엽니다. 제 컴퓨터에서 되던 것이 학생 기기에서는 다르게 보이기도 합니다.
  2. 두세 번 제출해 보기빈칸으로도, 아주 긴 글로도, 버튼 연타로도학생들은 빈칸으로도 내고, 아주 길게도 쓰고, 버튼을 여러 번 누릅니다. 수업 중에 처음 겪는 것보다 미리 겪는 편이 낫습니다.
  3. Table Editor에서 모인 줄 보기왼쪽 [Table Editor] → 표 이름. 새로고침하면 줄이 늘어납니다다음 단계에서 교사 대시보드를 만들기 전에, 줄이 제대로 들어오는지 여기서 먼저 봅니다.
  4. CSV로 내려받기표 위쪽의 내보내기(Export) 메뉴에서 CSV. 엑셀에서는 [데이터] → [텍스트/CSV]로 열고 UTF-8을 고릅니다모인 답을 평가나 기록의 근거로 쓰려면 엑셀로 옮겨야 합니다.
  5. 연습으로 넣은 줄 지우기줄 앞 칸을 골라 [Delete]연습 줄이 남아 있으면 수업 날 모인 답과 섞입니다.
1모둠
2모둠
3모둠
submissions 표
모둠부피(mL)결론
145…
238…
342…
교사Table Editor로 보고CSV로 받기
표 메뉴의 CSV 내보내기
CSV로 받기표 이름 옆 ⋯에서 Export data의 Export table as CSV를 고릅니다. 아래쪽 Delete table은 누르지 않습니다.

모인 답을 수업에서 보는 화면은 다음 단계에서 교사 대시보드로 따로 만듭니다. 로그인 없이 읽기를 열어 두면 주소를 아는 누구나 학생 답을 볼 수 있어서, 대시보드는 로그인한 교사만 읽게 합니다. 학교 심의 자료 만들기는 학생 데이터 연수 자료에 따로 정리해 두었습니다.

막혔을 때

제출했는데 표에 줄이 생기지 않습니다. 앱에서 F12를 눌러 [Console]에 빨간 글이 있는지 보고, 그 글을 그대로 AI에게 보냅니다. RLS 규칙이 빠졌거나 표 이름이 다른 경우가 가장 많습니다.

교사 화면에 1,000줄까지만 보입니다. Supabase는 한 번에 1,000줄까지만 돌려줍니다. 오류 없이 조용히 잘리기 때문에, AI에게 "1,000줄씩 나눠서 모두 받아 오게 고쳐 줘"라고 합니다.

엑셀에서 한글이 깨집니다. CSV 파일을 두 번 눌러 열지 말고, 엑셀의 [데이터] 탭에서 [텍스트/CSV]로 불러와 UTF-8을 고릅니다.

5

교사 대시보드 만들기

11분

모인 제출을 로그인한 교사만 보는 대시보드를 따로 만들어보겠습니다!

교사 화면은 따로 둡니다

Table Editor는 Supabase 계정 주인이 보는 관리 화면입니다. 수업에서 반별로 보고, 안 낸 모둠을 찾고, 피드백을 다는 일은 교사 대시보드에서 합니다.

같은 표를 두 화면이 나눠 씁니다

학생 화면(index.html)은 넣기만 하고, 교사 대시보드(teacher.html)는 로그인한 교사만 읽고 고칩니다.

수업에 맞춘 화면

반과 모둠으로 거르기, 아직 안 낸 모둠, 교사 메모, CSV 받기, 이름을 가린 발표 화면을 한곳에 둡니다.

주소가 새어도 괜찮게

대시보드 주소를 학생이 알아도, 로그인하지 않으면 아무 줄도 보이지 않게 규칙으로 막습니다.

AI는 여기에 붙입니다

6단계에서 만드는 AI 함수를 대시보드의 [AI 피드백 초안] 단추로 부르면, 학생은 AI와 직접 대화하지 않습니다.

학생 화면index.html넣기만 합니다
submissions 표제출이 쌓임RLS 규칙이 지킴
막힘
교사 대시보드teacher.html로그인 화면만 보입니다
학생 화면index.html넣기만 합니다
submissions 표제출이 쌓임교사 이메일만 읽기 허락
교사 대시보드 · teacher.html기체의 성질 · 실험 결과
전체1반2반
모둠낸 시각결론
310:12…
110:13…
510:15…
아직 안 냄 · 2, 4, 6CSV로 받기

로그인하지 않으면 대시보드 주소를 알아도 표가 열리지 않습니다. 학생 제출은 그대로 쌓입니다.

저도 학생이 쓰는 화면과 교사 화면을 따로 둡니다. 질문 과수원에는 교사 대시보드가, 칭찬 도장판에는 관찰 기록부가, MBL 센서 수업 허브에는 교사 화면이 따로 있습니다. 학생 화면 하나에 교사용 단추까지 넣으면, 학생에게 보이면 안 되는 기록을 숨기느라 코드가 복잡해지고 실수도 생기기 쉽습니다.

교사 계정 하나, 규칙 하나, 화면 하나

Supabase에 교사 계정을 만들고, 교사만 읽는 규칙을 더하고, teacher.html을 받아 학생 앱 옆에 올립니다.

  1. Supabase에서 교사 계정 만들기왼쪽 [Authentication] → [Users] → [Add user] → [Create new user] → 교사 이메일과 비밀번호, [Auto Confirm User] 켜기대시보드에 들어올 사람을 Supabase가 알아야, 규칙에서 「이 이메일로 로그인한 사람만」을 가를 수 있습니다.
  2. 새 가입은 막기[Authentication]의 가입 설정(Sign In / Providers)에서 Allow new users to sign up 끄기. 같은 프로젝트에 학생이 가입해서 쓰는 다른 앱이 있으면 그대로 둡니다가입이 열려 있으면 누구나 계정을 만들 수 있습니다. 규칙을 교사 이메일 하나로 좁혀서 읽지는 못하지만, 쓰지 않는 문은 닫는 편이 안전합니다.
  3. 부탁문을 보내 규칙 SQL과 teacher.html 받기아래 빌더에 교사 이메일을 넣고 복사해 보냅니다규칙과 화면을 한 대화에서 받아야 표 이름과 칸 이름이 어긋나지 않습니다.
  4. SQL Editor에서 규칙 SQL 실행하기[SQL Editor] → [+ New query] → 붙여넣기 → [Run]3단계의 「학생은 넣기만」 규칙 옆에 「교사만 읽고 고치기」를 더합니다. 이 규칙이 없으면 로그인해도 대시보드에 아무 줄도 보이지 않습니다.
  5. teacher.html을 학생 앱과 같은 곳에 올리기앱이면 이 폴더에 저장, 웹 채팅이면 받은 코드를 teacher.html로 저장한 뒤 학생 앱과 같은 저장소에 올리고 배포 주소 뒤에 /teacher.html을 붙여 엽니다같은 곳에 두면 한 번에 올라가고 연결 정보도 같습니다. 대시보드 주소는 학생에게 알리지 않지만, 알려져도 로그인 없이는 아무것도 보이지 않습니다.
  6. 세 가지로 확인하기학생 화면에서 제출하면 대시보드에 바로 보이는지 · 로그아웃하면 사라지는지 · 시크릿 창에서 teacher.html을 열면 로그인 화면만 나오는지규칙이 제대로 걸렸는지는 로그인하지 않은 쪽에서 열어 봐야 알 수 있습니다.

빌더교사 대시보드 부탁문

3단계에서 넣은 주소·키·표 이름·모을 내용을 그대로 가져옵니다. 교사 이메일은 이 페이지에 저장하지 않습니다.

화면에 넣을 것
교사 대시보드 부탁문
막혔을 때

로그인했는데 표가 비어 있습니다. 규칙 SQL을 실행했는지, 규칙에 적힌 이메일이 교사 계정의 이메일과 같은지 봅니다. 그래도 비어 있으면 F12의 [Console]에 나온 빨간 글을 그대로 AI에게 보냅니다.

로그인하면 「Email not confirmed」가 나옵니다. 계정을 만들 때 [Auto Confirm User]를 켜지 않은 경우입니다. [Users]에서 그 계정을 지우고, 켠 채로 다시 만듭니다. 계정을 지워도 학생 제출은 그대로입니다.

교사 비밀번호를 학생이 알게 됐습니다. [Users]에서 그 계정을 지우고 새 비밀번호로 다시 만듭니다. 이메일이 같으면 규칙을 고칠 필요가 없습니다.

제출이 많은데 1,000줄까지만 보입니다. 부탁문에 나눠서 받아 오라는 줄이 들어 있습니다. 이미 만든 뒤라면 "1,000줄씩 나눠서 모두 받아 오게 고쳐 줘"라고 합니다.

6

내 앱에 AI 연결하기

10분

AI를 붙이면 무엇이 되는지 보고, 키를 숨긴 채 연결하는 구조와 결제 한도를 걸어보겠습니다!

AI를 붙이면 되는 일

학생 글에 피드백 초안

실험 결론이나 서술형 답을 넣으면 채점 기준에 맞춘 피드백 초안이 나옵니다. 교사가 읽고 고쳐서 돌려줍니다.

질문 모으고 나누기

학생 질문을 주제별로 묶고, 수업에서 다룰 만한 질문을 골라 줍니다.

문제 바꿔 만들기

같은 개념으로 숫자와 상황만 바꾼 연습 문제를 만듭니다.

대화 상대

역사 속 인물, 작품 속 인물, 과학자처럼 누군가가 되어 학생 질문에 답하는 역할 놀이입니다. 학생이 AI와 직접 대화하므로 아래 기준을 먼저 봅니다.

학생이 AI와 직접 대화하는 앱은 회사 약관과 법을 먼저 확인합니다. OpenAI API는 미성년자가 쓰게 하려면 보호자 동의와 나이에 맞는 안전장치를 두게 되어 있고, Anthropic(Claude) API는 미성년자가 쓰는 서비스에 나이 확인, 내용 거르기, AI라는 사실 밝히기 같은 안전장치를 요구합니다. 개인정보 보호법은 만 14세 미만의 개인정보를 처리하려면 법정대리인의 동의를 받게 합니다. Google(Gemini API)은 제가 아직 잘 알지 못해 준비 중입니다.

그래서 교사가 쓰는 도구에 AI를 붙이는 쪽이 시작하기 쉽습니다. 5단계의 교사 대시보드에 [AI 피드백 초안] 단추를 붙이는 것이 그 예입니다(이 단계 끝의 카드). 학생 글을 넣을 때도 이름과 번호는 지우고 넣습니다. 약관 내용은 2026년 9월 각 회사의 안내를 기준으로 정리했고, 바뀔 수 있어서 쓰시기 전에 한 번 더 확인하시길 권합니다.

AI 키는 브라우저에 두지 않습니다

AI 회사의 키는 쓴 만큼 결제되는 법인카드입니다. 앱 코드에 넣으면 누구나 F12로 볼 수 있습니다.

앱 파일KEY = "sk-…"
F12로 누구나파일 속 키가 보임
다른 사람키를 복사해 마구 부름
내 카드쓴 만큼 결제
프론트엔드내 앱키 없이 부탁만
백엔드 · 금고Edge Function키를 꺼내 대신 묻고 횟수를 셈
APIAI 회사답만 돌려줌

앱 파일에 적은 키는 누구나 F12로 봅니다. 누가 가져가 부르면 그만큼 제 카드로 결제됩니다.

앱의 코드는 브라우저로 내려받아 실행되는 것이라, 파일에 적힌 글자는 누구나 볼 수 있습니다. 그래서 AI 키는 Supabase의 Edge Function 같은 서버 쪽 금고에 넣고, 앱은 그 함수에게 부탁만 합니다. 함수가 금고에서 키를 꺼내 AI에게 묻고, 답만 앱으로 돌려줍니다. Netlify나 Vercel의 함수, Render의 서버에 키를 환경변수로 넣어도 같은 구조가 됩니다.

브라우저는 다른 주소의 서버에 부탁할 때, 그 서버가 "이 주소의 페이지는 답을 읽어도 된다"고 허락해야 답을 보여 줍니다. 이 허락이 CORS입니다. 함수가 내 앱 주소만 허락하면 다른 사이트의 페이지가 내 함수를 끌어다 쓰기 어려워집니다. 다만 CORS는 브라우저만 지키는 규칙이라 다른 프로그램으로 직접 부르는 것까지 막지는 못해서, 호출 횟수 제한과 결제 한도를 함께 겁니다.

키를 받기 전에 결제 한도부터

선불로 조금만 넣고, 자동 충전을 끄고, 월 한도를 겁니다.

회사키 받는 곳결제한도 거는 곳꼭 볼 것
OpenAIplatform.openai.com의 API keys선불 크레딧, 5달러부터Settings의 Limits에서 월 한도를 정하고 "Enforce a hard limit" 켜기 (조직 또는 프로젝트)결제를 등록할 때 자동 충전(auto-reload)이 켜진 채로 시작하니 끕니다
Anthropic (Claude)platform.claude.com의 API keys선불 크레딧, 다 쓰면 멈춤Settings의 Billing에서 Spend limits. 수업용 Workspace를 따로 만들어 그 Workspace에 월 한도자동 충전(Auto-reload)이 꺼져 있는지 봅니다. 기본 Workspace에는 한도를 걸 수 없습니다
Google (Gemini)준비 중입니다. 제가 아직 잘 알지 못하는 부분이라, 직접 써 보고 확인한 뒤에 채우겠습니다.
OpenAI Billing 첫 화면
OpenAI · Billing처음에는 크레딧이 0달러입니다. 화면에 적힌 대로 API 크레딧은 ChatGPT 구독과 따로라서, ChatGPT를 유료로 쓰고 있어도 여기에는 따로 충전합니다. 결제 수단은 [Add payment details]에서 등록합니다.
OpenAI Limits의 등급 안내
OpenAI · LimitsBilling의 Usage limits(Set monthly spend limits)를 누르면 이 화면으로 옵니다. 결제 수단을 아직 등록하지 않은 제 계정에서는 월 한도 칸 없이 등급(Usage Tiers)만 보였습니다. 산 크레딧이 모두 5달러가 되면 Tier 1로 저절로 올라갑니다.
OpenAI 속도 제한 표
OpenAI · 속도 제한같은 Limits 화면 아래쪽입니다. 등급마다 1분에(RPM), 하루에(RPD) 부를 수 있는 횟수가 정해져 있습니다. 무료 등급에서 gpt-5.5는 1분에 3번, 하루 50번이고, Tier 1이 되면 1분에 500번까지 늘어납니다.

처음에는 크레딧을 5~10달러만 넣고 자동 충전을 끈 채로 시작하면, 무슨 일이 생겨도 넣은 돈 이상은 나가기 어렵습니다. 다만 회사들은 한도에 닿은 뒤 몇 분 동안은 조금 더 쓰일 수 있다고 적어 두었습니다. 메뉴 이름은 2026년 9월 기준이고 자주 바뀝니다.

빌더AI 함수 부탁문

함수 코드와 앱 쪽 코드를 한 번에 받습니다. 코드는 대시보드에 붙여넣기만 하면 됩니다.

AI 회사
누가 쓰나
AI 함수 부탁문
  1. AI 회사에서 결제 한도를 걸고 키 만들기위 표의 순서대로. 키는 만들 때 한 번만 보이니 바로 다음 칸으로키가 새어 나가면 제 카드로 결제됩니다. 한도를 먼저 걸면 최악의 경우에도 넣은 돈 안에서 멈춥니다.
  2. Supabase의 금고(Secrets)에 키 넣기[Edge Functions] → [Secrets] → Key에 OPENAI_API_KEY, Value에 키 → [Save]. 넣자마자 쓸 수 있습니다앱 파일에 적은 글자는 F12로 누구나 봅니다. Secrets에 넣은 키는 함수만 꺼내 씁니다.
  3. 부탁문을 보내 함수 코드와 앱 쪽 코드 받기되묻는 질문에는 짧게 답합니다
  4. 대시보드에서 함수 만들기[Edge Functions] → [Deploy a new function] → [Via Editor] → 함수 코드 붙여넣기 → 이름 정하고 [Deploy function]함수는 Supabase의 서버에서 돌아서 학생 기기로 내려가지 않습니다. 그래서 키를 꺼내 쓸 수 있습니다.
  5. 함수 설정의 Verify JWT 확인하기publishable 키로 부르는 함수는 끄고, 대신 함수 안에서 호출 횟수를 셉니다. AI가 알려 준 대로publishable 키로 부르면 로그인한 사람의 표(JWT)가 없어서, 이 스위치가 켜져 있으면 401 오류로 막힙니다. 대신 함수 안에서 부르는 횟수를 세어 막습니다.
  6. 앱에서 불러 보기답이 오면 성공. 오류 글은 그대로 AI에게 보냅니다
OpenAI API keys 화면
OpenAI · API keys왼쪽 메뉴의 API Keys입니다. 처음에는 키가 하나도 없고, 오른쪽 위 [+ Create new secret key]로 만듭니다.
OpenAI 새 키 만들기 창
OpenAI · 키 만들기 창Name에 쓰임새를 적고, 만료에서 날짜를 고르면 그날이 지난 뒤에는 키를 쓸 수 없습니다. [Create secret key]를 누르면 키가 한 번만 보이니 바로 Supabase 금고로 옮깁니다.
Edge Function Secrets
SecretsName에 키 이름, Value에 키를 넣고 [Save]를 누릅니다.
Deploy a new function 메뉴
새 함수[Deploy a new function]에서 [Via Editor]를 고르면 브라우저에서 바로 만듭니다.
함수 편집기
편집기받은 코드를 붙여넣고, 아래 Function name을 정한 뒤 [Deploy function]을 누릅니다.
함수 설정의 Verify JWT
Verify JWT함수의 [Settings]에 있는 스위치입니다. publishable 키로 부를 때는 AI가 알려 준 대로 끕니다.
막혔을 때

앱에서 부르니 CORS 오류가 납니다. 오류 글을 그대로 AI에게 보내고 "함수의 CORS 설정에 내 앱 주소를 넣고, OPTIONS 요청에 답하게 고쳐 줘"라고 합니다. 허락할 주소는 https://아이디.github.io처럼 뒤에 폴더 이름 없이 적습니다.

401 오류가 납니다. Verify JWT가 켜져 있으면 publishable 키로는 들어가지 못합니다. 함수 설정에서 끄고 다시 불러 봅니다. 함수를 다시 배포한 뒤 이 설정이 되돌아가는 일이 있어서 한 번 더 확인합니다.

보관함 미리보기에서는 AI 답이 오지 않습니다. 함수가 내 앱 주소만 허락하기 때문입니다. 배포한 주소로 열어서 확인합니다.

Render 서버의 첫 답이 1분 가까이 걸립니다. 무료 서버가 잠들었다 깨는 시간입니다. 수업 시작 전에 한 번 불러 깨워 둡니다.

카드대시보드에 [AI 피드백 초안] 단추 붙이기

함수를 만든 뒤 이 카드를 보내면, 교사 대시보드에서 제출마다 AI 초안을 받아 읽고 고쳐서 저장합니다.

AI 피드백 초안 단추
teacher.html의 제출 상세 창에 [AI 피드백 초안] 단추를 붙여 줘. 누르면 방금 만든 Edge Function을 불러 그 줄의 결론을 보내고, 돌아온 초안을 교사 메모 칸에 넣어 줘. 저장은 내가 읽고 고친 뒤 [저장]을 누를 때만 해 줘. 함수는 로그인한 교사가 부를 때만 답하게 하고, 다른 부분은 그대로 둬.

학생 글을 AI에 보내기 전에 이름과 번호가 들어 있지 않은지 봅니다. 초안은 초안일 뿐이라, 학생에게 돌려주는 글은 제가 읽고 고친 것만 저장합니다.

7

학생에게 내놓기 전 다섯 가지

5분

학생에게 내놓기 전에 다섯 가지를 하나씩 확인해보겠습니다!

이 다섯 가지만 답할 수 있으면 됩니다

  1. 학생 정보가 어디로 가는지앱이 무엇을 어디로 보내는지 적어 봅니다. Supabase의 표, AI 회사. 이름·번호·얼굴 사진은 보내지 않고, 학교의 심의 절차를 확인합니다
  2. API 키가 드러나지 않는지앱 파일에서 Ctrl+F로 sk-, sb_secret, AIza를 찾아 봅니다. 하나라도 나오면 올리지 않습니다
  3. AI가 틀렸을 때 어떻게 하는지AI 답 아래에 "AI가 쓴 답이라 틀릴 수 있어요"를 붙이고, 평가에 쓰는 답은 교사가 먼저 읽습니다
  4. 비용이 폭주하지 않게 무엇으로 막는지세 겹. 회사 쪽 월 한도와 자동 충전 끄기, 함수의 호출 횟수 제한, 짧은 답과 가벼운 모델
  5. 서비스가 고장 났을 때 수업 대안이 있는지같은 활동을 종이 활동지나 AI 없는 판으로 할 수 있게 준비하고, 앱은 오류가 나도 멈추지 않고 안내 문구를 보여 주게 합니다
비용 폭주를 막는 세 겹
요청이 몰림버튼 연타, 퍼 간 주소
함수의 호출 횟수 제한1분에 20번, 하루 300번
짧은 답 · 가벼운 모델한 번에 드는 돈을 줄임
회사 쪽 월 한도넣은 돈에서 멈춤, 자동 충전 끔

몰려온 요청은 호출 횟수 제한에서 대부분 걸러지고, 지나간 요청도 한 번에 드는 돈이 작고, 끝에서는 회사 쪽 한도에서 멈춥니다.

AI 회사나 Supabase도 멈추는 날이 있습니다. 수업 한 차시를 통째로 앱에 걸어 두면 그날 수업이 같이 멈추기 때문에, 앱이 없던 때의 방법을 옆에 남겨 두는 편이 안전합니다.

키가 새어 나갔다면

  1. 그 키를 바로 지우기회사 대시보드의 API keys에서 삭제(Revoke)
  2. 새 키를 만들어 금고에 다시 넣기Supabase [Edge Functions] → [Secrets]에서 값만 바꿉니다
  3. 사용량 화면에서 모르는 사용이 있었는지 보기날짜별 사용량이 갑자기 튀었는지
  4. 모르는 결제가 있으면 회사에 바로 문의하기키를 지운 시각과 사용 기록을 함께 보냅니다

GitHub 공개 저장소에 키를 올리면 GitHub가 찾아내 회사에 알려 주고, OpenAI와 Anthropic은 그 키를 곧바로 막습니다. Supabase도 공개 저장소에서 찾은 secret 키를 없앱니다. 그래도 그 사이에 누군가 쓸 수 있습니다. 2026년 2월에는 한 작은 회사의 Google 키가 새어 나가 48시간 만에 8만 2천 달러, 우리 돈으로 1억 원이 넘게 청구된 일이 보도되기도 했습니다.

학생 정보를 모으거나 학생이 AI를 쓰게 하는 앱은 학교의 절차를 먼저 확인합니다. 2026학년도부터 학교에서 쓰는 에듀테크와 소프트웨어는 학교운영위원회 심의를 거치게 되었습니다.

8

한 번 더 확인하고 보관함에

5분

파일에 비밀 키가 없는지 확인하고, 보관함에 올려보겠습니다!

  1. 앱 파일에서 비밀 키 찾기Ctrl+F로 sk-, sb_secret, AIza. publishable 키(sb_publishable_)는 들어 있어도 괜찮습니다
  2. 연습으로 넣은 줄 지우기Table Editor에서 줄을 골라 [Delete]
  3. 보관함에 올리기회차와 PIN을 고르고 index.html을 끌어다 놓기
GiteacherHub · 올리기제출 기능이 붙은 앱도 보관함에서 열어 볼 수 있습니다.
올리기 열기 ↗

학생 제출 모으기, 교사 로그인, 학교 심의 자료까지 더 깊이 다룬 자료는 학생 데이터, 모으기 전에에 있습니다.

연수 허브로 돌아가기

←→ 단계 이동 · t 타이머 · p 📖/🎤