VIBE CODING / FIELD HANDBOOK

3일차 · 본문 교재

이 폴더 안에서 발표·교재·코드·심화 원문을 오프라인으로 이동할 수 있습니다.

03일차
04교시
38발표 슬라이드
04공통 원문 파일
TECHNOLOGY

프런트엔드·백엔드·DB의 실제 역할

기술종류역할
HTML·CSS마크업·스타일 언어화면 구조와 표현
JavaScript·TypeScript프로그래밍 언어화면·서버의 동작
React·Next.jsUI 라이브러리·웹 프레임워크컴포넌트·페이지·서버 경로
Node.js서버 실행 환경TypeScript/JavaScript 서버 실행
PostgreSQL·SQL관계형 DB·질의 언어저장·조회·무결성
Supabase백엔드 플랫폼DB·Auth·Storage·API
Docker·Vercel컨테이너 도구·배포 플랫폼로컬 스택·공개 앱

세 프로젝트의 주 DB는 Supabase PostgreSQL이다. MySQL·SQLite는 관계형 DB, MongoDB는 문서형 DB의 비교 예시다. uc-anchor의 선택형 Python PDF 서비스는 Next.js·Vercel 기본 배포와 분리해 설명한다. 현재 운영 전체 기능을 재검증한 표는 아니다.

목차와 처음으로 ↑
FIELD NOTES

과제 앱의 DB·로그인·Vercel 공개

Supabase Auth·PostgreSQL·RLS로 회원별 저장을 연결하고 Vercel에서 검증

CLASS / D3-1

3일차 1교시 · 과제 앱의 Supabase DB·RLS 설계

과제 앱의 Supabase DB·RLS 설계를 실제 과제 체크 앱에서 구현·검증한다.

D3-150분도입8·환경10·DB/RLS20·짝검증8·정리4

산출물: tasks 스키마·RLS SQL·로컬 Vite 앱

교시별 슬라이드 구성

번호제목진행 내용
084같은 앱, 저장 위치를 바꾸다아래 단계별 실습을 진행한다.
085테이블 권한과 행 권한을 함께tasks: id · user_id · title · subject · due · done · created_at / authenticated 최소 GRANT · anon 접근 차단 / SELECT/DELETE USING · INSERT WITH CHECK / UPDATE USING + WITH CHECK · 소유자/id/생성시각 보존
086과제 앱의 Supabase DB·RLS 설계과제 앱의 Supabase DB·RLS 설계를 실제 과제 체크 앱에서 구현·검증한다. / 산출물: tasks 스키마·RLS SQL·로컬 Vite 앱 / 도입8·환경10·DB/RLS20·짝검증8·정리4분
087핵심 개념브라우저 저장과 회원별 PostgreSQL / 테이블 GRANT와 행 RLS / Vite·공개 설정·publishable key
088AI Studio 비교에서 회원별 DB 설계로AI Studio는 빠른 시제품 경로로 비교하고 주 실습은 Codex 앱을 이어간다. / 생성된 화면과 실제 PostgreSQL 저장·Auth·권한은 구분한다. / tasks의 user_id와 입력 제약을 설계하고 GRANT·RLS를 함께 확인한다. / 로컬과 클라우드 프로젝트의 URL·DB 대상을 명시한다.
089u-livet · 이번 실습에 적용할 판단기록: 데이터 구조·운영 화면을 만든 뒤 로컬 인증과 업무 기능을 검증했다. / 판단: 데이터 저장 구조와 운영 환경을 구분했다. / 적용: 과제 앱은 user_id를 기준으로 계정별 PostgreSQL 행을 설계한다.
090실습 절차아래 단계별 실습을 진행한다.
091Codex에 입력할 요청아래 전체 구현 요청을 사용한다.
092완료 확인과 오류 대응필수 범위는 이메일 로그인과 회원별 tasks CRUD다. Google·Kakao·Naver·MFA는 4일차에서 이어간다. 브라우저의 전날 목록은 자동 업로드하지 않으며 가상 과제를 새로 만든다. / Node는 설치 버전의 요구사항을 만족해야 한다(제공 예제는22.12이상). .env.local은 Git에서 무시된다. VITE_ 값은 브라우저에 포함되는 공개 설정이며 secret/service_role을 숨겨주는 기능이 아니다. / tasks.user_id는 auth.users.id와 연결된다. SELECT/DELETE는 소유자 USING, INSERT는 WITH CHECK, UPDATE는 USING+WITH CHECK다. anon에는 권한이 없다. 명시적 GRANT와 RLS는 각각 “테이블 접근”과 “행 접근”을 담당한다.

같은 과제 앱의 회원별 DB 실습

K01~K08과 C01~C08을 이어서 사용한다. 전날 화면·검색·수정은 유지하고 Supabase DB·Auth와 Vercel을 연결한다.

3일차 전체 단계·SQL·설정·강사 설명 ↗ · 전날 시작·DB 완성 소스 ZIP

AI Studio 비교에서 회원별 DB 설계로

  • AI Studio는 빠른 시제품 경로로 비교하고 주 실습은 Codex 앱을 이어간다.
  • 생성된 화면과 실제 PostgreSQL 저장·Auth·권한은 구분한다.
  • tasks의 user_id와 입력 제약을 설계하고 GRANT·RLS를 함께 확인한다.
  • 로컬과 클라우드 프로젝트의 URL·DB 대상을 명시한다.

u-livet 사례 · 이번 실습에 적용할 판단

  • 기록: 데이터 구조·운영 화면을 만든 뒤 로컬 인증과 업무 기능을 검증했다.
  • 판단: 데이터 저장 구조와 운영 환경을 구분했다.
  • 적용: 과제 앱은 user_id를 기준으로 계정별 PostgreSQL 행을 설계한다.

u-livet 전체 구축 과정·기술 역할 ↗

선택 심화 · 원문 2개 열기

해당 교시의 설명을 대체하거나 실습 뒤 선택한다. 별도 수업시간을 추가하지 않는다.

연결 내용을 설명하는 강사 메모

Google AI Studio15분 안내는 선택 비교로 유지한다. 모두가 새 프로젝트를 만들도록 요구하지 않고 Supabase DB·RLS 설계 실습으로 이어간다.

강사용 설명

1교시 도입8분 중 AI Studio는 선택 비교 시연5분만 사용한다. 주 실습은 Codex 경로다. 프런트엔드 HTML/CSS/JavaScript, Vite 빌드 도구, Supabase PostgreSQL·Auth·Data API의 역할을 실제 앱으로 비교한다. 별도 서버 언어를 새로 배우는 시간이 아니다. 2일차에 clone한 폴더를 그대로 사용한다. Vite는 기존 HTML·JS를 빌드하는 도구다. ZIP의 solution 안 파일을 저장소 루트에 놓고 .git은 교체하지 않는다. GitHub Pages는 Vite 소스를 그대로 실행하지 못하므로 3일차 공개 주소는 Vercel로 기록한다. 이전 Pages 화면은 2일차 커밋에서 다시 확인할 수 있다. 1교시50분은 도입8·프로젝트/환경10·스키마/RLS20·짝점검8·정리4다. 테이블이 보인다는 이유로 API 접근 성공을 단정하지 않는다. 최신 Supabase의 자동 노출 변화에 맞춰 명시적 GRANT를 사용한다. SQL Editor의 관리자 권한은 일반 사용자 RLS 검사를 대신하지 못한다. 프로젝트 생성·계정 준비는 수업 전에 마친다. C01~C08과 K01~K08의 상세 교재·전날 시작/완성 소스/SQL ZIP을 사용한다.

실습 절차

  1. 같은 앱의 저장 위치와 완료 기준 정하기: 전날 수정·검색 앱을 열고 “이 브라우저 저장”과 “계정별 DB 저장”의 차이를 적는다. 오늘의 완료 기준은 회원가입→이메일 확인→로그인→내 과제 저장→새로고침·다른 브라우저 재조회→다른 계정 차단→공개 Vercel URL이다.
  2. 기능 브랜치와 Vite·공개 설정 준비: 본인 저장소의 깨끗한 main을 최신화하고 feature/supabase-tasks를 만든다. Codex에 요청1을 입력해 기존 화면을 Vite 프로젝트로 구성한다. ZIP solution을 참고하면 index.html/styles.css/src/·package.json·lockfile·sql/을 저장소 루트에 둔다. .env.example을 .env.local로 복사해 본인 수업 프로젝트 URL과 publishable key를 입력하고 npm ci, npm run dev를 실행한다.
  3. 새 수업용 DB에 tasks·GRANT·RLS 적용: 자신의 새 수업용 Supabase 프로젝트에서 SQL Editor를 열어 sql/setup.sql 전체를 한 번 실행한다. 기존 tasks가 있으면 구조와 정책부터 비교하고 임의로 삭제하지 않는다. sql/inspect.sql로 RLS·네 정책·authenticated의 접근 권한과 편집 가능한 열을 확인한다. Data API의 public 노출과 테이블 권한을 함께 확인한다.

Codex 구현 요청

