# skill-publish 서비스 구현 및 오류 해결 ## 작성일: 2025-09-06 ## 작성자: happybell80 ## 관련: skill-publish (포트 8511), company-x_hompage 코드 이식 ## 1. 프로젝트 초기 구성 **목표**: company-x_hompage/src/publishers 코드를 skill-publish로 분리 - 저장소: https://git.ro-being.com/ivada_Ro-being/skill-publish.git - 포트: 8511 (내부 통신용, Nginx 불필요) - 서버: 51124 ## 2. 주요 오류 및 해결 ### 2.1 pyproject.toml 패키지 경로 오류 **오류**: `No directory matches the name of your project (skill_publish)` **원인**: hatchling이 패키지 경로를 찾지 못함 **해결**: pyproject.toml에 추가 ```toml [tool.hatch.build.targets.wheel] packages = ["app"] ``` ### 2.2 Docker network 오류 **오류**: `network ivada-network declared as external, but could not be found` **원인**: 외부 네트워크 불필요 (내부 통신만 사용) **해결**: docker-compose.yml에서 제거 - 삭제: `version: '3.8'` (obsolete) - 삭제: networks 섹션 전체 ### 2.3 Gitea Actions SSH 배포 오류 **오류**: 로컬 경로 접근 시도 **원인**: skill_news 참고하여 SSH 방식 누락 **해결**: .gitea/workflows/deploy.yml 수정 ```yaml - name: Setup SSH run: | echo "${{ secrets.SSH_PRIVATE_KEY_51124 }}" > ~/.ssh/deploy_key chmod 600 ~/.ssh/deploy_key ssh-keyscan -p 51124 -H ${{ secrets.SSH_HOST_51124 }} >> ~/.ssh/known_hosts - name: Deploy to 51124 Server run: | ssh -p 51124 -i ~/.ssh/deploy_key admin@${{ secrets.SSH_HOST_51124 }} << 'DEPLOY_SCRIPT' cd /home/admin/ivada_project/skill-publish git pull origin main --rebase docker compose down || echo "Container was not running" docker compose up -d --build DEPLOY_SCRIPT ``` ### 2.4 Import 경로 오류 (src → app) **오류**: `ImportError: No module named 'src'` **원인**: company-x_hompage는 src/, skill-publish는 app/ 구조 **해결**: 모든 파일에서 일괄 변경 ```bash find app/services -name "*.py" -exec sed -i 's/from src\./from app./g' {} \; ``` **수정 파일**: - app/services/*.py (8개 파일) - squarespace_login.py, post_formatter.py, image_uploader.py 등 ### 2.5 get_logger 함수 누락 **오류**: `ImportError: cannot import name 'get_logger'` **원인**: company-x_hompage와 logger 구조 차이 **해결**: app/utils/logger.py에 호환성 함수 추가 ```python def get_logger(name: str, category: str = 'general') -> logging.Logger: return setup_logger(name) ``` ### 2.6 login_to_squarespace 함수 누락 **오류**: `ImportError: cannot import name 'login_to_squarespace'` **원인**: publisher_service.py에서 함수형 호출, 원본은 클래스만 존재 **해결**: app/services/squarespace_login.py에 호환 함수 추가 ```python async def login_to_squarespace(page: Page) -> bool: login_instance = SquarespaceLogin() success, error = await login_instance.login(page) return success ``` ### 2.7 NewsDataManager 클래스 누락 **오류**: `NameError: name 'NewsDataManager' is not defined` **원인**: company-x_hompage의 collectors 모듈 미포함 **해결**: app/services/post_formatter.py에서 직접 파일 I/O로 대체 ```python # 변경 전 self.manager = NewsDataManager(keyword) unpublished = self.manager.get_unposted_articles(limit=100) # 변경 후 self.news_file = self.news_dir / f"{self.safe_keyword}_news.json" if self.news_file.exists(): with open(self.news_file, 'r', encoding='utf-8') as f: all_news = json.load(f) unpublished = [a for a in all_news if not a.get('posted', False)][:100] ``` ### 2.8 ImageDownloader 클래스 누락 **해결**: app/services/image_uploader.py:10에서 주석 처리 ```python # from app.image_downloader import ImageDownloader ``` ### 2.9 post_formatter.py 들여쓰기 문법 오류 **오류**: `SyntaxError: invalid syntax at line 85` **원인**: if-else 블록 잘못된 중첩 **해결**: app/services/post_formatter.py:77-84 들여쓰기 수정 ## 3. 환경변수 설정 (51124 서버) ```bash cat > /home/admin/ivada_project/skill-publish/.env << 'EOF' PORT=8511 SQUARESPACE_EMAIL=실제이메일 SQUARESPACE_PASSWORD=실제비밀번호 SQUARESPACE_SITE_URL=https://www.company-x.partners HEADLESS_BROWSER=true EOF ``` ## 4. 최종 구조 ``` skill-publish/ ├── app/ │ ├── main.py (FastAPI 앱) │ ├── config.py (설정) │ ├── services/ │ │ ├── publisher_service.py (메인 서비스) │ │ ├── squarespace_*.py (이식된 코드) │ │ └── post_formatter.py (수정됨) │ └── utils/ │ └── logger.py (호환성 추가) ├── Dockerfile (Playwright 포함) ├── docker-compose.yml (네트워크 제거) └── .gitea/workflows/deploy.yml (SSH 배포) ``` ## 5. 교훈 1. **코드 이식시 import 경로 전면 검토 필수** 2. **Docker 네트워크는 필요한 경우만 사용** 3. **Gitea Actions는 SSH 배포 패턴 통일** 4. **의존성 모듈은 독립적으로 구현 또는 제거** 5. **환경변수로 하드코딩 제거 (GEMINI_MODEL 등)** ## 6. 최종 상태 **서비스 정상 작동 확인** (2025-09-06) - 포트 8511 정상 리스닝 - Health 상태: healthy - **상태: ✅ 구현 완료 및 정상 작동 중** - 모든 오류 해결 완료