#!/bin/bash # FactoryOps v2 개발 환경 시작 스크립트 (Podman) # 색상 정의 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' NC='\033[0m' # 스크립트 위치 기준으로 프로젝트 루트 이동 cd "$(dirname "$0")" || exit 1 COMPOSE_FILE="docker-compose.dev.yml" PROJECT_NAME="factoryops-dev" # 도움말 show_help() { echo "사용법: $0 [OPTIONS]" echo "" echo "옵션:" echo " -l, --logs 로그 표시 모드 (기본: 백그라운드)" echo " -c, --clean 완전 초기화 (볼륨 포함 모든 리소스 삭제)" echo " -r, --rebuild 이미지 강제 재빌드" echo " -h, --help 도움말 표시" echo "" echo "실행 예시:" echo " $0 # 빠른 시작 (기존 이미지 재사용)" echo " $0 -l # 로그 표시 모드" echo " $0 -r # 이미지 재빌드" echo " $0 -c # 완전 초기화 후 시작" echo " $0 -c -r # 완전 초기화 + 이미지 재빌드" echo "" echo "서비스:" echo " PostgreSQL → localhost:5432" echo " FastAPI → localhost:8000 (uvicorn --reload)" echo " Next.js → localhost:3100 (npm run dev)" } # Podman 설치 확인 check_podman() { if ! command -v podman &> /dev/null; then echo -e "${RED}Podman이 설치되어 있지 않습니다.${NC}" echo "설치: brew install podman" exit 1 fi } # Podman Machine 상태 확인 및 복구 (macOS) check_and_fix_podman() { echo -e "${BLUE}Podman 상태 확인 중...${NC}" # Linux에서는 Podman Machine 불필요 if [[ "$(uname -s)" != "Darwin" ]]; then if podman ps >/dev/null 2>&1; then echo -e "${GREEN} Podman 정상 작동${NC}" return 0 else echo -e "${RED} Podman 연결 실패${NC}" exit 1 fi fi # macOS: Podman Machine 확인 if ! podman machine list 2>/dev/null | grep -q "Running"; then echo -e "${YELLOW} Podman Machine이 실행되지 않았습니다. 시작 중...${NC}" podman machine start 2>/dev/null || { echo -e "${YELLOW} Podman Machine 초기화 중...${NC}" podman machine init --cpus 4 --memory 8192 podman machine start } sleep 3 fi # 연결 테스트 (최대 3회) local max_attempts=3 local attempt=1 while [ $attempt -le $max_attempts ]; do if podman ps >/dev/null 2>&1; then echo -e "${GREEN} Podman 정상 작동${NC}" return 0 fi echo -e "${YELLOW} 연결 실패. 복구 시도 ($attempt/$max_attempts)...${NC}" pkill -9 -f "gvproxy" 2>/dev/null || true sleep 2 podman machine stop 2>/dev/null || true sleep 2 podman machine start 2>/dev/null || { echo -e "${RED} Podman Machine 재시작 실패${NC}" podman machine rm -f podman-machine-default 2>/dev/null || true podman machine init --cpus 4 --memory 8192 podman machine start } sleep 3 attempt=$((attempt + 1)) done echo -e "${RED}Podman 복구 실패. 수동으로 확인해주세요:${NC}" echo " podman machine stop && podman machine start" exit 1 } # factoryops-dev 관련 리소스만 정리 (다른 프로젝트 보존) cleanup_project_resources() { echo -e "${BLUE}FactoryOps 개발 리소스 정리 중...${NC}" echo "" # 1. 실행 중인 컨테이너 중지 echo -e "${BLUE} [1/5] 컨테이너 중지 및 제거...${NC}" local containers=$(podman ps -aq --filter "name=factoryops-dev" 2>/dev/null || true) if [ -n "$containers" ]; then echo "$containers" | xargs -r podman stop -t 5 2>/dev/null || true echo "$containers" | xargs -r podman rm -f 2>/dev/null || true echo -e "${GREEN} 컨테이너 제거 완료${NC}" else echo -e "${GREEN} 제거할 컨테이너 없음${NC}" fi # 2. Pod 정리 echo -e "${BLUE} [2/5] Pod 정리...${NC}" local pods=$(podman pod ls --filter "name=factoryops" --format "{{.ID}}" 2>/dev/null || true) if [ -n "$pods" ]; then echo "$pods" | xargs -r podman pod rm -f 2>/dev/null || true echo -e "${GREEN} Pod 제거 완료${NC}" else echo -e "${GREEN} 제거할 Pod 없음${NC}" fi # 3. 네트워크 정리 echo -e "${BLUE} [3/5] 네트워크 정리...${NC}" local networks=$(podman network ls --format "{{.Name}}" 2>/dev/null | grep "factoryops-dev" || true) if [ -n "$networks" ]; then echo "$networks" | xargs -r podman network rm -f 2>/dev/null || true echo -e "${GREEN} 네트워크 제거 완료${NC}" else echo -e "${GREEN} 제거할 네트워크 없음${NC}" fi # 4. 볼륨 정리 echo -e "${BLUE} [4/5] 볼륨 정리...${NC}" local volumes=$(podman volume ls --format "{{.Name}}" 2>/dev/null | grep "factoryops" || true) if [ -n "$volumes" ]; then echo "$volumes" | xargs -r podman volume rm -f 2>/dev/null || true echo -e "${GREEN} 볼륨 제거 완료 (DB 데이터 포함)${NC}" else echo -e "${GREEN} 제거할 볼륨 없음${NC}" fi # 5. 이미지 정리 echo -e "${BLUE} [5/5] 이미지 정리...${NC}" local images=$(podman images --format "{{.ID}} {{.Repository}}" 2>/dev/null | grep "factoryops" | awk '{print $1}' || true) if [ -n "$images" ]; then echo "$images" | xargs -r podman rmi -f 2>/dev/null || true echo -e "${GREEN} 이미지 제거 완료${NC}" else echo -e "${GREEN} 제거할 이미지 없음${NC}" fi echo "" echo -e "${GREEN} 초기화 완료 (다른 프로젝트 리소스 보존됨)${NC}" echo "" } # 포트 충돌 확인 및 해결 check_and_free_ports() { echo -e "${BLUE}포트 사용 확인 중...${NC}" local ports=(8000 3100) local port_names=("FastAPI" "Next.js") local ports_freed=false for i in "${!ports[@]}"; do local port=${ports[$i]} local name=${port_names[$i]} if lsof -ti:$port >/dev/null 2>&1; then echo -e "${YELLOW} 포트 $port ($name) 사용 중 → 프로세스 종료${NC}" lsof -ti:$port | xargs kill -9 2>/dev/null || true ports_freed=true sleep 1 fi done if [ "$ports_freed" = true ]; then echo -e "${GREEN} 포트 정리 완료${NC}" sleep 2 else echo -e "${GREEN} 모든 포트 사용 가능${NC}" fi } # 서비스 헬스체크 대기 wait_for_services() { echo "" echo -e "${BLUE}서비스 준비 대기 중...${NC}" # API 대기 waited=0 echo -ne "${BLUE} FastAPI " while [ $waited -lt $max_wait ]; do if curl -sf http://localhost:8000/api/health >/dev/null 2>&1; then echo -e " ${GREEN}ready${NC}" break fi echo -n "." sleep 2 waited=$((waited + 2)) done if [ $waited -ge $max_wait ]; then echo -e " ${YELLOW}timeout (로그를 확인하세요)${NC}" fi # Dashboard 대기 (npm install이 오래 걸릴 수 있음) waited=0 max_wait=120 echo -ne "${BLUE} Next.js " while [ $waited -lt $max_wait ]; do if curl -sf http://localhost:3100 >/dev/null 2>&1; then echo -e " ${GREEN}ready${NC}" break fi echo -n "." sleep 3 waited=$((waited + 3)) done if [ $waited -ge $max_wait ]; then echo -e " ${YELLOW}아직 준비 중 (npm install 진행 중일 수 있음)${NC}" fi } # ─── 인자 파싱 ─── SHOW_LOGS=false FULL_CLEAN=false FORCE_REBUILD=false while [[ $# -gt 0 ]]; do case $1 in -l|--logs) SHOW_LOGS=true; shift ;; -c|--clean) FULL_CLEAN=true; shift ;; -r|--rebuild) FORCE_REBUILD=true; shift ;; -h|--help) show_help; exit 0 ;; *) echo "알 수 없는 옵션: $1"; show_help; exit 1 ;; esac done # ─── 실행 시작 ─── echo -e "${CYAN}" echo "=================================================" echo " FactoryOps v2 개발 환경 시작" echo "=================================================" echo -e "${NC}" check_podman check_and_fix_podman # 완전 초기화 또는 빠른 시작 if [ "$FULL_CLEAN" = true ]; then echo -e "${YELLOW}완전 초기화 모드 (-c)${NC}" echo -e "${YELLOW} factoryops 관련 리소스만 삭제됩니다 (볼륨/DB 포함)${NC}" echo "" cleanup_project_resources else echo -e "${GREEN}빠른 시작 모드 (기존 리소스 재사용)${NC}" echo -e "${BLUE} 완전 초기화가 필요하면: $0 -c${NC}" echo "" # 실행 중인 컨테이너만 중지 running=$(podman ps -q --filter "name=factoryops-dev" 2>/dev/null || true) if [ -n "$running" ]; then echo -e "${YELLOW} 기존 컨테이너 중지 중...${NC}" echo "$running" | xargs -r podman stop -t 5 2>/dev/null || true echo -e "${GREEN} 기존 컨테이너 중지 완료${NC}" fi echo "" fi check_and_free_ports # 빌드 & 실행 옵션 BUILD_OPTIONS="" RUN_OPTIONS="" if [ "$FORCE_REBUILD" = true ]; then BUILD_OPTIONS="--build --no-cache" echo -e "${BLUE}이미지 재빌드 모드 활성화 (-r)${NC}" else echo -e "${GREEN}기존 이미지 재사용 (재빌드: $0 -r)${NC}" fi if [ "$SHOW_LOGS" = false ]; then RUN_OPTIONS="-d" fi echo "" echo -e "${BLUE}서비스 시작 중...${NC}" # compose 실행 podman compose -f "$COMPOSE_FILE" up $RUN_OPTIONS $BUILD_OPTIONS 2>&1 | \ grep -v "WARNING" || true if [ "$SHOW_LOGS" = false ]; then wait_for_services fi echo "" echo -e "${CYAN}" echo "=================================================" echo " FactoryOps v2 개발 환경 시작 완료" echo "=================================================" echo -e "${NC}" echo " 서비스 접속:" echo " Frontend http://localhost:3100" echo " Backend http://localhost:8000" echo " API Docs http://localhost:8000/docs" echo " Database 211.115.91.141:8200 (원격 DB)" echo "" if [ "$SHOW_LOGS" = false ]; then echo " 로그 확인:" echo " podman compose -f $COMPOSE_FILE logs -f" echo " podman compose -f $COMPOSE_FILE logs -f api" echo " podman compose -f $COMPOSE_FILE logs -f dashboard" echo "" fi echo " 중지:" echo " ./stop-dev.sh" echo ""