2026-05-11
# 2026-05-11 TIL — M12 마일스톤 설계 + T-120·T-121
## 오늘 한 일
### 1. M12 마일스톤 신규 설계 (T-120 ~ T-132, 13 Task / 40 SP)
출시 후 보강 마일스톤을 추가했다. 주제는 세 가지:
- 관리자 페이지 라우팅 결함 수정
- 학생 기본 정보(학년/반/학번) 프로필 노출 + 소속 단체 조회·변경
- 영양사 화면 통합 + AI 식단 생성 조건 UI 보강 (NEIS 학교 검색, 영양소 동적 항목, 단가 제약)
**모호점은 작성 전에 사용자에게 확인하고 가는 게 맞다.** 처음엔 그냥 적당히 추정하고 갈 뻔했는데, `AskUserQuestion`으로 세 가지를 먼저 물어서 스펙이 흔들리지 않게 했다:
| 모호점 | 결정 |
|---|---|
| 프로필에서 "소속 단체 정보 수정/삭제" 의미 | 조회 + 소속 변경만 (삭제 없음) |
| 메뉴별 단가 산정 방법 (NEIS는 단가 미제공) | NEIS 과거 메뉴를 키워드 기반 참고가격으로 사전화 |
| 학생 추가 정보 스키마 처리 | `User`에 grade/classNo/studentCode 컬럼 추가 |
산출물: `docs/Generate_task.md`에 M12 본문, `.claude/commands/m12-start.md` 슬래시 커맨드. 커밋 `f5fcebf`.
---
### 2. T-120 — 관리자 패널 라우팅 결함 수정 (PR #42)
#### 재현
admin 로그인 → 사이드바 "사용자 관리" 클릭 → `/`로 튕김. 관리자 패널 도달 불가.
#### 원인
- `Sidebar.tsx`: admin 네비 4개 링크가 `/admin/users`, `/admin/schools`, `/admin/allergens`, `/admin/logs`
- `App.tsx`: 정의된 라우트는 **`/admin` 단 하나**
- 매칭 실패 → catch-all `<Route path="*" element={<Navigate to="/" replace />} />`가 잡아서 `/`로 리다이렉트
- 사이드바에 `/admin` 자체 링크가 없어서 관리자 패널 도달 경로가 사실상 없음
#### 수정 (최소 변경 3곳)
1. `App.tsx`: `<Route path="/admin/:tab" element={<AdminPanelPage />} />` 추가
2. `AdminPanelPage.tsx`: 탭 상태를 `useState` → `useParams` + `useNavigate`로 전환. 잘못된 tab 값은 'orgs' 폴백
3. `Sidebar.tsx`: `/admin/schools` → `/admin/orgs` (탭 eventKey 'orgs'와 일치)
#### 배운 점
- React Router catch-all `<Route path="*">`는 그 위치(중첩 깊이)에 따라 잡는 범위가 다르다. 이번 케이스는 ProtectedRoute **밖**에 있어서 인증된 사용자라도 잡혀버림 → 정의 안 된 모든 경로가 `/`로 리다이렉트
- **사이드바 링크와 라우트 정의가 어긋나면 조용히 실패한다.** 404 페이지 같은 명시적 표시도 없이 그냥 홈으로 튕기니까 원인 찾기 까다로움. 다음에 라우트 만들 땐 사이드바·라우트 정의·탭 키 3자 일치를 체크리스트로
---
### 3. T-121 — User 스키마에 학생 기본 정보 컬럼 추가 (PR #43)
#### 변경
```prisma
model User {
// ...
grade Int?
classNo String? @map("class_no")
studentCode String? @map("student_code")
// ...
@@index([orgId, grade, classNo])
}
```
#### 키 포인트
- **모두 NULL 허용**: 기존 row 마이그레이션 충돌 없음. 학생이 아닌 사용자(영양사·관리자 등)에게도 자연스러움
- **복합 인덱스 `(org_id, grade, class_no)`**: 학교 내 학년·반 조회 시 풀스캔 방지
- 기존 `group_info` JSON 컬럼은 보조 필드로 유지(자유 입력 여지)
#### 마이그레이션 실행 중 만난 함정
- `prisma migrate dev`는 잘 돌아갔는데 끝에 `prisma generate`가 EPERM으로 실패
- 원인: 백엔드 dev 서버가 켜져 있어서 `node_modules/.prisma/client/query_engine-windows.dll.node`를 점유 중 → Windows에서 rename 거부
- **해결: 무시해도 됨.** dev 서버 재기동 시 자동으로 generate가 다시 도는 구조. 마이그레이션 자체(DB 적용 + migration.sql 파일 생성)는 성공한 상태
---
## 부수적으로 알게 된 것
### `migration_lock.toml`이 뭔지
```
provider = "postgresql"
```
세 줄짜리 파일. Prisma가 "이 migrations 폴더는 어떤 DB용인지"를 못박는 잠금 파일. **`node_modules`처럼 무시되는 게 아니라 커밋 대상이 맞다.** 단지 거의 안 바뀌고, 이번에는 line ending(CRLF/LF) 차이만 있어서 의미 있는 변경이 없어 스킵했을 뿐.
### `@google/generative-ai` 모듈 not found 에러
- `package.json`엔 등재돼 있는데 import에서 빨갛게 뜨면 → 최근 `git pull`에서 의존성이 새로 추가됐다는 신호
- `npm install` 한 번 돌리면 끝. 다른 사람이 작업 중 추가한 패키지를 잊고 install 안 한 케이스
### Git 작업 디렉터리가 옮겨졌을 때
`cd backend && npm run dev` 같은 명령으로 shell의 cwd가 옮겨졌을 때, 그 다음 `git add frontend/...`를 하면 경로 매칭 실패한다. 해결책 두 가지:
- `cd`로 다시 돌아가기
- **`git -C <절대경로> <command>`로 working tree를 명시**
후자가 깔끔. 세션 전체에서 cwd를 일관되게 유지하려면 절대 경로 + `-C` 패턴이 안전.
### Conventional Commits + Task ID 본문
이 프로젝트 룰: `fix(fe): 짧은 제목` / `feat(db): 짧은 제목` 형식으로 헤더 짓고, 본문 끝에 `T-XXX` 한 줄. PR 머지하면 `Merge pull request #N from feature/T-XXX-...` 로 자연스럽게 추적 가능.
---
## 내일 할 일
- **T-122**: 회원가입 API에 학생 정보 필드(grade/classNo/studentCode) 반영
- **T-123**: 프로필 조회 API에 소속 단체 정보 포함
- ... M12 나머지 11개 Task 순차 진행
댓글
댓글이 없습니다.
