Final Presentation Script

SYDR — Soyongdori Club Website

Building a Platform to Streamline Archiving and Member Management
Team Cook · Chungbuk National University

github.com/openWEBsw/project-soyongdori

▶ Phase 1 — Demo Video (MP4)

~0:00 – 2:00

Hello everyone. Before we get into the slides, we'd like to start with a short pre-recorded demo video so you can get a feel for the actual product — what it looks like, how it flows, and what it can do — before we explain how it was built. Please take a look.

맥락 / Stage Direction
여기서 미리 준비한 mp4 시연 영상 재생. 영상이 끝난 뒤 PPT 세션으로 자연스럽게 이어질 것. 영상 재생 중에는 별도로 말하지 않아도 됨.

Alright, now that you've seen the product in action, let's walk through the slides and explain the decisions behind it.

맥락
영상 종료 후 PPT로 전환. 목차(슬라이드 2)·조원 소개(슬라이드 3)는 대본 없이 빠르게 넘기고, 프로젝트 배경(슬라이드 4)부터 시작.

📊 Phase 2 — Slide Presentation

~2:00 – 8:30
Project Background & ObjectivesPPT 4–6

Our project is called SYDR — short for Soyongdori. Soyongdori is the central band club here at Chungbuk National University, and SYDR is the web platform we built for it.

맥락
동아리 이름(소용돌이)과 약자(SYDR)만 짧게 소개. 길게 설명하지 말 것.

Before this project, the club ran almost entirely on manual processes. Announcements went out over KakaoTalk, event schedules lived in personal calendar apps, and documents were scattered across Google Drive with no consistent structure. There was no single place to find anything.

맥락
기존의 문제점 슬라이드. KakaoTalk·캘린더앱·구글드라이브 3가지 흩어진 채널을 강조.

Membership management was just as fragmented. Joining the club meant filling out a form somewhere and waiting for someone to manually approve it. No one could easily see who had what role, and when leadership changed every semester, there was no structured handover — the next president just got a spreadsheet and hoped for the best.

맥락
회원 관리의 비효율성 슬라이드. 수기 승인, 역할 불투명, 인수인계 문제를 순서대로 짚어줄 것.

Access permissions were also unclear — in practice anyone who had the Google Drive link could see everything, which is a real security risk. And club accounting meant someone manually photographing receipts and typing amounts into a spreadsheet by hand. Our goal was to replace all of that with one systematic, always-accessible web platform: proper permission controls, durable archiving, and a clear workflow for every process the club relies on.

맥락
권한 불분명 + 회계 수작업 문제 → 프로젝트 목표 슬라이드. 마지막 문장이 프로젝트 한 줄 요약임.
Page Flow & SitemapPPT 7

Before we get into the individual features, here's the overall structure of the site. There are about thirteen screens, organized by permission tier. A visitor starts as a guest, signs up to become a temporary member, submits a membership application, gets approved by an admin, and finally becomes a full member — and what each screen shows and allows follows that progression. You can think of this map as the blueprint that ties together all the features I'm about to walk through.

맥락
사이트맵 / 페이지 흐름도 슬라이드. 권한 단계(비회원 → 회원가입 → 임시회원 → 입부신청 → 승인 → 일반회원) 흐름을 손으로 짚으며 설명. 전체 그림만 제시하고 너무 자세히 읽지 말 것.
Full Web Technology StackPPT 8

A quick rundown of what we used. The whole project is written in TypeScript — a typed superset of JavaScript — on both the frontend and the backend. On the frontend: React, Tailwind CSS, and FullCalendar.js. On the backend: Node.js with Express, as a stateless REST API. The database is MySQL with Prisma as the ORM. And for infrastructure, we deploy with Docker Compose on Oracle Cloud, with Cloudflare handling the tunnel and the CDN.

맥락
스택 슬라이드. 레이어별 기술 이름만 읽고 넘어갈 것 — 길게 설명하지 말 것.
Key Feature 1 — RBAC Permission SystemPPT 9

