본문으로 바로가기
development2026년 3월 15일·조회 124

워커 프로세스 장애 대응기: CLI 경로 오류부터 환경변수 중복까지

408번의 연속 실패를 해결한 4가지 크리티컬 이슈와 실전 디버깅 노하우

SP

SpacePlanning

SpacePlanning AI Team

## 도입: 왜 워커가 멈췄을까? 분산 시스템에서 워커(Worker) 프로세스는 백그라운드 작업을 처리하는 핵심 컴포넌트입니다. 그런데 어느 날 갑자기 워커가 무한 재시작 루프에 빠지고, 408번의 연속 실패가 발생했다면 어떻게 해야 할까요? 이 글에서는 실제 프로덕션 환경에서 겪은 4가지 크리티컬 이슈와 해결 과정을 공유합니다. --- ## 1. CLI 실행 경로 불일치 문제 ### 문제 상황 워커가 외부 CLI 도구를 호출할 때 **경로가 잘못 설정**되어 있었습니다. - **기존 경로**: `C:/nvm4w/nodejs/cli-tool.cmd` (npm 설치 버전) - **실제 경로**: `C:/Users/PC/.local/bin/cli-tool.exe` (네이티브 바이너리) - **결과**: 408번 연속 실패, 모든 메시지 처리 중단 ### 해결 방법 1. **환경 설정 파일 수정**: `.env` 파일에서 CLI 경로를 실제 바이너리 경로로 업데이트 2. **프로세스 매니저 설정 동기화**: PM2 등의 설정 파일에서도 동일하게 반영 3. **자동 탐지 로직 개선**: 래퍼 스크립트에 Windows 환경에서 `.local/bin` 경로를 우선 탐색하도록 수정 ```python # 래퍼 스크립트 예시 import os def find_cli_path(): if os.name == 'nt': # Windows local_bin = os.path.expanduser('~/.local/bin/cli-tool.exe') if os.path.exists(local_bin): return local_bin return 'cli-tool' # fallback ``` **교훈**: CLI 도구를 재설치하거나 버전을 변경할 때는 설정 파일의 절대 경로도 함께 확인해야 합니다. --- ## 2. 중첩 세션 오류 ### 문제 상황 `Error: CLI tool cannot be launched inside another session` PM2로 워커를 실행할 때 부모 프로세스의 환경변수가 자식 프로세스로 그대로 전달되어, CLI 도구가 "이미 실행 중"이라고 오판했습니다. ### 해결 방법 워커가 CLI를 실행하기 전에 **특정 환경변수를 제거**합니다. ```python import os import subprocess def spawn_cli(): worker_env = os.environ.copy() # 중첩 세션 감지용 환경변수 제거 for key in ['TOOL_SESSION', 'TOOL_ENTRYPOINT']: worker_env.pop(key, None) subprocess.run(['cli-tool', 'command'], env=worker_env) ``` **교훈**: `os.environ.copy()`로 환경을 복사할 때는 부모 프로세스의 컨텍스트 정보도 함께 복사됩니다. 자식 프로세스가 독립적으로 실행되어야 한다면 불필요한 플래그는 제거해야 합니다. --- ## 3. 환경변수 중복 관리 (DRY 원칙 위반) ### 문제 상황 7개의 설정값이 `.env`와 `ecosystem.config.js` 두 곳에 중복 선언되어 있었고, 심지어 `.env` 내부에서도 같은 변수가 두 번 선언되어 충돌했습니다. ```env # .env 파일 KAFKA_SERVERS=localhost:9092 SESSION_CHECK=true # 51번 줄 ... SESSION_CHECK=false # 55번 줄 - 충돌! ``` ### 해결 방법 **단일 진실 공급원(Single Source of Truth)** 원칙 적용: - `.env`: 애플리케이션 설정 (DB URL, 카프카 주소, 워커 설정 등) - `ecosystem.config.js`: PM2/OS 전용 설정 (시스템 경로, 버퍼 모드 등) ```javascript // ecosystem.config.js - PM2 전용 설정만 module.exports = { apps: [{ env: { PYTHONUNBUFFERED: '1', // PM2 전용 PATH: process.env.PATH + ';C:\\Tools' // OS 경로 // 애플리케이션 설정은 .env에서 load_dotenv()로 로드 } }] }; ``` **교훈**: 설정 관리는 계층별로 명확히 분리해야 합니다. 중복은 버그의 온상입니다. --- ## 4. 하드코딩된 슬롯 설정 ### 문제 상황 워커의 동시 처리 슬롯 중 일부는 하드코딩되어 있고, 일부는 환경변수로 관리되어 일관성이 없었습니다. ```python URGENT_SLOTS = 1 # 하드코딩 NORMAL_SLOTS = int(os.getenv("NORMAL_SLOTS", "2")) # 환경변수 ``` ### 해결 방법 모든 슬롯 설정을 환경변수로 통일: ```python URGENT_SLOTS = int(os.getenv("URGENT_SLOTS", "1")) NORMAL_SLOTS = int(os.getenv("NORMAL_SLOTS", "2")) BATCH_SIZE = int(os.getenv("BATCH_SIZE", "3")) ``` `.env`에서 중앙 관리: ```env URGENT_SLOTS=1 NORMAL_SLOTS=2 BATCH_SIZE=3 ``` **교훈**: 운영 중 조정이 필요한 값은 처음부터 설정 파일로 외부화해야 합니다. --- ## 검증 결과 모든 수정 후: - 워커 상태: 정상 가동, 재시작 0회 - 메시지 처리: 1시간당 6건 정상 처리, 대기 0건 - 오류: CLI 경로 오류 0건, 중첩 세션 오류 0건 --- ## 결론: 안정적인 워커 운영을 위한 체크리스트 1. **경로 검증**: 외부 도구 경로는 절대 경로로 명시하고, 변경 시 모든 설정 파일 동기화 2. **환경 격리**: 자식 프로세스 실행 시 불필요한 부모 컨텍스트 제거 3. **설정 단일화**: 중복 선언 금지, 계층별 책임 분리 (앱 설정 vs 시스템 설정) 4. **외부화 원칙**: 하드코딩 최소화, 운영 파라미터는 환경변수로 관리 다음 글에서는 워커 모니터링과 자동 복구 메커니즘에 대해 다뤄보겠습니다.
#워커프로세스#환경변수관리#프로덕션디버깅#PM2#프로세스관리#시스템운영
공유하기:

이 주제에 대해 더 알아보고 싶으신가요?

프로젝트 상담을 통해 맞춤형 솔루션을 제안받으세요.