E01 전날 앱 복원과 두 환경 준비
학생: 4일차 완성 앱이 있는 본인 clone 폴더를 연다. ZIP의 starter는 비교용이며 기존 .git과 .env.local을 덮어쓰지 않는다. 강사는 staging 브랜치와 수업용 staging/production Supabase 두 환경을 사전 준비한다. 학생은 main의 최신 이력에서 feature/csv-release를 만들고 로컬 가입·로그인·MFA·과제 CRUD부터 확인한다.
git status -sb
git fetch origin
git switch main
git pull --ff-only
git switch -c feature/csv-release
npm ci
npm run dev
확인: 미커밋 변경을 먼저 정리하고 잘못된 저장소에서 실행하지 않는다. 환경표에 URL·브랜치·DB 이름만 적는다. 두 환경은 같은 DB를 가리키지 않는다.
강사: 1교시50분은 목표5·복원8·CSV구현22·경계검증11·정리4다. 두 Supabase 프로젝트/키 준비가 지연되지 않게 강사가 별도 수업 프로젝트를 미리 확보한다. 계정 무료 프로젝트 한도를 수업 전에 확인하고 필요하면 강사 제공 환경으로 진행한다. 실제 프로젝트의 운영 DB를 재사용하지 않는다.

E02 본인 전체 과제를 CSV로 내보내기
학생: 요청1을 Codex에 입력하고 변경 파일을 검토한다. solution의 csv-export.js·task-store.js·main.js·HTML/CSS와 비교한다. 추가 인증 후 내 과제 CSV 내보내기를 누른다. 검색 결과가 1건이어도 본인 전체 DB 과제가 들어가는지 확인한다. 내려받은 파일은 스프레드시트에서 텍스트로 가져오고 한글·열 이름·완료 상태를 확인한다.

확인: 한글·쉼표·큰따옴표·줄바꿈·=1+2·전각＝1+2와 빈 목록을 검사한다. 위험한 자유 입력 앞의 탭은 열람용 변환이며 DB 원본은 유지된다. 토큰·이메일·uid가 CSV에 없다.
강사: CSV 인용은 형식 보존, 수식 위험 변환은 별도 보안 처리다. 탭 접두어는 Excel 열람의 위험을 줄이지만 모든 스프레드시트와 재저장에 대한 보장은 아니다. 코드 검증과 실제 교실 Excel/Sheets에서 텍스트 가져오기 검증을 나눠 기록한다. UI 입력이 trim하는 경우 줄바꿈/선행 제어문자 검사는 코드 테스트로 보충한다.

E03 A/B·익명·인증 강도별 권한 검사
학생: 가상 A/B 계정을 서로 다른 브라우저 프로필에서 사용한다. 두 계정 모두 TOTP를 준비하고 본인 과제를 하나씩 만든다. A의 id를 검사에만 사용해 B의 실제 Data API로 조회·수정·삭제·user_id 위조를 시도한다. 로그아웃 뒤 재로그인한 AAL1과 추가 인증 후 AAL2를 비교한다. 아래 개발 서버 전용 검사 예시와 checks.csv에 실제 결과를 적는다.

확인: AAL2는 관리자 권한이 아니다. B의 A행 조회/수정/삭제는0행 또는 거절이며 A원본 불변. 익명은 거절. AAL1은 본인 조회0행·쓰기거절/0행이며 내보내기 불가. 소유권 위조 추가/변경은 거절.
강사: 2교시50분은 원리7·A/B/API20·실패/취소10·비밀검사9·정리4다. 표의 기대 결과를 읽는 것과 실제 요청 성공/거절을 구분한다. HTTP200의 빈 배열도 RLS 차단일 수 있으므로 반환 행과 A원본을 함께 확인한다. 이메일이 같음/화면의 관리자 표기/user_metadata.role을 권한 근거로 쓰지 않는다.

E04 페이지 실패·계정 전환·비밀 노출 점검
학생: 네트워크 차단 또는 모의 테스트로 CSV 조회 중간 실패를 재현한다. 다운로드가 한 번도 발생하지 않아야 한다. 조회 중 로그아웃/다른 계정으로 전환했을 때 이전 계정 파일이 생성되지 않는지도 검사한다. 로컬 가상 데이터1,203건으로 페이지 조회를 확인한다. .gitignore·git diff·빌드 산출물을 검사하고 실패/미확인 사유를 남긴다.
npm run build
git status --short
git diff --check
git diff -- src index.html styles.css
git ls-files .env.local .env.production
확인: 부분 CSV·이전 계정 CSV·중복 다운로드0회. 예제 상한10,000건을 넘으면 명시 오류. 위 git ls-files 결과는 비어야 한다. 공개 URL/key 외 secret·service_role·SMTP·OAuth 비밀이 소스/번들에 없다.
강사: 1,203건은 기능 테스트가 끝나면 가상 수업 DB에서만 정리한다. 화면 목록의1,000건 한도와 CSV10,000건 한도를 구분한다. 다른 탭의 동시 편집은 잠시 멈춘다. 페이지 조회는 단일 트랜잭션 스냅샷이 아니며 동일 건수의 동시 편집까지 완전 감지하는 구현이 아니다. 실패를 RLS 해제로 해결하지 않는다.