Our first key feature is the permission system. We implemented a Role-Based Access Control model using JWT — JSON Web Tokens — for stateless authentication. When a user logs in, the server issues an access token and a refresh token. The access token carries the user's job title — their position — and the server derives the permission level from that on each request. It never needs to look up a session in the database, which keeps the API fast and horizontally scalable.

맥락
RBAC 슬라이드. JWT access/refresh 토큰 다이어그램이 있다면 짚어줄 것. "stateless" 개념 간략히 설명.

For granularity, we defined permission levels from zero to eight, derived from the club's job-title hierarchy. A brand-new applicant is level zero, a regular member is level one, the club president is level seven, and the system super-admin sits at the very top, at level eight. A couple of titles even share a level — our treasurer and planning lead are both level five. On the backend, we built a custom Express middleware using a helper called requireLevel, which wraps any route you want to protect. If the token's level doesn't meet the threshold, the request is rejected right at the middleware layer — before any business logic runs.

맥락
권한 레벨 0~8 매핑 슬라이드. requireLevel() 미들웨어 코드 스니펫이 있으면 여기서 짚어줄 것.

Concretely, permissions control: who can write or only read on the bulletin board, who can access the admin dashboard, whether a user can create and edit calendar events or just view them, and who can see personal member information. This directly solved the access-control problem the club had before — where visibility into club data was basically all-or-nothing.

맥락
권한이 제어하는 4가지 범위 슬라이드. 게시판·어드민·캘린더·회원정보 각 항목 읽으면서 슬라이드 체크리스트를 짚어줄 것.
Key Feature 2 — Automated Sign-Up WorkflowPPT 10

The second feature is the membership application workflow. We designed it as a four-step pipeline. In step one, a prospective member signs up on the site: a user record is created, their status is set to "pending," and their basic info is saved to the MEMBERS table.

맥락
4단계 파이프라인 슬라이드 중 1단계. "pending" 상태 표시가 있는 다이어그램 슬라이드.

In step two, they fill out an application form — their instrument part and a short motivation. That data gets inserted into a separate JOIN_APPLICATIONS table, linked to the user record via a foreign key.

맥락
2단계 슬라이드. JOIN_APPLICATIONS 테이블과 외래 키 관계를 ER 다이어그램으로 표시하면 좋음.

Step three: the admin opens the dashboard and sees a list of pending applications. There's an approve or reject button for each one. One click is all it takes — no spreadsheets, no KakaoTalk messages back and forth.

맥락
3단계 슬라이드. 어드민 대시보드 캡처 이미지가 있으면 짚어줄 것.

And step four is where everything resolves atomically. When an application is approved, it's processed within a single transaction: the user's status changes to "active," and permissions are automatically granted based on their job title — all in one atomic step. Because it's transactional, there's no state where a user is approved but still has no permissions, or vice versa. Data integrity is guaranteed.

맥락
4단계 슬라이드. "트랜잭션" 개념 강조 — DB 수업 연계 포인트.
Key Feature 3 — Interactive, Responsive Web UI/UXPPT 11

Third feature: the user interface itself. One of the most visible parts of the site is the schedule management system, built on FullCalendar.js. It's a custom integration of the library, set up so that personal, member, and official calendars can be configured separately, all with real-time rendering. Members can create events, while editing or deleting is limited to the event's author or a vice-leader and above.

맥락
캘린더 기능 슬라이드. 3가지 캘린더 레이어(personal/member/official) 구분을 시각적으로 보여줄 것.

Responsive design was a core priority. The same codebase runs on a wide desktop monitor and on a 375-pixel-wide phone screen without any separate mobile site. We used Tailwind's responsive utilities throughout so every layout adapts seamlessly — which matters because club members check the schedule on their phones far more than on a desktop.

맥락
반응형 디자인 슬라이드. 데스크탑/모바일 비교 스크린샷이 있으면 여기서 보여줄 것.
Key Feature 4 — AI-Based Receipt AnalysisPPT 12

The fourth feature was probably the most exciting one to build. On the club's accounting board, you can upload receipt images. The system runs automatic character recognition and parsing, automatically extracting the dates, the number of items, and the amounts. This streamlines how the club manages its ledgers — no more manual transcription.