2일차 과제 체크 앱과 현재 Git 브랜치·diff를 먼저 읽어줘. 기존 HTML/CSS·수정·검색·완료·집계를 유지하면서 Vite와 @supabase/supabase-js로 구성해줘. 현재 공식 문서와 설치 버전의 Node 요구를 확인하고 패키지 버전을 고정해 lockfile을 남겨줘. DB는 새 수업용 Supabase의 public.tasks에 id uuid, user_id(auth.users 참조), title(공백만 불가·60자), subject(20자), due(date), done, created_at을 둬. user_id·due 인덱스, RLS, authenticated의 최소 GRANT와 본인 user_id=auth.uid() 조건의 SELECT/INSERT/UPDATE/DELETE 정책을 SQL 파일로 만들어줘. UPDATE는 USING과 WITH CHECK를 모두 쓰고 소유자·id·생성시각은 수정하지 못하게 해줘. anon은 데이터에 접근하지 못하게 해줘. 공개 URL과 publishable key만 VITE_SUPABASE_URL/VITE_SUPABASE_PUBLISHABLE_KEY로 읽고 .env.example과 .gitignore를 만들어줘. secret/service_role·DB 비밀번호는 브라우저나 Git에 넣지 마. 기존 운영 DB에 SQL을 실행하지 말고 새 수업 프로젝트에서 적용할 SQL과 검증 절차를 보여줘.

AI 검증·오류 해결 요청

수업용 Supabase에서 계정 A와 B를 만들어 실제 가입 메일·로그인을 확인해줘. A가 만든 과제를 새로고침과 다른 브라우저의 A 로그인으로 다시 읽고 수정·완료·삭제·되돌리기를 검사해줘. B에서는 A 행 조회0건, A id를 지정한 수정·삭제0건 또는 거절, user_id=A로 위조INSERT 거절, 소유자변경 거절을 Data API 요청으로 검사해줘. 미로그인 요청도 차단되는지 확인해줘. SQL Editor 관리자 조회를 RLS 통과 증거로 쓰지 마. 계정 전환 직후와 늦은 이전 요청 응답에서 A 목록이 B 화면에 나타나지 않는지, 네트워크 실패가 저장 성공으로 표시되지 않는지 확인해줘. 공개 Vercel URL의 배포commit·환경·가입복귀URL도 대조하고 결과를 통과/실패/미확인으로 기록해줘. 이메일·비밀번호·토큰은 보고서에 넣지 마.

완료 확인

  • 필수 범위는 이메일 로그인과 회원별 tasks CRUD다. Google·Kakao·Naver·MFA는 4일차에서 이어간다. 브라우저의 전날 목록은 자동 업로드하지 않으며 가상 과제를 새로 만든다.
  • Node는 설치 버전의 요구사항을 만족해야 한다(제공 예제는22.12이상). .env.local은 Git에서 무시된다. VITE_ 값은 브라우저에 포함되는 공개 설정이며 secret/service_role을 숨겨주는 기능이 아니다.
  • tasks.user_id는 auth.users.id와 연결된다. SELECT/DELETE는 소유자 USING, INSERT는 WITH CHECK, UPDATE는 USING+WITH CHECK다. anon에는 권한이 없다. 명시적 GRANT와 RLS는 각각 “테이블 접근”과 “행 접근”을 담당한다.

자주 막히는 지점

  • Invalid API key/설정 전: 변수명·VITE_접두사·재시작/재빌드
  • permission denied: 명시GRANT와소유자정책확인
  • 목록0건: 빈목록정상인지API오류인지구분
  • 수정/삭제0건: 반환행없음을성공으로표시하지않기
  • 가입메일없음: 강사사전준비SMTP/로컬Mailpit사용
  • 확인후localhost복귀: 실제Production루트로정정
  • PKCE교환실패: 같은브라우저에서새링크또는확인후로그인
  • Vercel빌드실패: npm ci/npm run build로재현
  • 이전환경이보임: 환경변경뒤새배포
  • 전날목록이없음: 자동업로드없음·가상DB과제로시작
  • B가A과제를봄: 공개중단후소유자정책/세션분리수정

확인 질문

로그인 버튼을 숨기면 다른 사람의 DB 접근도 막히는가?

화면과 별개로 GRANT와 소유자 RLS가 DB 요청을 제한해야 한다.

이 교시 발표 화면 열기 ↗

근거와 참고 자료
목차와 처음으로 ↑
CLASS / D3-2

3일차 2교시 · 과제 앱 회원가입·이메일 확인·로그인

과제 앱 회원가입·이메일 확인·로그인를 실제 과제 체크 앱에서 구현·검증한다.

D3-250분흐름8·구현22·메일/세션8·짝검증8·정리4

산출물: 가입/확인대기/로그인/로그아웃 흐름

교시별 슬라이드 구성

번호제목진행 내용
093가입 요청과 로그인 완료는 다르다아래 단계별 실습을 진행한다.
094Codex: 인증과 회원별 과제 연결아래 전체 구현 요청을 사용한다.
095과제 앱 회원가입·이메일 확인·로그인과제 앱 회원가입·이메일 확인·로그인를 실제 과제 체크 앱에서 구현·검증한다. / 산출물: 가입/확인대기/로그인/로그아웃 흐름 / 흐름8·구현22·메일/세션8·짝검증8·정리4분
096핵심 개념이메일 가입과 확인 대기 / PKCE·복귀 URL·세션 복원 / 로그아웃 시 목록 비우기
097가입·로그인과 실제 인증 메일의 연결가입 요청·이메일 확인·세션 생성·비밀번호 복구를 구분한다. / Resend 도메인/DNS→Supabase SMTP→메일 템플릿·복귀 주소 순서로 확인한다. / 발송 요청 성공과 수신함 도착·링크 처리 성공을 따로 기록한다. / Site URL·Redirect URLs·비밀번호 정책과 비밀 보관 위치를 대조한다.
098u-livet · 이번 실습에 적용할 판단기록: 로그인 성공 뒤에도 가입 완료 상태와 업무 자격을 따로 확인했다. / 비교: uc-anchor의 Resend 구축 기록은 DNS·SMTP·메일 링크를 구분한다. / 적용: 과제 앱에서 확인 대기·실제 수신·로그인·복구를 각각 검사한다.
099실습 절차아래 단계별 실습을 진행한다.
100Codex에 입력할 요청아래 전체 구현 요청을 사용한다.
101완료 확인과 오류 대응가입 요청 성공과 메일 도착·확인·로그인 성공을 따로 기록한다. PKCE 확인 링크는 요청한 같은 브라우저에서 연다. 다른 브라우저에서 확인했다면 이메일 확인 완료 후 원래 앱에서 이메일/비밀번호 로그인을 다시 시도한다.

같은 과제 앱의 회원별 DB 실습

K01~K08과 C01~C08을 이어서 사용한다. 전날 화면·검색·수정은 유지하고 Supabase DB·Auth와 Vercel을 연결한다.

3일차 전체 단계·SQL·설정·강사 설명 ↗ · 전날 시작·DB 완성 소스 ZIP

가입·로그인과 실제 인증 메일의 연결

  • 가입 요청·이메일 확인·세션 생성·비밀번호 복구를 구분한다.
  • Resend 도메인/DNS→Supabase SMTP→메일 템플릿·복귀 주소 순서로 확인한다.
  • 발송 요청 성공과 수신함 도착·링크 처리 성공을 따로 기록한다.
  • Site URL·Redirect URLs·비밀번호 정책과 비밀 보관 위치를 대조한다.

u-livet 사례 · 이번 실습에 적용할 판단

  • 기록: 로그인 성공 뒤에도 가입 완료 상태와 업무 자격을 따로 확인했다.
  • 비교: uc-anchor의 Resend 구축 기록은 DNS·SMTP·메일 링크를 구분한다.
  • 적용: 과제 앱에서 확인 대기·실제 수신·로그인·복구를 각각 검사한다.

u-livet 전체 구축 과정·기술 역할 ↗

선택 심화 · 원문 9개 열기

해당 교시의 설명을 대체하거나 실습 뒤 선택한다. 별도 수업시간을 추가하지 않는다.

연결 내용을 설명하는 강사 메모

DNS·SMTP는 강사가 미리 준비한다. 도메인 설정과 메일 실패 진단표는 별도 원문으로 제공하고 교시에서는 실제 가입·확인 대기·로그인을 완주한다.

강사용 설명

2교시 50분은 흐름8·Auth 구현22·메일/세션8·짝 검증8·정리4다. 기본 SMTP는 발송 대상과 사용량 제한이 있다. 강사는 Resend 검증 도메인·SMTP 또는 로컬 Mailpit를 사전 준비한다. 메일이 막히면 이메일 확인 기능을 끄지 않고 발송 경로를 고친다. 비밀번호 분실 복구·변경은 완성 예제와 F09~F14를 보충으로 사용한다. C01~C08과 K01~K08의 상세 교재·전날 시작/완성 소스/SQL ZIP을 사용한다.

