docs: 무한스크롤 및 API 프록시 트러블슈팅 문서 추가
This commit is contained in:
parent
6a68db9a6c
commit
382f51d365
185
troubleshooting/250818_happybell80_무한스크롤및API프록시.md
Normal file
185
troubleshooting/250818_happybell80_무한스크롤및API프록시.md
Normal file
@ -0,0 +1,185 @@
|
||||
# 무한 스크롤 및 Gateway API 프록시 문제 해결
|
||||
|
||||
## 오후 11시 12분
|
||||
|
||||
### ChromaDB 대화 히스토리 fetch_limit 문제
|
||||
|
||||
#### 문제 상황
|
||||
- **증상**: `/api/history`가 오래된 대화(8/12)만 반환, 오늘(8/18) 대화 누락
|
||||
- **원인**: ChromaDB의 fetch_limit이 `limit * 3` (60개)로 작아서 최근 대화를 가져오지 못함
|
||||
- **영향**: 사용자가 최근 대화를 볼 수 없음
|
||||
|
||||
#### 문제 분석
|
||||
- ChromaDB는 벡터 DB로 시간순 정렬을 보장하지 않음
|
||||
- `collection.get()`이 무작위 순서로 데이터 반환
|
||||
- 42개 대화 중 무작위 60개를 요청하면 최근 대화가 누락될 수 있음
|
||||
|
||||
#### 해결 방법
|
||||
```python
|
||||
# app/core/memory/storage.py 수정
|
||||
# 기존
|
||||
fetch_limit = limit * 3 if (before or after) else limit
|
||||
|
||||
# 수정
|
||||
fetch_limit = 1000 # 충분히 큰 값으로 설정
|
||||
```
|
||||
|
||||
#### 추가 개선 (미래 대비)
|
||||
```python
|
||||
# date 필드 추가로 날짜별 필터링 준비
|
||||
metadata = {
|
||||
"timestamp": "2024-08-18T10:13:41.444000", # 기존
|
||||
"date": "2024-08-18", # 새로 추가 (날짜만)
|
||||
}
|
||||
```
|
||||
|
||||
### Gateway API 프록시 404 문제
|
||||
|
||||
#### 문제 상황
|
||||
- **증상**: 프론트엔드에서 `/gateway/api/config`, `/gateway/api/history` 404 에러
|
||||
- **원인**: Gateway가 `/api/chat`만 프록시하고 나머지 엔드포인트 없음
|
||||
- **영향**: 프론트엔드 설정 로드 실패, 대화 히스토리 조회 불가
|
||||
|
||||
#### 해결 방법
|
||||
```python
|
||||
# robeing-gateway/app/main.py에 추가
|
||||
@app.get("/api/{path:path}")
|
||||
async def proxy_get(path: str, request: Request, x_user_id: str = Depends(get_verified_user)):
|
||||
"""Proxy GET requests to robing service"""
|
||||
robing_info = user_cache.get(x_user_id) or get_default_robing_info()
|
||||
base_url = robing_info['robing_url'].rstrip('/') if 'robing_url' in robing_info else f"http://{robing_info['host']}:{robing_info['port']}"
|
||||
|
||||
response = await http_client.get(
|
||||
f"{base_url}/api/{path}",
|
||||
params=request.query_params,
|
||||
headers={"X-User-Id": x_user_id}
|
||||
)
|
||||
return response.json() if response.status_code == 200 else {}
|
||||
```
|
||||
|
||||
### 프론트엔드 getUserHistory 중복 API 문제
|
||||
|
||||
#### 문제 상황
|
||||
- **증상**: `/api/user/{username}/history` 엔드포인트 404 에러
|
||||
- **원인**: 불필요한 중복 API (getMessages와 기능 중복)
|
||||
|
||||
#### 해결 방법
|
||||
```typescript
|
||||
// src/services/robing-api.ts 수정
|
||||
export async function getUserHistory(_userId: string, _token: string = '') {
|
||||
// getMessages 재사용하여 중복 제거
|
||||
const result = await getMessages(undefined, 1);
|
||||
|
||||
return {
|
||||
has_history: result.messages.length > 0,
|
||||
last_conversation: result.messages[0]?.timestamp || null,
|
||||
last_topic: result.messages[0]?.text?.substring(0, 50) || null,
|
||||
greeting: '안녕하세요',
|
||||
conversation_count: result.messages.length
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### 무한 스크롤 작동 불가 문제
|
||||
|
||||
#### 문제 상황
|
||||
- **증상**: 스크롤을 올려도 이전 대화가 로드되지 않음
|
||||
- **원인**: `oldestMessageTime`이 초기화되지 않아 loadMoreMessages 조건 충족 안 됨
|
||||
- **영향**: 과거 대화를 볼 수 없음
|
||||
|
||||
#### 문제 분석
|
||||
```javascript
|
||||
// loadMoreMessages 조건
|
||||
if (!hasMore || isLoadingMore || !oldestMessageTime || !config) return;
|
||||
// oldestMessageTime이 null이면 항상 return
|
||||
```
|
||||
|
||||
#### 해결 방법
|
||||
```javascript
|
||||
// 초기 메시지 로드 시 oldestMessageTime 설정
|
||||
if (initialMessages.length > 0) {
|
||||
const oldestMsg = initialMessages[0];
|
||||
setOldestMessageTime(oldestMsg.timestamp instanceof Date ?
|
||||
oldestMsg.timestamp.toISOString() : oldestMsg.timestamp);
|
||||
}
|
||||
|
||||
// 히스토리 로드 시에도 설정
|
||||
if (sortedMessages.length > 0) {
|
||||
const oldestTime = sortedMessages[0].timestamp;
|
||||
setOldestMessageTime(oldestTime instanceof Date ? oldestTime.toISOString() : oldestTime);
|
||||
}
|
||||
```
|
||||
|
||||
#### 디버깅 팁
|
||||
```javascript
|
||||
// 콘솔 로그 추가로 문제 추적
|
||||
console.log('[무한스크롤] Observer 설정 시도', {
|
||||
triggerRef: !!loadMoreTriggerRef.current,
|
||||
config: !!config,
|
||||
hasMore,
|
||||
isLoadingMore
|
||||
});
|
||||
```
|
||||
|
||||
### TypeScript 빌드 오류 해결
|
||||
|
||||
#### 문제 상황
|
||||
- **증상**: 70개 이상의 TypeScript 타입 오류
|
||||
- **원인**: shared/schema.ts 파일 누락, Chart.js 타입 불일치 등
|
||||
|
||||
#### 해결 방법
|
||||
1. **schema.ts 생성**
|
||||
```typescript
|
||||
// shared/schema.ts
|
||||
export interface Integration {
|
||||
id: string;
|
||||
name: string;
|
||||
status: 'connected' | 'disconnected';
|
||||
// ... 필요한 필드 추가
|
||||
}
|
||||
```
|
||||
|
||||
2. **Chart.js font weight 수정**
|
||||
```typescript
|
||||
// 기존
|
||||
weight: '500'
|
||||
// 수정
|
||||
weight: 'normal' as const
|
||||
```
|
||||
|
||||
## 교훈
|
||||
|
||||
### 1. **ChromaDB는 벡터 DB의 한계를 인지해야 함**
|
||||
- 시간순 조회에는 부적합
|
||||
- 대화 히스토리는 PostgreSQL이 더 적합
|
||||
- 임시방편으로 fetch_limit 증가, 장기적으로 DB 변경 필요
|
||||
|
||||
### 2. **Gateway 설계 시 확장성 고려**
|
||||
- 처음부터 범용 프록시 패턴 구현
|
||||
- 특정 엔드포인트만 하드코딩하지 말 것
|
||||
- `/{path:path}` 패턴으로 유연하게 처리
|
||||
|
||||
### 3. **무한 스크롤 구현 시 초기값 설정 필수**
|
||||
- 모든 상태 변수의 초기화 시점 명확히
|
||||
- 특히 조건문에 사용되는 변수는 반드시 초기화
|
||||
- 디버그 로그를 미리 추가하여 문제 추적 용이하게
|
||||
|
||||
### 4. **TypeScript 오류와 빌드 성공은 별개**
|
||||
- Vite는 타입 오류 무시하고 빌드
|
||||
- 타입 오류는 개발 경험 저하시키지만 런타임 영향 없음
|
||||
- 점진적으로 타입 오류 해결 필요
|
||||
|
||||
### 5. **API 중복 제거**
|
||||
- 비슷한 기능의 API 여러 개 만들지 말 것
|
||||
- 기존 API 재사용으로 복잡도 감소
|
||||
- getUserHistory처럼 wrapper 함수로 해결
|
||||
|
||||
### 6. **로그 기반 디버깅의 중요성**
|
||||
- 51124 서버 로그 분석으로 ChromaDB 문제 파악
|
||||
- 프론트엔드 콘솔 로그로 무한 스크롤 문제 추적
|
||||
- 문제 발생 전 로그 추가가 해결 시간 단축
|
||||
|
||||
---
|
||||
|
||||
*작성자: happybell80 & Claude*
|
||||
*관련 파일: rb10508_micro/app/core/memory/storage.py, robeing-gateway/app/main.py, frontend-customer/src/components/chat-interface.tsx*
|
||||
Loading…
x
Reference in New Issue
Block a user