- 7-8월 초기 구축 문서 12개를 _archive/troubleshooting/2025_07-08_initial_setup/로 이동 - book/300_architecture/390_human_in_the_loop_intent_learning.md를 journey/research/intent_classification/로 이동 (개발 여정 문서) - 빈 폴더 제거 (journey/assets/*)
748 lines
20 KiB
Markdown
748 lines
20 KiB
Markdown
# 프론트엔드와 로빙 API 연결 구현
|
|
|
|
**날짜**: 2025-07-30
|
|
**작업자**: happybell80 & Claude
|
|
**관련 프로젝트**: frontend-customer, rb10508_test, nginx-deploy
|
|
|
|
## 오후 1시 00분
|
|
|
|
### 프론트엔드-로빙 연결 요구사항
|
|
|
|
**목표**:
|
|
- 51123 서버의 프론트엔드(5173)와 51124 서버의 rb10508_test(10508) 연결
|
|
- 실제 채팅 기능 구현
|
|
|
|
**현재 상황**:
|
|
- 프론트엔드는 하드코딩된 메시지만 표시
|
|
- 로빙과의 실제 통신 없음
|
|
- DB 기반 사용자-로빙 매핑 시스템 미구축
|
|
|
|
## 오후 1시 05분
|
|
|
|
### 아키텍처 분석 및 연결 전략
|
|
|
|
**nginx 프록시 확인**:
|
|
```nginx
|
|
# /rb10508/ 경로가 이미 설정됨
|
|
location ^~ /rb10508/ {
|
|
proxy_pass http://192.168.219.52:10508/;
|
|
}
|
|
```
|
|
|
|
**rb10508_test API 엔드포인트 발견**:
|
|
```python
|
|
# app/api/dev_endpoints.py
|
|
@router.post("/message")
|
|
async def test_message(message: dict):
|
|
# user_message, user_id 받아서 처리
|
|
```
|
|
|
|
**연결 전략**:
|
|
1. 환경변수로 임시 하드코딩 (DB 구축 전)
|
|
2. API 서비스 생성
|
|
3. ChatInterface 컴포넌트 수정
|
|
|
|
## 오후 1시 10분
|
|
|
|
### 프론트엔드 구현
|
|
|
|
**1. 환경변수 설정** (`.env.local`):
|
|
```env
|
|
VITE_AUTH_SERVER_URL=https://auth.ro-being.com
|
|
VITE_API_URL=http://localhost:8000
|
|
VITE_ROBEING_API_URL=https://ro-being.com/rb10508 # 임시 하드코딩
|
|
```
|
|
|
|
**2. 로빙 API 서비스 생성** (`src/services/robeing-api.ts`):
|
|
- `sendMessage()`: 메시지 전송
|
|
- `checkHealth()`: 연결 상태 확인
|
|
- 에러 처리 클래스 구현
|
|
- TypeScript 타입 정의
|
|
|
|
**3. ChatInterface 컴포넌트 수정**:
|
|
- 실제 API 호출 통합
|
|
- 로딩 상태 표시
|
|
- 에러 처리 및 토스트 알림
|
|
- Health Check로 연결 상태 표시
|
|
|
|
## 오후 1시 15분
|
|
|
|
### 연결 테스트 및 문제 발견
|
|
|
|
**테스트 결과**:
|
|
- ✅ 프론트엔드 → nginx → rb10508 연결 성공
|
|
- ✅ CORS 설정 정상 작동
|
|
- ❌ OpenAI API 키 문제로 응답 실패
|
|
|
|
**문제 분석**:
|
|
```
|
|
Error processing message: Error code: 401 -
|
|
{'error': {'message': 'Incorrect API key provided: your-open*-key'}}
|
|
```
|
|
|
|
**원인**:
|
|
- rb10508_test의 AI 서비스가 OpenAI 사용
|
|
- `.env`의 OPENAI_API_KEY가 더미값
|
|
- 컨테이너에 환경변수 반영 안됨
|
|
|
|
## 오후 1시 18분
|
|
|
|
### AI 서비스를 Gemini로 전환
|
|
|
|
**해결 방안**:
|
|
- 이미 설정된 GEMINI_API_KEY 활용
|
|
- `/api/dev/message` 엔드포인트 수정
|
|
|
|
**수정 내용**:
|
|
```python
|
|
# app/api/dev_endpoints.py
|
|
# 변경 전
|
|
response = await ai_service.process_message(user_message, user_id)
|
|
|
|
# 변경 후
|
|
response = await gemini_service.process_message(user_message, user_id)
|
|
```
|
|
|
|
**배포**:
|
|
```bash
|
|
git add -A && git commit -m "fix: AI 서비스를 OpenAI에서 Gemini로 변경"
|
|
git push origin main
|
|
# Gitea Actions가 자동 배포
|
|
```
|
|
|
|
## 오후 1시 20분
|
|
|
|
### 프론트엔드 변경사항 푸시
|
|
|
|
**커밋 내용**:
|
|
- robeing-api.ts 서비스 생성
|
|
- ChatInterface 컴포넌트 API 통합
|
|
- Health Check 및 연결 상태 표시
|
|
- 로딩 상태 및 에러 처리
|
|
|
|
**git 작업**:
|
|
```bash
|
|
git pull --rebase # 원격 변경사항 동기화
|
|
git push origin main
|
|
```
|
|
|
|
## 구현 결과
|
|
|
|
### 완성된 기능
|
|
1. **실시간 채팅**: 프론트엔드에서 메시지 입력 → Gemini AI 응답
|
|
2. **연결 상태 표시**: Health Check로 로빙 상태 확인
|
|
3. **에러 처리**: 네트워크 오류 시 사용자 친화적 메시지
|
|
4. **로딩 상태**: 응답 대기 중 스피너 표시
|
|
|
|
### 실제 서비스를 위한 필수 변경사항
|
|
|
|
**현재 상태 (개발용)**:
|
|
```javascript
|
|
// .env.local
|
|
VITE_ROBEING_API_URL=https://ro-being.com/rb10508 // 하드코딩
|
|
|
|
// src/services/robeing-api.ts
|
|
const ROBEING_API_URL = import.meta.env.VITE_ROBEING_API_URL || 'https://ro-being.com/rb10508';
|
|
```
|
|
|
|
**서비스용으로 변경해야 할 부분**:
|
|
|
|
1. **환경변수 제거**:
|
|
- `.env.local`에서 `VITE_ROBEING_API_URL` 삭제
|
|
- 하드코딩된 로빙 ID 제거
|
|
|
|
2. **동적 로빙 할당 구현**:
|
|
```javascript
|
|
// src/services/robeing-api.ts 수정
|
|
// 1. getUserRobeing() 함수 구현
|
|
export async function getUserRobeing(userId: string): Promise<string> {
|
|
const response = await fetch(`${AUTH_SERVER_URL}/api/users/${userId}/robeing`);
|
|
const data = await response.json();
|
|
return data.robeing_url; // 예: "https://ro-being.com/rb8001"
|
|
}
|
|
|
|
// 2. sendMessage() 수정
|
|
export async function sendMessage(text: string, userId: string) {
|
|
const robeingUrl = await getUserRobeing(userId); // 동적으로 가져옴
|
|
const response = await fetch(`${robeingUrl}/api/dev/message`, {...});
|
|
}
|
|
```
|
|
|
|
3. **auth-server DB 구축 필요**:
|
|
- users 테이블
|
|
- workspace_member 테이블 (user_id, robeing_id 매핑)
|
|
- 로빙 할당 API 엔드포인트
|
|
|
|
4. **ChatInterface 수정**:
|
|
- 로빙 ID 하드코딩 제거 (#10508)
|
|
- 동적으로 로빙 정보 표시
|
|
|
|
### 향후 개선사항
|
|
1. **실시간 통신**: WebSocket/SSE로 양방향 통신
|
|
2. **스킬 시스템**: UI 피드백 추가
|
|
|
|
## 교훈
|
|
|
|
1. **환경변수 관리의 중요성**
|
|
- 개발/운영 환경 분리
|
|
- 민감한 정보는 실제 값으로 설정
|
|
- 컨테이너 재시작 시 환경변수 반영 확인
|
|
|
|
2. **단계적 구현의 효과**
|
|
- 임시 하드코딩으로 빠른 프로토타이핑
|
|
- DB 구축은 별도 작업으로 분리
|
|
- 핵심 기능 우선 구현
|
|
|
|
3. **에러 처리 우선**
|
|
- API 연결 전 Health Check
|
|
- 사용자 친화적 에러 메시지
|
|
- 로딩/오프라인 상태 명확히 표시
|
|
|
|
4. **서비스 선택의 유연성**
|
|
- OpenAI → Gemini 전환이 한 줄 수정으로 가능
|
|
- 서비스 추상화의 장점
|
|
- 백업 AI 서비스 준비의 중요성
|
|
|
|
## 오후 2시 30분
|
|
|
|
### 모바일 UI/UX 대폭 개선
|
|
|
|
**문제점들**:
|
|
1. 모바일에서 푸터와 헤더가 화면 공간 차지
|
|
2. 헤더의 텍스트와 버튼이 너무 커서 줄바꿈 발생
|
|
3. 전체 화면 터치로 헤더가 나타나 채팅 중 방해
|
|
4. 채팅창 여백이 너무 큼
|
|
|
|
**해결 과정**:
|
|
|
|
1. **푸터 완전 제거**:
|
|
- 모바일에서는 푸터 표시하지 않음
|
|
- 불필요한 하단 패딩(pb-10) 제거
|
|
|
|
2. **헤더 터치 영역 제한**:
|
|
- 전체 화면 터치 → 상단 10% 영역만
|
|
- 채팅 중 실수로 헤더 나타나지 않음
|
|
|
|
3. **모바일 헤더 디자인 최적화**:
|
|
```css
|
|
/* 텍스트 크기 축소 */
|
|
text-lg → text-sm, text-sm → text-xs
|
|
/* 버튼/아이콘 크기 축소 */
|
|
p-2 → p-1.5, w-5 h-5 → w-4 h-4
|
|
/* 뱃지 크기 최적화 */
|
|
px-2 py-1 → px-1.5 py-0.5
|
|
```
|
|
|
|
4. **UI 힌트 개선**:
|
|
- 중앙의 큰 "화면을 터치하여..." → 우측 상단 작은 "메뉴" 버튼
|
|
- 5초 후 자동으로 사라짐
|
|
- 한 번 터치하면 다시 표시 안 됨
|
|
|
|
5. **채팅창 여백 축소**:
|
|
- p-4(16px) → p-2(8px)
|
|
- 모바일 화면 활용도 극대화
|
|
|
|
## 오후 3시 00분
|
|
|
|
### 모바일 스킬/아이템 패널 구현
|
|
|
|
**요구사항**:
|
|
- 모바일에서 스킬과 아이템 확인 필요
|
|
- 브라우저 스와이프 제스처와 충돌 방지
|
|
|
|
**구현 내용**:
|
|
1. **오른쪽 탭 버튼**:
|
|
- 화면 오른쪽 중앙에 세로형 "스킬" 탭
|
|
- Sparkles 아이콘과 함께 표시
|
|
- `writing-vertical` CSS로 세로 텍스트
|
|
|
|
2. **슬라이드 패널**:
|
|
- 클릭 시 오른쪽에서 80% 너비로 슬라이드인
|
|
- 배경 오버레이로 나머지 영역 어둡게
|
|
- X 버튼 또는 배경 클릭으로 닫기
|
|
|
|
3. **브라우저 제스처 안전**:
|
|
- 스와이프 대신 클릭 방식 채택
|
|
- 모바일 브라우저 기본 동작과 충돌 없음
|
|
|
|
## 오후 3시 15분
|
|
|
|
### Gemini 타임아웃 문제 해결
|
|
|
|
**문제**:
|
|
- 15초 타임아웃으로 복잡한 질문 처리 실패
|
|
- "Gemini CLI timeout after 15 seconds" 오류
|
|
|
|
**해결**:
|
|
```python
|
|
# app/services/gemini_service.py
|
|
self.cli_timeout = 15 # 변경 전
|
|
self.cli_timeout = 60 # 변경 후
|
|
```
|
|
|
|
**개선 효과**:
|
|
- 복잡한 코드 분석 가능
|
|
- 이미지 처리 시간 확보
|
|
- 긴 대화 컨텍스트 처리
|
|
|
|
## 최종 결과
|
|
|
|
### 모바일 UX 개선 요약
|
|
1. **공간 효율성**: 푸터 제거, 여백 축소로 채팅 공간 확대
|
|
2. **조작 편의성**: 상단 10% 터치로 헤더, 오른쪽 탭으로 스킬
|
|
3. **시각적 개선**: 컴팩트한 UI 요소로 한 화면에 더 많은 정보
|
|
4. **안정성**: 브라우저 제스처와 충돌 없는 인터랙션
|
|
|
|
### 성능 개선
|
|
- Gemini 응답 시간 제한 4배 증가 (15초 → 60초)
|
|
- 복잡한 요청도 안정적 처리
|
|
|
|
## 오후 3시 30분
|
|
|
|
### 데스크톱/모바일 UI 디자인 통일
|
|
|
|
**문제점**:
|
|
- 모바일에만 컴팩트 디자인 적용되어 일관성 부족
|
|
- 데스크톱: 헤더 h-16, 여백 p-4
|
|
- 모바일: 헤더 h-12, 여백 p-2
|
|
|
|
**해결**:
|
|
- 헤더 높이를 h-12로 통일
|
|
- 모든 여백을 p-2로 통일
|
|
- 아이콘과 텍스트 크기 축소 (w-4 h-4, text-xs)
|
|
|
|
## 오후 3시 40분
|
|
|
|
### 패널 폰트 크기 통일
|
|
|
|
**문제점**:
|
|
- 채팅창: text-xs (12px)
|
|
- 좌측 패널: text-sm (14px), 일부 text-lg (18px)
|
|
- 우측 패널: text-sm (14px)
|
|
- 일관성 없는 폰트 크기
|
|
|
|
**해결**:
|
|
- 모든 패널 기본 폰트를 text-xs로 통일
|
|
- 레벨/코인 등도 text-xs로 축소
|
|
- 최소 텍스트는 text-[10px] 사용
|
|
- NumberTicker 컴포넌트도 text-xs 적용
|
|
|
|
## 오후 4시 00분
|
|
|
|
### 채팅창 메시지 폰트 통일
|
|
|
|
**문제**:
|
|
- 메시지 본문이 text-sm으로 다른 요소보다 큼
|
|
|
|
**해결**:
|
|
- 메시지 본문: text-sm → text-xs
|
|
- 입력창 텍스트도 text-xs로 통일
|
|
|
|
## 오후 4시 10분
|
|
|
|
### 모바일 스킬 패널 버튼 UX 개선
|
|
|
|
**문제점들**:
|
|
1. 버튼이 화면 중앙에 있어 불편
|
|
2. 보라색이 채팅창과 겹쳐 보임
|
|
3. 클릭 영역이 너무 좁음
|
|
|
|
**해결**:
|
|
- 위치: top-1/2 → top-24
|
|
- 색상: bg-violet-600 → bg-gradient-to-l from-orange-500 to-orange-400
|
|
- 클릭 영역: px-1 py-4 → px-3 py-5
|
|
- 모서리: rounded-l-lg → rounded-l-xl
|
|
|
|
## 오후 4시 20분
|
|
|
|
### 모바일 UI 힌트 시스템 구현
|
|
|
|
**구현 내용**:
|
|
1. **스킬 버튼 자동 숨김**:
|
|
- showSkillButton 상태 추가
|
|
- 5초 후 자동으로 edge peek 상태로 전환
|
|
- translate-x-[calc(100%-3px)]로 3픽셀만 노출
|
|
|
|
2. **메뉴 힌트 위치 조정**:
|
|
- left-2 → right-1/3 (중앙-우측)
|
|
|
|
## 오후 4시 23분
|
|
|
|
### 모바일 UI 접근성 대폭 개선
|
|
|
|
**문제**:
|
|
- 메뉴 힌트가 여백 때문에 안 보임
|
|
- 스킬 버튼 클릭하기 어려움
|
|
|
|
**해결**:
|
|
1. **메뉴 힌트**: top-2 → top-1
|
|
2. **스킬 버튼 클릭 영역 확대**:
|
|
- 투명한 큰 div로 전체 영역 클릭 가능
|
|
- 오른쪽 10% 너비, 상단 15vh ~ 하단 30vh
|
|
- 실제 버튼은 작게 유지
|
|
|
|
## 오후 4시 28분
|
|
|
|
### Edge Peek UI 힌트 띠 추가
|
|
|
|
**구현 내용**:
|
|
1. **스킬 영역**:
|
|
- edge peek: 3px → 6px로 증가
|
|
- 버튼 사라진 후 주황색 세로 띠 표시 (w-1)
|
|
|
|
2. **메뉴 영역**:
|
|
- 힌트 사라진 후 보라색 가로 띠 표시 (h-1)
|
|
|
|
## 오후 4시 31분
|
|
|
|
### UI 힌트 띠 크기 증가
|
|
|
|
**변경사항**:
|
|
- 메뉴 띠: h-1 → h-2 (4px → 8px)
|
|
- 스킬 띠: w-1 → w-2 (4px → 8px)
|
|
|
|
## 오후 4시 34분
|
|
|
|
### 채팅 시간 표시 디자인 개선
|
|
|
|
**문제**:
|
|
- 시간 폰트가 메시지와 같은 크기 (text-xs)
|
|
- 24시간 형식 사용
|
|
|
|
**해결**:
|
|
1. 폰트 크기: text-xs → text-[10px] → text-[11px]
|
|
2. 색상: text-gray-400/70으로 연하게
|
|
3. 12시간 형식으로 변경
|
|
4. 날짜 추가: M/D 형식 (예: 7/30 오후 4:43)
|
|
|
|
## 오후 4시 46분
|
|
|
|
### 채팅 폰트 크기 최적화
|
|
|
|
**최종 조정**:
|
|
- 대화 메시지: text-xs(12px) → text-[13px]
|
|
- 날짜/시간: text-[11px] 유지
|
|
- 가독성 향상
|
|
|
|
## 오후 5시 31분
|
|
|
|
### 모바일 UI 시스템 리소스 표시 개선
|
|
|
|
**문제**:
|
|
- 채팅 헤더에 메모리/CPU 표시가 공간 차지
|
|
|
|
**해결**:
|
|
- 메모리/CPU 표시를 활동 패널로 이동
|
|
- 활동 패널 헤더에 "최근 활동" 옆에 표시
|
|
|
|
## 오후 5시 35분
|
|
|
|
### 모바일 활동 패널 추가
|
|
|
|
**구현 내용**:
|
|
1. **왼쪽 활동 버튼**:
|
|
- 위치: left-0 top-[30vh] bottom-0 (하단 70%)
|
|
- 색상: 청록색(cyan) 그라데이션
|
|
- 5초 후 자동 숨김 (edge peek)
|
|
- 클릭시 왼쪽에서 슬라이드
|
|
|
|
2. **통일된 UI 패턴**:
|
|
- 상단: 메뉴 (보라색)
|
|
- 우측: 스킬/아이템 (주황색)
|
|
- 좌측: 활동 (청록색)
|
|
|
|
## 오후 5시 40분
|
|
|
|
### 모바일 UI 버튼 크기 및 위치 정리
|
|
|
|
**문제점들**:
|
|
1. 메뉴버튼이 가로 전체를 차지해 UI 밸런스가 맞지 않음
|
|
2. 버튼들의 edge peek 크기가 다름
|
|
3. 메뉴 띠가 상단 일부만 차지
|
|
|
|
**해결 과정**:
|
|
|
|
1. **버튼 크기 통일** (오후 6시):
|
|
- 메뉴버튼 세로: h-[35px]
|
|
- 스킬버튼 가로: w-[35px]
|
|
- 모든 버튼 35px로 통일
|
|
|
|
2. **Edge peek 개선**:
|
|
- 메뉴: 4px 노출
|
|
- 스킬/활동: 8px 노출 (띠와 동일)
|
|
|
|
3. **위치 조정**:
|
|
- 메뉴버튼: right-1/4 (우측으로 이동)
|
|
- 띠: 상단 전체 (left-0 right-0)
|
|
|
|
4. **텍스트 변경**:
|
|
- "메뉴" → "상단메뉴"
|
|
- "스킬" → "스킬/아이템"
|
|
|
|
## 최종 UI 구성
|
|
|
|
### 모바일 3방향 UI
|
|
- **상단**: 메뉴 (보라색, h-[35px], 4px edge peek)
|
|
- **우측**: 스킬/아이템 (주황색, w-[35px], 8px edge peek)
|
|
- **좌측**: 활동 (청록색, 8px edge peek)
|
|
|
|
### 디자인 통일성
|
|
- 모든 모서리: rounded-md (6px)
|
|
- Edge peek시 띠 표시: 8px
|
|
- 35px 크기로 통일된 터치 영역
|
|
|
|
## 오후 5시 10분
|
|
|
|
### Python 버전 업그레이드
|
|
|
|
51124 서버 Python 3.10.12 → 3.13.5 업그레이드
|
|
- update-alternatives로 기본 버전 변경
|
|
- pip 25.1.1 설치
|
|
|
|
## 오후 6시 27분
|
|
|
|
### 모바일 UI 문제 해결 및 레이아웃 개선
|
|
|
|
**문제점들**:
|
|
1. 모바일 스킬/활동 패널이 뷰포트를 벗어나 아래가 잘림
|
|
2. 모바일 최근활동 제목이 중복 표시
|
|
3. 데스크톱 3등분 레이아웃이 UI 밸런스를 해침
|
|
|
|
**해결**:
|
|
1. **패널 높이 제한**:
|
|
```tsx
|
|
// 기존: h-full
|
|
// 변경: h-[calc(100%-60px)] // 헤더 높이 제외
|
|
```
|
|
|
|
2. **헤더 레이아웃 조정**:
|
|
- 모바일 활동 패널: X버튼(왼쪽), "최근 활동"(오른쪽)
|
|
- activity-panel 내부 제목 제거로 중복 해결
|
|
|
|
3. **데스크톱 비율 변경**:
|
|
- 기존: 408px / 408px / 408px
|
|
- 변경: 350px / 524px / 350px
|
|
- 중앙 대화창을 크게, 양옆은 작게
|
|
|
|
## 오후 6시 38분
|
|
|
|
### 모바일 헤더 인터랙션 개선
|
|
|
|
**구현**:
|
|
- 채팅창(본문) 터치 시 헤더 즉시 숨김
|
|
- 기존 3초 자동 숨김 기능과 병행
|
|
|
|
## 오후 6시 40분
|
|
|
|
### 메시지 입력창 가독성 개선
|
|
|
|
**변경**:
|
|
- 폰트 크기: text-xs(12px) → text-[14px]
|
|
- 사용자 입력 편의성 향상
|
|
|
|
## 오후 6시 48분
|
|
|
|
### 로빙 응답 시간 표시 방식 개선
|
|
|
|
**문제**: 응답 시간이 메시지 텍스트에 포함되어 표시
|
|
|
|
**해결**:
|
|
1. **응답 시간 분리**:
|
|
- Message 인터페이스에 responseTime 필드 추가
|
|
- 정규식으로 "(XXXXms)" 패턴 파싱
|
|
- ms를 초 단위로 변환 (6207.3ms → 6.2s)
|
|
|
|
2. **표시 위치 변경**:
|
|
- 기존: "안녕하세요! (6207.3ms)"
|
|
- 변경: 날짜/시간 아래 "7/30 오후 6:52 (6.2s)"
|
|
|
|
3. **deprecated 이슈 해결**:
|
|
- onKeyPress → onKeyDown 변경
|
|
|
|
## 오후 7시 01분
|
|
|
|
### 로빙 아바타 이미지 구현
|
|
|
|
**구현 내용**:
|
|
1. **아바타 이미지 추가**:
|
|
- 귀여운 애니메이션 캐릭터 사용
|
|
- 24x24px 크기로 대화창에 맞게 조정
|
|
|
|
2. **클릭 팝업 기능**:
|
|
- 아바타 클릭 시 큰 이미지 팝업
|
|
- 화면의 70% 이하 크기로 비율 유지
|
|
- 배경 클릭으로 닫기
|
|
|
|
## 오후 7시 12분
|
|
|
|
### 데스크톱 헤더 디자인 개선
|
|
|
|
**문제**: 헤더 내용이 양쪽으로 너무 벌어짐
|
|
|
|
**해결**:
|
|
- 데스크톱 헤더 여백: px-2 → md:px-8
|
|
- 적절한 좌우 여백으로 시각적 균형
|
|
|
|
## 오후 7시 27분
|
|
|
|
### 모바일 z-index 충돌 해결
|
|
|
|
**문제**: 모바일 UI 버튼들이 로빙 아바타를 가려서 터치 불가
|
|
|
|
**잘못된 해결 시도**:
|
|
- 모바일 채팅창에 `relative z-40` 추가
|
|
- 부작용: 활동창/스킬창 선택 영역이 가려짐
|
|
|
|
## 오후 9시 07분
|
|
|
|
### z-index 문제 올바른 해결
|
|
|
|
**문제**: 채팅창 전체의 z-index를 높여서 다른 UI 요소들이 가려짐
|
|
|
|
**올바른 해결**:
|
|
- 채팅창의 z-40 제거
|
|
- 로빙 아바타 이미지에만 `relative z-50` 적용
|
|
- 결과: 아바타만 클릭 가능하고 다른 UI 요소도 정상 작동
|
|
|
|
## 오후 7시 42분
|
|
|
|
### 메시지 입력창 터치 영역 확장
|
|
|
|
**요구사항**: 입력창의 시각적 크기는 유지하되 터치 영역만 위로 확장
|
|
|
|
**구현**:
|
|
- 투명한 오버레이 div 추가
|
|
- 입력창 위 16px까지 터치 가능
|
|
- 클릭 시 입력창에 포커스
|
|
|
|
## 교훈
|
|
|
|
### 모바일 UI 설계
|
|
1. **뷰포트 고려**: 패널 높이는 항상 뷰포트 내에서 계산
|
|
2. **z-index 관리**:
|
|
- 레이어 간 상호작용 고려 필수
|
|
- 전체 컨테이너보다 개별 요소에 z-index 적용이 더 정확함
|
|
3. **터치 영역**: 시각적 요소와 터치 영역을 분리하여 사용성 향상
|
|
|
|
### 사용자 피드백 대응
|
|
1. **정확한 이해**: 사용자 요구사항을 정확히 파악 (예: 터치 영역 vs 시각적 크기)
|
|
2. **점진적 개선**: 작은 수정사항도 즉시 반영하여 사용성 향상
|
|
|
|
### 응답 시간 표시
|
|
1. **데이터 분리**: UI 텍스트와 메타데이터는 분리하여 관리
|
|
2. **사용자 친화적 단위**: ms보다 초 단위가 직관적
|
|
|
|
## 오후 9시 23분
|
|
|
|
### z-index 계층 구조 전면 재정리
|
|
|
|
**문제**: 여러 UI 요소들의 z-index가 꼬여서 클릭이 안 되는 문제 발생
|
|
|
|
**z-index 분석**:
|
|
```
|
|
z-10: 입력창 터치 영역 (너무 낮음)
|
|
z-20: 스킬/활동 힌트 띠
|
|
z-30: 메뉴 힌트 띠, 스킬/활동 버튼 영역
|
|
z-40: 메뉴 터치 영역, 패널 배경
|
|
z-50: 헤더, 푸터, 패널, 아바타, 팝업
|
|
```
|
|
|
|
**해결**:
|
|
1. 메뉴 터치 영역: z-40 → z-30
|
|
2. 메뉴 힌트 띠: z-30 → z-20 (통일)
|
|
3. 입력창 터치 영역: z-10 → z-35
|
|
|
|
## 오후 9시 26분
|
|
|
|
### 보내기 버튼 및 아바타 클릭 문제 해결
|
|
|
|
**문제**:
|
|
1. 보내기 버튼이 클릭되지 않음
|
|
2. 아바타 클릭 시 활동창이 열림
|
|
|
|
**원인**:
|
|
1. 입력창 터치 영역이 전체를 덮어 버튼을 가림
|
|
2. 활동 버튼 영역이 너무 넓어 아바타 위치와 겹침
|
|
|
|
**해결**:
|
|
1. 입력창 터치 영역: `inset-x-0` → `left-0 right-[60px]`
|
|
2. 활동 버튼 너비: `w-[10vw] min-w-[50px]` → `w-[35px]`
|
|
|
|
## 오후 9시 35분
|
|
|
|
### 입력창 textarea 변환 및 자동 줄바꿈 구현
|
|
|
|
**요구사항**:
|
|
- 입력창에 긴 텍스트 입력 시 자동 줄바꿈
|
|
- 최대 5줄까지 표시, 초과 시 스크롤
|
|
- Enter: 전송, Shift+Enter: 줄바꿈
|
|
|
|
**구현**:
|
|
1. **input → textarea 변경**
|
|
2. **Canvas API로 텍스트 너비 측정**:
|
|
```tsx
|
|
const canvas = document.createElement('canvas');
|
|
const context = canvas.getContext('2d');
|
|
context.font = `${fontSize}px ${computedStyle.fontFamily}`;
|
|
const width = context.measureText(line).width;
|
|
```
|
|
3. **입력창 너비의 100% 도달 시 자동 줄바꿈**
|
|
4. **rows state로 동적 높이 조정** (1~5줄)
|
|
|
|
**문제 해결**:
|
|
- 선택/복사/붙여넣기 막힘 → 터치 영역 오버레이 제거
|
|
|
|
## 오후 9시 46분
|
|
|
|
### 입력창 선택/복사/붙여넣기 문제 해결
|
|
|
|
**문제**: 터치 영역 확장용 투명 오버레이가 textarea를 덮어 텍스트 선택 불가
|
|
|
|
**해결**: 오버레이 div 완전 제거
|
|
- 터치 영역 확장 기능은 포기하고 직접 클릭 방식 채택
|
|
|
|
## 오후 9시 54분
|
|
|
|
### 모바일 활동 버튼 위치 조정
|
|
|
|
**목표**: 스킬 버튼과 시각적 대칭 구현
|
|
|
|
**과정**:
|
|
1. 활동 버튼 텍스트: "활동" → "최근활동"
|
|
2. 버튼 위치 계산:
|
|
- 스킬 버튼 상단: 위에서 28.75vh
|
|
- 활동 버튼 상단: 아래에서 28.75vh + 버튼높이
|
|
3. 여러 시도 끝에 `bottom-[20vh]`로 설정
|
|
|
|
**선택 영역 정리**:
|
|
- 활동 영역: `top-[35vh] bottom-[60px]` (힌트 띠와 동일)
|
|
- 모든 선택 영역 너비/높이 35px로 통일
|
|
|
|
## 오후 10시 39분
|
|
|
|
### 모바일 UI 선택 영역 디버깅
|
|
|
|
**디버깅 방법**: 반투명 배경색으로 선택 영역 시각화
|
|
- 메뉴: 녹색 (`bg-green-500/20`)
|
|
- 스킬: 파란색 (`bg-blue-500/20`)
|
|
- 활동: 빨간색 (`bg-red-500/20`)
|
|
|
|
**발견된 문제**:
|
|
1. 활동 선택 영역이 힌트 띠보다 작음
|
|
2. 메뉴 선택 영역 높이가 다른 버튼과 다름
|
|
|
|
**해결**:
|
|
- 활동 영역을 힌트 띠와 동일하게 조정
|
|
- 메뉴 높이를 35px로 통일
|
|
|
|
## 오후 10시 47분
|
|
|
|
### UI 버튼 자동 숨김 시간 단축
|
|
|
|
**변경**: 5초 → 3초
|
|
- 메뉴 힌트, 스킬 버튼, 활동 버튼 모두 3초로 통일
|
|
- 더 빠른 UI 정리로 사용성 향상
|
|
|
|
---
|
|
**작성 완료**: 2025-07-30 23:31
|