docs: 현행화 17개 설계서 Approved + 후속 이슈 백로그 등록
Reviewer 결과 17 PASS / 1 REJECT (#267 admin 권한 critical). - 17개 설계서를 Draft → Approved로 갱신 - #267(backend-user)은 critical 결함으로 06-Reviewer 유지 - 후속 17개 개선 이슈(#289~#305) 자동 등록 — 결함 124건 백로그 반영 (critical 3 / major 46 / minor 75) - docs/README.md에 18개 설계서 인덱스 추가 - CHANGELOG.md 2026-06-15 섹션 추가 Refs: #266 #268-#283 (현행화 완료) #267 (대기) #289-#305 (백로그)
This commit is contained in:
118
CHANGELOG.md
Normal file
118
CHANGELOG.md
Normal file
@@ -0,0 +1,118 @@
|
||||
# Tasteby 작업 기록
|
||||
|
||||
> 작업 내용, 이슈, 해결 방법을 기록하는 문서. 커밋/배포 시 참고용.
|
||||
|
||||
---
|
||||
|
||||
## 2026-06-15
|
||||
|
||||
### ch-bootstrap 적용 (페르소나 파이프라인 + Design-First)
|
||||
- Redmine 8단계 페르소나 큐(`01-Planner` ~ `09-Done`) + 9개 카테고리 자동 생성
|
||||
- Design-First 게이트(설계서 없으면 코드 작성 금지) 도입
|
||||
- `.claude/agents/` 8개 페르소나 + `.claude/workflows/persona-pipeline.js`
|
||||
- 안전-최대 권한 정책(`.claude/settings.json`)
|
||||
- `docs/{design,adr,pipeline}/` 골격 + `scripts/enqueue.sh`
|
||||
- 기존 Tasteby 고유 규칙(존댓말, CHANGELOG, 디자인 패턴, CORS, PM2)은 `CLAUDE.md` 0/7/8장으로 보존
|
||||
- Redmine 프로젝트 description + Wiki 4페이지(Overview/Dev-Env/Prod-Env/Deploy) 작성
|
||||
|
||||
### tasteby 기존 18개 기능 Design-First 현행화
|
||||
- 백엔드 12개(auth/user/restaurant/video/extract-pipeline/search/review-memo/channel/stats/daemon/cache/health) + 프론트 6개(map/restaurant-detail/filter/review-memo/admin/login)
|
||||
- 각 기능별 `docs/design/<issue>-<slug>/README.md` 12개 섹션 채움 (총 3,830줄)
|
||||
- 추적성: 각 설계서가 구현 파일/Redmine 이슈/커밋 SHA와 연결됨
|
||||
- **Reviewer 결과**: 17 PASS w/notes, 1 REJECT (#267 admin 권한 critical)
|
||||
- 후속 17개 개선 이슈(#289~#305) 자동 등록 — 결함 총 124건(critical 3 / major 46 / minor 75) 백로그 반영
|
||||
- 코드 변경 없음 — 문서화 + 백로그화 전용
|
||||
|
||||
---
|
||||
|
||||
## 2026-04-04
|
||||
|
||||
### 코드 리뷰 스크립트 추가 + 리뷰 지적사항 반영
|
||||
- `scripts/code_review.py`: 페르소나 기반 코드 리뷰 스크립트 (OpenRouter API, 프론트/백엔드/보안/아키텍처 4관점)
|
||||
- `UserService.updateAdmin()`: 존재하지 않는 userId에 대해 404 응답 추가
|
||||
- `AdminUserController.updateAdmin()`: 자기 자신 admin 권한 변경 차단 + 감사 로그 추가 + 응답에 변경 결과 포함
|
||||
- `JsonUtil.normalizeEvaluation()`: evaluation 정규화 로직을 공통 유틸로 통합 (RestaurantService, VideoService 중복 제거)
|
||||
- `RestaurantService.linkVideoRestaurant()`: evaluation 저장 시 평문→JSON 정규화 + 300자 제한
|
||||
|
||||
### 가격대 필터 5단계 세분화
|
||||
- 기존 3단계(저렴/보통/고가) → 5단계(저렴/가성비/보통/프리미엄/럭셔리)
|
||||
- `PRICE_GROUPS` 상수 수정, 정규식 패턴 세분화
|
||||
|
||||
### 모바일 터치 영역 개선 (44×44px 통일)
|
||||
- **별점 선택기**: 0.5단위 10개 숫자 버튼(24px) → 별 아이콘 5개(44px), 탭으로 정수/반점수 전환
|
||||
- **FilterSheet 닫기 버튼**: `p-1` → `p-2` (터치 영역 확대)
|
||||
- **RestaurantDetail 찜 버튼**: 패딩 추가 + `touch-manipulation` 적용
|
||||
- **필터 초기화 X 버튼**: 아이콘 12px → 14px + 패딩 추가
|
||||
|
||||
### 채널 필터 시 식당이 3개만 나오는 버그 수정
|
||||
- **원인**: 전체 식당 500개만 가져와서 클라이언트 필터링 → 특정 채널 식당이 상위 500개에 일부만 포함
|
||||
- **수정**: `page.tsx`에서 채널 필터 변경 시 서버에 `channel` 파라미터를 보내 서버 사이드 필터링 적용
|
||||
|
||||
---
|
||||
|
||||
## 2026-03-29
|
||||
|
||||
### 식당 평가(evaluation) 표시 안 되는 버그 수정
|
||||
- **원인**: LLM이 추출한 evaluation이 대부분 평문 문자열로 DB에 저장되어 있었으나, 프론트에서 `evaluation.text`로 접근하여 표시되지 않음
|
||||
- **수정**:
|
||||
- `JsonUtil.parseMap()`: JSON 파싱 실패 시 `{"text":"원본문자열"}`로 감싸서 반환
|
||||
- `VideoService.findDetail()`: `VideoRestaurantLink`의 evaluation 평문을 JSON 객체로 정규화
|
||||
|
||||
---
|
||||
|
||||
## 2026-03-16
|
||||
|
||||
### Admin 유저 관리 — 관리자 권한 토글 기능 추가
|
||||
- **Backend**
|
||||
- `UserMapper.xml`: `findAllWithCounts`에 `is_admin` 컬럼 추가, `updateAdmin` 쿼리 추가
|
||||
- `UserMapper.java`: `updateAdmin()` 메서드 추가
|
||||
- `UserService.java`: `updateAdmin()` 메서드 추가
|
||||
- `AdminUserController.java`: `PATCH /api/admin/users/{userId}/admin` 엔드포인트 추가
|
||||
- **Frontend**
|
||||
- `api.ts`: `updateAdminUserAdmin()` API 함수 추가, 유저 타입에 `is_admin` 필드 추가
|
||||
- `admin/page.tsx`: 유저 테이블에 "관리자" 컬럼 + ON/OFF 토글 버튼 추가
|
||||
|
||||
### CORS PATCH 메서드 허용
|
||||
- **문제**: PATCH 요청 시 CORS preflight(OPTIONS)에서 403 차단
|
||||
- **원인**: `WebConfig.java`의 `allowedMethods`에 `PATCH`가 빠져 있었음
|
||||
- **해결**: `List.of("GET", "POST", "PUT", "DELETE", "OPTIONS")` → `"PATCH"` 추가
|
||||
|
||||
### Icon 시스템 개선
|
||||
- Material Symbols `sake` 아이콘 종횡비 문제 수정 — `width`/`height`를 `fontSize`와 동일하게 고정 + `overflow: hidden`
|
||||
- 이자카야 아이콘: `sake` → `local_bar` (술잔 모양으로 변경)
|
||||
- 삼겹살/돼지구이, 족발/보쌈, 돈카츠: `PiggyBank` → `food:pig` (커스텀 돼지 SVG)
|
||||
|
||||
### LLM 추출 프롬프트 수정
|
||||
- `ExtractorService.java`: `evaluation` 필드 → "평가 내용을 100자 이내로 요약"으로 변경
|
||||
|
||||
### 브랜드 가이드 문서 생성
|
||||
- `frontend/docs/brand-guide.md`: 브랜드 아이덴티티, 컬러, 타이포, 아이콘 정책 등 정리
|
||||
|
||||
### PM2 프론트엔드 포트 고정
|
||||
- **문제**: `pm2 restart` 후 Next.js가 3000(Gitea 포트)으로 fallback → nginx 502
|
||||
- **해결**: PM2에 `PORT=3001` 환경변수 고정하여 재등록 + `pm2 save`
|
||||
|
||||
---
|
||||
|
||||
## 2026-03-14
|
||||
|
||||
### 홈 탭 장르 카드 픽토그램 적용
|
||||
- Phosphor Icons (`@phosphor-icons/react`) + 커스텀 SVG FoodIcon 시스템 구축
|
||||
- `cuisine-icons.ts`에 `getPhosphorCuisineIcon()` 함수 추가 (46개 소분류 매핑)
|
||||
- `FoodIcon.tsx` 생성 — jjigae, tteok, noodle, tempura, pig 커스텀 SVG 아이콘
|
||||
- `food:` 접두어로 Phosphor vs 커스텀 SVG 분기 처리
|
||||
|
||||
### 지역 필터 추가 + 배포
|
||||
- 홈 탭에 지역 필터 드롭다운 추가
|
||||
- v0.1.11로 OKE 배포 완료
|
||||
|
||||
---
|
||||
|
||||
## 참고: 주의사항
|
||||
|
||||
| 항목 | 내용 |
|
||||
|------|------|
|
||||
| 새 HTTP 메서드 추가 시 | `WebConfig.java`의 CORS `allowedMethods`에 반드시 추가 |
|
||||
| 백엔드 코드 수정 후 | `bootJar` 빌드 성공 확인 → `pm2 restart tasteby-api` |
|
||||
| 프론트엔드 dev 포트 | 3001 고정 (3000은 Gitea) |
|
||||
| tasteby-web 실행 방식 | `npm run dev` (standalone 아님) |
|
||||
@@ -60,4 +60,34 @@ docs/
|
||||
|
||||
`Draft`(작성) → `Approved`(QA/Reviewer 통과 후) → `Superseded`(대체 시 상단 표기, 삭제 금지).
|
||||
구현이 설계서와 달라지면 **코드가 아니라 설계서를 먼저 고치고** 다시 구현한다.
|
||||
|
||||
## 현존 설계서 인덱스 (2026-06-15 현행화)
|
||||
|
||||
### 백엔드 (12)
|
||||
| Issue | 기능 | 설계서 |
|
||||
|-------|------|--------|
|
||||
| #266 | 인증/로그인 | [`design/266-backend-auth/README.md`](design/266-backend-auth/README.md) |
|
||||
| #267 | 사용자 관리 | [`design/267-backend-user/README.md`](design/267-backend-user/README.md) |
|
||||
| #268 | 식당 CRUD | [`design/268-backend-restaurant/README.md`](design/268-backend-restaurant/README.md) |
|
||||
| #269 | 영상 관리 + SSE | [`design/269-backend-video/README.md`](design/269-backend-video/README.md) |
|
||||
| #270 | 영상→식당 추출 파이프라인 | [`design/270-backend-extract-pipeline/README.md`](design/270-backend-extract-pipeline/README.md) |
|
||||
| #271 | 검색/벡터 추천 | [`design/271-backend-search/README.md`](design/271-backend-search/README.md) |
|
||||
| #272 | 리뷰/메모 | [`design/272-backend-review-memo/README.md`](design/272-backend-review-memo/README.md) |
|
||||
| #273 | 채널 관리 | [`design/273-backend-channel/README.md`](design/273-backend-channel/README.md) |
|
||||
| #274 | 통계/대시보드 | [`design/274-backend-stats/README.md`](design/274-backend-stats/README.md) |
|
||||
| #275 | 데몬/스케줄러 | [`design/275-backend-daemon/README.md`](design/275-backend-daemon/README.md) |
|
||||
| #276 | 캐시 관리 | [`design/276-backend-cache/README.md`](design/276-backend-cache/README.md) |
|
||||
| #277 | Health/모니터링 | [`design/277-backend-health/README.md`](design/277-backend-health/README.md) |
|
||||
|
||||
### 프론트 (6)
|
||||
| Issue | 기능 | 설계서 |
|
||||
|-------|------|--------|
|
||||
| #278 | 지도 뷰 | [`design/278-frontend-map/README.md`](design/278-frontend-map/README.md) |
|
||||
| #279 | 식당 상세 시트 | [`design/279-frontend-restaurant-detail/README.md`](design/279-frontend-restaurant-detail/README.md) |
|
||||
| #280 | 필터 시스템 | [`design/280-frontend-filter/README.md`](design/280-frontend-filter/README.md) |
|
||||
| #281 | 리뷰/메모 UI | [`design/281-frontend-review-memo/README.md`](design/281-frontend-review-memo/README.md) |
|
||||
| #282 | 어드민 페이지 | [`design/282-frontend-admin/README.md`](design/282-frontend-admin/README.md) |
|
||||
| #283 | 로그인 메뉴 | [`design/283-frontend-login/README.md`](design/283-frontend-login/README.md) |
|
||||
|
||||
후속 개선 이슈는 Redmine 백로그(#289~#305)에서 추적.
|
||||
```
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
# 설계서: 백엔드 - 인증/로그인 (#266)
|
||||
|
||||
> **상태**: Draft
|
||||
> **상태**: Approved <!-- Draft | Approved | Superseded -->
|
||||
> **작성**: [AI] Architect · **최종수정**: 2026-06-15
|
||||
> **추적성** — Redmine: #266 · 관련 ADR: 없음
|
||||
> · 구현 파일: `backend-java/src/main/java/com/tasteby/service/AuthService.java`, `backend-java/src/main/java/com/tasteby/controller/AuthController.java` · 테스트: TBD (현재 없음)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
# 설계서: 백엔드 - 식당 CRUD (#268)
|
||||
|
||||
> **상태**: Draft
|
||||
> **상태**: Approved <!-- Draft | Approved | Superseded -->
|
||||
> **작성**: [AI] Architect · **최종수정**: 2026-06-15
|
||||
> **추적성** — Redmine: #268 · 관련 ADR: 없음
|
||||
> · 구현 파일: `backend-java/src/main/java/com/tasteby/service/RestaurantService.java`, `backend-java/src/main/java/com/tasteby/controller/RestaurantController.java` · 테스트: TBD (현재 없음)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
# 설계서: 백엔드 - 영상 관리 + SSE (#269)
|
||||
|
||||
> **상태**: Draft <!-- Draft | Approved | Superseded -->
|
||||
> **상태**: Approved <!-- Draft | Approved | Superseded -->
|
||||
> **작성**: [AI] Architect · **최종수정**: 2026-06-15
|
||||
> **추적성** — Redmine: #269 · 관련 ADR: 없음
|
||||
> · 구현 파일: `backend-java/src/main/java/com/tasteby/service/VideoService.java`, `backend-java/src/main/java/com/tasteby/service/YouTubeService.java`, `backend-java/src/main/java/com/tasteby/controller/VideoController.java`, `backend-java/src/main/java/com/tasteby/controller/VideoSseController.java` · 테스트: TBD (현재 없음)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
# 설계서: 백엔드 - 영상→식당 추출 파이프라인 (LLM+Geocoding) (#270)
|
||||
|
||||
> **상태**: Draft <!-- Draft | Approved | Superseded -->
|
||||
> **상태**: Approved <!-- Draft | Approved | Superseded -->
|
||||
> **작성**: [AI] Architect · **최종수정**: 2026-06-15
|
||||
> **추적성** — Redmine: #270 · 관련 ADR: 없음
|
||||
> · 구현 파일: `backend-java/src/main/java/com/tasteby/service/ExtractorService.java`, `backend-java/src/main/java/com/tasteby/service/PipelineService.java`, `backend-java/src/main/java/com/tasteby/service/OciGenAiService.java`, `backend-java/src/main/java/com/tasteby/service/GeocodingService.java` · 테스트: TBD (현재 없음)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
# 설계서: 백엔드 - 검색/벡터 추천 (#271)
|
||||
|
||||
> **상태**: Draft <!-- Draft | Approved | Superseded -->
|
||||
> **상태**: Approved <!-- Draft | Approved | Superseded -->
|
||||
> **작성**: [AI] Architect · **최종수정**: 2026-06-15
|
||||
> **추적성** — Redmine: #271 · 관련 ADR: 없음
|
||||
> · 구현 파일: `backend-java/src/main/java/com/tasteby/service/SearchService.java`, `backend-java/src/main/java/com/tasteby/service/VectorService.java`, `backend-java/src/main/java/com/tasteby/controller/SearchController.java` · 테스트: TBD (현재 없음)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
# 설계서: 백엔드 - 리뷰/메모 (#272)
|
||||
|
||||
> **상태**: Draft <!-- Draft | Approved | Superseded -->
|
||||
> **상태**: Approved <!-- Draft | Approved | Superseded -->
|
||||
> **작성**: [AI] Architect · **최종수정**: 2026-06-15
|
||||
> **추적성** — Redmine: #272 · 관련 ADR: 없음
|
||||
> · 구현 파일: `backend-java/src/main/java/com/tasteby/service/ReviewService.java`, `backend-java/src/main/java/com/tasteby/service/MemoService.java`, `backend-java/src/main/java/com/tasteby/controller/ReviewController.java`, `backend-java/src/main/java/com/tasteby/controller/MemoController.java` · 테스트: TBD (현재 없음)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
# 설계서: 백엔드 - 채널 관리 (#273)
|
||||
|
||||
> **상태**: Draft <!-- Draft | Approved | Superseded -->
|
||||
> **상태**: Approved <!-- Draft | Approved | Superseded -->
|
||||
> **작성**: [AI] Architect · **최종수정**: 2026-06-15
|
||||
> **추적성** — Redmine: #273 · 관련 ADR: 없음
|
||||
> · 구현 파일: `backend-java/src/main/java/com/tasteby/service/ChannelService.java`, `backend-java/src/main/java/com/tasteby/controller/ChannelController.java` · 테스트: TBD (현재 없음)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
# 설계서: 백엔드 - 통계/대시보드 (#274)
|
||||
|
||||
> **상태**: Draft <!-- Draft | Approved | Superseded -->
|
||||
> **상태**: Approved <!-- Draft | Approved | Superseded -->
|
||||
> **작성**: [AI] Architect · **최종수정**: 2026-06-15
|
||||
> **추적성** — Redmine: #274 · 관련 ADR: 없음
|
||||
> · 구현 파일: `backend-java/src/main/java/com/tasteby/service/StatsService.java`, `backend-java/src/main/java/com/tasteby/controller/StatsController.java` · 테스트: TBD (현재 없음)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
# 설계서: 백엔드 - 데몬/스케줄러 (#275)
|
||||
|
||||
> **상태**: Draft
|
||||
> **상태**: Approved <!-- Draft | Approved | Superseded -->
|
||||
> **작성**: [AI] Architect · **최종수정**: 2026-06-15
|
||||
> **추적성** — Redmine: #275 · 관련 ADR: 없음
|
||||
> · 구현 파일: `backend-java/src/main/java/com/tasteby/service/DaemonScheduler.java`, `backend-java/src/main/java/com/tasteby/service/DaemonConfigService.java`, `backend-java/src/main/java/com/tasteby/controller/DaemonController.java` · 테스트: TBD (현재 없음)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
# 설계서: 백엔드 - 캐시 관리 (#276)
|
||||
|
||||
> **상태**: Draft
|
||||
> **상태**: Approved <!-- Draft | Approved | Superseded -->
|
||||
> **작성**: [AI] Architect · **최종수정**: 2026-06-15
|
||||
> **추적성** — Redmine: #276 · 관련 ADR: 없음
|
||||
> · 구현 파일: `backend-java/src/main/java/com/tasteby/service/CacheService.java`, `backend-java/src/main/java/com/tasteby/controller/AdminCacheController.java` · 테스트: TBD (현재 없음)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
# 설계서: 백엔드 - Health/모니터링 (#277)
|
||||
|
||||
> **상태**: Draft
|
||||
> **상태**: Approved <!-- Draft | Approved | Superseded -->
|
||||
> **작성**: [AI] Architect · **최종수정**: 2026-06-15
|
||||
> **추적성** — Redmine: #277 · 관련 ADR: 없음
|
||||
> · 구현 파일: `backend-java/src/main/java/com/tasteby/controller/HealthController.java` · 테스트: TBD (현재 없음)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
# 설계서: 프론트 - 지도 뷰 (#278)
|
||||
|
||||
> **상태**: Draft <!-- Draft | Approved | Superseded -->
|
||||
> **상태**: Approved <!-- Draft | Approved | Superseded -->
|
||||
> **작성**: [AI] Architect · **최종수정**: 2026-06-15
|
||||
> **추적성** — Redmine: #278 · 관련 ADR: 없음
|
||||
> · 구현 파일: `frontend/src/components/MapView.tsx`, `frontend/src/app/page.tsx` · 테스트: TBD (현재 없음)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
# 설계서: 프론트 - 식당 상세 시트 (#279)
|
||||
|
||||
> **상태**: Draft <!-- Draft | Approved | Superseded -->
|
||||
> **상태**: Approved <!-- Draft | Approved | Superseded -->
|
||||
> **작성**: [AI] Architect · **최종수정**: 2026-06-15
|
||||
> **추적성** — Redmine: #279 · 관련 ADR: 없음
|
||||
> · 구현 파일: `frontend/src/components/RestaurantDetail.tsx`, `frontend/src/components/BottomSheet.tsx`, `frontend/src/components/RestaurantList.tsx` · 테스트: TBD (현재 없음)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
# 설계서: 프론트 - 필터 시스템 (FilterSheet + SearchBar) (#280)
|
||||
|
||||
> **상태**: Draft <!-- Draft | Approved | Superseded -->
|
||||
> **상태**: Approved <!-- Draft | Approved | Superseded -->
|
||||
> **작성**: [AI] Architect · **최종수정**: 2026-06-15
|
||||
> **추적성** — Redmine: #280 · 관련 ADR: 없음
|
||||
> · 구현 파일: `frontend/src/components/FilterSheet.tsx`, `frontend/src/components/SearchBar.tsx`, 호출부: `frontend/src/app/page.tsx` · 테스트: TBD (현재 없음)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
# 설계서: 프론트 - 리뷰/메모 UI (#281)
|
||||
|
||||
> **상태**: Draft
|
||||
> **상태**: Approved <!-- Draft | Approved | Superseded -->
|
||||
> **작성**: [AI] Architect · **최종수정**: 2026-06-15
|
||||
> **추적성** — Redmine: #281 · 관련 ADR: 없음
|
||||
> · 구현 파일: `frontend/src/components/ReviewSection.tsx`, `frontend/src/components/MemoSection.tsx`, `frontend/src/components/MyReviewsList.tsx` · 테스트: TBD (현재 없음)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
# 설계서: 프론트 - 어드민 페이지 (#282)
|
||||
|
||||
> **상태**: Draft
|
||||
> **상태**: Approved <!-- Draft | Approved | Superseded -->
|
||||
> **작성**: [AI] Architect · **최종수정**: 2026-06-15
|
||||
> **추적성** — Redmine: #282 · 관련 ADR: 없음
|
||||
> · 구현 파일: `frontend/src/app/admin/page.tsx` · 테스트: TBD (현재 없음)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
# 설계서: 프론트 - 로그인 메뉴 (#283)
|
||||
|
||||
> **상태**: Draft
|
||||
> **상태**: Approved <!-- Draft | Approved | Superseded -->
|
||||
> **작성**: [AI] Architect · **최종수정**: 2026-06-15
|
||||
> **추적성** — Redmine: #283 · 관련 ADR: 없음
|
||||
> · 구현 파일: `frontend/src/components/LoginMenu.tsx` · 테스트: TBD (현재 없음)
|
||||
|
||||
Reference in New Issue
Block a user