Add: 로빙 컨테이너 경량화 전략 문서
- 300_architecture에 경량화 전략 문서 추가 - 현재 문제점: 31개 파일, 82개 함수의 monolithic 구조 - 목표: Stateless Router + Microservices (512MB 메모리) - 실행 로드맵: 3단계 (분석/설계 → 공용서비스 → 코어경량화) - 스킬 서버 분리 (Email, News, Slack 등) - 로그 관리, 환경변수, 함수형 프로그래밍, 보안 전략 포함 - README.md 업데이트
This commit is contained in:
parent
285c7c0a5f
commit
ee76763ed0
328
300_architecture/360_로빙_컨테이너_경량화_전략.md
Normal file
328
300_architecture/360_로빙_컨테이너_경량화_전략.md
Normal file
@ -0,0 +1,328 @@
|
|||||||
|
# 360. 로빙 컨테이너 경량화 전략
|
||||||
|
|
||||||
|
## 개요
|
||||||
|
|
||||||
|
현재 rb10508은 31개 파일, 82개 함수가 거미줄처럼 얽혀있는 monolithic 구조로, 메모리 사용량이 2GB를 넘어가고 있습니다. 이를 512MB 이하의 경량 컨테이너로 전환하여 100개 이상의 로빙을 동시에 운영할 수 있는 구조로 개선하고자 합니다.
|
||||||
|
|
||||||
|
> "컨테이너는 몸, 기억은 영혼 - 100개 로빙이 하나의 스킬 서비스를 공유한다"
|
||||||
|
|
||||||
|
## 현재 상황 분석
|
||||||
|
|
||||||
|
### 문제점
|
||||||
|
1. **모든 기능이 한 컨테이너에 집중**
|
||||||
|
- LLM 호출, ChromaDB, PostgreSQL 접근
|
||||||
|
- 메모리 관리, 스킬 처리, Slack 통신
|
||||||
|
- 파일 간 강한 결합도
|
||||||
|
|
||||||
|
2. **리소스 과다 사용**
|
||||||
|
- 메모리: 2GB 이상
|
||||||
|
- CPU: 지속적인 높은 사용률
|
||||||
|
- 확장 시 비용 급증
|
||||||
|
|
||||||
|
3. **상태 의존성 (Stateful)**
|
||||||
|
- ChromaDB가 컨테이너 내부에 위치
|
||||||
|
- 재시작 시 상태 복구 필요
|
||||||
|
- 스케일링 어려움
|
||||||
|
|
||||||
|
## 목표 아키텍처
|
||||||
|
|
||||||
|
### Stateless Router + Microservices
|
||||||
|
|
||||||
|
```
|
||||||
|
현재 구조: 목표 구조:
|
||||||
|
┌─────────────────┐ ┌──────────────────┐
|
||||||
|
│ rb10508 │ │ rb10508-lite │
|
||||||
|
│ (2GB+) │ ──→ │ (512MB) │
|
||||||
|
│ - 모든 기능 포함 │ │ - 라우팅만 담당 │
|
||||||
|
└─────────────────┘ └────────┬─────────┘
|
||||||
|
│
|
||||||
|
┌──────────┴──────────┐
|
||||||
|
│ │
|
||||||
|
┌──────▼──────┐ ┌──────▼──────┐
|
||||||
|
│State Service│ │ LLM Service │
|
||||||
|
│ (공용 DB) │ │(Gemini/GPT) │
|
||||||
|
└─────────────┘ └─────────────┘
|
||||||
|
|
||||||
|
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
||||||
|
│Skill-Email │ │ Skill-News │ │ Skill-Slack │
|
||||||
|
│ (HTTP API) │ │ (HTTP API) │ │ (HTTP API) │
|
||||||
|
└─────────────┘ └─────────────┘ └─────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### 핵심 설계 원칙
|
||||||
|
|
||||||
|
1. **경량화**: 로빙 컨테이너는 최소한의 리소스로 운영
|
||||||
|
2. **무상태 (Stateless)**: 언제든 재시작 가능, 상태는 외부 관리
|
||||||
|
3. **확장성**: 스킬 서버는 독립적으로 스케일링
|
||||||
|
4. **비용 효율성**: LLM API는 공용 서버에서만 호출
|
||||||
|
5. **독립성**: 각 컴포넌트별 독립 배포/업데이트
|
||||||
|
|
||||||
|
## 실행 로드맵
|
||||||
|
|
||||||
|
### Phase 1: 분석 및 설계
|
||||||
|
|
||||||
|
#### 주요 작업
|
||||||
|
1. **의존성 맵 작성**
|
||||||
|
- file-graph-visualizer 결과 분석
|
||||||
|
- 실행 경로 기준 우선순위 설정
|
||||||
|
- 가장 빈번한 경로부터 분리 (예: Slack → 의도 분석 → LLM)
|
||||||
|
|
||||||
|
2. **API 인터페이스 정의**
|
||||||
|
- RESTful API + WebSocket (실시간 업데이트)
|
||||||
|
- 내부 서비스용 gRPC 검토
|
||||||
|
- 인증/인가 체계 설계
|
||||||
|
|
||||||
|
#### 용어 설명
|
||||||
|
- **의존성 맵**: 코드 파일들 간의 import/호출 관계를 시각화한 다이어그램
|
||||||
|
- **gRPC**: Google이 개발한 고성능 RPC 프레임워크, HTTP/2 기반으로 빠른 통신 지원
|
||||||
|
- **WebSocket**: 실시간 양방향 통신을 위한 프로토콜
|
||||||
|
|
||||||
|
### Phase 2: 공용 서비스 구축
|
||||||
|
|
||||||
|
#### State Service (상태 관리 서비스)
|
||||||
|
```python
|
||||||
|
# 주요 기능
|
||||||
|
- 사용자 상태 관리 (레벨, 스탯, 경험치)
|
||||||
|
- 메모리 저장/검색 (ChromaDB 통합)
|
||||||
|
- 회사별 설정 관리
|
||||||
|
- 실시간 상태 동기화
|
||||||
|
```
|
||||||
|
|
||||||
|
**구현 포인트**:
|
||||||
|
- PostgreSQL + ChromaDB 외부화
|
||||||
|
- 세션 데이터와 장기 기억 논리적 분리
|
||||||
|
- pgvector + materialized view로 검색 최적화
|
||||||
|
- 버전 필드로 점진적 마이그레이션 지원
|
||||||
|
|
||||||
|
#### LLM Service (언어모델 관리 서비스)
|
||||||
|
```python
|
||||||
|
# 주요 기능
|
||||||
|
- Gemini/OpenAI 통합 관리
|
||||||
|
- 지능형 캐싱 (프롬프트 해시 기반)
|
||||||
|
- Rate limiting 및 API 키 풀 관리
|
||||||
|
- 비용 최적화 (스탯 기반 모델 선택)
|
||||||
|
```
|
||||||
|
|
||||||
|
**구현 포인트**:
|
||||||
|
- 프롬프트 길이 ≥ n일 때만 캐싱 적용
|
||||||
|
- API 키를 3개 그룹으로 분류 (고속/보통/저비용)
|
||||||
|
- 연산 스탯에 따라 적절한 그룹 선택
|
||||||
|
|
||||||
|
#### 용어 설명
|
||||||
|
- **pgvector**: PostgreSQL의 벡터 검색 확장 기능
|
||||||
|
- **materialized view**: 쿼리 결과를 물리적으로 저장하는 뷰, 성능 향상
|
||||||
|
- **Rate limiting**: API 호출 횟수를 제한하여 과부하 방지
|
||||||
|
- **API 키 풀**: 여러 API 키를 순환 사용하여 한도 분산
|
||||||
|
|
||||||
|
### Phase 3: 로빙 코어 경량화
|
||||||
|
|
||||||
|
#### 남길 기능 (최소한의 핵심)
|
||||||
|
1. **Slack 이벤트 수신 및 ACK**
|
||||||
|
2. **간단한 키워드 기반 라우팅**
|
||||||
|
3. **외부 서비스 호출 클라이언트**
|
||||||
|
4. **헬스체크 및 모니터링**
|
||||||
|
|
||||||
|
#### 로빙 브레인의 새로운 역할
|
||||||
|
```python
|
||||||
|
class RobingBrain:
|
||||||
|
"""경량화된 로빙 브레인 - 라우터 역할만 수행"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.skill_endpoints = {
|
||||||
|
"email": "http://skill-email:8501",
|
||||||
|
"news": "http://skill-news:8505",
|
||||||
|
"slack": "http://skill-slack:8503",
|
||||||
|
"pdf": "http://skill-pdf:8502"
|
||||||
|
}
|
||||||
|
|
||||||
|
async def route_to_skill(self, message: str, user_id: str):
|
||||||
|
# 1. 간단한 키워드 매칭 (LLM 없이)
|
||||||
|
if "이메일" in message or "메일" in message:
|
||||||
|
skill_url = self.skill_endpoints["email"]
|
||||||
|
elif "뉴스" in message or "news" in message:
|
||||||
|
skill_url = self.skill_endpoints["news"]
|
||||||
|
elif "요약" in message or "스레드" in message:
|
||||||
|
skill_url = self.skill_endpoints["slack"]
|
||||||
|
|
||||||
|
# 2. 외부 스킬 서비스 호출
|
||||||
|
response = await self.http_client.post(
|
||||||
|
skill_url,
|
||||||
|
json={"message": message, "user_id": user_id}
|
||||||
|
)
|
||||||
|
|
||||||
|
# 3. 결과만 반환 (처리는 스킬 서버에서)
|
||||||
|
return response.json()
|
||||||
|
```
|
||||||
|
|
||||||
|
**현재**: 로빙이 직접 스킬 로직 실행
|
||||||
|
**개선**: 로빙은 라우팅만, 실제 처리는 독립된 스킬 서버에서
|
||||||
|
|
||||||
|
#### 제거할 기능 (외부 서비스로 이동)
|
||||||
|
1. **gemini_service.py** → LLM Service
|
||||||
|
2. **chroma_service.py** → State Service
|
||||||
|
3. **복잡한 의도 분석 로직** → LLM Service
|
||||||
|
4. **메모리 관리 로직** → State Service
|
||||||
|
|
||||||
|
#### 최적화 방법
|
||||||
|
- FastAPI → Starlette 다운사이징
|
||||||
|
- Uvicorn workers = 1로 제한
|
||||||
|
- 불필요한 의존성 제거
|
||||||
|
- Policy Object로 라우팅 결과 직렬화
|
||||||
|
|
||||||
|
#### 용어 설명
|
||||||
|
- **ACK (Acknowledgment)**: 메시지 수신 확인 응답
|
||||||
|
- **Starlette**: FastAPI의 기반이 되는 경량 웹 프레임워크
|
||||||
|
- **Uvicorn**: Python 비동기 웹 서버
|
||||||
|
- **Policy Object**: 의사결정 규칙을 객체로 표현한 패턴
|
||||||
|
|
||||||
|
## 즉시 실행 가능한 개선사항
|
||||||
|
|
||||||
|
### 1. 하드코딩 제거
|
||||||
|
```python
|
||||||
|
# 현재 (gemini_service.py:190-192)
|
||||||
|
좋은 답변: "김종태님, 아드님은 초등학교 2학년이시고..."
|
||||||
|
|
||||||
|
# 개선
|
||||||
|
# 모델 컨피그 테이블에서 동적으로 로드
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 메모리 제한 설정
|
||||||
|
```yaml
|
||||||
|
# docker-compose.yml에 추가
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: 512m
|
||||||
|
cpus: '0.5'
|
||||||
|
reservations:
|
||||||
|
memory: 256m
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 문서 이동 및 정리
|
||||||
|
- `/DOCS/_archive/docs/architecture/로빙_아키텍쳐_설계_경량.md`
|
||||||
|
- → `/DOCS/300_architecture/360_로빙_컨테이너_경량화_전략.md`
|
||||||
|
- ADR(Architecture Decision Record)로 등록
|
||||||
|
|
||||||
|
## 위험 요소 및 대응 방안
|
||||||
|
|
||||||
|
### 1. 네트워크 지연 증가
|
||||||
|
- **문제**: 서비스 분리로 1-2 RTT 추가
|
||||||
|
- **대응**:
|
||||||
|
- 내부 로드밸런서(Envoy) 사용
|
||||||
|
- Keep-alive 연결 유지
|
||||||
|
- 중요 경로 캐싱 강화
|
||||||
|
|
||||||
|
### 2. 운영 복잡도 증가
|
||||||
|
- **문제**: 서비스 수 증가로 관리 어려움
|
||||||
|
- **대응**:
|
||||||
|
- 공통 미들웨어 프레임워크
|
||||||
|
- 중앙집중식 로깅/모니터링
|
||||||
|
- 자동화된 헬스체크
|
||||||
|
|
||||||
|
### 3. 배포 파편화
|
||||||
|
- **문제**: 여러 서비스의 일관된 배포 어려움
|
||||||
|
- **대응**:
|
||||||
|
- GitOps (Argo CD) 도입
|
||||||
|
- Blue-Green 배포
|
||||||
|
- 단계별 트래픽 미러링
|
||||||
|
|
||||||
|
#### 용어 설명
|
||||||
|
- **RTT (Round Trip Time)**: 요청-응답 왕복 시간
|
||||||
|
- **Envoy**: 고성능 프록시 및 로드밸런서
|
||||||
|
- **GitOps**: Git을 통한 인프라 관리 방법론
|
||||||
|
- **Blue-Green 배포**: 두 환경을 번갈아 사용하는 무중단 배포
|
||||||
|
|
||||||
|
## 기대 효과
|
||||||
|
|
||||||
|
### 리소스 절감
|
||||||
|
- 메모리: 2GB+ → 512MB (75% 감소)
|
||||||
|
- CPU: 1 core → 0.5 core (50% 감소)
|
||||||
|
- 비용: 서버당 약 70% 절감
|
||||||
|
|
||||||
|
### 확장성 향상
|
||||||
|
- 현재: 서버당 5-10개 로빙
|
||||||
|
- 목표: 서버당 100+ 로빙
|
||||||
|
- 수평 확장 용이
|
||||||
|
|
||||||
|
### 운영 효율성
|
||||||
|
- 컴포넌트별 독립 배포
|
||||||
|
- 장애 격리 및 빠른 복구
|
||||||
|
- 중앙집중식 모니터링
|
||||||
|
|
||||||
|
## 추가 고려사항
|
||||||
|
|
||||||
|
### 로그 관리 전략
|
||||||
|
```yaml
|
||||||
|
# 현재: SSD에 로그 저장 (문제)
|
||||||
|
volumes:
|
||||||
|
- ./logs:/code/logs
|
||||||
|
|
||||||
|
# 개선: HDD로 심링크 설정
|
||||||
|
# 호스트에서: ln -s /mnt/hdd/logs/rb10508 ./logs
|
||||||
|
volumes:
|
||||||
|
- ./logs:/code/logs:rw
|
||||||
|
```
|
||||||
|
|
||||||
|
**로그 경량화**:
|
||||||
|
- 로그 레벨 동적 조정 (DEBUG → INFO)
|
||||||
|
- 구조화된 로그 (JSON 형식)
|
||||||
|
- 외부 로그 수집기로 전송 (Fluentd/Logstash)
|
||||||
|
|
||||||
|
### 환경변수 관리
|
||||||
|
```python
|
||||||
|
# State Service에서 중앙 관리
|
||||||
|
class ConfigService:
|
||||||
|
async def get_robing_config(self, robing_id: str):
|
||||||
|
return {
|
||||||
|
"log_level": "INFO",
|
||||||
|
"memory_limit": "512m",
|
||||||
|
"skill_endpoints": {...},
|
||||||
|
"feature_flags": {...}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 함수형 프로그래밍 접근
|
||||||
|
```python
|
||||||
|
# 순수 함수로 스킬 처리
|
||||||
|
def route_message(message: str, skill_map: dict) -> str:
|
||||||
|
"""부작용 없는 라우팅 함수"""
|
||||||
|
for keyword, skill in skill_map.items():
|
||||||
|
if keyword in message:
|
||||||
|
return skill
|
||||||
|
return "default"
|
||||||
|
|
||||||
|
# 불변성 유지
|
||||||
|
RouteResult = namedtuple('RouteResult', ['skill', 'confidence'])
|
||||||
|
```
|
||||||
|
|
||||||
|
### 메트릭 수집
|
||||||
|
```python
|
||||||
|
# Prometheus 메트릭
|
||||||
|
robing_request_count = Counter('robing_requests_total', 'Total requests')
|
||||||
|
robing_memory_usage = Gauge('robing_memory_bytes', 'Memory usage')
|
||||||
|
robing_response_time = Histogram('robing_response_seconds', 'Response time')
|
||||||
|
```
|
||||||
|
|
||||||
|
### 보안 강화
|
||||||
|
- **네트워크 격리**: 스킬 서버는 내부망에서만 접근
|
||||||
|
- **인증 토큰 순환**: JWT 토큰 주기적 갱신
|
||||||
|
- **Rate Limiting**: 로빙별 요청 제한
|
||||||
|
- **감사 로그**: 모든 API 호출 기록
|
||||||
|
|
||||||
|
## 다음 단계
|
||||||
|
|
||||||
|
1. **아키텍처 결정**
|
||||||
|
- State Service와 LLM Service 간 통신 방식
|
||||||
|
- 이벤트 버스(Kafka/NATS) vs HTTP + 캐시
|
||||||
|
|
||||||
|
2. **파일럿 프로젝트**
|
||||||
|
- rb10508_lite 프로토타입 개발
|
||||||
|
- 성능 벤치마크 및 검증
|
||||||
|
|
||||||
|
3. **점진적 마이그레이션**
|
||||||
|
- 기능별 단계적 분리
|
||||||
|
- 트래픽 미러링으로 안정성 확보
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*"로빙을 가볍게, 그러나 더 강하게 - 진정한 디지털 동료로의 진화"*
|
||||||
@ -29,6 +29,7 @@
|
|||||||
- [330. 백엔드: PostgreSQL + ChromaDB Vector Memory](./300_architecture/330_백엔드_PostgreSQL_ChromaDB_Vector_Memory.md)
|
- [330. 백엔드: PostgreSQL + ChromaDB Vector Memory](./300_architecture/330_백엔드_PostgreSQL_ChromaDB_Vector_Memory.md)
|
||||||
- [340. GUI 공유 아키텍처: 레벨 기반 권한](./300_architecture/340_GUI_공유_아키텍처_레벨기반_권한.md)
|
- [340. GUI 공유 아키텍처: 레벨 기반 권한](./300_architecture/340_GUI_공유_아키텍처_레벨기반_권한.md)
|
||||||
- [350. DID 기반 정체성과 다중 에이전트](./300_architecture/350_DID_기반_정체성과_다중에이전트.md)
|
- [350. DID 기반 정체성과 다중 에이전트](./300_architecture/350_DID_기반_정체성과_다중에이전트.md)
|
||||||
|
- [360. 로빙 컨테이너 경량화 전략](./300_architecture/360_로빙_컨테이너_경량화_전략.md)
|
||||||
|
|
||||||
#### Part 4: 성장과 진화 (400_growth)
|
#### Part 4: 성장과 진화 (400_growth)
|
||||||
- [410. 레벨업 알고리즘과 사용자 피드백](./400_growth/410_레벨업_알고리즘과_사용자_피드백.md)
|
- [410. 레벨업 알고리즘과 사용자 피드백](./400_growth/410_레벨업_알고리즘과_사용자_피드백.md)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user