본문으로 건너뛰기

한 사람이 AI와 함께 만든 i-하루

아내는 매일 아침 자기 출근 준비와 아이 등교 준비를 함께 했습니다.

날씨와 시간표, 학사일정을 확인하려면 앱을 서너 개 열어야 했습니다.

책을 좋아하는 아이에게 도서관 소식이나 새로 나온 책을 챙겨주는 일은 또 따로였습니다.

이 정보를 한 화면에 모으면 아침에 드는 시간이 줄어듭니다.

i-하루는 이 판단에서 시작했습니다.

아이는 학업에 더 집중하고, 부모는 아이의 하루를 조금 더 쉽게 챙길 수 있도록.

2026.02.19, 첫 줄의 코드 → 2026.09, 사용자에게 닿기까지의 기록

—
개발 일수
첫 줄 코드부터 오늘까지
2600+
Commits
git 기준 누적
14
핵심 기능
급식 · 시간표 · 진로 · 도서 · 탐방 …
0원
인프라 비용
AI 도구 + 도메인 외 무료
보기 모드
Phase 0 · 2026.02

첫 줄

고민 하나가 코드가 되기까지

2026.02.19이정표

2026.02.19 — 첫 커밋

2026년 2월 19일 저녁 첫 커밋을 남겼습니다. 아내가 출근 준비와 아이 등교 준비를 동시에 하면서 날씨 앱과 학교 알림을 번갈아 확인하는 상황이 출발점이었습니다.

첫 커밋 메시지에 '매일 쓰는 학교생활 도우미'를 명시했습니다. 기능을 붙이기 전에 서비스 정체성을 먼저 고정하는 순서로 진행했습니다.

commit 712d4a8 — "EduLife v6.1 initial commit"

기술 디테일
사용 도구
Claude Code · Claude Opus 4.7
자동화
프로젝트 골격 자동 스캐폴딩 (Next.js + Expo + Supabase 모노레포)
사람이 결정한 것
"매일 쓰는 학교생활 도우미"라는 정체성을 첫 commit 메시지에 박음
2026.02.20덜어냄

2026.02.20 — 유료 API 전면 배제

진로 추천 기능에 OpenAI API 사용을 검토했습니다. 월 비용을 산정한 결과 사용자 수에 비례해 비용이 증가하는 구조였습니다.

당일 관련 코드를 전부 제거하고 환경 변수 OPENAI_API_KEY를 삭제했습니다. 운영비가 늘면 결국 사용자 요금으로 전가되고, 수익이 없는 기간에 그 비용을 감당할 근거도 없다고 판단했습니다.

이후 원칙을 두 가지로 고정했습니다. i-하루는 무료로 유지한다. 모든 기능은 국내 무료 공공데이터로만 구현한다.

기술 디테일
사람이 결정한 것
비용이 사용자 수에 비례하는 외부 API(OpenAI 등)는 전면 금지
통계
OpenAI 의존 코드 100% 제거 · 환경 변수 OPENAI_API_KEY 삭제
2026.02 마지막 주

2026.02 4주차 — 공공데이터 3종 연동

학교 정보, 날씨, 급식 영양, 도서관 정보를 처음으로 한 화면에 통합했습니다. NEIS, 기상청, 도서관정보나루 3종을 연동했습니다.

OpenAPI 명세를 입력하면 TypeScript 타입과 fetcher를 자동 생성하는 패턴을 이 시점에 정착시켰습니다. 이후 공공데이터 추가 연동은 모두 같은 절차를 따랐습니다.

기술 디테일
사용 도구
Claude Code
자동화
OpenAPI 명세를 그대로 입력 → TypeScript 타입 + fetcher 자동 생성하는 패턴 정착
통계
첫 연결 공공데이터 3종: NEIS · 기상청 · 도서관정보나루
2026.02 마지막 주

2026.02 4주차 — 5탭 구조 확정

React Native와 Expo로 홈·급식·시간표·학사일정·설정 5탭 골격을 구성했습니다.

당시에는 학원, 체험학습, 병원 정보까지 포함할 계획이었습니다. 탭은 5개를 상한으로 두었습니다. 매일 사용하는 앱에서 탭이 늘어나면 단순함이 무너진다고 판단했습니다.

기술 디테일
사용 도구
React Native · Expo · React Navigation
자동화
홈·급식·시간표·학사일정·설정 5탭을 Bottom Tabs + Native Stack 골격으로 구성
사람이 결정한 것
탭은 5개까지만 — 늘리면 매일 쓰는 앱의 단순함이 깨진다고 판단
Phase 1 · 2026.03

옷 입히기

코드에 얼굴을 만든 한 달

2026.03이정표

2026.03 — 브랜드 확정

브랜드명 'i-하루'에는 '나의 하루'와 '내 아이의 하루' 두 가지 뜻을 함께 담았습니다. 로고는 떠오르는 해 아래 흰색 'i' 한 글자로 정했습니다. 크림색 배경 #FFF7ED에 오렌지 #F97316을 사용합니다.

