디스코드 채팅으로 앱 하나를 통째로 만든 5주의 기록
- 19 Feb, 2026
왜 이 앱을 만들었나
집에서 매일 이런 대화가 반복됐습니다.
“카톡으로 몇 번을 말했어?” “언제 말했어? 못 들었는데?”
아내가 카톡으로 일정을 보내면 퇴근하고 확인하는데, 그때는 이미 까먹은 뒤예요. 읽씹도 아니고 진짜 못 봤는데, 상대방 입장에선 알 수가 없으니 싸우게 되는 거죠.
amadda(아마따)는 이 문제에서 출발했습니다. 단순한 공유 캘린더가 아니라, “앱이 대신 잔소리해주는” 가족 일정 관리 도구. 일정을 등록하면 담당자한테 푸시가 가고, 안 하면 30분마다 다시 알림이 오고, 완료하면 가족 전원한테 “아빠가 해냈다!” 알림이 가는 구조예요.
MVP 기능만 정리해도 꽤 많았습니다.
- 가족 그룹 생성 + 초대 (코드/QR/딥링크)
- 일정 CRUD + 미션 할당 + 체크리스트
- Nudging 알림 — 안 하면 30분/1시간마다 재알림, 2시간 지나면 등록자한테까지 알림
- 공지게시판 + 읽음 확인
- Freemium 구독 (무료 30개/월, 프리미엄 무제한)
혼자 코딩으로 만들면 3~4개월은 잡아야 할 분량이었습니다.
그래서 실험을 해보기로 했어요.
실험: 디스코드 채팅으로 앱을 만들 수 있을까?
1월 12일 새벽, 디스코드에 이렇게 쳤습니다.
“가족 일정 공유 앱 만들자. 이름은 amadda.”
5주 뒤, 146개 커밋이 쌓여 있었고, Play Console에 올라간 앱이 있었습니다. 그 사이에 제가 코드 에디터를 직접 연 건 손에 꼽을 정도예요. 나머지는 전부 디스코드 채팅창에서 벌어진 일입니다.
이건 그 5주의 기록입니다.
개발 환경
윈도우 데스크탑 한 대가 전부입니다. 원래 Windows에서 직접 Flutter 개발을 하려고 했는데, 에뮬레이터 세팅이나 리눅스 도구들이 필요한 부분이 많아서 결국 WSL2(Windows Subsystem for Linux)로 갔어요. 리눅스 환경이 훨씬 편하더라고요.
- OpenClaw — AI 에이전트 게이트웨이. Discord 메시지를 받아서 Claude한테 전달하고, Claude가 터미널 명령이나 코딩 에이전트를 실행
- OpenCode — 코딩 전문 에이전트 CLI. 파일 읽기/쓰기/수정을 알아서 함
- Flutter 3.27 — 앱 프레임워크 (Android + Web)
- Firebase — 백엔드 전부 (인증, DB, 스토리지, 푸시, 배포)
- Android Emulator — WSL2 안에서 KVM으로 돌림
디스코드에 메시지 치면 → OpenClaw가 받아서 → Claude가 판단하고 → OpenCode한테 코딩 시키거나 직접 셸 명령을 때리는 흐름이에요. IDE를 열 필요가 없습니다.
1주차: 1월 12-18일 — 뼈대를 세우다
Day 1 (1/12): 18개 Phase를 하루에
아침에 “가족 일정 앱 만들자”고 했더니, 에이전트가 Phase를 쪼개서 하나씩 진행하기 시작했습니다.
Phase 1 — Flutter 프로젝트 셋업 + Firebase 연동
Phase 3 — Firestore 데이터 모델, Repository 패턴
Phase 4 — Service Provider + 정적 분석 수정
Phase 5 — 가족 생성/참여 플로우
Phase 6 — 실시간 캘린더
Phase 7 — 미션(할 일) 완료 기능
Phase 8 — FCM 푸시 알림
Phase 9 — 공지게시판
Phase 10 — 구독 결제 인프라
...
Phase 18 — 회원 탈퇴 + 안전 장치
하루에 18개 커밋. 물론 각 Phase가 완벽했던 건 아닙니다. 뼈대를 빠르게 세우고, 디테일은 나중에 잡는 방식이었어요. 중요한 건 저녁쯤에 이미 앱이 돌아가고 있었다는 겁니다. 로그인하고, 가족 만들고, 일정 추가하고, 푸시 알림까지.
Phase 2는요? 건너뛰었습니다. 에이전트가 순서를 실수한 건데, 지적하기엔 나머지가 잘 돌아가고 있어서 그냥 넘어갔어요.
Day 3 (1/14): 빌드와 배포
AdMob 광고 붙이고, APK 빌드 스크립트 작성하고, GitHub Actions CI 세팅까지 한 번에. google-services.json 키가 안 맞아서 Google 로그인이 안 되는 문제도 이 날 잡았습니다. SHA-1 fingerprint 갱신하고 OAuth 클라이언트 추가.
Firebase App Distribution으로 첫 테스트 APK를 뿌렸어요. 디스코드에 “빌드해줘”라고 치면 빌드하고 배포까지 했습니다.
Day 5 (1/16): 디자인 시스템 전면 개편
기본 Material 디자인으로 만든 UI가 영 아니었어요. 색도 제각각이고 다크모드도 깨지고.
나: "전체 디자인 개편하자. TimeTree, Todoist, Linear 참고해서."
에이전트가 웹에서 레퍼런스 앱들을 검색하고 분석한 뒤, Figma 디자인 시스템 스타일로 코드를 짰습니다.
처음 에이전트가 만든 로그인 화면은 인터넷에서 따온 제너릭 템플릿이었어요. “Logoipsum” 브랜딩에 Facebook 로그인까지 달린. 디자인 시스템 적용 후에야 amadda다운 화면이 나왔습니다.
Day 1: 에이전트가 가져온 제너릭 템플릿. “Logoipsum”이 그대로
최종: amadda 브랜딩 + Google SSO 우선 배치
같은 날 Play Store용 에셋(스크린샷, 설명문)도 만들고 버전을 1.2.0으로 올렸어요.
Day 6-7 (1/17-18): 디테일
스플래시 스크린, 온보딩 플로우, Pretendard 한글 폰트 적용. GNB(글로벌 네비게이션 바)를 만들고 전 화면에 일관되게 적용. Firestore 400 에러가 일정 생성 시 터지는 걸 잡았고, DSDialog 에러 핸들링 컴포넌트도 만들었습니다.
온보딩 3단계 중 첫 화면. “스마트한 가족 캘린더”
첫 주 성적: 48개 커밋, 앱의 전체 기능이 동작하는 상태.
2주차: 1월 20-26일 — 갈아엎고 다듬다
1/20: 버그 잔치
Gemini AI 통합이 크래시, 캘린더 리스트뷰 깨짐, 알림 버튼 안 눌림, QR 스캐너 디버깅. 하루에 버그 6개 잡았습니다. 그리고 전체화면 알람 기능 추가 — 알람 시간에 화면 전체를 덮는 알림.
1/21: 백그라운드 알림의 늪
FCM data-only 메시지로 바꿔야 백그라운드에서 전체화면 알람이 뜬다는 걸 삽질 끝에 알아냈어요. notification 메시지는 시스템 트레이로만 가고, 앱이 직접 핸들링을 못 하거든요.
1/25-26: 국제화 + 프리미엄
SSO 아이콘을 공식 SVG로 교체하고, i18n 커버리지를 대폭 늘렸습니다. 웹에서 infinite width 에러가 터지는 것도 잡았고. 알림 사운드 설정, 오프라인 가족 구성원 등록 기능까지.
2주차 성적: 20개 커밋, 안정화 + 기능 보강 위주.
3주차: 1월 30일-2월 2일 — 보안과 구조
1/30: 보안 점검
Firestore 보안 규칙을 전면 재작성했습니다. 아무 사용자나 다른 사람의 문서를 읽을 수 있던 걸 잠그고, Cloud Function에 가족 검증 로직 추가.
나: "보안 규칙 한번 점검해봐"
에이전트: (전체 규칙 분석) "user 문서에 owner-only read 제한이 없네요.
다른 사람 프로필을 API로 직접 읽을 수 있습니다."
이런 건 사람이 지시하지 않으면 에이전트가 먼저 하기 어려운 영역이에요. “보안 점검해”라는 한 마디가 중요했습니다.
1/31-2/2: 네비게이션 대수술
바텀 네비게이션 → Drawer + FAB 패턴으로 전환. 그리고 전체 화면에 흩어져 있던 하드코딩된 스타일을 전부 DS 토큰으로 통일하는 대규모 리팩토링.
3주차 성적: 7개 커밋, 적지만 하나하나가 큼직한 구조 변경.
4주차: 2월 13-17일 — 폭풍 개발
2주 공백 후 다시 시작했는데, 이 주가 가장 밀도 높았어요.
2/13: 하루에 15개 커밋
유닛 테스트 + 위젯 테스트 대량 추가, 웹 한국어화, GitHub Actions CI/CD, 딥링크, Firestore 인덱스 추가, 광고 위치 변경, 공지 이미지 업로드 버그, 알림음 미리듣기, 초대 코드 UI, 가족 참여 플로우 수정…
에이전트한테 “오늘 이슈 전부 훑어서 하나씩 잡아”라고 했더니 정말 15개를 잡았습니다. 이런 식의 “벌크 버그 수정”은 에이전트가 압도적으로 빠릅니다. 사람이면 우선순위 정하느라 하루가 갈 텐데, 에이전트는 그냥 위에서부터 쭉 처리해요.
2/14: 멀티 가족 + 디자인 시스템 Phase 2
사용자 모델에 familyIds 배열 추가하고, Drawer에 가족 전환 기능 넣고, QR 스캔 네비게이션 수정. 그리고 디자인 시스템 Phase 2 전면 적용 — 이번엔 에이전트가 웹 리서치까지 해서 레퍼런스 분석 문서를 작성한 뒤에 작업했어요.
에이전트: "TimeTree 2026 리디자인 분석했습니다.
캘린더뷰에 수평 스와이프 제스처를 쓰고,
이벤트 카드에 가족 멤버 아바타를 겹쳐 표시하네요."
5단계에 걸친 디자인 시스템 전면 적용:
- 컬러 스킴 + 반응형 위젯 + 공통 컴포넌트 (
DSEmptyState,DSSkeletonLoader) - ScheduleDetailPage → CalendarPage → HomePage 순서대로 DS 토큰 적용
- 반응형 네비게이션 (모바일 Drawer → 태블릿 BottomNav → 데스크탑 NavigationRail)
- 나머지 페이지 통일
- 다크모드 완성 + 테마 전환
에이전트가 처음 참고한 레퍼런스 디자인과 최종 결과를 비교하면 이렇습니다.
에이전트가 분석한 레퍼런스 디자인: 프로젝트 카드 + 태스크 리스트 패턴
캘린더 레퍼런스: 월간 그리드 + 우선순위별 색상. 이 패턴을 amadda에 적용
2/15: UX 대폭 개편 + 릴리즈
홈 화면을 완전히 다시 그렸어요. 인사말 + 타임라인 형태로 바꾸고, 온보딩 3단계 추가, 마이크로 카피(빈 화면일 때 뜨는 안내 문구) 전부 작성, Drawer를 없애고 허브 페이지로 대체.
최종 홈 화면. “좋은 새벽이에요” 인사말 + AI 빠른 입력 + 이번주 미션 완료 배지
일정 등록. “내일 오후 3시 민수 치과”처럼 자연어로 입력하면 AI가 파싱
이 날 v1.3.0으로 태깅하고 Play Store 준비 완료.
2/16: 테스트 + 인앱결제
웹 통합 테스트 작성, E2E 테스트 파일 분할, 그리고 RevenueCat에서 Google Play 인앱결제(in_app_purchase)로 전환. RevenueCat은 Play Console 계정 설정이 복잡해서 직접 결제 API로 갔습니다.
관리자 대시보드도 이 날 만들었어요. 사용자 수, 일별 통계 등을 보는 화면.
2/17: 프리미엄 + 알림
프리미엄 구독 UI 전체 (업그레이드 프롬프트, 사용량 카드, 축하 온보딩, 배지, 구독 관리), 로컬 알림 스케줄링 디버깅. zonedSchedule이 동작 안 해서 3초 뒤 테스트 알림을 쏘는 디버그 모드까지 넣어봤습니다.
그리고 GNB를 Notion/Slack 스타일로 리디자인 — 가족 전환 버튼 + 알림 뱃지 + 프로필 개선.
4주차 성적: 50개 커밋. 미친 속도.
5주차: 2월 18-19일 — 웹 호환
2/18: dart:io 제거 작전
Flutter 웹 빌드에서 dart:io를 쓰면 바로 크래시합니다. File 클래스를 전부 XFile로 교체하는 리팩토링. storage_service, profile_edit, notice_create 3곳.
2/19: locale 크래시
headless Chrome에서 navigator.language가 en-US@posix를 뱉는 바람에 Dart Intl 라이브러리가 파싱을 못 해서 백화면. index.html에 JavaScript polyfill을 넣어서 @posix 수식어를 잘라냈습니다.
Playwright로 모바일 뷰포트(390×844) 테스트해서 공개 페이지 전부 정상 렌더링 확인.
Playwright 테스트로 캡처한 웹 랜딩 페이지 (390×844)
기능 소개 페이지. 일정 공유, 미션, 알림 설명
가격 페이지. Free / Premium / Family 3단 구성
에뮬레이터와 E2E 테스트
이 프로젝트에서 가장 삽질을 많이 한 부분이에요. 별도로 다룰 가치가 있습니다.
WSL2에서 에뮬레이터 돌리기
WSL2에서 안드로이드 에뮬레이터를 돌리려면 KVM이 필요한데, 권한 설정이 까다롭습니다. sg kvm -c "emulator @Pixel_7_API_34" 이런 식으로 실행해야 하고, SwiftShader(소프트웨어 GPU)로 돌려서 느립니다. 그래도 부팅 22초면 쓸 만해요.
결정적인 건 tmux였어요. 에뮬레이터를 tmux 세션에 넣지 않으면 OpenClaw 세션 끝날 때 같이 죽습니다.
WSL2 에뮬레이터에서 캡처. 온보딩 화면 위에 알림 권한 요청이 뜸
에뮬레이터에서 온보딩 플로우 테스트. 실기기 없이도 가능
회원가입 화면. 비밀번호 확인 유효성 검증(빨간 테두리)까지 동작
E2E 테스트 자동화
에뮬레이터가 돌아가니 E2E 테스트도 자동화할 수 있었습니다. 에이전트가 테스트 코드를 짜고, 실행하고, 스크린샷을 찍어서 결과를 보고합니다.
E2E 자동 캡처: 홈 화면. 오늘 일정 없음 상태 + 이번주 미션 완료
“병원 가기”라고 입력하면 AI가 제목, 날짜, 시간, 카테고리를 자동 파싱해서 확인 팝업을 띄움
pumpAndSettle 무한 대기
Flutter E2E 테스트에서 pumpAndSettle()이 영원히 안 끝나는 문제. 원인은 AdMob 배너의 무한 애니메이션이었어요. 애니메이션이 끝나야 settle하는데, 광고는 계속 움직이니까.
// 해결: 유한한 pump 호출로 대체
Future<void> safePump(WidgetTester tester, {int times = 30}) async {
for (int i = 0; i < times; i++) {
await tester.pump(const Duration(milliseconds: 100));
}
}
Flutter obscureText + adb
비밀번호 입력칸에 adb shell input text가 안 먹힙니다. Flutter의 obscureText: true 필드는 IME composition만 받아서 raw key event를 무시해요. 결국 테스트용 자동 로그인 플래그를 넣는 해킹으로 우회했습니다.
기타 삽질
병렬 세션 메모리 OOM
디스코드 채널 4개에서 동시에 에이전트를 쓰다가 WSL2 메모리가 터졌습니다. OpenCode 에이전트 5개를 동시에 돌리면 SIGKILL. 2~3개가 현실적인 한계라는 걸 배웠어요.
완성된 주요 화면들
5주간 만들어진 화면 일부입니다.
캘린더 탭. 일정이 없을 때의 빈 상태 + “일정 추가” 버튼
알림장 탭. 가족에게 공유할 공지를 작성하는 곳
더보기(설정) 탭. 가족 구성원 관리, 초대, 통계, 알림 설정, 프리미엄 업그레이드
숫자로 보는 5주
| 항목 | 수치 |
|---|---|
| 총 커밋 | 146개 |
| 개발 기간 | 5주 (1/12 - 2/19) |
| 가장 많은 날 | 2/13 (15개 커밋) |
| Flutter 위젯 테스트 | 499개 통과 |
| E2E 시나리오 | 8개, 20+ 테스트 |
| 사용한 채널 | #개발, #디자인, #테스트, DM |
| 에이전트가 작성한 코드 비율 | 체감 95%+ |
이 방식이 진짜 되나?
됩니다. 단, 조건이 있어요.
에이전트가 잘하는 것
- 반복 작업 — 12개 화면에 같은 디자인 토큰 적용하기
- 벌크 버그 수정 — “이슈 전부 잡아”라고 하면 위에서부터 쭉 처리
- 보일러플레이트 — Firebase 설정, 테스트 코드, 빌드 스크립트
- 디버깅 — 에러 로그 읽고 원인 찾고 수정까지
- 리서치 — 경쟁 앱 분석, 라이브러리 비교
사람이 해야 하는 것
- “가족 일정 앱을 만들자”라는 기획 자체
- “이 UI가 좀 별로인데?”라는 감각
- “보안 점검해봐”라는 지시 (에이전트가 알아서 하긴 어려움)
- 최종 승인 — 앱스토어 제출, 결제 설정, 2FA 인증
핵심 패턴. 디스코드 채널을 역할별로 분리하세요. #개발, #디자인, #테스트 각각에서 에이전트가 다른 맥락으로 움직입니다. 한 채널에 다 섞으면 맥락이 오염돼요.
그리고 솔직히 말하면, 이게 “코딩을 몰라도 된다”는 뜻은 아닙니다. 에이전트가 만든 코드를 리뷰하고, 방향이 이상할 때 꺾어줄 수 있어야 해요. 다만 키보드로 코드를 치는 시간은 확실히 줄어듭니다. 그 시간에 기획하고, 테스트하고, 사용자한테 보여주는 데 쓸 수 있어요.
기술 스택 정리
| 컴포넌트 | 역할 |
|---|---|
| OpenClaw | AI 에이전트 게이트웨이 (Discord ↔ Claude) |
| OpenCode | 코딩 에이전트 CLI |
| Flutter 3.27 | 앱 프레임워크 (Android + Web) |
| Firebase | Auth, Firestore, Functions, Storage, FCM, App Distribution |
| Android Emulator (WSL2) | 에뮬레이터 E2E 테스트 |
| Playwright | 웹 뷰포트 테스트 |
| GitHub Actions | CI/CD |
궁금한 거 있으면 AI for Work 코스에서 직접 따라해보세요.