
로컬 개발 환경을 위한 서비스 컨트롤 플레인. 여러 개의 로컬 프로젝트(각자 다른 포트에서 실행됨)를 http://localhost 하나의 진입점 아래 경로 기반으로 묶어주는 역할.
| 구성 요소 | 내용 |
|---|---|
| 백엔드 | FastAPI + uvicorn, 127.0.0.1:8080 |
| ├ UI | / |
| ├ REST API | /api |
| └ MCP 엔드포인트 | /mcp |
| 서비스 레지스트리 | SQLite (routes 테이블) |
| 라우팅 | nginx (runtime/nginx/conf.d/routes.conf) — 등록 시 자동 생성 + nginx -t 검증 후 reload |
중요: hearth는 앱 프로세스를 직접 실행(spawn)하지 않는다.
frontend_port/backend_port로 서비스를 등록하면 그 포트에 nginx location만 연결해줄 뿐,npm run dev/uvicorn같은 실제 프로세스는 사용자가 직접 띄워야 함.
launchd/com.hearth.plist)로 hearth 백엔드 자체를 로그인 시 상시 기동 가능 (KeepAlive=true, 크래시 시 자동 재시작).--kubernetes)로 k3s 클러스터를 띄우고 공유 PostgreSQL(pgvector) + Gateway API(NGINX Gateway Fabric)를 배포하면, 앱을 로컬 프로세스가 아니라 k8s Deployment로 올리는 경로도 지원.brew install nginx node python@3.14
./scripts/setup-sudoers.sh
./scripts/start.sh
start.sh가 venv 자동 생성 + 프론트 빌드(frontend/package-lock.json 변경 원인) + uvicorn :8080 기동까지 처리.
curl -X POST localhost:8080/api/nginx/install
curl -X POST localhost:8080/api/nginx/start
cp launchd/com.hearth.plist ~/Library/LaunchAgents/
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.hearth.plist
등록 전 plist 파일에 오타 발견 → 세션 중 같이 수정:
StandardOutPath / StandardErrorPath에 >, < 문자가 잘못 섞여 있었음Projects → projects)가 실제 리포 경로와 불일치plutil -lint launchd/com.hearth.plist → OK 확인launchctl list | grep hearth
tail -f runtime/backend.out.log
결과: com.hearth의 PID가 -, 종료코드 3, 로그에 [start] uvicorn ... 배너가 반복 → 크래시 루프.
tail -n 60 runtime/backend.err.log
# → ERROR: [Errno 48] address already in use (127.0.0.1:8080)
lsof -nP -iTCP:8080 -sTCP:LISTEN
# → PID 52480 (launchd 등록 전에 수동으로 띄워둔 ./scripts/start.sh 프로세스)
ps -p 52480 -o pid,ppid,lstart,command
kill 52480
launchctl list com.hearth
curl -s -o /dev/null -w '%{http_code}\n' http://localhost:8080
# → 200, PID가 안정적인 새 프로세스로 정착 (예: 70049)
원인: 수동 기동 프로세스가 8080을 물고 있어서 launchd가 올린 인스턴스가 bind 실패 → KeepAlive가 재시작 → 무한 반복.
brew install colima docker kubectl helm
colima status 2>/dev/null || echo "미기동"
colima start --kubernetes --cpu 6 --memory 12 --disk 100
kubectl config use-context colima
kubectl get nodes
colima status
colima list
kubectl config current-context
kubectl get nodes -o wide
kubectl get pods -A
결과: 노드 1대 Ready (v1.35.0+k3s1), kube-system의 coredns / local-path-provisioner / metrics-server 3개 파드 Running. postgres·Gateway는 아직 미배포(bare cluster).
k8s/README.md "재현" 절provision_db, k8s_httproute_manifest 적용(apply)이 작동하려면 아래를 순서대로 실행.
kubectl create namespace data
PW=$(openssl rand -hex 24)
kubectl create secret generic postgres-superuser -n data \
--from-literal=POSTGRES_USER=postgres --from-literal=POSTGRES_PASSWORD="$PW"
kubectl apply -f k8s/postgres/postgres.yaml
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.5.1/standard-install.yaml
helm install ngf oci://ghcr.io/nginx/charts/nginx-gateway-fabric --version 2.6.3 \
-n nginx-gateway --create-namespace --wait
kubectl patch nginxproxy ngf-proxy-config -n nginx-gateway --type merge \
-p '{"spec":{"kubernetes":{"service":{"type":"NodePort"}}}}'
kubectl apply -f k8s/gateway/gateway.yaml
kubectl apply -f k8s/gateway/httproutes.yaml
hearth의 update_route 또는 /api/routes 사용. NodePort 확인:
kubectl get svc -n default -l gateway.networking.k8s.io/gateway-name=hearth-gw \
-o jsonpath='{.items[0].spec.ports[0].nodePort}'
curl -s localhost:8080/api/k8s/status # GatewayClass/Gateway/postgres/워크로드 상태
# 이미지 빌드 (레지스트리/push 불필요, imagePullPolicy: Never로 로컬 태그 그대로 사용)
docker build -t myapp:local .
# Deployment/Service 매니페스트 작성 후 적용 (직접 작성하거나 k8s_apply 사용)
kubectl apply -f myapp-deployment.yaml
# HTTPRoute 생성 — MCP/REST의 k8s_httproute_manifest(...) 호출 후
kubectl apply -f <생성된 httproute.yaml>
전용 DB가 필요하면 MCP/REST의 provision_db(svc) 호출.
launchctl list | grep hearth # hearth 백엔드 launchd 상태
tail -f runtime/backend.out.log # 백엔드 stdout
tail -f runtime/backend.err.log # 백엔드 stderr
colima status # colima/k3s 상태
kubectl get nodes # 클러스터 노드
kubectl get pods -A # 전체 파드
lsof -nP -iTCP:8080 -sTCP:LISTEN # 8080 포트 점유 프로세스 확인