Flutter + Gemini AI 앱을 만들어 내 대학 출석을 '해킹'한 방법 (오픈소스)
Source: Dev.to
만약 당신이 (저처럼) 모라투와 대학교에 다니는 공학도라면 80 % 규칙이 얼마나 끔찍한지 잘 알 것입니다.
간단한 수학: 수업의 80 %에 참석하거나 시험에서 추방당한다.
현실은 악몽과 같습니다.
- “오늘 강의를 빼먹으면 내 출석 비율이 79.9 %로 떨어질까?”
- “강사가 의료 휴가를 인정해 줄까?”
- “내일은 늦게 일어나도 괜찮을까?”
나는 새벽 2시에도 아침 강의를 빼먹을지 말지를 결정하기 위해 복잡한 대수를 풀곤 했습니다. 단순히 습관을 추적하는 것이 아니라 전략을 세워주는 도구가 필요했습니다.
그래서 **The 80 Percent**를 만들었습니다.
아래는 Flutter, Google Gemini AI, 그리고 무료 티어를 유지하면서도 고도로 최적화된 Firebase 백엔드로 구현한 풀‑스택 솔루션의 전체 과정을 소개합니다.
1. 전략 엔진: “안전하게 건너뛸 수 있음” 로직
대부분의 습관 추적기는 “현재 75 %입니다.” 라고만 말합니다. 이는 쓸모 없는 정보입니다. 나는 실행 가능한 조언이 필요했습니다.
“버퍼” 공식
목표를 초과했을 때, 위험 구역에 도달하기 전에 몇 번의 수업을 결석할 수 있나요?
// The Magic Formula
int calculateSafeSkips(int present, int total, double target) {
// Formula: floor((present / target) - total)
int skips = ((present / target) - total).floor();
return skips < 0 ? 0 : skips;
}
시나리오: 18/20 수업에 참석했습니다. 목표 = 80 %.
결과: 안전하게 2번 더 결석할 수 있습니다.
왜 중요한가: 학생들이 필요 없는 수업에 불안하게 참석하는 것을 막아 번아웃을 예방합니다.
“회복” 공식
만약 실패 상태라면, 다시 안전해지기 위해 연속해서 몇 번의 수업에 참석해야 할까요?
// The Recovery Formula
int calculateRecovery(int present, int total, double target) {
// Formula: ceil((target * total - present) / (1 - target))
return ((target * total - present) / (1 - target)).ceil();
}
이는 중요합니다. 왜냐하면 70 %인 학생은 언제 다시 안전해질지 정확히 알아야 하기 때문입니다.
2. AI 도전 과제: Gemini 2.5로 시간표 파싱
학생용 앱에서 가장 큰 마찰은 설정입니다. 15개의 모듈과 시간대를 일일이 입력하고 싶어 하는 사람은 없습니다.
왜 Gemini 2.5 Flash인가?
| Reason | Benefit |
|---|---|
| Speed & Cost | 무료 학생 앱에 이상적 – 저지연, 저비용 추론. |
| Multimodal Intelligence | PDF/이미지 입력을 직접 받아들임. |
| Zero‑Shot Capability | 긴 few‑shot 예제가 필요 없으며, 하나의 잘 구조화된 시스템 지시만 있으면 충분합니다. |
구현 (Zero‑Shot Prompt)
final model = GenerativeModel(
model: 'gemini-2.5-flash',
apiKey: apiKey,
);
final prompt = """
You are an intelligent assistant that extracts university timetable data.
**GOAL**: Extract timetable metadata, modules, and classes into structured JSON.
**SCHEMA**:
{
"modules": [{"code": String, "name": String, ...}],
"classes": [{"day": String, "time": String, "location": String, ...}]
}
""";
final response = await model.generateContent([
Content.text(prompt),
Content.data('image/png', timetableImageBytes),
]);
앱은 JSON 응답을 파싱하고 클래스를 로컬 데이터베이스에 배치‑쓰기합니다. 이 “Zero‑Shot” 접근 방식은 요청 페이로드를 작고 빠르게 유지합니다.
3. 아키텍처: Firebase 무료 티어에서 살아남기
학생인 저는 $0 예산을 가지고 있습니다. Firebase는 훌륭하지만 Firestore 제한(하루 50 000 읽기)은 함정입니다. 500명의 사용자가 하루에 10번씩 앱을 열고 각각 10개의 레코드를 가져간다면 첫날에 바로 할당량을 초과하게 됩니다.
나의 “오프라인‑우선” 솔루션
| Component | What it does |
|---|---|
| Local Caching | 앱 실행 시 기기에서 데이터를 즉시 로드합니다. |
| Lazy Syncing | 사용자가 명시적으로 무언가를 변경할 때만 Firestore에 기록합니다 (예: 출석 표시). |
| No Images in DB | 유료 “Blaze” 플랜이나 부피가 큰 Base64 해킹을 피하기 위해 프로필 사진 동기화를 생략했습니다. |
리포지토리 패턴을 사용하면 앱을 수천 명의 사용자까지 비용을 전혀 들이지 않고 확장할 수 있습니다.
4. 결과: 프로덕션‑레디 베타
“80 %”는 단순한 계산기가 아니라 전체 스택 학술 도구입니다.
- 기술 스택: Flutter, Firebase Auth / Firestore, Provider, Gemini API.
- 상태: 오픈‑소스 및 베타 라이브.
이 프로젝트를 구축하면서 엔지니어링은 트레이드‑오프에 관한 것이라는 것을 배웠습니다 – 안정성(무료 티어 제한)을 위해 화려한 기능(클라우드 이미지)을 포기했고, 앱을 실제로 유용하게 만들기 위해 단순한 로직을 정밀한 수학으로 대체했습니다.
Screenshot
시도해 보기
저는 동료 개발자와 학생들의 피드백을 찾고 있습니다.
- 👉 Notion Documentation (원본에서 링크가 잘렸습니다; 사용 가능한 경우 올바른 URL로 교체하세요)
레포를 복제하고, 이슈를 열거나, 개선 사항을 제안해 주세요!
[The 80% Attendance Strategy for Undergrads](https://ill-grenadilla-8a4.notion.site/The-80-Attendance-Strategy-for-Undergrads-2d4d8852a123808c900cd5c78f7de104?pvs=74)
👉 [Demo code and APK file](https://github.com/inusha-thathsara/attendance-tracker-demo/tree/main)
*(Star the repo if you think the project is cool! ⭐)* 