메인 슬로건은 '학교생활의 모든 것, i-하루'로 확정했습니다.

기술 디테일
사람이 결정한 것
메인 슬로건 "학교생활의 모든 것, i-하루" · 일출 로고(크림 #FFF7ED + 오렌지 #F97316) 확정
2026.03

2026.03 — 공유 컴포넌트 정리

화면을 개별로 만들면서 버튼과 카드를 매번 새로 작성하고 있었습니다. 반복되는 요소를 공유 컴포넌트 11개로 추출했습니다.

신규 화면 제작 시간이 약 절반으로 줄었습니다. 어느 화면을 열어도 동일한 UI 규칙이 적용됩니다.

기술 디테일
사용 도구
React Native Paper · Material Design 3
자동화
EduCard·EduButton·EduChip·EduTab·EduBadge·CardSkeleton 등 공유 컴포넌트로 추출
통계
공유 UI 11개 · 신규 화면 제작 시간 약 절반 단축
2026.03덜어냄

2026.03 — 다크모드 보류

다크모드를 구현했으나 화면별 색 일관성이 확보되지 않았습니다.

완성도가 낮은 다크모드는 제공하지 않는 편이 낫다고 판단해 출시 후 재검토로 보류했습니다. 기능을 접는 것도 의사결정 항목으로 기록했습니다.

기술 디테일
사람이 결정한 것
"잘 안 되는 다크모드는 없느니만 못하다" — 색 일관성 확보 전까지 출시 후로 보류
2026.03 말

2026.03 말 — 핵심 기능 12종 골격 완성

급식, 시간표, 학사일정, 아침 브리핑, 날씨, 도서관, 추천도서, 교육청 공지, 직업, 학과, 자격증, 심리검사 12종의 골격을 완성했습니다. 메인 페이지 12카드 그리드가 이 시점에 확정됐습니다.

기술 디테일
통계
핵심 기능 12종 골격 + 메인 12카드 그리드 확정
Phase 2 · 2026.04

사업이 되다

취미가 책임이 된 한 달

2026.04.06덜어냄

2026.04.06 — 기능 축소 (v7.0~v7.1)

두 달간 추가한 기능을 일괄 점검했습니다. 레시피, 병원·약국, 학원 목록, 교육체험, 안전지도를 제거했습니다. 개별 완성도와 무관하게 '학교생활'이라는 정의에서 거리가 있다고 판단했습니다.

급식, 시간표, 학사일정, 진로, 도서관, 날씨, 교육청 공지 7갈래만 남겼습니다. 이 7갈래가 이후 진로(직업·학과·자격증·심리검사)와 도서(도서관·추천도서)로 분화하고 아침 브리핑이 더해져, 출시 시점에 12종이 됩니다.

v7.0~v7.1 축소

기술 디테일
사람이 결정한 것
"학교생활"에서 한 발 먼 기능은 좋아도 제거 — 레시피·병원·학원·교육체험·안전지도
통계
v7.0~v7.1 기능 축소 · 핵심 7갈래 잔존 → 출시 시점 12가지로 확장
2026.04.07덜어냄

2026.04.07 — 체험학습 서류 기능 제거

학부모 사용 빈도가 높은 기능이었으나 제거했습니다. 공식 양식을 자동 생성하는 책임은 학교 시스템에 있다고 판단했습니다.

기술 디테일
사람이 결정한 것
양식 자동 생성의 책임은 학교 시스템 몫이라 판단 — 체험학습 서류 기능도 정리
2026.04.21

2026.04.21 — 날씨 화면 응답 32초에서 2~4초로

학교 위치 기반 날씨를 제공하기 위해 여러 API를 순차 호출한 결과, 한 화면 로딩에 32초가 걸렸습니다. 사용자 관점에서는 동작하지 않는 화면입니다.

일주일간 호출 구조를 재설계했습니다. 순차 호출을 병렬로 전환하고 Upstash Redis에 12시간 캐시를 적용했으며 로직을 helpers.ts로 분리했습니다.

응답 시간은 2~4초로 줄었습니다. 약 8~15배 개선입니다.

기술 디테일
사용 도구
Upstash Redis · Next.js Route Handler
자동화
순차 호출을 병렬로 전환 + Redis 12시간 캐시 + helpers.ts 로직 분리
통계
날씨 화면 응답 32초 → 2~4초 (약 8~15배 개선)
2026.04.22

2026.04.22 — 신규 가입자 아침 브리핑 자동화 (v1.1.3)

신규 가입 시 프로필과 푸시 토큰을 자동 설정해, 다음 날 아침 브리핑이 자동 발송되도록 구성했습니다. 시간표, 급식, 날씨, D-day가 한 줄로 전달됩니다.

'가입 직후 첫 아침에 가치를 경험한다'는 온보딩 원칙이 이 시점에 정해졌습니다.

v1.1.3 신규 가입 자동화

기술 디테일
사용 도구
FCM
자동화
신규 가입 시 프로필·푸시 토큰 자동 세팅 → 다음 날 아침 브리핑 자동 발송 (매일 새벽 배치)
사람이 결정한 것
온보딩 직후 첫 아침에 시간표·급식·날씨·D-day를 한 줄로 — "가입하고 바로 가치"
2026.04.24이정표

2026.04.24 — 사업자등록

개발 시작 두 달 만에 사업자등록을 마쳤습니다. 상호 '아이하루', 일반과세자, 등록번호 594-56-00915입니다.

광고 수주나 투자 유치가 목적은 아니었습니다. 사용자에게 책임을 지는 주체를 명확히 하기 위한 절차였습니다. 이후 모든 의사결정에 '사용자에게 떳떳한가'를 판단 기준으로 추가했습니다.

두 달 전에는 아내의 아침 하나만 생각하면 됐습니다. 등록을 마친 날부터는 그렇지 않았습니다.

사업자등록번호 594-56-00915

기술 디테일
사람이 결정한 것
광고·투자가 아니라 사용자에 대한 정직한 책임으로 사업자 등록. 이후 "사용자에게 떳떳한가"를 기준에 추가
2026.04.26이정표

2026.04.26 — 한국관광공사 공모전 제출

한국관광공사 공모전에 가족 3명이 한 팀으로 참여했습니다. 제안서는 11회 개고했고 마감 6일 전에 제출했습니다.

제출 전에 한 가지를 정해 두었습니다. 선정 여부와 관계없이 해당 기능은 개발한다. 학교 밖에서 보내는 하루도 학교생활의 연장이라고 봤습니다.

기술 디테일
사람이 결정한 것
출전 여부와 무관하게 개발 진행 결정 · 가족 3명이 한 팀 · 제안서 11회 개고 후 마감 6일 전 제출

100일간의 기능 가지치기

7
도입했다 덜어낸 기능
  • · 레시피
  • · 병원·약국
  • · 학원 목록
  • · 교육체험
  • · 체험학습 서류
  • · 안전지도
  • · Sentry
2
접었다 다시 부른 기능
  • · 실종아동
  • · 관광 (탐방 모듈)
1
시도 후 보류한 기능
  • · 다크모드 (출시 후 재검토)
Phase 3 · 2026.05

어른의 일들

보이지 않는 곳에서 더 많은 일이 일어난 한 달

2026.05.03

2026.05.03 — RLS 전수 적용 및 로그 개인정보 마스킹

Supabase 27개 테이블에 행 단위 보안(RLS)을 일괄 적용했습니다. 미사용 테이블 3개는 삭제했습니다.

에러 로그와 분석 로그는 기록 시점에 개인정보를 자동 마스킹하도록 처리했습니다. 로그에 평문 개인정보가 남지 않습니다.

사용자에게 보이지 않는 작업이지만, 처리하지 않으면 서비스를 운영할 수 없는 항목이라 출시 전 최우선으로 처리했습니다.

기술 디테일
자동화
Supabase 27개 테이블에 행 단위 보안(RLS) 일괄 적용 + 로그 write 시점 PII 자동 마스킹(allowlist)
사람이 결정한 것
사용자가 볼 수 없지만, 안 하면 서비스를 할 수 없는 일이라 출시 전 우선 처리
통계
27 테이블 RLS · dead 테이블 3개 DROP · 로그 평문 개인정보 0
2026.05.04덜어냄

2026.05.04 — Sentry 제거

에러 모니터링용으로 Sentry를 연동해 두었으나, 환경 변수명이 어긋나 단 한 건도 전송되지 않고 있었습니다.

수정 대신 제거를 선택했습니다. 자체 error-report API와 Supabase 로그로 필요한 수준이 충족됐고, 비용이 발생하는 외부 서비스를 늘리지 않는다는 원칙을 우선했습니다. (commit 2d2daed)

commit 2d2daed

기술 디테일
사람이 결정한 것
오작동하던 Sentry를 고쳐 살리는 대신 제거 — 비용 발생 외부 서비스를 늘리지 않는다는 원칙 우선
통계
에러 모니터링은 자체 error-report API + Supabase 로그 + PII 마스킹으로 통일
2026.05.05

2026.05.05 — 교육청·교육부 공지 18곳 통합

전국 17개 시도교육청과 교육부 공지사항을 매일 새벽 크롤링해 DB에 적재하고 한 화면에서 제공합니다. Puppeteer와 Oracle Cloud VM을 사용합니다.

전체 탭과 개별 탭을 두고 새 글 배지를 표시합니다. 학부모가 개별 사이트를 순회할 필요가 없어졌습니다.

기술 디테일
사용 도구
Puppeteer · Oracle Cloud VM
자동화
17개 시도 교육청 + 교육부 공지를 매일 새벽 VM에서 크롤링 → DB 적재 → 한 화면 통합
통계
교육청 17곳 + 교육부 · 전체/개별 탭 + 새 글 뱃지
2026.05.09이정표

2026.05.09 — 도메인 및 App Links 전환

정식 도메인 i-haru.co.kr을 적용했습니다. 공유 링크 14곳과 App Links 경로 11개를 일괄 이전하고, 기존 vercel.app 주소는 308 리다이렉트로 처리했습니다.

공유 링크를 받은 기기는 앱이 설치돼 있으면 앱으로, 없으면 웹으로 열립니다. 수신자가 별도 조치를 하지 않아도 되는 구조입니다.

기술 디테일
사용 도구
Android App Links · Cloudflare
자동화
공유 링크 14곳 + App Links 경로 11개를 i-haru.co.kr로 일괄 마이그레이션 + vercel.app 308 리다이렉트
사람이 결정한 것
앱 설치 폰은 앱으로, 미설치는 웹으로 — production keystore SHA-256 등록
2026.05.10 → 05.12부활

2026.05.10~05.12 — 실종아동 알림 재도입 (v2)

정체성 불일치를 이유로 한 차례 제외했던 실종아동 알림 기능을 재도입했습니다. 아이를 키우는 입장에서 해당 가족의 상황을 외면하기 어렵다고 판단했습니다.

광고 슬롯을 공유하는 방식으로 배치했습니다. 노출 비율은 초기 30%로 설정했으나, 실기기에서 확인한 뒤 10%로 조정했습니다.

safe182 데이터를 조회한 결과 전국 168명이었고 1년 이내 사건은 4명이었습니다. 1958년 사건도 미해결 상태였습니다. 기존 365일 필터를 제거하고 우리 동네·같은 시도·전국·장기 미해결 순으로 노출하도록 v2를 재설계했습니다. 가중치는 우리 동네 5배, 같은 시도 3배, 전국 2배입니다.

부활 결정 → v2 12 task 완료 (18 + 12 commit)

기술 디테일
사용 도구
safe182 OpenAPI · Oracle Cloud VM
사람이 결정한 것
"1년 이내가 4명뿐인데 365일 cutoff?" — 사용자 직관이 AI 가정을 정정
통계
우리 동네 ×5 / 같은 시도 ×3 / 전국 ×2 가중 · 광고:실종 = 90:10 · v2 12 task
2026.05.14이정표

2026.05.14 — D-U-N-S 번호 발급

App Store 조직 등록에 필요한 D-U-N-S 번호를 신청 5일 만에 발급받았습니다. 통상 소요되는 7~14영업일보다 빠른 처리입니다.

Google Play 조직 계정은 본인·웹사이트·전화 3중 인증을 통과했습니다. Apple 등록은 출시 안정화 이후로 보류했습니다.

기술 디테일
사람이 결정한 것
Google Play 조직 계정 + 본인·웹사이트·전화 3중 인증 통과 · Apple은 출시 안정화 후로 보류
통계
D-U-N-S 발급 — 신청 5일 만에(예상 7~14영업일보다 빠름)
2026.05.14

2026.05.14 — 광고주 관리 파이프라인 구축

무료 유지를 위해 광고가 필요했습니다. 다만 수주 절차를 자동 검증 위에 올렸습니다.

신청, 검토, 게재, 월간 리포트 발송까지 전 과정을 구성했습니다. reCAPTCHA v3와 Gmail SMTP, Vercel Cron을 사용하고 사업자번호 진위 검증과 자동 만료 cron을 포함했습니다. 커밋 9건과 테스트 535건 통과 후 프로덕션에 적용했습니다.

기술 디테일
사용 도구
reCAPTCHA v3 · Gmail SMTP · Vercel Cron
자동화
광고주 신청→검토→게재→월간 리포트 자동화 + 사업자번호 진위 검증 + 자동 만료 cron
통계
9 commit · 535 tests 통과 · production 라이브
2026.05.17

2026.05.17 — 광고 슬롯 가중 노출 및 분점 운영

하나의 광고 슬롯에 광고주 배너, 실종아동 알림, AdMob 자동 광고를 가중 랜덤으로 노출합니다. 노출 비율은 운영 화면의 슬라이더로 조정합니다.

분점 운영을 위해 사업자번호·학원명·지역 조합에 UNIQUE 제약을 적용하고 지역 자동 매칭을 구현했습니다. subagent 기반 28개 task, 마이그레이션 3종입니다.

기술 디테일
자동화
광고주 배너·실종아동·AdMob을 한 슬롯에서 가중 랜덤 노출 + 분점 운영(사업자번호+학원명+지역 UNIQUE) + 지역 자동 매칭
통계
subagent-driven 28 task · 마이그레이션 3종 · 노출 비율 슬라이더로 운영 제어
2026.05.17

2026.05.17 — 서점 신간·베스트셀러 연동

도서관 장서에 더해 서점 신간까지 제공하기 위해 알라딘 TTB OpenAPI를 연동했습니다. 신간 44권과 베스트셀러 50권을 매일 새벽 동기화합니다.

ISBN10과 ISBN13을 정규화하고 VM 프록시를 경유해 호출합니다. 도서관(정보나루)과 서점(알라딘) 데이터는 완전히 분리했습니다. 커밋 36건, 마이그레이션 4종입니다.

기술 디테일
사용 도구
알라딘 TTB OpenAPI · Oracle Cloud VM
자동화
ISBN10↔13 정규화 + VM 프록시 경유 호출 + 신간·베스트셀러 매일 새벽 동기화
통계
신간 44권 · 베스트셀러 50권 · 36 commit · 마이그레이션 4종 · 도서관(정보나루)·서점(알라딘) 완전 분리
2026.05.20부활

2026.05.20 — 공모전 예비심사 합격

공모전 예비심사 합격 통지를 받았습니다. 개발 시작 이후 처음으로 외부의 평가를 받은 결과입니다.

서비스 방향성의 이유로 잠시 보류했던 관광 기능 개발을 이 시점에 재개했습니다.

기술 디테일
통계
예비심사 합격 · 접어 두었던 관광 기능 재개
2026.05.27

2026.05.27 — 미디어킷 공개, 스토리 페이지 착수

기자와 리뷰어가 사용할 수 있도록 로고와 앱 스크린샷을 정리한 미디어킷 페이지를 공개했습니다. 같은 날 이 스토리 페이지 작성을 시작했습니다.

기술 디테일
사람이 결정한 것
기자·리뷰어용 미디어킷 정식 가동(로고·스크린샷) + 같은 날 이 스토리 페이지 착수
Phase 4 · 2026.06~07

세상에 내보내기

준비를 마치고 문을 여는 시간

2026.06.15이정표

2026.06.15 — 위치기반서비스사업 신고 완료

주변 도서관을 위치 기반으로 안내하는 기능 때문에 위치정보법상 사업자 신고가 필요했습니다. 1인이 만든 무료 앱도 예외가 아니었습니다.

신청 후 보완 요청을 받아 양식을 재작성했고, 2026년 6월 15일 방송미디어통신사무소의 수리증을 받았습니다. 신고번호는 제1170호입니다.

부가통신사업은 신고 면제 대상으로 확인됐습니다. 위치 정보는 서버에 저장하지 않고 일회성으로만 처리합니다.

위치기반서비스사업 신고번호 제1170호

기술 디테일
사람이 결정한 것
기능 하나에도 법이 요구하는 절차는 다 밟는다 — 위치 정보는 서버에 저장하지 않고 일회성으로만
통계
부가통신 = 신고 면제 확정 / 위치기반 = 수리 완료(제1170호)
2026.06

2026.06 — 약관·개인정보처리방침 전수 점검

출시를 앞두고 개인정보처리방침과 이용약관을 전수 점검했습니다.

데이터가 경유하는 수탁사를 전부 명시했습니다. 이메일 발송, 캐시, 크롤러 서버를 포함하며 국외 이전 경로와 이전 항목을 함께 기재했습니다. 만 14세 미만 보호 조항도 반영했습니다.

'위치 정보를 서버에 저장하지 않는다'는 조항은 실제 코드와 대조해 일치 여부를 확인했습니다.

기술 디테일
사람이 결정한 것
사용자가 잘 읽지 않는 페이지일수록 더 정직하게 — 약관의 문장과 실제 코드를 대조
통계
처리위탁·국외이전 수탁자 전수 명시 · 만 14세 미만 보호 · 위치정보 서버 미저장 코드 검증
2026.06.15

2026.06.15 — 소셜 로그인 버튼 BI 재작업

네이버 로그인 검수가 승인으로 회신됐습니다. 다만 로그인 버튼을 가이드에 맞춰 달라는 권장 사항이 포함돼 있었습니다.

권장 사항이었으나 카카오·네이버·구글 3사의 공식 가이드를 모두 확인해 버튼을 재작업했습니다. 각 브랜드의 공식 로고와 지정 문구, 지정 색상을 적용하고 로그인과 회원가입에 동시 반영했습니다. 시안은 빌드 전에 목업으로 확인한 뒤 확정했습니다.

기술 디테일
사람이 결정한 것
‘권장’도 기왕이면 제대로 — 버튼 시안은 빌드 전에 목업으로 먼저 확인하고 결정
통계
카카오·네이버·구글 공식 BI 준수 · 로그인·회원가입 동시 적용
2026.06

2026.06 — 프로덕션 심사 제출

클로즈드 테스트를 거쳐 Play Console에 프로덕션 심사를 제출했습니다. 대기 기간에는 스토어 소개 문구와 스크린샷을 재작성했습니다.

기술 디테일
통계
클로즈드 테스트를 거쳐 프로덕션 심사 제출
2026.06~07

2026.06~07 — 실사용 시나리오 전 구간 점검

실제 학교의 하루를 순서대로 따라가며 전 구간을 점검했습니다. 아침에 앱을 열고, 급식을 확인하고, 시간표를 보고, 도서관을 찾는 순서입니다.

2026.07.03이정표

2026.07.03 — 정식 출시

심사를 통과해 정식 출시했습니다. 첫 커밋으로부터 134일째입니다.

처음 목표는 우리 집 아침에 여는 앱의 개수를 줄이는 것이었습니다. 이제 그 대상이 우리 집만은 아닙니다.

출시 이후 작업량은 줄지 않았습니다. 출시는 운영이 시작되는 시점이었습니다.

기술 디테일
통계
2026.02.19 첫 커밋 → 2026.07.03 정식 출시 (134일)
Phase 5 · 2026.07~09

닿고 나서

출시 이후가 더 바빴던 석 달

2026.07~09

2026.07~09 — 출시 후 커밋 862건

출시 이후 석 달간 커밋 862건이 추가됐습니다. 7월 239건, 8월 481건, 9월 142건입니다.

개발자 본인만 사용할 때는 지나쳤던 지점이 사용자 관점에서 드러났습니다. 방학 기간에 급식이 없는 날의 빈 화면, 학교를 변경한 뒤에도 남아 있던 이전 학교 기준 거리 등입니다.

기능을 추가하기 전에 기존 화면이 정직하게 동작하는지 먼저 점검하는 순서로 전환했습니다.

기술 디테일
사람이 결정한 것
기능을 더하기 전에 이미 있는 화면이 정직한지부터 다시 본다
통계
출시 후 커밋 862 (7월 239 · 8월 481 · 9월 142)
2026.07~09부활

2026.07~09 — 탐방·축제 모듈

공모전 준비에 다섯 달을 사용했습니다. 개발을 진행하면서 이 기능의 우선순위가 공모전보다 앞서게 됐습니다.

한국관광공사 OpenAPI 8종을 연동해 전국 관광지와 축제, 걷기 좋은 길, 오디오 해설을 수집합니다. 배치가 새벽에 지역별 추천을 미리 채워 두고 화면은 그 결과를 읽는 구조입니다.

음식점과 숙박은 처음부터 제외했습니다. 학생과 가족이 방문할 만한 장소만 남겨 시·도별로 정리했습니다.

탐방 · 축제 — 한국관광공사 공공데이터

기술 디테일
사용 도구
한국관광공사 OpenAPI 8종 · 배치가 새벽에 지역별 추천을 미리 채워 두고 화면은 그것을 읽는다
사람이 결정한 것
음식점·숙박은 처음부터 뺐다 — 학생과 가족이 갈 만한 곳만 남긴다
통계
전국 관광정보 · 이번 달 축제와 상설 전시 · 시·도별 추천
2026.08

2026.08 — 외부 데이터 상태 감시 체계 도입

외부에서 받아 오는 데이터는 장애가 표면에 드러나지 않습니다. 응답은 정상으로 오는데 내용이 갱신되지 않는 형태의 장애가 발생합니다.

실제로 한 교육청 공지가 두 달간 갱신되지 않았으나 인지하지 못했습니다. 화면에 이전 데이터가 남아 있어 사용자 신고도 들어오지 않았습니다.

외부에서 받아 오는 데이터 전반에 감시를 적용했습니다. '응답 여부'와 '신규 데이터 유입 여부'를 분리해 점검하고, 2회 연속 실패 시 알림, 회복 시 재알림하는 구조입니다.

임계값은 고정할 수 없었습니다. 지역에 따라 139일 공백이 정상인 곳이 있고 60일 공백이 장애인 곳이 있었습니다. 지역별 과거 공백 기록을 기준으로 자동 보정하도록 설계했습니다.

기술 디테일
자동화
외부 데이터 감시 · 연속 2회 실패면 알림, 회복하면 한 통 더
사람이 결정한 것
고정 임계로는 못 가른다 — 어떤 지역은 139일 공백이 정상이고 어떤 지역은 60일이 고장이었다. 각자의 역대 공백을 기준으로 스스로 보정하게 했다
2026.09.03

2026.09.03 — 주 2~3회 추천 알림 발송

조회 기능은 완성돼 있었으나 사용자가 앱을 열어야만 정보를 확인할 수 있었습니다. 발신 채널을 추가했습니다.

주 2~3회 저녁에 알림을 발송합니다. 주말에 인근에서 열리는 축제나 학교에서 가까운 박물관 등이 대상입니다. 다섯 장르가 회전하며 알림 내역에서 다시 확인할 수 있습니다.

회전 슬롯 7칸 중 4칸을 주변 지역에 배정했습니다. 대구에 사는 사용자에게 서울 축제를 추천하면 정보가 아니라 광고가 됩니다.

발송 기능보다 수신 거부 스위치를 먼저 구현한 뒤 발송을 활성화했습니다.

기술 디테일
사람이 결정한 것
알림을 끄는 스위치를 먼저 만들고 나서 발송을 켰다
통계
주 2~3회 · 다섯 장르 회전 · 알림 내역에서 다시 볼 수 있음
2026.09.05이정표

2026.09.05 — 46일 만의 배포, 게시 직전 결함 1건

2026년 9월 5일, 다섯 달치 작업을 반영한 버전을 배포했습니다. 직전 배포로부터 46일이 지난 시점입니다.

패키지 빌드와 업로드를 마친 뒤 실기기 점검을 한 차례 더 진행했고, 여기서 결함 1건을 발견했습니다. 한 항목을 연 뒤 다른 항목을 열면 처음 열었던 항목이 반복 표시되는 문제였습니다.

자동 검증 1,567건은 전부 통과한 상태였습니다. 타입 검사와 빌드에서도 오류가 없었습니다. 실기기에서 두 항목을 연속으로 열어본 점검만이 이 결함을 검출했습니다.

버전을 올려 재빌드했고, 당일 수정한 화면 13개를 실기기에서 개별 확인한 뒤 23시 25분에 게시했습니다. 게시 4시간 후 크래시 0건입니다. 자동 검증 통과는 깨지지 않았다는 뜻이며, 정확하다는 뜻은 아닙니다.

2026.09.05 23:25 — 게시

기술 디테일
사람이 결정한 것
초록불은 안 깨졌다는 뜻이지 맞다는 뜻이 아니다 — 마지막 확인은 손으로 한다
통계
자동 검증 1,567 전부 통과 · 폰 실기에서 결함 1건 발견 · 게시 4시간 뒤 크래시 0
Phase 6 · 계속

다음

계속 만들고 있습니다

계속

학생과 학부모의 하루를 더

학생은 학업에, 학부모는 아이의 하루에 집중할 수 있도록 기능을 하나씩 더해갑니다.

거창한 목표는 없습니다. 매일 쓰는 앱이 매일 조금씩 나아지면 됩니다.

바이브 코딩, 우리는 이렇게 했습니다

100일간 AI 도구로 1인 서비스를 만든 실전 워크플로

01워크플로 — 사람이 결정하고 AI가 구현

모든 작업을 네 단계로 나눴습니다. 브레인스토밍에서 무엇을 왜 만들지 합의하고, 스펙 문서에서 화면과 데이터, 예외 처리를 문서로 고정하고, 플랜에서 작업을 독립적인 task로 분할한 뒤 구현합니다.

각 단계는 사람의 승인 없이는 다음으로 넘어가지 않습니다. AI가 전체 설계를 임의로 변경하는 경로가 구조적으로 차단됩니다.

구현은 task 하나당 subagent 하나를 할당하고, 완료 후 두 차례 검토합니다. 1차는 스펙 대비 누락과 추가 여부, 2차는 코드 품질입니다.

이 스토리 페이지도 14개 task 플랜으로 분할해 컴포넌트 단위로 구현했고, 각 단계마다 타입 검사와 테스트, 커밋을 거쳤습니다.

스펙과 플랜은 전부 git에 문서로 남깁니다. 설계 근거는 코드가 아니라 문서에서 확인합니다.

  1. 브레인스토밍
    사람 결정
  2. 스펙
    AI 작성 + 사람 승인
  3. 플랜
    AI 작성 + 사람 승인
  4. 구현
    AI 작성 + 사람 검증

02컨텍스트 보존 — 대화는 끊겨도 기록은 남는다

AI와의 대화는 길어지면 컨텍스트가 끊깁니다. 대화가 끝날 때마다 결정 사항과 피드백, 시행착오를 메모리 파일로 남깁니다.

메모리는 네 종류입니다. 사용자 정보, 행동 지침, 프로젝트 현황, 외부 참조입니다.

한 파일에 사실 하나를 담습니다. 상단에 요약을 두고 본문에 결정 근거와 적용 방법을 기록합니다. 인덱스 한 장으로 전체를 조회합니다.

'존댓말로 작성할 것', '보라 그라디언트 같은 AI 기본 색상 금지', '공공데이터 키는 전부 동일한 키' 같은 지침이 기록돼 있어, 세션이 바뀌어도 같은 실수가 반복되지 않습니다.

100일 넘게 세션이 수백 번 교체됐지만, AI는 매번 이 프로젝트의 결정 이력을 가지고 시작합니다.

03AI에게 맡긴 일 / 사람이 결정한 일

역할 경계를 명확히 나눴습니다. AI는 구현 방법을 담당하고, 사람은 대상과 근거를 결정합니다.

AI는 코드 작성과 테스트, 리팩토링, 마이그레이션 SQL, 커밋 메시지, 문서, 시각 디자인 1차안을 담당합니다.

사람은 기능의 추가와 제거, 무료 정책 유지, 사업자 등록, 마케팅 톤, 상표 출원을 결정합니다. 실기기에 설치해 체감 속도를 확인하는 작업도 사람이 합니다.

AI가 작성한 코드라도 보안, DB 마이그레이션, 결제처럼 되돌리기 어려운 영역은 사람이 한 번 더 검토한 뒤 반영했습니다.

AI 영역

  • · 코드 작성, 테스트, 리팩토링
  • · 마이그레이션 SQL, 커밋 메시지
  • · 문서, 시각 디자인 1차안
  • · 자동 검증 (type-check · lint · test)

사람 영역

  • · 기능 추가·제거 판단
  • · 사업자 등록, 가격 정책
  • · 마케팅 톤, 상표 출원
  • · 실폰 베타 검증, 사용자 피드백

04검증이 먼저, 선언은 나중 — 매 변경마다 직접 돌려본다

'완료'라고 말하기 전에 검증 명령을 실제로 실행하고 결과를 확인합니다. 타입 검사 통과, 테스트 통과, 배포 후 실제 주소 호출로 정상 응답을 확인한 시점이 완료입니다.

이 원칙이 작동한 사례가 있습니다. 이 스토리 페이지를 배포한 직후 주소는 열렸으나 본문이 비어 있었습니다. 공통 레이아웃의 한 줄 때문에 본문이 검색엔진에 노출되지 않는 상태였고, 한 줄 수정으로 해결했습니다. 화면이 열리는 것만 확인했다면 검출하지 못했을 문제입니다.

사람의 판단이 AI의 가정을 정정한 사례도 여러 건입니다. '공공데이터 키는 사실 전부 동일한 키다', '실종아동 1년 이내 사건이 4명뿐인데 365일로 자를 이유가 있는가' 같은 지적이 며칠의 작업을 절약했습니다.

AI는 빠르지만 틀린 경우에도 확신을 가지고 답합니다. 빠르게 만들되 그대로 신뢰하지 않고 확인합니다.

05비용 — 운영비를 0원에 가깝게

운영비를 0원 수준으로 유지하는 것은 성과 지표가 아니라 사용자와의 약속에 해당합니다. 비용이 늘면 결국 사용자 요금으로 전가됩니다.

지출 항목은 두 가지입니다. AI 코딩 도구 하나, 도메인 하나입니다.

나머지는 전부 무료 등급으로 운영합니다. 웹과 예약 작업은 Vercel, 데이터베이스와 인증, 저장소는 Supabase, 캐시는 Upstash, 매일 실행되는 크롤러는 Oracle Cloud의 평생 무료 서버를 사용합니다.

데이터도 전부 국내 무료 공공데이터입니다. 급식과 시간표는 교육부 NEIS, 날씨는 기상청, 진로는 커리어넷, 도서는 도서관정보나루입니다. 사용자가 늘어도 추가 요금이 발생하지 않는 구조만 선택했습니다.

인프라 0원

유료

  • AI 코딩 도구Claude Code / Claude Opus 4.7
  • 도메인i-haru.co.kr

무료 인프라

  • VercelFree Tier (웹 호스팅 · cron)
  • SupabaseFree Tier (DB · Auth · Storage)
  • Upstash RedisFree Tier (캐시)
  • Oracle CloudAlways Free (크롤러 VM)
  • 공공데이터NEIS · 기상청 · 커리어넷 외 12종 무료

06AI의 한계, 그리고 우회법

AI는 만능이 아닙니다. 한계를 파악하고 우회하는 것이 작업의 절반이었습니다.

첫째, 기억이 낡습니다. 메모리에 기록한 '이 파일 몇 번째 줄'은 며칠 뒤 어긋나 있습니다. 메모리는 참조하되 코드는 항상 다시 열어 확인합니다.

둘째, 모르는 것을 그럴듯하게 생성합니다. 빈 결과가 나오면 필수 파라미터 누락부터 의심하도록 가드레일을 메모리에 명시했습니다.

셋째, 마케팅 문구에서 과장으로 흐릅니다. '검증할 수 없는 단언은 사용하지 않는다' 같은 규칙을 메모리에 기록해 두면 해당 표현을 회피합니다.

AI의 한계는 사람이 정한 규칙으로 보완했습니다. 한 번 정한 규칙은 메모리에 남아 다음 세션까지 적용됩니다.

07추천 패턴 (비슷한 시도를 하실 분들에게)

  • 할 일을 문서로 남기십시오. 작업 목록이 있으면 진행 상황을 사람과 AI가 동일하게 파악합니다.
  • 독립적인 작업은 병렬로 처리하십시오. 서로 간섭하지 않는 작업은 여러 subagent에 분배하면 속도가 확보됩니다.
  • 비밀값은 자동으로 차단하십시오. 커밋 직전 검사로 환경 변수와 키가 git에 포함되는 것을 막았습니다.
  • AI가 작성한 코드도 사람이 검토하십시오. 보안, DB 마이그레이션, 결제는 되돌리기 어렵습니다.
  • '완료'는 직접 실행해 확인한 뒤에 말하십시오. 검증 없는 확신이 가장 비쌉니다.

아침에 앱을 서너 개 열지 않아도 되도록

오늘의 시간표와 급식, 날씨, D-day를 한 줄 알림으로 보내드립니다.