실습 절차

  1. 회원가입·메일 확인·로그인·로그아웃 연결: 요청2를 Codex에 입력하고 Authentication의 Email 가입과 Confirm email을 확인한다. 비밀번호 최소12자 정책을 앱과 서버에서 맞춘다. URL Configuration의 Site URL과 Redirect URLs에 실제 로컬 루트(http://localhost:5173/ 등)를 설정한다. 수신 가능한 수업 계정 A로 가입하고 메일 확인 뒤 로그인·새로고침·로그아웃을 각각 시험한다.

Codex 구현 요청

현재 앱에 Supabase 이메일 회원가입·확인 대기·로그인·로그아웃과 회원별 과제 CRUD를 연결해줘. 가입 응답에서 session이 없으면 메일 확인 대기로 표시하고 로그인 성공과 구분해줘. 단일 브라우저 앱은 PKCE·현재 루트 복귀 주소·SDK 세션 복원을 일관되게 사용하고 허용 Redirect URL을 안내해줘. 가입 new-password/로그인 current-password, label·POST form·비밀번호 표시·12자 가입 규칙·중복 제출 방지를 넣어줘. 비밀번호·토큰·계정 존재 여부를 로그나 오류에 노출하지 마. 로그인 전 목록을 숨기고 계정 변경 즉시 이전 목록·편집·되돌리기를 지워줘. 이전 계정의 늦은 요청 응답도 무시해줘. DB select/insert/update/delete의 error와 반환 행을 확인한 뒤만 성공을 표시해줘. 수정은 동일 id·완료·생성시각을 보존하고 삭제 되돌리기도 DB에 반영해줘. 검색·완료 필터·날짜 집계를 유지하며 다른 기기 변경은 새로 불러오기로 조회해줘. localStorage의 전날 과제를 자동 업로드하지 말고 가상 DB 과제로 시작해줘. 네트워크 실패 때 미저장 입력을 유지해줘. 실제 실행 결과와 미실행을 구분해줘.

AI 검증·오류 해결 요청

수업용 Supabase에서 계정 A와 B를 만들어 실제 가입 메일·로그인을 확인해줘. A가 만든 과제를 새로고침과 다른 브라우저의 A 로그인으로 다시 읽고 수정·완료·삭제·되돌리기를 검사해줘. B에서는 A 행 조회0건, A id를 지정한 수정·삭제0건 또는 거절, user_id=A로 위조INSERT 거절, 소유자변경 거절을 Data API 요청으로 검사해줘. 미로그인 요청도 차단되는지 확인해줘. SQL Editor 관리자 조회를 RLS 통과 증거로 쓰지 마. 계정 전환 직후와 늦은 이전 요청 응답에서 A 목록이 B 화면에 나타나지 않는지, 네트워크 실패가 저장 성공으로 표시되지 않는지 확인해줘. 공개 Vercel URL의 배포commit·환경·가입복귀URL도 대조하고 결과를 통과/실패/미확인으로 기록해줘. 이메일·비밀번호·토큰은 보고서에 넣지 마.

완료 확인

  • 가입 요청 성공과 메일 도착·확인·로그인 성공을 따로 기록한다. PKCE 확인 링크는 요청한 같은 브라우저에서 연다. 다른 브라우저에서 확인했다면 이메일 확인 완료 후 원래 앱에서 이메일/비밀번호 로그인을 다시 시도한다.

자주 막히는 지점

  • Invalid API key/설정 전: 변수명·VITE_접두사·재시작/재빌드
  • permission denied: 명시GRANT와소유자정책확인
  • 목록0건: 빈목록정상인지API오류인지구분
  • 수정/삭제0건: 반환행없음을성공으로표시하지않기
  • 가입메일없음: 강사사전준비SMTP/로컬Mailpit사용
  • 확인후localhost복귀: 실제Production루트로정정
  • PKCE교환실패: 같은브라우저에서새링크또는확인후로그인
  • Vercel빌드실패: npm ci/npm run build로재현
  • 이전환경이보임: 환경변경뒤새배포
  • 전날목록이없음: 자동업로드없음·가상DB과제로시작
  • B가A과제를봄: 공개중단후소유자정책/세션분리수정

확인 질문

가입 요청 성공을 로그인 완료라고 표시하면 왜 안 되는가?

이메일 확인과 세션 생성이 남아 있을 수 있으므로 대기 상태와 실제 로그인을 구분한다.

이 교시 발표 화면 열기 ↗

근거와 참고 자료
목차와 처음으로 ↑
CLASS / D3-3

3일차 3교시 · 회원별 과제 CRUD와 A/B 권한 검증

회원별 과제 CRUD와 A/B 권한 검증를 실제 과제 체크 앱에서 구현·검증한다.

D3-350분읽기/쓰기8·CRUD18·계정/권한12·짝검증8·정리4

산출물: 회원별 DB 과제와 A/B 검증표

교시별 슬라이드 구성

번호제목진행 내용
102저장 성공은 DB 재조회로 확인아래 단계별 실습을 진행한다.
103B 계정으로 A의 과제를 요청하면?B가 A id 조회:0건 · 수정/삭제:0건 또는 거절 / B의 user_id 위조 INSERT·소유자 변경:거절 / 미로그인 차단 · 로그아웃 즉시 목록 비우기 / 관리자 SQL 조회로 RLS 성공을 판단하지 않는다
104회원별 과제 CRUD와 A/B 권한 검증회원별 과제 CRUD와 A/B 권한 검증를 실제 과제 체크 앱에서 구현·검증한다. / 산출물: 회원별 DB 과제와 A/B 검증표 / 읽기/쓰기8·CRUD18·계정/권한12·짝검증8·정리4분
105핵심 개념비동기 CRUD와 반환 행 확인 / 계정별 검색·필터·집계 / A/B·익명 요청과 소유자 위조 차단
106저장 성공 표시보다 재조회·계정 분리A가 추가한 과제를 새로고침해 같은 값으로 읽는지 확인한다. / B가 A의 id를 알아도 조회·수정·삭제할 수 없어야 한다. / SQL Editor 관리자 결과와 일반 사용자의 Data API 검사는 다르다. / 소유권 위조·빈 결과·오류를 정상 CRUD와 함께 기록한다.
107kysong · 이번 실습에 적용할 판단기록: 임시저장·복구와 최종 제출 판정의 일관성을 보완했다. / 판단: 저장 성공 안내만으로 실제 DB 결과를 판단하지 않는다. / 적용: 과제 앱에서 재조회 값과 사용자별 기록 분리를 함께 확인한다.
108실습 절차아래 단계별 실습을 진행한다.
109Codex에 입력할 요청아래 전체 구현 요청을 사용한다.
110완료 확인과 오류 대응insert/update/delete의 error와 반환 행을 확인해야 성공이다. 수정 후 id·done·created_at과 개수는 유지된다. 다른 기기에서 같은 계정으로 로그인한 뒤 다시 조회하면 같은 DB 목록을 읽는다. 이 예제의 새로 불러오기는 Realtime 자동 동기화가 아니다. / A는 자기 행만 CRUD, B의 A 조회는0건, 수정·삭제는0건 또는 오류, 위조 INSERT·소유자 변경은거절되어야 한다. 미로그인도 데이터에 접근하지 못한다. 화면이 숨겨졌다는 이유만으로 RLS 통과라 하지 않는다.

같은 과제 앱의 회원별 DB 실습

K01~K08과 C01~C08을 이어서 사용한다. 전날 화면·검색·수정은 유지하고 Supabase DB·Auth와 Vercel을 연결한다.

3일차 전체 단계·SQL·설정·강사 설명 ↗ · 전날 시작·DB 완성 소스 ZIP

저장 성공 표시보다 재조회·계정 분리

  • A가 추가한 과제를 새로고침해 같은 값으로 읽는지 확인한다.
  • B가 A의 id를 알아도 조회·수정·삭제할 수 없어야 한다.
  • SQL Editor 관리자 결과와 일반 사용자의 Data API 검사는 다르다.
  • 소유권 위조·빈 결과·오류를 정상 CRUD와 함께 기록한다.

kysong 사례 · 이번 실습에 적용할 판단

  • 기록: 임시저장·복구와 최종 제출 판정의 일관성을 보완했다.
  • 판단: 저장 성공 안내만으로 실제 DB 결과를 판단하지 않는다.
  • 적용: 과제 앱에서 재조회 값과 사용자별 기록 분리를 함께 확인한다.

kysong 전체 구축 과정·기술 역할 ↗

선택 심화 · 원문 1개 열기

해당 교시의 설명을 대체하거나 실습 뒤 선택한다. 별도 수업시간을 추가하지 않는다.

연결 내용을 설명하는 강사 메모

이 교시의 과제 앱은 아직4일차 MFA를 추가하기 전이다. RLS A/B 기본 검사를 하고 MFA 전후 통합 검사는4~5일차로 이어간다.

강사용 설명

3교시 50분은 읽기/쓰기8·CRUD 구현18·계정/권한12·짝 검증8·정리4다. DB 저장에서는 비동기 오류와 인증 상태를 함께 다룬다. 저장 실패 때 입력값을 남기고 성공 안내를 보내지 않는지 보여준다. 예제는 최대1,000건을 조회하며 대량 데이터는 페이지 나누기를 추후 설계한다. 완성 ZIP의 절차와 Codex 검증 요청을 사용한다. 토큰을 스크린샷이나 과제물에 넣지 않는다. 화면 검색으로 A의 과제를 숨기는 것과 DB가 접근을 거절하는 것은 다르다. 빈 목록이 테이블 권한 오류인지 정상 RLS 차단인지 구분한다. 계정을 바꾸는 동안 도착한 이전 요청의 응답도 다른 계정 화면에 나타나지 않아야 한다. C01~C08과 K01~K08의 상세 교재·전날 시작/완성 소스/SQL ZIP을 사용한다.

실습 절차

  1. 내 과제 CRUD를 DB에 저장하고 다시 읽기: A로 로그인해 가상 과제 두 개를 DB에 추가한다. 완료 상태를 바꾸고 제목·과목·마감일을 수정한다. 새로고침과 새로 불러오기로 DB 값을 재조회하고 삭제/되돌리기도 확인한다. 제목·과목 검색과 완료 필터·오늘/기한 지남 집계가 현재 계정 목록에서 작동하는지 확인한다.
  2. A·B 계정과 미로그인으로 권한 검증: 브라우저 일반 창의 A와 별도 프로필/다른 브라우저의 B로 각각 로그인한다. A의 과제 id를 가상 테스트 기록에만 적고, B의 Data API로 A id 조회·수정·삭제와 user_id 위조 INSERT를 검사한다. 로그아웃 직후 목록과 폼이 비워지는지도 확인한다. 상세 검증표의 실제 결과를 기록한다.

Codex 구현 요청

현재 앱에 Supabase 이메일 회원가입·확인 대기·로그인·로그아웃과 회원별 과제 CRUD를 연결해줘. 가입 응답에서 session이 없으면 메일 확인 대기로 표시하고 로그인 성공과 구분해줘. 단일 브라우저 앱은 PKCE·현재 루트 복귀 주소·SDK 세션 복원을 일관되게 사용하고 허용 Redirect URL을 안내해줘. 가입 new-password/로그인 current-password, label·POST form·비밀번호 표시·12자 가입 규칙·중복 제출 방지를 넣어줘. 비밀번호·토큰·계정 존재 여부를 로그나 오류에 노출하지 마. 로그인 전 목록을 숨기고 계정 변경 즉시 이전 목록·편집·되돌리기를 지워줘. 이전 계정의 늦은 요청 응답도 무시해줘. DB select/insert/update/delete의 error와 반환 행을 확인한 뒤만 성공을 표시해줘. 수정은 동일 id·완료·생성시각을 보존하고 삭제 되돌리기도 DB에 반영해줘. 검색·완료 필터·날짜 집계를 유지하며 다른 기기 변경은 새로 불러오기로 조회해줘. localStorage의 전날 과제를 자동 업로드하지 말고 가상 DB 과제로 시작해줘. 네트워크 실패 때 미저장 입력을 유지해줘. 실제 실행 결과와 미실행을 구분해줘.

AI 검증·오류 해결 요청

수업용 Supabase에서 계정 A와 B를 만들어 실제 가입 메일·로그인을 확인해줘. A가 만든 과제를 새로고침과 다른 브라우저의 A 로그인으로 다시 읽고 수정·완료·삭제·되돌리기를 검사해줘. B에서는 A 행 조회0건, A id를 지정한 수정·삭제0건 또는 거절, user_id=A로 위조INSERT 거절, 소유자변경 거절을 Data API 요청으로 검사해줘. 미로그인 요청도 차단되는지 확인해줘. SQL Editor 관리자 조회를 RLS 통과 증거로 쓰지 마. 계정 전환 직후와 늦은 이전 요청 응답에서 A 목록이 B 화면에 나타나지 않는지, 네트워크 실패가 저장 성공으로 표시되지 않는지 확인해줘. 공개 Vercel URL의 배포commit·환경·가입복귀URL도 대조하고 결과를 통과/실패/미확인으로 기록해줘. 이메일·비밀번호·토큰은 보고서에 넣지 마.

완료 확인

  • insert/update/delete의 error와 반환 행을 확인해야 성공이다. 수정 후 id·done·created_at과 개수는 유지된다. 다른 기기에서 같은 계정으로 로그인한 뒤 다시 조회하면 같은 DB 목록을 읽는다. 이 예제의 새로 불러오기는 Realtime 자동 동기화가 아니다.
  • A는 자기 행만 CRUD, B의 A 조회는0건, 수정·삭제는0건 또는 오류, 위조 INSERT·소유자 변경은거절되어야 한다. 미로그인도 데이터에 접근하지 못한다. 화면이 숨겨졌다는 이유만으로 RLS 통과라 하지 않는다.

자주 막히는 지점

  • Invalid API key/설정 전: 변수명·VITE_접두사·재시작/재빌드
  • permission denied: 명시GRANT와소유자정책확인
  • 목록0건: 빈목록정상인지API오류인지구분
  • 수정/삭제0건: 반환행없음을성공으로표시하지않기
  • 가입메일없음: 강사사전준비SMTP/로컬Mailpit사용
  • 확인후localhost복귀: 실제Production루트로정정
  • PKCE교환실패: 같은브라우저에서새링크또는확인후로그인
  • Vercel빌드실패: npm ci/npm run build로재현
  • 이전환경이보임: 환경변경뒤새배포
  • 전날목록이없음: 자동업로드없음·가상DB과제로시작
  • B가A과제를봄: 공개중단후소유자정책/세션분리수정

확인 질문

B가 A의 과제 id를 알게 되어도 안전한가?

RLS와 GRANT가 올바르면 조회·수정·삭제 및 소유자 위조가 차단된다. 실제 API 요청으로 확인한다.

이 교시 발표 화면 열기 ↗

근거와 참고 자료
목차와 처음으로 ↑
CLASS / D3-4

3일차 4교시 · 과제 앱 Vercel 배포와 공개 검증

과제 앱 Vercel 배포와 공개 검증를 실제 과제 체크 앱에서 구현·검증한다.

D3-450분빌드/Git8·배포12·URL/메일10·공개검증12·정리8

산출물: Vercel 공개 URL·PR·배포 근거

교시별 슬라이드 구성

번호제목진행 내용
111GitHub에서 Vercel 공개 앱으로아래 단계별 실습을 진행한다.
112공개 URL에서 끝까지 확인하기Supabase Site URL:고정 Production 루트 / Redirect URLs:정확한 로컬/공개/필요 Preview 주소 / 공개 앱에서 가입·로그인·CRUD·기기간·A/B 검증 / 제출:PR · 배포 SHA · Vercel URL · 실제 검사표
113과제 앱 Vercel 배포와 공개 검증과제 앱 Vercel 배포와 공개 검증를 실제 과제 체크 앱에서 구현·검증한다. / 산출물: Vercel 공개 URL·PR·배포 근거 / 빌드/Git8·배포12·URL/메일10·공개검증12·정리8분
114핵심 개념Vite build·dist·Root Directory / 환경 범위·재빌드·Site URL / 배포 상태와 공개 기능 검증
115GitHub에서 Vercel·Supabase로 이어지는 설정GitHub는 소스 이력, Vercel은 앱 배포, Supabase는 DB·Auth를 담당한다. / Root Directory·build·dist와 환경변수 범위를 확인한다. / 공개 URL/key와 서버 비밀을 구분하고 환경 변경 뒤 재빌드한다. / READY 후 공개 URL의 로그인·메일 복귀·저장/재조회를 검사한다.
116uc-anchor · 이번 실습에 적용할 판단기술: TypeScript 프런트엔드·Node.js API·PostgreSQL이 다른 역할을 맡는다. / 비교: Git의 코드와 Supabase Auth/SMTP 설정은 별도 기록이다. / 적용: 과제 앱의 배포 commit·앱 URL·DB 대상을 한 표에 적는다.
117실습 절차아래 단계별 실습을 진행한다.
118Codex에 입력할 요청아래 전체 구현 요청을 사용한다.
119완료 확인과 오류 대응solution 안 파일을 저장소 루트에 넣었다면 Root Directory는 루트다. solution 폴더 자체를 저장소에 넣었다면 실제 경로를 지정한다. Vercel이 Next.js 또는 public/을 빌드하도록 설정되어 있으면 고친다. DB 비밀번호나 service_role은 입력하지 않는다. / 제출: PR URL·main 커밋·배포 커밋·Vercel URL·Supabase 프로젝트 식별자(키 제외)·메일/로그인/DB/권한 체크표. READY는 빌드·배포 상태이며 실제 가입·저장 통과와 다르다. 대기나 미실행은 미확인으로 기록한다.

같은 과제 앱의 회원별 DB 실습

K01~K08과 C01~C08을 이어서 사용한다. 전날 화면·검색·수정은 유지하고 Supabase DB·Auth와 Vercel을 연결한다.

3일차 전체 단계·SQL·설정·강사 설명 ↗ · 전날 시작·DB 완성 소스 ZIP

GitHub에서 Vercel·Supabase로 이어지는 설정

  • GitHub는 소스 이력, Vercel은 앱 배포, Supabase는 DB·Auth를 담당한다.
  • Root Directory·build·dist와 환경변수 범위를 확인한다.
  • 공개 URL/key와 서버 비밀을 구분하고 환경 변경 뒤 재빌드한다.
  • READY 후 공개 URL의 로그인·메일 복귀·저장/재조회를 검사한다.

uc-anchor 사례 · 이번 실습에 적용할 판단

  • 기술: TypeScript 프런트엔드·Node.js API·PostgreSQL이 다른 역할을 맡는다.
  • 비교: Git의 코드와 Supabase Auth/SMTP 설정은 별도 기록이다.
  • 적용: 과제 앱의 배포 commit·앱 URL·DB 대상을 한 표에 적는다.

uc-anchor 전체 구축 과정·기술 역할 ↗

선택 심화 · 원문 2개 열기

해당 교시의 설명을 대체하거나 실습 뒤 선택한다. 별도 수업시간을 추가하지 않는다.

연결 내용을 설명하는 강사 메모

서버 설정이 저장소에 모두 포함돼 있다고 가정하지 않는다. 배포 성공과 회원 서비스의 실제 동작 성공을 구분한다.

강사용 설명

4교시 50분은 빌드/Git8·Vercel12·URL/메일10·공개 A/B 검증12·짝 확인/정리8이다. 전날의 PR 절차를 재사용한다. Framework 자동 감지 결과를 검토한다. 환경값은 빌드에 포함되므로 변경 후 재배포한다. 앱 배포와 DB 스키마 적용은 별개이며 Vercel이 SQL을 자동 실행하지 않는다. Resend SMTP는 Supabase Auth 설정에 보관한다. 앱이 별도 메일을 보내지 않는다면 Resend 키를 Vercel 클라이언트 환경에 넣지 않는다. SNS와 MFA는4일차에 진행하고 오늘은 이메일·DB·배포를 완주한다. 강의자료의 배포 검증과 학생 개인 프로젝트의 실제 통합 검증을 구분한다. C01~C08과 K01~K08의 상세 교재·전날 시작/완성 소스/SQL ZIP을 사용한다.

실습 절차

  1. Git PR → Vercel Vite 배포: 아래처럼 소스·SQL·lockfile·환경 예시만 stage하고 diff를 검토해 commit·push한다. 본인 저장소의 main을 대상으로 PR을 만들고 검토·병합한다. Vercel Add New Project→본인 GitHub 저장소 Import에서 앱이 있는 Root Directory, Vite, npm run build, dist를 확인한다. 두 VITE 공개 변수를 Production과 필요한 Preview에 입력하고 Deploy한다.
  2. 공개 URL·인증 복귀·DB 재조회 최종 확인: Vercel의 실제 Production URL을 Supabase Site URL로 넣고 Redirect URLs에 정확한 공개 루트와 필요한 로컬/Preview 루트를 허용한다. 설정 변경 뒤 새 배포를 만들고 가입메일이 공개 앱으로 돌아오는지 확인한다. 공개 앱에서 추가·수정·검색·완료·로그아웃·새로고침·다른 브라우저 A 재조회·B 차단을 다시 검사한다.

Codex 구현 요청

이 과제 앱을 학생 본인 GitHub 저장소에서 Vercel로 배포할 절차를 준비해줘. 현재 경로·브랜치·remote, package.json·lockfile·build를 확인해줘. Vercel Root Directory는 실제 앱 위치, Framework는 Vite, Build는 npm run build, Output은 dist로 맞추고 두 VITE 공개 변수의 Production/필요한 Preview 범위를 설명해줘. .env.local·키·토큰은 commit하지 마. Supabase Site URL은 실제 고정 Production 루트, Redirect URLs는 로컬5173/와 정확한 공개 루트로 맞추고 환경값 변경 뒤 재빌드하도록 안내해줘. PR diff·검증표·병합·배포 SHA를 남겨줘. 가입 요청/메일 도착/확인/로그인/DB 저장/재조회/다른 브라우저 동일계정 복원/A·B 분리/미로그인 차단을 따로 검사해줘. RLS 실패를 UI 숨김·RLS 해제·service_role 노출로 우회하지 마. 원격 변경과 SQL 적용은 수업 단계에서 대상 프로젝트를 확인한 뒤 실행하게 해줘.

AI 검증·오류 해결 요청

수업용 Supabase에서 계정 A와 B를 만들어 실제 가입 메일·로그인을 확인해줘. A가 만든 과제를 새로고침과 다른 브라우저의 A 로그인으로 다시 읽고 수정·완료·삭제·되돌리기를 검사해줘. B에서는 A 행 조회0건, A id를 지정한 수정·삭제0건 또는 거절, user_id=A로 위조INSERT 거절, 소유자변경 거절을 Data API 요청으로 검사해줘. 미로그인 요청도 차단되는지 확인해줘. SQL Editor 관리자 조회를 RLS 통과 증거로 쓰지 마. 계정 전환 직후와 늦은 이전 요청 응답에서 A 목록이 B 화면에 나타나지 않는지, 네트워크 실패가 저장 성공으로 표시되지 않는지 확인해줘. 공개 Vercel URL의 배포commit·환경·가입복귀URL도 대조하고 결과를 통과/실패/미확인으로 기록해줘. 이메일·비밀번호·토큰은 보고서에 넣지 마.

완료 확인

  • solution 안 파일을 저장소 루트에 넣었다면 Root Directory는 루트다. solution 폴더 자체를 저장소에 넣었다면 실제 경로를 지정한다. Vercel이 Next.js 또는 public/을 빌드하도록 설정되어 있으면 고친다. DB 비밀번호나 service_role은 입력하지 않는다.
  • 제출: PR URL·main 커밋·배포 커밋·Vercel URL·Supabase 프로젝트 식별자(키 제외)·메일/로그인/DB/권한 체크표. READY는 빌드·배포 상태이며 실제 가입·저장 통과와 다르다. 대기나 미실행은 미확인으로 기록한다.

자주 막히는 지점

  • Invalid API key/설정 전: 변수명·VITE_접두사·재시작/재빌드
  • permission denied: 명시GRANT와소유자정책확인
  • 목록0건: 빈목록정상인지API오류인지구분
  • 수정/삭제0건: 반환행없음을성공으로표시하지않기
  • 가입메일없음: 강사사전준비SMTP/로컬Mailpit사용
  • 확인후localhost복귀: 실제Production루트로정정
  • PKCE교환실패: 같은브라우저에서새링크또는확인후로그인
  • Vercel빌드실패: npm ci/npm run build로재현
  • 이전환경이보임: 환경변경뒤새배포
  • 전날목록이없음: 자동업로드없음·가상DB과제로시작
  • B가A과제를봄: 공개중단후소유자정책/세션분리수정

확인 질문

Vercel READY만 확인하면 수업이 끝나는가?

실제 공개 URL에서 메일·복귀·로그인·DB 저장/재조회·계정 분리까지 확인한다.

이 교시 발표 화면 열기 ↗

근거와 참고 자료
목차와 처음으로 ↑
DAY 03 / HANDS-ON

3일차 · 계정별 DB에서 공개 앱까지

같은 과제 체크 앱을 이어 회원가입·로그인, 회원별 Supabase DB 저장과 Vercel 공개까지 완주한다.

전날 시작·DB 완성 코드 ZIP · 2일차 이어 보기 · 메일·비밀번호 설정 상세

교시실습50분 배분
3일차1교시기존앱→Vite·tasks·RLS도입8·환경10·DB/RLS20·짝검증8·정리4
3일차2교시가입·메일확인·로그인흐름8·구현22·메일/세션8·짝검증8·정리4
3일차3교시회원별CRUD·권한검증읽기/쓰기8·CRUD18·계정/권한12·짝검증8·정리4
3일차4교시Git→Vercel·공개검증빌드/Git8·배포12·URL/메일10·공개검증12·정리8
전날3일차
브라우저 localStorage에만 저장로그인 계정의 PostgreSQL tasks에 저장
다른 기기에 목록 없음같은 계정으로 로그인하고 DB 재조회
단일 HTML·Pages 배포HTML/CSS/JS 유지 + Vite 빌드·Vercel 배포
비밀번호/DB 없음Supabase Auth + user_id + RLS + GRANT

강사 사전 준비

각 학생의 새 수업용 Supabase 프로젝트·GitHub·Vercel 권한, Node/Git/Codex, 로그인/메일 수신을 수업 전에 확인한다. 기본 SMTP는 발송 대상과 한도가 있으므로 일반 학생 메일에 자동 발송된다고 가정하지 않는다. 검증한 Resend 도메인/SMTP 또는 로컬 Mailpit를 준비한다. 비밀번호 최소12자 정책을 앱/서버에서 맞춘다. 계정/도구 한도에 막히면 ZIP 체크포인트로 진행하고 클라우드 검증은 미확인으로 남긴다.

학생은 solution 안 파일들을 본인 clone 저장소 루트에 넣고 .git은 유지한다. starter는2일차 완성 단일HTML이다. 완성 소스는 개인 Supabase 설정이 필요한 프로젝트이며 다운로드만으로 로그인·공유 DB가 연결되지는 않는다. 기존 운영 DB와 실제 개인 과제는 사용하지 않는다.

목차와 처음으로 ↑
PROMPT CARDS

Codex 예제 요청 3종과 검증 요청

1. 프로젝트·DB·RLS

2일차 과제 체크 앱과 현재 Git 브랜치·diff를 먼저 읽어줘. 기존 HTML/CSS·수정·검색·완료·집계를 유지하면서 Vite와 @supabase/supabase-js로 구성해줘. 현재 공식 문서와 설치 버전의 Node 요구를 확인하고 패키지 버전을 고정해 lockfile을 남겨줘. DB는 새 수업용 Supabase의 public.tasks에 id uuid, user_id(auth.users 참조), title(공백만 불가·60자), subject(20자), due(date), done, created_at을 둬. user_id·due 인덱스, RLS, authenticated의 최소 GRANT와 본인 user_id=auth.uid() 조건의 SELECT/INSERT/UPDATE/DELETE 정책을 SQL 파일로 만들어줘. UPDATE는 USING과 WITH CHECK를 모두 쓰고 소유자·id·생성시각은 수정하지 못하게 해줘. anon은 데이터에 접근하지 못하게 해줘. 공개 URL과 publishable key만 VITE_SUPABASE_URL/VITE_SUPABASE_PUBLISHABLE_KEY로 읽고 .env.example과 .gitignore를 만들어줘. secret/service_role·DB 비밀번호는 브라우저나 Git에 넣지 마. 기존 운영 DB에 SQL을 실행하지 말고 새 수업 프로젝트에서 적용할 SQL과 검증 절차를 보여줘.

2. 회원가입·로그인·DB CRUD

현재 앱에 Supabase 이메일 회원가입·확인 대기·로그인·로그아웃과 회원별 과제 CRUD를 연결해줘. 가입 응답에서 session이 없으면 메일 확인 대기로 표시하고 로그인 성공과 구분해줘. 단일 브라우저 앱은 PKCE·현재 루트 복귀 주소·SDK 세션 복원을 일관되게 사용하고 허용 Redirect URL을 안내해줘. 가입 new-password/로그인 current-password, label·POST form·비밀번호 표시·12자 가입 규칙·중복 제출 방지를 넣어줘. 비밀번호·토큰·계정 존재 여부를 로그나 오류에 노출하지 마. 로그인 전 목록을 숨기고 계정 변경 즉시 이전 목록·편집·되돌리기를 지워줘. 이전 계정의 늦은 요청 응답도 무시해줘. DB select/insert/update/delete의 error와 반환 행을 확인한 뒤만 성공을 표시해줘. 수정은 동일 id·완료·생성시각을 보존하고 삭제 되돌리기도 DB에 반영해줘. 검색·완료 필터·날짜 집계를 유지하며 다른 기기 변경은 새로 불러오기로 조회해줘. localStorage의 전날 과제를 자동 업로드하지 말고 가상 DB 과제로 시작해줘. 네트워크 실패 때 미저장 입력을 유지해줘. 실제 실행 결과와 미실행을 구분해줘.

3. GitHub·Vercel·공개 검증

이 과제 앱을 학생 본인 GitHub 저장소에서 Vercel로 배포할 절차를 준비해줘. 현재 경로·브랜치·remote, package.json·lockfile·build를 확인해줘. Vercel Root Directory는 실제 앱 위치, Framework는 Vite, Build는 npm run build, Output은 dist로 맞추고 두 VITE 공개 변수의 Production/필요한 Preview 범위를 설명해줘. .env.local·키·토큰은 commit하지 마. Supabase Site URL은 실제 고정 Production 루트, Redirect URLs는 로컬5173/와 정확한 공개 루트로 맞추고 환경값 변경 뒤 재빌드하도록 안내해줘. PR diff·검증표·병합·배포 SHA를 남겨줘. 가입 요청/메일 도착/확인/로그인/DB 저장/재조회/다른 브라우저 동일계정 복원/A·B 분리/미로그인 차단을 따로 검사해줘. RLS 실패를 UI 숨김·RLS 해제·service_role 노출로 우회하지 마. 원격 변경과 SQL 적용은 수업 단계에서 대상 프로젝트를 확인한 뒤 실행하게 해줘.

추가: A/B 권한·회귀 검사

수업용 Supabase에서 계정 A와 B를 만들어 실제 가입 메일·로그인을 확인해줘. A가 만든 과제를 새로고침과 다른 브라우저의 A 로그인으로 다시 읽고 수정·완료·삭제·되돌리기를 검사해줘. B에서는 A 행 조회0건, A id를 지정한 수정·삭제0건 또는 거절, user_id=A로 위조INSERT 거절, 소유자변경 거절을 Data API 요청으로 검사해줘. 미로그인 요청도 차단되는지 확인해줘. SQL Editor 관리자 조회를 RLS 통과 증거로 쓰지 마. 계정 전환 직후와 늦은 이전 요청 응답에서 A 목록이 B 화면에 나타나지 않는지, 네트워크 실패가 저장 성공으로 표시되지 않는지 확인해줘. 공개 Vercel URL의 배포commit·환경·가입복귀URL도 대조하고 결과를 통과/실패/미확인으로 기록해줘. 이메일·비밀번호·토큰은 보고서에 넣지 마.
목차와 처음으로 ↑
FOLLOW ALONG

C01 · 같은 앱의 저장 위치와 완료 기준 정하기

전날 수정·검색 앱을 열고 “이 브라우저 저장”과 “계정별 DB 저장”의 차이를 적는다. 오늘의 완료 기준은 회원가입→이메일 확인→로그인→내 과제 저장→새로고침·다른 브라우저 재조회→다른 계정 차단→공개 Vercel URL이다.

학생 확인

필수 범위는 이메일 로그인과 회원별 tasks CRUD다. Google·Kakao·Naver·MFA는 4일차에서 이어간다. 브라우저의 전날 목록은 자동 업로드하지 않으며 가상 과제를 새로 만든다.

강사용 설명

1교시 도입8분 중 AI Studio는 선택 비교 시연5분만 사용한다. 주 실습은 Codex 경로다. 프런트엔드 HTML/CSS/JavaScript, Vite 빌드 도구, Supabase PostgreSQL·Auth·Data API의 역할을 실제 앱으로 비교한다. 별도 서버 언어를 새로 배우는 시간이 아니다.

목차와 처음으로 ↑
FOLLOW ALONG

C02 · 기능 브랜치와 Vite·공개 설정 준비

본인 저장소의 깨끗한 main을 최신화하고 feature/supabase-tasks를 만든다. Codex에 요청1을 입력해 기존 화면을 Vite 프로젝트로 구성한다. ZIP solution을 참고하면 index.html/styles.css/src/·package.json·lockfile·sql/을 저장소 루트에 둔다. .env.example을 .env.local로 복사해 본인 수업 프로젝트 URL과 publishable key를 입력하고 npm ci, npm run dev를 실행한다.

현재 폴더에서 한 줄씩 실행

git status -sb
git switch main
git pull --ff-only origin main
git switch -c feature/supabase-tasks
node --version
npm ci
npm run dev

이 단계의 Codex 요청

2일차 과제 체크 앱과 현재 Git 브랜치·diff를 먼저 읽어줘. 기존 HTML/CSS·수정·검색·완료·집계를 유지하면서 Vite와 @supabase/supabase-js로 구성해줘. 현재 공식 문서와 설치 버전의 Node 요구를 확인하고 패키지 버전을 고정해 lockfile을 남겨줘. DB는 새 수업용 Supabase의 public.tasks에 id uuid, user_id(auth.users 참조), title(공백만 불가·60자), subject(20자), due(date), done, created_at을 둬. user_id·due 인덱스, RLS, authenticated의 최소 GRANT와 본인 user_id=auth.uid() 조건의 SELECT/INSERT/UPDATE/DELETE 정책을 SQL 파일로 만들어줘. UPDATE는 USING과 WITH CHECK를 모두 쓰고 소유자·id·생성시각은 수정하지 못하게 해줘. anon은 데이터에 접근하지 못하게 해줘. 공개 URL과 publishable key만 VITE_SUPABASE_URL/VITE_SUPABASE_PUBLISHABLE_KEY로 읽고 .env.example과 .gitignore를 만들어줘. secret/service_role·DB 비밀번호는 브라우저나 Git에 넣지 마. 기존 운영 DB에 SQL을 실행하지 말고 새 수업 프로젝트에서 적용할 SQL과 검증 절차를 보여줘.

학생 확인

Node는 설치 버전의 요구사항을 만족해야 한다(제공 예제는22.12이상). .env.local은 Git에서 무시된다. VITE_ 값은 브라우저에 포함되는 공개 설정이며 secret/service_role을 숨겨주는 기능이 아니다.

강사용 설명

2일차에 clone한 폴더를 그대로 사용한다. Vite는 기존 HTML·JS를 빌드하는 도구다. ZIP의 solution 안 파일을 저장소 루트에 놓고 .git은 교체하지 않는다. GitHub Pages는 Vite 소스를 그대로 실행하지 못하므로 3일차 공개 주소는 Vercel로 기록한다. 이전 Pages 화면은 2일차 커밋에서 다시 확인할 수 있다.

목차와 처음으로 ↑
FOLLOW ALONG

C03 · 새 수업용 DB에 tasks·GRANT·RLS 적용

자신의 새 수업용 Supabase 프로젝트에서 SQL Editor를 열어 sql/setup.sql 전체를 한 번 실행한다. 기존 tasks가 있으면 구조와 정책부터 비교하고 임의로 삭제하지 않는다. sql/inspect.sql로 RLS·네 정책·authenticated의 접근 권한과 편집 가능한 열을 확인한다. Data API의 public 노출과 테이블 권한을 함께 확인한다.

학생 확인

tasks.user_id는 auth.users.id와 연결된다. SELECT/DELETE는 소유자 USING, INSERT는 WITH CHECK, UPDATE는 USING+WITH CHECK다. anon에는 권한이 없다. 명시적 GRANT와 RLS는 각각 “테이블 접근”과 “행 접근”을 담당한다.

강사용 설명

1교시50분은 도입8·프로젝트/환경10·스키마/RLS20·짝점검8·정리4다. 테이블이 보인다는 이유로 API 접근 성공을 단정하지 않는다. 최신 Supabase의 자동 노출 변화에 맞춰 명시적 GRANT를 사용한다. SQL Editor의 관리자 권한은 일반 사용자 RLS 검사를 대신하지 못한다. 프로젝트 생성·계정 준비는 수업 전에 마친다.

목차와 처음으로 ↑
FOLLOW ALONG

C04 · 회원가입·메일 확인·로그인·로그아웃 연결

요청2를 Codex에 입력하고 Authentication의 Email 가입과 Confirm email을 확인한다. 비밀번호 최소12자 정책을 앱과 서버에서 맞춘다. URL Configuration의 Site URL과 Redirect URLs에 실제 로컬 루트(http://localhost:5173/ 등)를 설정한다. 수신 가능한 수업 계정 A로 가입하고 메일 확인 뒤 로그인·새로고침·로그아웃을 각각 시험한다.

이 단계의 Codex 요청

현재 앱에 Supabase 이메일 회원가입·확인 대기·로그인·로그아웃과 회원별 과제 CRUD를 연결해줘. 가입 응답에서 session이 없으면 메일 확인 대기로 표시하고 로그인 성공과 구분해줘. 단일 브라우저 앱은 PKCE·현재 루트 복귀 주소·SDK 세션 복원을 일관되게 사용하고 허용 Redirect URL을 안내해줘. 가입 new-password/로그인 current-password, label·POST form·비밀번호 표시·12자 가입 규칙·중복 제출 방지를 넣어줘. 비밀번호·토큰·계정 존재 여부를 로그나 오류에 노출하지 마. 로그인 전 목록을 숨기고 계정 변경 즉시 이전 목록·편집·되돌리기를 지워줘. 이전 계정의 늦은 요청 응답도 무시해줘. DB select/insert/update/delete의 error와 반환 행을 확인한 뒤만 성공을 표시해줘. 수정은 동일 id·완료·생성시각을 보존하고 삭제 되돌리기도 DB에 반영해줘. 검색·완료 필터·날짜 집계를 유지하며 다른 기기 변경은 새로 불러오기로 조회해줘. localStorage의 전날 과제를 자동 업로드하지 말고 가상 DB 과제로 시작해줘. 네트워크 실패 때 미저장 입력을 유지해줘. 실제 실행 결과와 미실행을 구분해줘.

학생 확인

가입 요청 성공과 메일 도착·확인·로그인 성공을 따로 기록한다. PKCE 확인 링크는 요청한 같은 브라우저에서 연다. 다른 브라우저에서 확인했다면 이메일 확인 완료 후 원래 앱에서 이메일/비밀번호 로그인을 다시 시도한다.

강사용 설명

2교시 50분은 흐름8·Auth 구현22·메일/세션8·짝 검증8·정리4다. 기본 SMTP는 발송 대상과 사용량 제한이 있다. 강사는 Resend 검증 도메인·SMTP 또는 로컬 Mailpit를 사전 준비한다. 메일이 막히면 이메일 확인 기능을 끄지 않고 발송 경로를 고친다. 비밀번호 분실 복구·변경은 완성 예제와 F09~F14를 보충으로 사용한다.

목차와 처음으로 ↑
FOLLOW ALONG

C05 · 내 과제 CRUD를 DB에 저장하고 다시 읽기

A로 로그인해 가상 과제 두 개를 DB에 추가한다. 완료 상태를 바꾸고 제목·과목·마감일을 수정한다. 새로고침과 새로 불러오기로 DB 값을 재조회하고 삭제/되돌리기도 확인한다. 제목·과목 검색과 완료 필터·오늘/기한 지남 집계가 현재 계정 목록에서 작동하는지 확인한다.

학생 확인

insert/update/delete의 error와 반환 행을 확인해야 성공이다. 수정 후 id·done·created_at과 개수는 유지된다. 다른 기기에서 같은 계정으로 로그인한 뒤 다시 조회하면 같은 DB 목록을 읽는다. 이 예제의 새로 불러오기는 Realtime 자동 동기화가 아니다.

강사용 설명

3교시 50분은 읽기/쓰기8·CRUD 구현18·계정/권한12·짝 검증8·정리4다. DB 저장에서는 비동기 오류와 인증 상태를 함께 다룬다. 저장 실패 때 입력값을 남기고 성공 안내를 보내지 않는지 보여준다. 예제는 최대1,000건을 조회하며 대량 데이터는 페이지 나누기를 추후 설계한다.

목차와 처음으로 ↑
FOLLOW ALONG

C06 · A·B 계정과 미로그인으로 권한 검증

브라우저 일반 창의 A와 별도 프로필/다른 브라우저의 B로 각각 로그인한다. A의 과제 id를 가상 테스트 기록에만 적고, B의 Data API로 A id 조회·수정·삭제와 user_id 위조 INSERT를 검사한다. 로그아웃 직후 목록과 폼이 비워지는지도 확인한다. 상세 검증표의 실제 결과를 기록한다.

학생 확인

A는 자기 행만 CRUD, B의 A 조회는0건, 수정·삭제는0건 또는 오류, 위조 INSERT·소유자 변경은거절되어야 한다. 미로그인도 데이터에 접근하지 못한다. 화면이 숨겨졌다는 이유만으로 RLS 통과라 하지 않는다.

강사용 설명

완성 ZIP의 절차와 Codex 검증 요청을 사용한다. 토큰을 스크린샷이나 과제물에 넣지 않는다. 화면 검색으로 A의 과제를 숨기는 것과 DB가 접근을 거절하는 것은 다르다. 빈 목록이 테이블 권한 오류인지 정상 RLS 차단인지 구분한다. 계정을 바꾸는 동안 도착한 이전 요청의 응답도 다른 계정 화면에 나타나지 않아야 한다.

목차와 처음으로 ↑
FOLLOW ALONG

C07 · Git PR → Vercel Vite 배포

아래처럼 소스·SQL·lockfile·환경 예시만 stage하고 diff를 검토해 commit·push한다. 본인 저장소의 main을 대상으로 PR을 만들고 검토·병합한다. Vercel Add New Project→본인 GitHub 저장소 Import에서 앱이 있는 Root Directory, Vite, npm run build, dist를 확인한다. 두 VITE 공개 변수를 Production과 필요한 Preview에 입력하고 Deploy한다.

현재 폴더에서 한 줄씩 실행

npm run build
git status -sb
git add index.html styles.css src package.json package-lock.json .gitignore .env.example sql
git diff --cached
git commit -m "Add Supabase auth and per-user tasks"
git push -u origin feature/supabase-tasks

이 단계의 Codex 요청

이 과제 앱을 학생 본인 GitHub 저장소에서 Vercel로 배포할 절차를 준비해줘. 현재 경로·브랜치·remote, package.json·lockfile·build를 확인해줘. Vercel Root Directory는 실제 앱 위치, Framework는 Vite, Build는 npm run build, Output은 dist로 맞추고 두 VITE 공개 변수의 Production/필요한 Preview 범위를 설명해줘. .env.local·키·토큰은 commit하지 마. Supabase Site URL은 실제 고정 Production 루트, Redirect URLs는 로컬5173/와 정확한 공개 루트로 맞추고 환경값 변경 뒤 재빌드하도록 안내해줘. PR diff·검증표·병합·배포 SHA를 남겨줘. 가입 요청/메일 도착/확인/로그인/DB 저장/재조회/다른 브라우저 동일계정 복원/A·B 분리/미로그인 차단을 따로 검사해줘. RLS 실패를 UI 숨김·RLS 해제·service_role 노출로 우회하지 마. 원격 변경과 SQL 적용은 수업 단계에서 대상 프로젝트를 확인한 뒤 실행하게 해줘.

학생 확인

solution 안 파일을 저장소 루트에 넣었다면 Root Directory는 루트다. solution 폴더 자체를 저장소에 넣었다면 실제 경로를 지정한다. Vercel이 Next.js 또는 public/을 빌드하도록 설정되어 있으면 고친다. DB 비밀번호나 service_role은 입력하지 않는다.

강사용 설명

4교시 50분은 빌드/Git8·Vercel12·URL/메일10·공개 A/B 검증12·짝 확인/정리8이다. 전날의 PR 절차를 재사용한다. Framework 자동 감지 결과를 검토한다. 환경값은 빌드에 포함되므로 변경 후 재배포한다. 앱 배포와 DB 스키마 적용은 별개이며 Vercel이 SQL을 자동 실행하지 않는다.

목차와 처음으로 ↑
FOLLOW ALONG

C08 · 공개 URL·인증 복귀·DB 재조회 최종 확인

Vercel의 실제 Production URL을 Supabase Site URL로 넣고 Redirect URLs에 정확한 공개 루트와 필요한 로컬/Preview 루트를 허용한다. 설정 변경 뒤 새 배포를 만들고 가입메일이 공개 앱으로 돌아오는지 확인한다. 공개 앱에서 추가·수정·검색·완료·로그아웃·새로고침·다른 브라우저 A 재조회·B 차단을 다시 검사한다.

현재 폴더에서 한 줄씩 실행

git switch main
git pull --ff-only origin main
git log --oneline -3

학생 확인

제출: PR URL·main 커밋·배포 커밋·Vercel URL·Supabase 프로젝트 식별자(키 제외)·메일/로그인/DB/권한 체크표. READY는 빌드·배포 상태이며 실제 가입·저장 통과와 다르다. 대기나 미실행은 미확인으로 기록한다.

강사용 설명

Resend SMTP는 Supabase Auth 설정에 보관한다. 앱이 별도 메일을 보내지 않는다면 Resend 키를 Vercel 클라이언트 환경에 넣지 않는다. SNS와 MFA는4일차에 진행하고 오늘은 이메일·DB·배포를 완주한다. 강의자료의 배포 검증과 학생 개인 프로젝트의 실제 통합 검증을 구분한다.

목차와 처음으로 ↑
DATABASE / RLS

tasks SQL 전체와 권한 해설

새 수업용 프로젝트에서 setup.sql을 한 번 실행한다. 기존 tasks가 있으면 먼저 구조를 비교한다. 이 SQL은 Supabase의 auth.users·auth.uid()와 anon/authenticated 역할을 전제로 한다.

-- 새 수업용 프로젝트에서 한 번 실행합니다. 기존 tasks가 있으면 먼저 구조를 확인하세요.
begin;
create table public.tasks (
  id uuid primary key default gen_random_uuid(),
  user_id uuid not null default auth.uid() references auth.users(id) on delete cascade,
  title text not null check (char_length(title) between 1 and 60 and title ~ '[^[:space:]]'),
  subject text not null default '' check (char_length(subject) <= 20),
  due date not null check (due between date '0001-01-01' and date '9999-12-31'),
  done boolean not null default false,
  created_at timestamptz not null default now()
);
create index tasks_user_due_idx on public.tasks (user_id, due);
alter table public.tasks enable row level security;
revoke all on table public.tasks from public, anon, authenticated;
grant usage on schema public to authenticated;
grant select, insert, delete on table public.tasks to authenticated;
-- 소유자·id·생성시각은 UPDATE로 바꿀 수 없습니다.
grant update (title, subject, due, done) on public.tasks to authenticated;
create policy tasks_read_own on public.tasks for select to authenticated
  using ((select auth.uid()) = user_id);
create policy tasks_insert_own on public.tasks for insert to authenticated
  with check ((select auth.uid()) = user_id);
create policy tasks_update_own on public.tasks for update to authenticated
  using ((select auth.uid()) = user_id)
  with check ((select auth.uid()) = user_id);
create policy tasks_delete_own on public.tasks for delete to authenticated
  using ((select auth.uid()) = user_id);
commit;

관리자 메타데이터 점검

-- 관리자 메타데이터 점검입니다. 아래 성공만으로 A/B 계정 RLS 검사를 대체하지 않습니다.
select relrowsecurity from pg_class where oid = 'public.tasks'::regclass;
select policyname, cmd, roles, qual, with_check from pg_policies
where schemaname = 'public' and tablename = 'tasks';
select grantee, privilege_type from information_schema.role_table_grants
where table_schema = 'public' and table_name = 'tasks' order by grantee, privilege_type;
select grantee, column_name, privilege_type from information_schema.column_privileges
where table_schema = 'public' and table_name = 'tasks' and privilege_type = 'UPDATE';

GRANT는 테이블·열에 접근할 권한, RLS는 그중 자신의 행에 접근할 조건이다. 공개 publishable key만으로 다른 사람의 행을 읽을 수 없도록 둘을 함께 사용한다. UPDATE에 SELECT 정책도 필요하다. 관리자 SQL 조회는 A/B 권한 검사가 아니다.

목차와 처음으로 ↑
DEPLOY / CONFIG

Vercel·Supabase·메일 연결 설정표

설정수업 예제의 값·확인
Root Directory본인 저장소에서 package.json·index.html이 있는 실제 앱 폴더
Framework / Build / OutputVite / npm run build / dist
Node제공 예제는22.12이상, Vercel에서 지원하는 버전 확인
VITE_SUPABASE_URL해당 수업 Supabase 프로젝트 URL
VITE_SUPABASE_PUBLISHABLE_KEY동일 프로젝트 publishable key, secret/service_role 금지
환경 범위Production 및 필요한 Preview, 값 변경 후 재빌드
Supabase Site URLhttps://실제-고정-운영주소/
Supabase Redirect URLs실제 로컬5173/ + 정확한 운영 루트/ + 필요한 Preview 루트/
메일 복귀PKCE·emailRedirectTo·기본 확인메일 템플릿을 일관되게 사용
Resend SMTPSupabase Auth에만 설정; 별도 앱 메일이 없으면 Vercel에 Resend 키 불필요
VITE_SUPABASE_URL=https://YOUR_PROJECT_REF.supabase.co
VITE_SUPABASE_PUBLISHABLE_KEY=sb_publishable_REPLACE_WITH_YOUR_KEY

위 값은 자리표시자다. .env.local에 본인 값을 넣고 Git에 올리지 않는다. VITE_는 비밀 보관 접두사가 아니며 브라우저 번들에 포함된다. 프런트엔드에서 DB 비밀번호·secret/service_role을 사용하지 않는다.

목차와 처음으로 ↑
CHECK

학생·강사용 최종 검증표

검사행동기대 결과
설정URL/publishable key·.env.local 제외공개2변수만 사용·비밀키없음
스키마setup.sql/inspect.sqlRLS·소유자4정책·명시GRANT
가입이메일/12자비밀번호로가입확인대기·실제메일·확인구분
로그인잘못된암호/정상로그인/새로고침오류안내·정상세션복원
추가/조회A의가상과제추가→재조회DB동일행·고유id
수정/취소완료한과제수정→취소검사id/done/created_at유지·취소불변
기존기능검색/필터/날짜/삭제·되돌리기현재계정목록기준정상
기기간다른브라우저의A로그인후조회같은DB목록
A/B조회B로A id Data API 조회0건
A/B쓰기B로A id 수정·삭제0건또는거절·A행불변
소유자위조B가user_id=A로INSERT/소유자변경거절
미로그인로그아웃화면·익명Data API목록즉시비움·DB차단
비동기경합A요청중B전환늦은A응답표시없음
네트워크오류DB접속실패/미저장폼성공표시없음·입력유지
공개배포Production URL/commit/환경최신빌드·설정일치
공개메일가입메일확인후공개앱복귀허용URL·메일·로그인완료

Codex A/B API 검증 요청

수업용 Supabase에서 계정 A와 B를 만들어 실제 가입 메일·로그인을 확인해줘. A가 만든 과제를 새로고침과 다른 브라우저의 A 로그인으로 다시 읽고 수정·완료·삭제·되돌리기를 검사해줘. B에서는 A 행 조회0건, A id를 지정한 수정·삭제0건 또는 거절, user_id=A로 위조INSERT 거절, 소유자변경 거절을 Data API 요청으로 검사해줘. 미로그인 요청도 차단되는지 확인해줘. SQL Editor 관리자 조회를 RLS 통과 증거로 쓰지 마. 계정 전환 직후와 늦은 이전 요청 응답에서 A 목록이 B 화면에 나타나지 않는지, 네트워크 실패가 저장 성공으로 표시되지 않는지 확인해줘. 공개 Vercel URL의 배포commit·환경·가입복귀URL도 대조하고 결과를 통과/실패/미확인으로 기록해줘. 이메일·비밀번호·토큰은 보고서에 넣지 마.

B의 로그인된 클라이언트로 A id를 직접 요청한다. 토큰을 복사해 과제물·스크린샷·로그에 넣지 않는다. 코드의 .eq(user_id)는 조회 조건이며 DB RLS를 대신하지 않는다. 각 항목의 통과/실패/미확인과 실제 결과를 ZIP checks.csv에 남긴다.

목차와 처음으로 ↑
TROUBLESHOOTING

막히는 지점과 검증 범위

증상확인조치
Invalid API key/설정 전URL과같은프로젝트publishable key인지확인변수명·VITE_접두사·재시작/재빌드
permission deniedGRANT·RLS·Data API 노출구분명시GRANT와소유자정책확인
목록0건현재계정·user_id·같은프로젝트확인빈목록정상인지API오류인지구분
수정/삭제0건id·소유자·SELECT/UPDATE정책확인반환행없음을성공으로표시하지않기
가입메일없음Auth응답·SMTP발송대상/한도·Resend로그·스팸함강사사전준비SMTP/로컬Mailpit사용
확인후localhost복귀Site URL·emailRedirectTo·허용URL·템플릿실제Production루트로정정
PKCE교환실패요청브라우저·원래주소·이미사용/만료링크같은브라우저에서새링크또는확인후로그인
Vercel빌드실패Root Directory·Vite·Node요구·lockfile·환경명npm ci/npm run build로재현
이전환경이보임환경대상과최근배포commit확인환경변경뒤새배포
전날목록이없음localStorage와DB의저장위치차이자동업로드없음·가상DB과제로시작
B가A과제를봄SQL/RLS·사용키·캐시·늦은응답확인공개중단후소유자정책/세션분리수정

완성 예제는 분리된 로컬 Supabase에서 가입 확인 대기·Mailpit 수신·확인 후 로그인·회원별 CRUD·A/B 조회/수정/삭제 차단·소유자 위조·익명 차단을 실제 검사했다. Vite 빌드도 확인했다. 학생 개인 클라우드의 실제 수신함·Vercel 앱 연결은 각자의 수업 계정으로 최종 검증해야 한다. 강의 사이트 배포와 학생 앱 배포는 별개다.

근거와 참고 자료
목차와 처음으로 ↑

프롬프트 직접 복사

아래 전체 문장을 선택해서 복사하세요.