# CompanyX 헤드라인 실패: 리소스 경합 및 OOM Kill

**작성일**: 2025-09-08  
**작성자**: happybell80  
**상태**: 원인 파악, 일부 해결

## 문제 요약
매일 09:00 CompanyX 헤드라인 실패, rb8001 로그에 빈 에러 메시지

## 증상
- rb8001 로그: "fetch_naver_headlines error: " (빈 메시지)
- 실패 빈도: 30-40%
- skill-news API 직접 테스트: 정상 (4-7초 소요)

## 원인

### 1. 리소스 경합
```
09:00:00 - 일일 브리핑 (skill-email)
09:00:00 - 헤드라인 (skill-news + Playwright)
```
동시 실행으로 메모리/CPU 피크

### 2. 빈 에러 메시지
```python
# rb8001/app/commands/skill_commands.py:241-243
except Exception as e:
    logger.error(f"error: {e}")  # MemoryError는 str(e)=""
```
MemoryError, InvalidURL 등은 str() 시 빈 문자열 반환

### 3. 09:01 서비스 다운 (2025-09-08)
- 09:01:15 크론 실행 시 rb8001 다운 ({"failed":3})
- 11:33 재시작 (OOM Kill 추정)
- 09:10 분리로 해결 (추가 메모리 제한 선택사항)

## 해결 조치

### 완료
1. 에러 로깅 개선
```python
error_msg = str(e) or f"{type(e).__name__}: {repr(e)}"
logger.error(f"error: {error_msg}", exc_info=True)
```

2. 스케줄 분리: 헤드라인 09:00 → 09:10

### 필요
1. 브라우저 풀 구현 (메모리 효율화)
2. 재시도 로직 (3회, 지수 백오프)
3. 메모리 모니터링

## 검증
```bash
# 메모리 확인
docker stats rb8001 skill-news

# 로그 확인  
docker logs rb8001 | grep "fetch_naver_headlines"

# 부하 테스트
for i in {1..5}; do
  curl -X POST http://localhost:8505/api/news/naver/startup-headlines &
done
```

## 교훈
1. MemoryError는 빈 문자열 → type(e).__name__ 필요
2. 리소스 집약 작업 시간 분리
3. OOM Kill 대비 메모리 제한 설정

## 관련 파일
- rb8001/app/commands/skill_commands.py:217-243
- skill_news/app/services/companyx_news_scraper.py