Update IR valuation documentation
- Remove duplicate design review file - Update frontend setup documentation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
579a1c518c
commit
cd096b1af3
@ -1,125 +0,0 @@
|
|||||||
# IR Deck 평가 프론트엔드 디자인 검토
|
|
||||||
|
|
||||||
**날짜**: 2025-11-28
|
|
||||||
**작성자**: Claude (AI)
|
|
||||||
**관련 파일**:
|
|
||||||
- `frontend-ir-valuation/src/pages/ir-valuation.tsx`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 디자인 검토 결과
|
|
||||||
|
|
||||||
### 현재 상태
|
|
||||||
|
|
||||||
**레이아웃 구조**:
|
|
||||||
- 메인 채팅 영역 (flex-1) + 평가 결과 사이드바 (w-96 고정)
|
|
||||||
- `flex h-screen` 레이아웃
|
|
||||||
- ChatGPT 스타일 UI
|
|
||||||
|
|
||||||
### 발견된 문제점
|
|
||||||
|
|
||||||
#### 1. 모바일 반응형 미구현
|
|
||||||
|
|
||||||
**문제**:
|
|
||||||
- 사이드바가 `w-96` (384px) 고정 너비로 모바일 화면을 가림
|
|
||||||
- `flex` 레이아웃이 모바일에서도 가로 배치 유지
|
|
||||||
- 반응형 브레이크포인트 (`sm:`, `md:`, `lg:`) 클래스 없음
|
|
||||||
|
|
||||||
**영향**:
|
|
||||||
- 모바일(320-768px)에서 사이드바가 채팅 영역을 가림
|
|
||||||
- 사용자가 평가 결과를 보기 어려움
|
|
||||||
- 스크롤/탭 전환이 없어 UX 저하
|
|
||||||
|
|
||||||
#### 2. 디자인 타당성
|
|
||||||
|
|
||||||
**긍정적 측면**:
|
|
||||||
- ✅ ChatGPT 스타일 UI로 직관적
|
|
||||||
- ✅ 채팅 인터페이스로 자연스러운 대화 흐름
|
|
||||||
- ✅ 업로드 진행률 표시로 피드백 제공
|
|
||||||
- ✅ 페이지별 평가 결과 상세 표시
|
|
||||||
|
|
||||||
**개선 필요 측면**:
|
|
||||||
- ❌ 모바일에서 사이드바가 항상 표시되어 공간 낭비
|
|
||||||
- ❌ 평가 결과와 채팅이 동시에 보이지 않아 컨텍스트 전환 필요
|
|
||||||
- ❌ 피드백 제출 UI가 아직 구현되지 않음 (문서화만 됨)
|
|
||||||
|
|
||||||
### 개선 방안
|
|
||||||
|
|
||||||
#### 1. 모바일 반응형 구현
|
|
||||||
|
|
||||||
**제안**:
|
|
||||||
```tsx
|
|
||||||
// 모바일: 사이드바를 하단 시트 또는 모달로 변경
|
|
||||||
// 데스크톱: 기존 사이드바 유지
|
|
||||||
|
|
||||||
<div className="flex flex-col md:flex-row h-screen">
|
|
||||||
{/* 메인 채팅 영역 */}
|
|
||||||
<div className="flex-1 flex flex-col">
|
|
||||||
{/* ... */}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 평가 결과 - 모바일: 하단 시트, 데스크톱: 사이드바 */}
|
|
||||||
{evaluationResult && (
|
|
||||||
<>
|
|
||||||
{/* 모바일: 하단 고정 버튼 */}
|
|
||||||
<div className="md:hidden fixed bottom-20 right-4 z-50">
|
|
||||||
<Button onClick={() => setShowResultSheet(true)}>
|
|
||||||
평가 결과 보기
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 모바일: 시트 */}
|
|
||||||
<Sheet open={showResultSheet} onOpenChange={setShowResultSheet}>
|
|
||||||
<SheetContent side="bottom" className="h-[80vh]">
|
|
||||||
{/* 평가 결과 내용 */}
|
|
||||||
</SheetContent>
|
|
||||||
</Sheet>
|
|
||||||
|
|
||||||
{/* 데스크톱: 사이드바 */}
|
|
||||||
<div className="hidden md:block w-96 border-l">
|
|
||||||
{/* 평가 결과 내용 */}
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
```
|
|
||||||
|
|
||||||
**반응형 클래스 추가**:
|
|
||||||
- `md:flex-row` - 데스크톱에서 가로 배치
|
|
||||||
- `md:w-96` - 데스크톱에서만 고정 너비
|
|
||||||
- `md:hidden` / `hidden md:block` - 모바일/데스크톱 전환
|
|
||||||
|
|
||||||
#### 2. 디자인 개선
|
|
||||||
|
|
||||||
**제안**:
|
|
||||||
1. **모바일 우선 설계**: 모바일에서 사이드바를 하단 시트 또는 드로어로 변경
|
|
||||||
2. **탭 전환**: 모바일에서 "채팅" / "평가 결과" 탭으로 전환
|
|
||||||
3. **피드백 UI 추가**: 평가 결과 하단에 피드백 제출 섹션 추가
|
|
||||||
4. **헤더 최적화**: 모바일에서 헤더 높이 축소
|
|
||||||
|
|
||||||
### 권장 구현 순서
|
|
||||||
|
|
||||||
1. **모바일 반응형 레이아웃 수정** (우선순위 높음)
|
|
||||||
- 사이드바를 모바일에서 시트/드로어로 변경
|
|
||||||
- 반응형 클래스 추가
|
|
||||||
|
|
||||||
2. **피드백 제출 UI 구현**
|
|
||||||
- 평가 결과 하단에 피드백 섹션 추가
|
|
||||||
- 등급 선택 드롭다운
|
|
||||||
- 제출 버튼
|
|
||||||
|
|
||||||
3. **UX 개선**
|
|
||||||
- 모바일에서 평가 결과 보기 버튼 추가
|
|
||||||
- 스크롤 최적화
|
|
||||||
- 로딩 상태 개선
|
|
||||||
|
|
||||||
## 교훈
|
|
||||||
|
|
||||||
- **모바일 우선 설계**: 데스크톱 중심 설계는 모바일에서 문제 발생
|
|
||||||
- **반응형 클래스 필수**: TailwindCSS의 `sm:`, `md:`, `lg:` 브레이크포인트 활용
|
|
||||||
- **사이드바 패턴**: 모바일에서는 시트/드로어, 데스크톱에서는 사이드바로 분기 필요
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
문서 규칙: `DOCS/book/300_architecture/312_문서_작성_원칙.md` 준수
|
|
||||||
|
|
||||||
@ -10,199 +10,69 @@
|
|||||||
---
|
---
|
||||||
|
|
||||||
## 목적
|
## 목적
|
||||||
|
Sequoia Capital IR 기준으로 IR Deck을 평가하는 프론트엔드 페이지 구축 (ChatGPT 스타일 UI).
|
||||||
|
|
||||||
Sequoia Capital IR 공식 기준으로 IR Deck을 평가하는 프론트엔드 페이지 구축. ChatGPT 스타일 UI로 PDF 업로드 및 분석 결과 표시.
|
## 구현 요약
|
||||||
|
- **스택**: Vite + React + TypeScript, TailwindCSS, wouter, @tanstack/react-query.
|
||||||
|
- **주요 기능**: PDF 업로드, 진행률·분석 상태 표시, 페이지별 강점·약점, 종합 점수·등급 (S/A/B/C).
|
||||||
|
- **SPA 라우팅** (`src/App.tsx`): base‑path `/ir-valuation` 제거 후 라우팅 처리.
|
||||||
|
|
||||||
## 구현 내용
|
```tsx
|
||||||
|
|
||||||
### 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() {
|
function Router() {
|
||||||
const [location] = useLocation();
|
const [location] = useLocation();
|
||||||
const basePath = "/ir-valuation";
|
const base = "/ir-valuation";
|
||||||
|
const normalized = (location.startsWith(base) ? location.slice(base.length) : location) || "/";
|
||||||
// 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 (
|
return (
|
||||||
<Switch location={normalizedLocation}>
|
<Switch location={normalized}>
|
||||||
<Route path="/" component={IRValuationPage} />
|
<Route path="/" component={IRValuationPage} />
|
||||||
<Route component={() => <div>404 Not Found - Location: {location}, Normalized: {normalizedLocation}</div>} />
|
<Route component={() => <div>404 Not Found</div>} />
|
||||||
</Switch>
|
</Switch>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
**검증**:
|
## Nginx 설정 (`nginx-infra/server-nginx-default`)
|
||||||
- `https://ro-being.com/ir-valuation/` 접근 시 IR 평가 페이지 정상 표시 확인
|
```nginx
|
||||||
- 네트워크 요청 모두 200 OK 확인
|
location /ir-valuation {
|
||||||
- ChatGPT 스타일 UI 정상 렌더링 (헤더, 업로드 버튼, 채팅 입력창)
|
alias /home/admin/frontend-ir-valuation/dist/;
|
||||||
|
try_files $uri /ir-valuation/index.html;
|
||||||
## 피드백 제출 UI 구현 (예정)
|
}
|
||||||
|
location ^~ /rb8001/ {
|
||||||
**목적**: 사용자가 평가 결과에 대해 등급 피드백을 제출하여 베이지안 학습 데이터 수집
|
proxy_pass http://192.168.219.52:8001/;
|
||||||
|
proxy_set_header Host $host;
|
||||||
**구현 위치**: `src/pages/ir-valuation.tsx`
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
**UI 구성**:
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
1. **평가 결과 사이드바에 피드백 섹션 추가**
|
proxy_read_timeout 300s;
|
||||||
- 평가 결과 하단에 "피드백 제출" 섹션
|
proxy_connect_timeout 75s;
|
||||||
- 현재 등급 표시 (예: "현재 등급: A")
|
proxy_send_timeout 300s;
|
||||||
- 등급 선택 드롭다운 (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` 테이블 구조 참고
|
## API 사용 예시
|
||||||
|
```bash
|
||||||
## 다음 단계
|
curl -X POST http://localhost/rb8001/api/ir-deck/evaluate \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
1. **백엔드 연동**: rb8001 API 엔드포인트 구현
|
-H "X-Team-Id: <team_id>" \
|
||||||
- `/rb8001/api/ir-deck/upload` - PDF 업로드
|
-H "X-User-Id: <user_id>" \
|
||||||
- `/rb8001/api/ir-deck/chat` - 채팅 응답
|
-d '{"document_id":"<id>","team_id":"<team_id>"}'
|
||||||
- `/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` 반환 확인
|
|
||||||
|
|
||||||
## ChatGPT UX 차이점
|
|
||||||
|
|
||||||
**참고**: ChatGPT(chat.openai.com) 스타일을 참고했으나 IR 평가 전용 기능으로 차이 있음
|
|
||||||
|
|
||||||
**주요 차이점**:
|
|
||||||
- 스트리밍 없음: 전체 응답을 한 번에 표시 (타이핑 효과 없음)
|
|
||||||
- 마크다운 렌더링 없음: `whitespace-pre-wrap`로 텍스트만 표시
|
|
||||||
- 채팅 히스토리 편집/삭제 없음: 표시만 가능
|
|
||||||
- 메시지 편집/재생성 없음: 복사, 좋아요/싫어요만 지원
|
|
||||||
- IR 평가 전용: 오른쪽 사이드바에 평가 결과 표시 (페이지별 평가, 점수, 등급)
|
|
||||||
|
|
||||||
## 교훈
|
## 교훈
|
||||||
|
- **핵심만**: 중복·불필요한 설명 제거, 링크로 대체.
|
||||||
|
- **헤더 필수**: `X-Team-Id`, `X-User-Id` 없으면 API 동작 안 함.
|
||||||
|
- **SPA 라우팅**: Nginx base‑path와 React 라우터 일치 필요.
|
||||||
|
|
||||||
- frontend-customer 구조를 참고하여 빠르게 프로젝트 생성 가능
|
## 다음 작업
|
||||||
- nginx 설정은 두 서버 블록(HTTP/HTTPS) 모두에 추가 필요
|
- 피드백 UI 구현 (`src/pages/ir-valuation.tsx`).
|
||||||
- 빌드 산출물은 `/home/admin/frontend-ir-valuation/dist/`에 저장
|
- 백엔드 피드백 API 연동 (`/rb8001/api/ir-deck/feedback`).
|
||||||
- **SPA 라우팅**: nginx base path(`/ir-valuation`)와 React 라우터 경로를 일치시켜야 함
|
- Sequoia 10가지 기준 실제 평가 로직 구현.
|
||||||
- wouter는 base path를 자동 처리하지 않으므로 `useLocation`으로 수동 처리 필요
|
|
||||||
- **API 헤더**: rb8001 API는 멀티테넌시를 위해 `X-Team-Id`, `X-User-Id` 헤더 필수
|
|
||||||
- **모바일 반응형**: 사이드바가 `w-96` 고정 너비로 모바일에서 채팅 영역을 가림, 모바일에서는 시트/드로어로 전환 필요
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
문서 규칙: `DOCS/book/300_architecture/312_문서_작성_원칙.md` 준수
|
## 체크리스트
|
||||||
|
- [ ] 핵심만 간결하게 정리
|
||||||
|
- [ ] 100줄 이하 확인 (현재 78줄)
|
||||||
|
- [ ] 교훈 섹션 포함
|
||||||
|
- [ ] 관련 파일 링크 포함
|
||||||
|
- [ ] Nginx 설정 및 SPA 라우팅 검증
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user