맥락
AI 영수증 분석 슬라이드. 영수증 업로드 → 분석 결과 UI 스크린샷 순서로 보여줄 것.

Under the hood, we integrated the Google Gemini 3.1 Flash Lite API. We chose it because it's a lightweight LLM with fast response times, which makes the AI feature cost-effective for a student project with real usage. The key engineering work was getting sophisticated, well-structured output through systematic prompting — a clean format with a date, item, quantity, and price for every line, plus a total. Once we had it dialed in, the results were surprisingly accurate even on low-quality receipt photos.

맥락
Gemini API 슬라이드. "structured output via system prompting" 개념 설명. 필요하면 프롬프트 예시 슬라이드 추가.
Version Control & GitHub CollaborationPPT 13

For collaboration, we used a structured Git branching strategy. Each new feature lived on its own feature branch. We integrated on a shared dev branch where we could run tests and catch cross-feature issues. When things were stable, we merged into main via pull requests. And releases got their own tagged release branches so we always had a clean production-ready snapshot.

맥락
브랜치 전략 슬라이드. feature → dev → main → release 플로우 다이어그램.

Every merge went through a pull request review. Team members read each other's code and left comments before anything landed on main. One person primarily owned merge responsibility and handled final bug checks before promoting to main or a release branch. This kept our main branch stable throughout the semester — we had a working, deployable version at all times.

맥락
PR 리뷰 슬라이드. GitHub PR 화면 캡처가 있으면 보여줄 것.
Technical Challenges & TroubleshootingPPT 14–15

Now I want to talk about the real challenges we hit — the things that didn't work the first time and what we did to fix them. These were some of the most valuable learning experiences of the project.

맥락
트러블슈팅 섹션 도입부. 발표 톤을 조금 가볍게 해도 좋음 — "실제로 겪은 일"이라는 공감 포인트.
Challenge 1

FullCalendar.js generates its own internal DOM structure, and you can't easily target those elements with standard CSS selectors. We needed to customize the look of the calendar to match our design system, but the library's internals were essentially a black box. We solved it by carefully studying the library's rendered HTML, mapping out the class names it generates, and using Tailwind's arbitrary-variant selectors to target them directly. It was tedious but it worked.

맥락
FullCalendar 스타일링 이슈 슬라이드. Tailwind arbitrary variant (예: [&_.fc-event]:bg-purple-500) 코드 예시가 있으면 보여줄 것.
Challenge 2

Timezone handling. Everything worked perfectly in local development, but after we deployed to the server, saved event times would drift by nine hours — sometimes forward, sometimes backward — depending on which direction the offset was applied. The root cause was a mismatch: the server operated in UTC, the database stored times in UTC, but the client was sending times in Korean Standard Time — KST, which is UTC plus nine. And in certain code paths, the offset was being applied twice. We fixed it by establishing a single conversion convention: UTC everywhere on the server and database side, KST conversion only at the presentation layer, applied exactly once.

맥락
UTC/KST 타임존 슬라이드. "서버는 UTC, 클라이언트는 KST, 변환은 한 번만" 원칙을 강조.
Results & Future PlansPPT 16

So where are we now? We have a fully deployed, production-grade TypeScript web platform that replaces every manual process the club was relying on. The deployment is live on Oracle Cloud behind Cloudflare. Real club members are using it for testing right now, and we're collecting feedback for the next iteration.

맥락
결과 슬라이드. "실 사용 중" 이라는 포인트 강조 — 단순 과제가 아닌 실제 서비스라는 점이 어필 포인트.

Looking ahead, we plan to continue improving the platform based on real usage — refining the admin experience, expanding the AI receipt analysis, and potentially adding push notifications for event reminders. The foundation is solid, and the architecture is set up to support these extensions without a rewrite.

맥락
향후 계획 슬라이드. 3가지 개선 방향을 간략히 읽어줄 것.
Future ImprovementsPPT 16 (cont.)

Being honest about what's left, one of the first things on our list is how much of the site is still hardcoded. Right now the home page's hero images, the part photos on the introduction page, and even highlights like our next stage and rehearsal times are baked into the code at build time — there is literally a "TODO" comment in our home page reminding us to wire these up to the API. The next step is to move that content into the database and give club officers a small admin panel, so changing a poster or an announcement doesn't require a developer and a redeploy.

