-
Notifications
You must be signed in to change notification settings - Fork 0
Retrospective Week3
기간: 2026-06-09 ~ 2026-06-15
Week 3는 “기능을 더 많이 만드는 주”라기보다, 실제 배포된 서비스를 사람에게 써 보게 하고 그 결과로 워크플로우를 완성하는 주였다. 실제 운동 후 부원들이 뮤런에 기록을 남겼고, 그 과정에서 로컬 개발 때는 보이지 않던 운영/UX 문제가 드러났다.
| 영역 | 결과 |
|---|---|
| 배포 |
main push → GHCR image → N100 prod 자동 배포 |
| 도메인 |
murun.duckdns.org + Caddy HTTPS |
| 인증 | Google OAuth + @snu.ac.kr + 관리자 승인 운영 |
| 핵심 흐름 | 세션 생성 → 사진 업로드 → 참여자 본인 기록 입력 → 아카이브 |
| 통계 |
/me, /runners/[id] 누적 거리/참여 수/평균 페이스/최근 페이스 차트 |
| 검색 |
/sessions 장소/멤버/월/참여 인원 필터 |
| 품질 | Vitest/RTL/Playwright 테스트 안전망 |
| 워크플로우 |
08-Agent-Workflow-Report로 최종 정리 |
실제로 운동 후 부원들이 각자 기록을 입력했다. 이게 가장 중요했다. 혼자 happy path를 클릭하는 것과, 실제 사람들이 단톡방 링크를 열고 자기 기록을 적는 것은 전혀 달랐다.
확인된 점:
- “그날 운동 주최자가 세션 페이지를 만들고, 참여자가 각자 자기 행을 채운다”는 모델은 자연스럽게 동작했다.
- 숫자 ID(
/sessions/1,/sessions/2)는 내부 동아리 서비스에서 공유하기 쉬웠다. - 사진 원본 보존 정책은 맞았다. 서버에서 임의 resize/crop을 하지 않는 쪽이 서비스 의도와 맞는다.
- 관리자 승인 흐름은 처음엔 번거롭지만, 동아리 내부 서비스라서 납득 가능한 마찰이었다.
부족했던 점:
- 호스트가 장소/시간/메모 오타를 고치는 세션 수정 UI가 없었다.
- 큰 사진, OAuth 오류, 관리자 페이지 권한처럼 prod에서만 드러나는 문제가 있었다.
- 테스트가 없던 시절엔 “내가 방금 고친 게 다른 입력 경계를 깨지 않았나?”를 확신하기 어려웠다.
Caddy 자체 설정 문제라기보다 DuckDNS 전파와 외부 검증 타이밍 문제가 있었다. 로그를 보며 DNS, 80/443 포트포워딩, Caddy challenge를 분리해서 봐야 했다.
배운 점: 자체 서버에서는 “앱 코드가 맞다”와 “외부에서 접속 가능하다”가 별개의 문제다.
middleware에서 role을 보려던 접근이 문제였다. Edge-safe auth config는 DB fresh role을 보장하지 못한다. 최종 권한 판단은 page/action의 requireAdmin()에서 해야 한다.
결론: middleware는 로그인 여부 정도만 다루고, DB 기반 권한은 서버 진입점에서 판단한다.
앱에서는 15MB 제한을 걸었지만, Next Server Action 기본 body limit 1MB에 먼저 걸려 generic error가 났다.
결론: 파일 업로드는 framework limit → client preflight → server validation 세 층을 모두 봐야 한다.
Google OAuth fetch timeout이나 설정 오류가 /api/auth/error?... 기본 페이지로 가면 사용자가 아무것도 할 수 없다. /login으로 error page를 라우팅하고 한국어 메시지를 보여주도록 바꿨다.
Week 3 요구사항에 “테스트 코드 포함”이 있었기 때문만은 아니다. 실제로 필요한 순간이 왔다.
- 참여 기록 입력은 빈 값/음수/초 60 이상 같은 negative case가 중요했다.
- 세션 필터는 URL 파라미터를 대충
parseInt하면3abc같은 값을 부분 parse할 수 있다. - 업로드 제한은 15MB와 MIME이 client/server에서 어긋나면 다시 같은 사고가 난다.
- 세션 수정/삭제는 실제 데이터 변경이라 E2E smoke가 필요했다.
그래서 순수 함수는 Vitest, UI 조각은 RTL, 핵심 사용자 흐름은 Playwright로 나눴다.
권한 매트릭스상 ADMIN이 다른 사람 기록을 고칠 수 있으면 운영상 편할 수 있다. 하지만 dogfooding 결과, 현재는 각자가 자기 기록을 직접 입력하는 모델이 더 중요하다.
보류 이유:
- 잘못 만들면 “관리자가 기록을 대신 고치는 서비스”가 되어 책임 경계가 흐려진다.
- UI도 단순하지 않다. 행별 편집, 감사 로그, 실수 방지가 필요하다.
- 현재 MVP에서는 본인 수정 + 세션 호스트 수정만으로 충분하다.
결론: 운영 중 실제 요청이 나오면 별도 이슈로 다룬다.
iPhone HEIC 업로드는 허용하지만, 브라우저별 표시 호환성은 완벽하지 않다. 다만 지금 바로 서버에서 JPEG 파생본을 만드는 것은 보류한다.
보류 이유:
- 원본 보존 정책이 중요하다.
- 변환을 넣으면 원본/표시용 파일 2개를 관리해야 하고 orphan cleanup/백업 범위도 커진다.
- 현재 dogfooding에서는 jpg 업로드로 충분했다.
결론: “원본 보존 + 표시용 JPEG 파생본” 설계를 따로 잡은 뒤 진행한다.
SQLite 파일 + uploads 백업은 운영상 중요하지만, 이번 주에는 자동화까지 넣지 않았다.
보류 이유:
- 백업은 스크립트만 만드는 것보다 복구 리허설이 더 중요하다.
- N100을 이 프로젝트 외 다른 용도로도 쓸 예정이라, 전체 서버 백업 정책과 같이 잡는 편이 낫다.
- 급한 위험은 Docker volume 위치를 알고 수동 복사할 수 있는 상태로 낮췄다.
결론: murun-prod_data, murun-prod_uploads 수동 백업 절차를 유지하고, 자동 백업+복구 리허설은 후속 TODO로 둔다.
- 버그는 바로 수정시키지 않고, 먼저 로그와 원인 후보를 분리한다.
- Agent가 “검증했다”고 해도 내가 실행한 명령/화면만 믿는다.
- 새 폼이 생기면 happy path보다 negative case를 먼저 묻는다.
- 배포 관련 작업은 로컬 build가 아니라 Docker/N100/prod smoke까지 본다.
- 문서와
.gjc/skills를 실제 다음 PR에 영향을 주는 규칙으로 유지한다.
- 사진 업로드/교체/삭제까지 포함한 E2E 확장
-
/admin/members승인/거절 E2E - 자동 백업 + 복구 리허설
- HEIC 표시용 파생본 설계
- 관리자 타인 기록 수정 여부 재검토
- 실제 모바일 기기에서 장기 사용성 확인
3주차의 결론은, 뮤런이 “완성된 앱”이라기보다 실제 동아리 기록을 쌓기 시작한 운영 가능한 소프트웨어가 됐다는 점이다. 그리고 Agent 워크플로우도 문서가 아니라 PR과 테스트, 배포 과정 안에 들어가기 시작했다.