E05 staging Preview와 DB·Auth 설정 대조
학생: 환경표를 채운다. Vercel Production Branch=main을 확인하고 staging은 Preview로 연결한다. Preview의 VITE_ 두 값은 별도 staging Supabase, Production 값은 production Supabase로 지정한다. 각 새 수업 DB를 inspect.sql로 확인하고 검토한 setup.sql→mfa-required.sql을 한 번 적용한다. 환경별 Auth·메일·SNS callback/redirect·Naver 어댑터를 점검한다.

확인: 환경 변수 변경 뒤 새 빌드를 만든다. 프런트엔드 URL/key 외 비밀값은 VITE_로 만들지 않는다. DB migration은 Vercel 코드 배포와 별도다. 기존 정책이 있으면 SQL을 무작정 재실행하지 않는다.
강사: 3교시50분은 환경8·PR/Preview15·검증10·main/운영13·정리4다. Git의 staging area는 커밋 대기 영역, staging 브랜치는 팀이 정한 이름이다. 브랜치 이름만으로 Vercel Production이 되지 않는다. 새 프로젝트의 Auth 사용자는 독립적이므로 같은 사람이 두 DB에서 다른 uid를 가질 수 있다. 운영 데이터 복제 없이 가상 계정으로 검증한다.

E06 feature→staging 검토 후 main 최종 배포
학생: 변경을 커밋·push하고 GitHub PR base=staging, compare=feature/csv-release를 만든다. 동료가 diff·비밀·검사표를 검토하고 병합한다. Vercel staging Preview의 READY와 commit을 확인한 뒤 실제 URL에서 검증한다. 모두 통과하면 PR base=main, compare=staging을 검토·병합한다. main의 새 Production 배포에서 같은 검사를 다시 하고 release-record.md를 완성한다.
npm run build
git add index.html styles.css src README.md
git diff --cached
git commit -m "Add secure task CSV export"
git push -u origin feature/csv-release
확인: PR별 base/head·commit·실제 URL·DB 이름·검증자·결과가 남는다. Preview 통과와 Production 재빌드 통과를 별도로 기록한다. 실패하면 배포 완료 표시를 멈추고 원인을 수정한다.
강사: 수업용 staging 브랜치는 시작 전에 main에서 생성해 원격에 둔다. main 병합은 Production 환경으로 새 빌드하므로 preview와 동일 실행물/설정이라고 단정하지 않는다. 배포 롤백은 앱 버전 복원이며 이미 저장한 DB 데이터나 스키마를 자동 복원하지 않는다. 잘못된 데이터 변경은 별도 검토된 DB 복구 절차가 필요하다.

E07 3분 발표·짝 피드백
학생: 요청3으로 발표 원고를 작성하고 발표용 가상 과제3개와 CSV를 준비한다. 청중에게 비밀이 보이지 않게 MFA를 사전 완료한다. 문제/사용자→핵심 동작→권한 검증 근거→두 배포 환경→한계 순서로3분 시연하고 짝에게 개선점1개를 받는다. 실SNS 연결 미완료는 미확인으로 설명한다.

확인: 저장소/운영 링크·화면 시연·권한 근거·staging/Production commit·다음 개선1개가 있다. QR·OTP·토큰·실제 학생 정보가 발표 화면/CSV/캡처에 없다.
강사: 4교시50분은 준비8·발표/짝피드백30·이슈/인수인계8·정리4다. 3분 발표+2분 피드백을6명 소그룹에서 병렬 진행하고 대표 사례만 전체 공유한다. 대규모 수업에서 전원이 전원 앞 발표하면 시간을 넘는다. “AI가 만들었다”보다 문제와 검증 근거를 평가한다.

E08 인수인계·릴리스 기록·다음 이슈
학생: README에 실행/환경 변수 이름/SQL 순서/검사 방법/CSV 범위/배포·복구를 정리한다. checks.csv와 release-record.md를 채우고 peer-feedback.md의 개선점 하나를 GitHub 이슈로 남긴다. 최종 main commit·운영URL·발표 원고·가상 CSV·미확인 항목을 제출한다.
git status -sb
git log -5 --oneline
git diff --check
확인: 본인이 하지 않은 실SNS·운영 검증을 통과로 표시하지 않는다. 발표용 CSV도 본인 가상 자료만 제출한다. 미커밋 작업·열린 PR·실패 검사·복구 담당자가 분명하다.
강사: 성공 기준은 공개 링크 하나가 아니라 재현 가능한 실행·권한·배포 근거다. 계정 삭제/보관기간/관리자 대시보드/원본 백업은 후속 기능으로 이슈화한다. 교육용 체크 통과는 전체 보안 감사 완료를 의미하지 않는다.