198 lines
6.4 KiB
Markdown
198 lines
6.4 KiB
Markdown
# IR Deck 평가 프론트엔드 초기 설정
|
|
|
|
**날짜**: 2025-11-28
|
|
**작성자**: Claude (AI)
|
|
**관련 파일**:
|
|
- `frontend-ir-valuation/src/pages/ir-valuation.tsx`
|
|
- `nginx-infra/server-nginx-default`
|
|
- `https://git.ro-being.com/ivada_Ro-being/frontend-ir-valuation.git`
|
|
|
|
---
|
|
|
|
## 목적
|
|
|
|
Sequoia Capital IR 공식 기준으로 IR Deck을 평가하는 프론트엔드 페이지 구축. ChatGPT 스타일 UI로 PDF 업로드 및 분석 결과 표시.
|
|
|
|
## 구현 내용
|
|
|
|
### 1. 프로젝트 생성
|
|
|
|
**기술 스택**: frontend-customer와 동일
|
|
- Vite + React + TypeScript
|
|
- TailwindCSS
|
|
- wouter (라우팅)
|
|
- @tanstack/react-query
|
|
|
|
**프로젝트 위치**: `/home/admin/frontend-ir-valuation`
|
|
|
|
### 2. 주요 기능
|
|
|
|
**파일**: `src/pages/ir-valuation.tsx`
|
|
|
|
- ChatGPT 스타일 채팅 인터페이스
|
|
- PDF 파일 업로드 (드래그 앤 드롭 또는 버튼 클릭)
|
|
- 업로드 진행률 표시
|
|
- 분석 중 상태 표시
|
|
- 페이지별 평가 결과 표시 (잘된 점/부족한 점)
|
|
- 종합 점수 및 등급 (S/A/B/C) 표시
|
|
|
|
### 3. nginx 설정
|
|
|
|
**파일**: `nginx-infra/server-nginx-default:91-95, 228-232`
|
|
|
|
```nginx
|
|
# IR Valuation Frontend
|
|
location /ir-valuation {
|
|
alias /home/admin/frontend-ir-valuation/dist/;
|
|
try_files $uri /ir-valuation/index.html;
|
|
}
|
|
```
|
|
|
|
### 4. Git 저장소
|
|
|
|
**저장소**: `https://git.ro-being.com/ivada_Ro-being/frontend-ir-valuation.git`
|
|
|
|
**초기 커밋**: `8235e25` - Initial commit: IR Deck valuation frontend with ChatGPT-style UI
|
|
|
|
## 배포
|
|
|
|
### 빌드
|
|
```bash
|
|
cd /home/admin/frontend-ir-valuation
|
|
npm run build
|
|
```
|
|
|
|
### nginx 배포
|
|
```bash
|
|
sudo cp /home/admin/nginx-infra/server-nginx-default /etc/nginx/sites-enabled/default
|
|
sudo systemctl reload nginx
|
|
```
|
|
|
|
### 접근 경로
|
|
- `http://ro-being.com/ir-valuation`
|
|
- `http://124.55.18.179/ir-valuation`
|
|
|
|
## SPA 라우팅 문제 해결
|
|
|
|
**문제**: `/ir-valuation` 경로 접근 시 nginx는 200 OK를 반환하지만 브라우저에서 404 표시
|
|
|
|
**원인**:
|
|
- nginx는 정상적으로 `dist/index.html`을 서빙 (curl/Network 탭 모두 200 OK)
|
|
- 하지만 `App.tsx`의 wouter 라우터가 `path="/"`만 정의되어 있어 `/ir-valuation` 경로에서 매칭 실패
|
|
- SPA 내부 라우터가 404 컴포넌트를 렌더링
|
|
|
|
**해결**:
|
|
- `App.tsx`에 base path 처리 로직 추가
|
|
- `useLocation` hook으로 `/ir-valuation` base path를 제거하고 라우팅
|
|
|
|
**파일**: `src/App.tsx:14-30`
|
|
```typescript
|
|
function Router() {
|
|
const [location] = useLocation();
|
|
const basePath = "/ir-valuation";
|
|
|
|
// Remove base path from location for routing
|
|
// Handle both /ir-valuation and /ir-valuation/ cases
|
|
let normalizedLocation = location;
|
|
if (location.startsWith(basePath + "/") || location === basePath) {
|
|
normalizedLocation = location.slice(basePath.length) || "/";
|
|
// Remove trailing slash if present (except root)
|
|
if (normalizedLocation !== "/" && normalizedLocation.endsWith("/")) {
|
|
normalizedLocation = normalizedLocation.slice(0, -1);
|
|
}
|
|
}
|
|
|
|
return (
|
|
<Switch location={normalizedLocation}>
|
|
<Route path="/" component={IRValuationPage} />
|
|
<Route component={() => <div>404 Not Found - Location: {location}, Normalized: {normalizedLocation}</div>} />
|
|
</Switch>
|
|
);
|
|
}
|
|
```
|
|
|
|
**검증**:
|
|
- `https://ro-being.com/ir-valuation/` 접근 시 IR 평가 페이지 정상 표시 확인
|
|
- 네트워크 요청 모두 200 OK 확인
|
|
- ChatGPT 스타일 UI 정상 렌더링 (헤더, 업로드 버튼, 채팅 입력창)
|
|
|
|
## 피드백 제출 UI 구현 (예정)
|
|
|
|
**목적**: 사용자가 평가 결과에 대해 등급 피드백을 제출하여 베이지안 학습 데이터 수집
|
|
|
|
**구현 위치**: `src/pages/ir-valuation.tsx`
|
|
|
|
**UI 구성**:
|
|
1. **평가 결과 사이드바에 피드백 섹션 추가**
|
|
- 평가 결과 하단에 "피드백 제출" 섹션
|
|
- 현재 등급 표시 (예: "현재 등급: A")
|
|
- 등급 선택 드롭다운 (S, A, B, C)
|
|
- 추가 의견 입력 텍스트 영역 (선택)
|
|
- "피드백 제출" 버튼
|
|
|
|
2. **피드백 제출 처리**
|
|
- `handleFeedbackSubmit()` 함수 구현
|
|
- `POST /rb8001/api/ir-deck/feedback` API 호출
|
|
- 성공 시 토스트 알림 표시
|
|
- 피드백 제출 후 버튼 비활성화
|
|
|
|
3. **상태 관리**
|
|
- `feedbackSubmitted` state 추가 (중복 제출 방지)
|
|
- `feedbackGrade` state 추가 (사용자 선택 등급)
|
|
- `feedbackText` state 추가 (추가 의견)
|
|
|
|
**API 스펙**:
|
|
```typescript
|
|
POST /rb8001/api/ir-deck/feedback
|
|
Body: {
|
|
evaluation_id: string;
|
|
user_grade: "S" | "A" | "B" | "C";
|
|
predicted_grade: "S" | "A" | "B" | "C";
|
|
feedback_text?: string;
|
|
}
|
|
```
|
|
|
|
**참고**: 백엔드 아키텍처 문서 `251128_ir_deck_valuation_backend_architecture.md`의 `ir_deck_feedback` 테이블 구조 참고
|
|
|
|
## 다음 단계
|
|
|
|
1. **백엔드 연동**: rb8001 API 엔드포인트 구현
|
|
- `/rb8001/api/ir-deck/upload` - PDF 업로드
|
|
- `/rb8001/api/ir-deck/chat` - 채팅 응답
|
|
- `/rb8001/api/ir-deck/evaluate` - 평가 결과 조회
|
|
- `/rb8001/api/ir-deck/feedback` - 피드백 제출
|
|
|
|
2. **실제 분석 로직**: Sequoia Capital 10가지 스토리 기준 평가
|
|
- 페이지별 분석
|
|
- 점수 계산
|
|
- 등급 분류 (베이지안 학습 준비)
|
|
|
|
3. **베이지안 학습**: 피드백 수집 및 학습 데이터 구성
|
|
|
|
## API 헤더 필수 사항
|
|
|
|
**문제**: API 호출 시 `X-Team-Id header required` 에러 발생
|
|
|
|
**원인**: skill-rag-file이 파일을 `/mnt/hdd/data/documents/{team_id}/` 경로에 저장하므로 team_id 필요
|
|
|
|
**해결**: 프론트엔드 API 호출에 헤더 추가
|
|
- `X-Team-Id: 79441171-3951-4870-beb8-916d07fe8be5` (기본 team_id)
|
|
- `X-User-Id: {user_id}` (사용자 ID)
|
|
|
|
**테스트 결과**: 헤더 추가 후 업로드 성공, `document_id` 반환 확인
|
|
|
|
## 교훈
|
|
|
|
- frontend-customer 구조를 참고하여 빠르게 프로젝트 생성 가능
|
|
- nginx 설정은 두 서버 블록(HTTP/HTTPS) 모두에 추가 필요
|
|
- 빌드 산출물은 `/home/admin/frontend-ir-valuation/dist/`에 저장
|
|
- **SPA 라우팅**: nginx base path(`/ir-valuation`)와 React 라우터 경로를 일치시켜야 함
|
|
- wouter는 base path를 자동 처리하지 않으므로 `useLocation`으로 수동 처리 필요
|
|
- **API 헤더**: rb8001 API는 멀티테넌시를 위해 `X-Team-Id`, `X-User-Id` 헤더 필수
|
|
- **모바일 반응형**: 사이드바가 `w-96` 고정 너비로 모바일에서 채팅 영역을 가림, 모바일에서는 시트/드로어로 전환 필요
|
|
|
|
---
|
|
|
|
문서 규칙: `DOCS/book/300_architecture/312_문서_작성_원칙.md` 준수
|
|
|