맥락
향후 개선 1 — 하드코딩 콘텐츠. home.tsx에 실제로 남아 있는 // TODO: API 연동 주석을 솔직하게 언급. 핵심 메시지: 운영진이 코드 수정 없이 직접 콘텐츠를 바꿀 수 있게 만들 것.

On the infrastructure side, uploaded files like profile pictures are currently stored as local file paths on the server, and high-resolution uploads can degrade — both already flagged as TODOs in our schema and code. We plan to move file storage to object storage such as MinIO or Cloudflare R2, fix the high-resolution handling, and replace the last few magic numbers — like the club's founding year and the default cohort — with values driven by configuration and the database. We've also already laid the groundwork in our schema for archiving the boards year by year, which ties directly back to our original goal: durable, organized record-keeping that survives every leadership handover.

맥락
향후 개선 2 — 인프라/설정. 프로필 이미지 로컬 저장(스키마의 MinIO 연결 TODO), 고화질 업로드 깨짐 TODO, 매직넘버(1978/기수), 게시판 연도별 아카이빙(스키마 year 필드)을 묶어서. 마지막 문장은 프로젝트 최초 목표(아카이빙)와 연결하며 마무리 포인트로 강조.

🎬 Phase 3 — Live Demo

~8:30 – 10:00

Now let's switch over to the live site. I'll walk through a few key flows so you can see everything working in real-time.

맥락 / Stage Direction
브라우저 또는 폰 화면 미러링으로 전환. 실제 배포 URL 열어둘 것.

First, the sign-up and membership approval flow. I'll create a new account — you can see the form validates in real-time. After sign-up, the account is in "pending" status. Now I'll fill out the membership application form. Let's switch to the admin dashboard — here's the application sitting in the queue. I'll approve it, assign a job title, and you'll see the status flip to "active" instantly, with permissions granted automatically.

맥락 / Stage Direction
시연 순서: 회원가입 → 신청서 작성 → 어드민 로그인 → 신청서 목록 → 승인 → 상태 변경 확인. 미리 테스트 계정 준비해둘 것.

Next, the calendar. I'll create a new event — notice that the interface is fully responsive. Let me resize the browser window down to phone width, or better yet, here's the same page on my phone. The calendar adjusts automatically — no horizontal scroll, everything fits. This is the concrete outcome of the responsive work we described earlier.

맥락 / Stage Direction
캘린더 이벤트 생성 후 브라우저 창 줄이거나 폰 화면으로 전환하여 반응형 동작 실시간 시연. 강의 핵심 포인트이므로 확실히 보여줄 것.

Finally, the AI receipt analysis. I'll navigate to the accounting board and upload a receipt image. Watch what happens — within a couple of seconds the system parses the receipt and populates the date, items, and total amount automatically. No typing required. This is the Gemini API at work behind the scenes.

맥락 / Stage Direction
회계 게시판 이동 → 영수증 이미지 업로드 → 자동 파싱 결과 표시. 미리 테스트용 영수증 이미지 준비해둘 것. 파싱에 2~3초 걸릴 수 있으므로 "지금 처리 중입니다" 한 마디 추가해도 좋음.
Closing

That's everything for our presentation. To summarize: we built SYDR — a full-stack TypeScript web platform for a real university band club — covering RBAC authentication, automated membership workflows, a responsive interactive calendar, and AI-assisted accounting. The site is live, it's responsive enough to use on the phone you're holding right now, and it's already in the hands of real users.

맥락
마무리 요약 슬라이드. 4가지 핵심 기능을 빠르게 recap. 자신감 있는 톤으로.

The source code is public at github.com/openWEBsw/project-soyongdori. We'd love for you to take a look, and if you want to check the responsive design claim for yourself, you can open the live site on your phone right now. Thank you very much for listening — we're happy to take any questions.

맥락
GitHub URL과 라이브 사이트 URL을 슬라이드에 QR코드로 넣어두면 좋음. 청중이 폰으로 직접 접속해볼 수 있도록 유도.