관리 지표
2026-09-23 기준(세는 대상의 마지막 커밋
4f8563b) · 스프린트 3 진행 중. 이 페이지의 숫자는 손으로 적지 않았다 — 생성기가 저장소 기록에서 센다. 절마다 「재는 법」을 펼치면 그 숫자를 뽑는 명령이 있다. 지나온 길은 진행 현황에, 일정 계획은 개발 구현 계획 4절에 있다.
1) 요청과 결정 — 미결 항목
팀원 사이의 요청과 결정은 미결 항목 한 곳으로 오간다. 올린 사람이 자기 구역에 적고, 담당과 기한을 달고, 처리하면 제목에 ✅ 를 단다. 닫힌 항목도 지우지 않는다.
누가 올리고 누가 맡았나. 구역은 올린 사람의 것이다. 굵은 칸(대각선)은 자기 할 일로 올린 것이고, 나머지는 다른 사람에게 요청한 것이다. 한 항목에 담당이 여럿이면 칸마다 하나씩 센다.
| 구역 (올린 사람) | 올린 항목 | 해소 | 열림 | 해소율 |
|---|---|---|---|---|
min 박민호 | 27 | 20 | 7 | 74% |
paik 백성검 | 48 | 36 | 12 | 75% |
jin 정어진 | 45 | 32 | 13 | 71% |
ho 정상호 | 55 | 23 | 32 | 42% |
| 올린 사람 ↓ · 맡은 사람 → | 박민호 | 백성검 | 정어진 | 정상호 |
|---|---|---|---|---|
| 박민호 | 13 | 7 | 12 | 4 |
| 백성검 | 5 | 14 | 40 | 10 |
| 정어진 | 18 | 16 | 13 | 19 |
| 정상호 | 15 | 8 | 17 | 27 |
| 맡은 항목 중 아직 열린 것 | 25 | 17 | 33 | 31 |
담당이 「미정」「없음」인 항목 5개와 담당 줄이 없는 항목 8개는 이 표에서 뺐다.
표로 보기 — 날짜별 누적 (값이 바뀐 날만)
| 날짜 | 올라온 (누적) | 해소 (누적) | 열림 |
|---|---|---|---|
| 08-20 | 0 | 0 | 0 |
| 08-25 | 6 | 0 | 6 |
| 08-26 | 7 | 3 | 4 |
| 08-28 | 9 | 3 | 6 |
| 08-31 | 10 | 3 | 7 |
| 09-01 | 18 | 3 | 15 |
| 09-02 | 27 | 4 | 23 |
| 09-03 | 42 | 15 | 27 |
| 09-04 | 56 | 21 | 35 |
| 09-07 | 60 | 22 | 38 |
| 09-08 | 79 | 36 | 43 |
| 09-09 | 91 | 49 | 42 |
| 09-10 | 112 | 60 | 52 |
| 09-11 | 128 | 72 | 56 |
| 09-14 | 137 | 74 | 63 |
| 09-15 | 140 | 88 | 52 |
| 09-16 | 152 | 98 | 54 |
| 09-17 | 165 | 104 | 61 |
| 09-18 | 170 | 108 | 62 |
| 09-19 | 171 | 109 | 62 |
| 09-21 | 173 | 109 | 64 |
| 09-22 | 174 | 110 | 64 |
| 09-23 | 175 | 111 | 64 |
재는 법
grep -c '^### ' jekyll/pages/pending.markdown # 올라온 항목
grep -c '^### .*✅' jekyll/pages/pending.markdown # 그중 해소(제목에 ✅)
awk '/^## [a-z]+ \(/{z=$2} /^### /{n[z]++; if(/✅/) d[z]++}
END{for(k in n) print k, n[k], d[k]+0}' jekyll/pages/pending.markdown # 구역별
날짜별 추이는 git 이력에서 항목 제목이 처음 생긴 커밋과 제목에 ✅ 가 처음 붙은 커밋을 찾아 센다(python3 tools/pages/gen_metrics.py). 날짜별 파일 사본으로 세지 않는 것은, 사람마다 자기 브랜치에서 일해서 같은 날의 사본이 브랜치마다 다르기 때문이다. 아카이브로 옮긴 항목은 원래 자리에 제목이 남아 있어 함께 센다.
2) 요구사항 — 약속한 것과 된 것
요구사항과 별도로 제약 9개와 전제 7개를 5장에서 관리한다(상태 없음).
표로 보기
| 분류 | ✅ 구현됨 | 🟡 부분 | ❌ 미구현 | ⚪ 미측정 | 합계 |
|---|---|---|---|---|---|
기능 SFR | 2 (SFR-001, SFR-010) | 5 (SFR-002, SFR-003, SFR-006, SFR-008, SFR-009) | 3 (SFR-004, SFR-005, SFR-007) | 0 | 10 |
보안 SEC | 5 (SEC-002, SEC-003, SEC-004, SEC-010, SEC-011) | 5 (SEC-005, SEC-006, SEC-008, SEC-009, SEC-012) | 2 (SEC-001, SEC-007) | 0 | 12 |
성능 PER | 0 | 2 (PER-001, PER-002) | 0 | 1 (PER-003) | 3 |
품질 QUA | 3 (QUA-001, QUA-002, QUA-003) | 0 | 0 | 0 | 3 |
재는 법
grep -E '^\| *(SFR|SEC|PER|QUA)-[0-9]{3} .*\| *(✅|🟡|❌|⚪) *\|$' \
jekyll/chapters/05-요구사항분석.markdown | awk -F'|' '{s=$(NF-1); gsub(/ /,"",s); print s}' | sort | uniq -c
5장은 분류마다 요약표(상태 기호)와 상세표(확인 방법)를 둔다. 요약표만 센다 — 둘 다 세면 두 번 센다.
3) 테스트 — 영역마다 지키고 있는 것
코드에 정의된 테스트를 센다. 러너가 매개변수로 늘리는 수는 넣지 않는다 — 백엔드는 pytest 가 1,154건을 모은다(2026-09-23). 올릴 때마다 GitHub Actions 가 돌리는 테스트는 백엔드 · 앱 2곳이고, AI 에이전트 · 웹 테스트는 아직 워크플로가 없다.
표로 보기 — 날짜별 (값이 바뀐 날만)
| 날짜 | 백엔드 | AI 에이전트 | 웹 | 앱 |
|---|---|---|---|---|
| 08-20 | 0 | 0 | 0 | 0 |
| 08-25 | 63 | 50 | 0 | 67 |
| 08-26 | 119 | 66 | 0 | 67 |
| 08-28 | 157 | 96 | 97 | 67 |
| 08-30 | 157 | 96 | 129 | 67 |
| 08-31 | 165 | 96 | 174 | 67 |
| 09-01 | 195 | 101 | 235 | 67 |
| 09-02 | 309 | 124 | 235 | 67 |
| 09-03 | 430 | 139 | 237 | 67 |
| 09-04 | 529 | 187 | 336 | 67 |
| 09-07 | 529 | 221 | 339 | 67 |
| 09-08 | 618 | 241 | 404 | 67 |
| 09-09 | 678 | 284 | 404 | 67 |
| 09-10 | 730 | 307 | 551 | 75 |
| 09-11 | 758 | 340 | 579 | 75 |
| 09-14 | 758 | 343 | 649 | 81 |
| 09-15 | 869 | 375 | 670 | 99 |
| 09-16 | 998 | 417 | 737 | 99 |
| 09-17 | 1,060 | 437 | 899 | 106 |
| 09-18 | 1,100 | 446 | 1,057 | 106 |
| 09-19 | 1,106 | 446 | 1,082 | 106 |
| 09-21 | 1,106 | 446 | 1,082 | 289 |
| 09-22 | 1,125 | 446 | 1,085 | 408 |
| 09-23 | 1,126 | 446 | 1,085 | 419 |
재는 법
git grep -c -E '^[[:space:]]*(async[[:space:]]+)?def[[:space:]]+test_' HEAD -- ':(glob)fastapi/tests/**/*.py' \
| awk -F: '{s+=$NF} END{print s}' # 백엔드
git grep -c -E '^[[:space:]]*(async[[:space:]]+)?def[[:space:]]+test_' HEAD -- ':(glob)agent/tests/**/*.py' \
| awk -F: '{s+=$NF} END{print s}' # AI 에이전트
git grep -c -E '^[[:space:]]*(it|test)(\.(each|skip|only|todo|concurrent))?[[:space:]]*\(' HEAD -- ':(glob)www/**/*.test.ts' ':(glob)www/**/*.test.tsx' ':(glob)www/**/*.spec.ts' ':(glob)www/**/*.spec.tsx' \
| awk -F: '{s+=$NF} END{print s}' # 웹
git grep -c -E '^[[:space:]]*(test|testWidgets)[[:space:]]*\(' HEAD -- ':(glob)flutter/test/**/*_test.dart' \
| awk -F: '{s+=$NF} END{print s}' # 앱
cd fastapi && uv run pytest --collect-only -q | tail -1 # pytest 가 모으는 수
날짜별 추이는 그날까지의 마지막 커밋에서 같은 명령으로 센다.
4) 규모
| 무엇 | 지금 |
|---|---|
| API 엔드포인트 | 100 |
| 서버를 나눈 단위 (서로의 코드를 가져다 쓰지 못하게 검사로 막음) | 7 — user · card · analysis · match · review · billing · notification |
| DB 스키마 변경 (마이그레이션) | 48 · 머리 1개 |
| 자동 워크플로 | 4 — 백엔드 이미지 빌드·Docker Hub push · 백엔드 테스트 · Flutter 테스트 · Deploy Jekyll site to Pages |
| 개발 로그 | 60편 |
재는 법
grep -rhoE '@[a-z_]*router\.(get|post|put|patch|delete)\(' fastapi/app | wc -l # API 엔드포인트
grep -m1 '^CONTEXTS' fastapi/tests/test_architecture.py # 서버 단위
ls fastapi/alembic/versions/*.py | wc -l # 스키마 변경
cd fastapi && uv run alembic heads # 머리
grep -h '^name:' .github/workflows/*.yml # 자동 워크플로
ls _posts/ | wc -l # 개발 로그
5) 목표 대비 — 잰 것과 아직 안 잰 것
잰 적 없는 숫자는 쓰지 않는다. 안 잰 것은 안 쟀다고 적고, 언제 잴지를 함께 둔다.
| 지표 | 목표 | 지금 | 잰 날 | 근거 |
|---|---|---|---|---|
| 채점 재현성 — 같은 영상을 5번 넣은 총점의 표준편차 | 3점 이내 | ✅ 0.00 (4편 모두) | 2026-09-09 | 미결 항목 보관 |
| 분석 한 편에 걸리는 시간 — 개발 GPU(8GB) | 서비스 목표로 쓰지 않음 | 72~125초 (100·300프레임) | 2026-09-15 | 시스템 설계 4절 |
| 추천 정확도 — Hit Rate · Recall@5 | 90% (09-11 결정) | ⚪ 안 잼 — 측정 코드가 아직 없다 | 스프린트 4 계획 | 개발 구현 계획 |
| 조회 API 응답 P95 (요구사항 PER-003) | 500ms 이내 | ⚪ 안 잼 — 서버가 지표를 내보내지만 모으는 곳이 없다 | — | 요구사항 분석 |
| 매칭 성사율 · 노쇼율 · 재사용률 | 60% 이상 · 10% 이하 · 40% 이상 | ⚪ 안 잼 — 실제 매칭이 쌓여야 잴 수 있다 | — | 테스트 및 검증 계획 |
| 채점 fps 불변성 — 프레임레이트만 바꿨을 때 등급 변동 | 1등급 이내 | 🟡 개선 중 (스프린트 3 과제, 정상호) | — | 개발 구현 계획 |
| 채점 지표 타당성 — 코치급 평가와 일치율 | 80% 이상 | ⚪ 잴 수 없음 — 지도자 검수 없이 가기로 했다(09-17) | — | 진행 현황 |
← 진행 현황 · 이 페이지는 tools/pages/gen_metrics.py 가 만든다 — 손으로 고치면 다음 실행 때 덮인다.