← 목록
기타 2026-06-10 12KB 읽기 12분

게이트웨이 안정화 — 최종 판정 및 복구 (2026-06-10)

개요

사용자 질문: "두 게이트웨이를 참고해 재설계할지, 한선씨 게이트웨이를 간단히 수정만 해도 충분한 완성도인지?" → 판정: 재설계 불필요. 간단한 수정으로 충분. 다만 수정 과정에서 바이너리 손상·워치독 경쟁 등 운영 사고가 겹쳐 전면 복구를 동반했다.

게이트웨이 근본원인 2건 (확정)

  1. SIGPIPE (exit 141) — 클라이언트가 응답 중 RST → 죽은 소켓 write → SIGPIPE로 프로세스 종료.
- 수정: crownyc.c main()에 signal(SIGPIPE, SIG_IGN); → 120 RST 부하 생존 검증.
  1. 배열 힙 누수 (exit 1, OOM) — 요청당 배열 ~5KB 누적, str_gc가 배열 미회수 → mem_count 12M 도달 시 OOM → 행(hang). 워치독은 :8080 TCP가 살아 못 잡음.
- 시도A (실패): 메모리마커/메모리복원 opcode(730/731)로 요청루프 끝에서 회수 → 콜프레임과 mem_count 영역 공유_요청처리 프레임 파괴 → 크래시. leaktest는 루프에 함수호출이 없어 통과했던 것. - 채택(밴드에이드): 읽기전용 메모리마커()로 mem_count > 11.5M 감지 시 클린 종료(반환) → 워치독 재기동으로 mem_count 리셋. OOM-행을 ~30s-갭 클린재시작으로 전환. - 완전한 해결(향후): crownyc VM의 프레임인식 배열 회수 — 중간 난이도, 재설계 아님.

운영 사고 & 복구

  • 바이너리 손상: cp crownyc.new crownyc를 라이브 사용 중 실행해 배포본 손상(출력값조차 무출력). → 깨끗이 재빌드 후 mv(원자적) 배포로 해결. 빌드 플래그: cc -O2 -o crownyc crownyc.c -lm -framework Security -framework CoreFoundation (crownyc.c가 crowny_tls.c=SecureTransport include).
  • 워치독 경쟁: 내가 게이트웨이 기동하는 순간 워치독도 :8080 다운 보고 게이트웨이재기동.sh 돌려 내 갓 띄운 crownyc를 SIGKILL(Killed: 9). → 복구 중에는 launchctl bootout 으로 워치독 PAUSE → 클린 기동 → bootstrap으로 재개.

백엔드 지속성 (별개 — 사용자 2차 관심사)

  • mpti 포트 불일치(근본수정): server.js 기본 MPTI_PORT||9906인데 :9906은 상담게이트웨이.js 점유, 게이트웨이/stack은 9907 기대 → EADDRINUSE 크래시. → crowny-stack.yaml 명령을 MPTI_PORT=9907 node server.js로 영구 수정. 워치독이 이제 올바른 포트로 복구.
  • tiomta 깜빡임은 워치독 kickstart가 유발한 재시작 캐스케이드 아티팩트(정착 후 200).
  • 잔여 갭: crowny.org → crowny-ai upstream :9852 다운 + stack 미등록(워치독 커버리지 밖). 후속 등록 필요.

최종 상태 (검증)

  • 게이트웨이 PID 단일, 6.5분+ 무크래시, admin :9100=200(상주)
  • tiomta.com / mpti.tiomta.com / docs / abti / amti = 200
  • 백엔드 tiomta:9878=200, mpti:9907=200
  • 워치독 데몬 가동, mpti stack 명령 영구 수정

관련 파일

  • /Users/ef/CrownyOS/crownyc/crownyc.c — SIGPIPE SIG_IGN, opcode 730/731(현재 게이트웨이 미사용)
  • /Users/ef/CrownyOS/crownyc/hanseonc_high.c — 메모리마커/메모리복원 키워드
  • /Users/ef/crowny-gateway/한선게이트웨이/게이트웨이통합.한선 — 요청루프에 mem_count 임계 자가종료
  • /Users/ef/crowny-gateway/한선게이트웨이/게이트웨이기동.sh, 게이트웨이재기동.sh — GW_PORT=8080 + 클린 정리
  • /Users/ef/crowny-infra/crowny-stack.yaml — crowny-mpti command MPTI_PORT=9907

잔여 이슈

  1. crownyc VM 프레임인식 배열 회수(완전 해결) — 임계 자가종료 대체
  2. crowny.org:9852(crowny-ai) 백엔드 기동 + 워치독 stack 등록
  3. 워치독 :8080 TCP프로브 → HTTP 헬스프로브 격상(OOM-행 직접 감지)

후속 3종 완료 (2026-06-10, 사용자 "셋다 같이")

① crownyc VM 배열 회수 (밴드에이드 → 진짜 회수)

  • 근본: crownyc.c case 79 FRAME_LEAVE가 mem_count를 의도적으로 안 줄임("데이터 안전 보장") → 함수호출마다 누적.
  • 재평가: 앞선 "마커가 프레임과 충돌해 크래시"는 오판이었음 — 실제론 배포 바이너리 손상. 깨끗한 바이너리로 격리 테스트: 10만회 함수호출+배열할당서 mem_count 기준선 유지, 무크래시.
  • 적용: 게이트웨이 요청루프에 메모리복원(_힙마커) 복원(마커=16236, 라우트맵 이후 캡처로 영속구조 보존). 그림자 2000요청 생존(구버전 ~2400 OOM). 임계종료는 안전망 병기.
  • FRAME_LEAVE 전역수정은 모든 서비스 반환배열 손상 위험이라 회피 — 회수는 호출자 루프 마커로.

② crowny.org 백엔드 복구 + 워치독 등록

  • crowny.org → crowny-ai upstream :9852 다운 → bash start-ai.sh로 기동(PID 확보, /api/health=200).
  • crowny-stack.yaml에 crowny-ai 등록(health/domains/autostart) → 워치독 자동복구 커버리지 편입. crowny.org=200.

③ 워치독 TCP→HTTP 프로브 격상

  • lib/watchdog.js _probe: crownyc 서비스 TCP-only → 연결+최소 HTTP요청→응답바이트 수신 확인. 어떤 상태줄이든 응답=정상, 무응답(행)만 재시작. 백엔드 503과 게이트웨이 행 분리.
  • 검증: 라이브 게이트웨이=true(오판 없음), 미사용포트=false.

보너스: tiomta 중복 프로세스 버그

  • tiomta가 5초마다 PID 교대(2개 프로세스 포트 쟁탈) → 원인=워치독 관리 서비스를 수동 기동(crowny-infra up/nohup)해서 중복. 교훈: 워치독 관리 서비스는 수동 기동 금지. 정리 후 단일 안정.

최종 (전부 200)

tiomta.com / crowny.org / mpti.tiomta.com / docs / abti / amti = 200. 게이트웨이 회수마커 활성, 백엔드 단일, 워치독 가동.


사용자 "연결 오류: Unexpected non-whitespace character after JSON at position 4" 근본추적 (2026-06-11)

에러 체인 (3단)

  1. 근본: tiomta /api/healthok = !!ANTHROPIC_KEY로 게이트됨 → tiomta는 ANTHROPIC 키 없이 Gemini로 동작하는데 키 부재로 503 반환.
  2. 워치독 프로브가 503(≥500)을 "다운"으로 해석 → 무한 재시작 루프 → 재시작 윈도우마다 게이트웨이가 503 Service Unavailable(평문) 반환.
  3. 프론트 index.html 채팅 핸들러(line 891)가 await r.json()을 res.ok 확인 없이 호출 → JSON.parse("503 Service Unavailable")503(숫자) 파싱 후 위치4 S에서 정확히 그 에러. catch가 "연결 오류:"로 노출.

수정 3종

  • A. tiomta server.js /api/health → 항상 200(liveness), status: degraded + premium/gemini 플래그로 키 상태 보고. 503 게이팅 제거 → 워치독 재시작 루프 종료.
  • B. crowny-stack.yaml crowny-tiomta commandset -a; . ./.env; set +a; node server.js. 워치독이 node server.js 직접 실행 시 .env 미로드(dotenv 없음) → Gemini 키 누락이었음. 이제 적재 → gemini:true, 채팅 동작.
  • C. index.html 채팅 핸들러if(!r.ok) 가드 추가: 503/502는 "잠시 후 다시 시도…✳", 그 외 상태코드 표시. r.json().catch(()=>({}))로 파싱 실패도 흡수. catch 메시지도 친절화.

검증

  • tiomta.com=200, /api/v2/types=200, /api/ai/lite Gemini=200 실응답("안녕하세요! 무엇을 도와드릴까요?")
  • 워치독 tiomta 재시작 0건(루프 종료), tiomta 단일 리스너 75177
  • 교훈: ① 헬스체크는 liveness(프로세스 가용)만 봐야지 선택적 키로 503 내면 워치독 학살 유발. ② 워치독 관리 node 서비스는 .env를 stack command에서 로드. ③ 프론트 fetch는 항상 res.ok 선확인 후 json().

티옴타 Gemini 채팅 품질 개선 (2026-06-11) — 환각·줄바꿈·게이트웨이지연

사용자 피드백: Gemini가 "티옴타=2024 인터넷 정신연령 테스트"로 환각, 줄바꿈 없이 한 덩어리(GPT2 느낌), 응답 불안정.

근본원인 + 수정 (server.js / index.html)

  1. 환각: 프론트 채팅이 그라운딩 없는 /api/ai/lite(생짜 passthrough) 호출 → Gemini가 티옴타를 몰라 지어냄. → buildConsultPrompt()티옴타 정체성(크라우니월드 자기이해 플랫폼, 9유형, TOAU, 729좌표) + 환각방지("인터넷 밈 아님, 모르면 솔직히") 시스템 컨텍스트 주입. 검증: "언제 만들어졌어?"에 "크라우니월드가 만든 도구, 제작시기는 모름"으로 정직 응답.
  2. 줄바꿈: .bubble innerHTML이 \n 무시 → CSS white-space: pre-wrap 추가.
  3. Gemini 지연 폭변동(0.7s~18s): Flash 2.5 thinking 모드 간헐 발동. → generationConfig.thinkingConfig.thinkingBudget: 0 → 일관 1~2s.
  4. 게이트웨이 멀티초 응답 503: 단일스레드 한선씨 게이트웨이가 업스트림 프록시에서 ~5s 바닥 + 멀티초 AI 응답에 503. → jobId+폴링 패턴(/api/consult/start 즉시 jobId + /api/consult/poll/:id 각 <100ms). 게이트웨이가 긴 응답 블로킹 없음. 게이트웨이 경유 5/5 done.
  5. Gemini 일시 실패(429/5xx/fetch failed): callGemini에 재시도 3회 백오프 + AbortController 15s 타임아웃.
  6. jsonRes에 Connection: close(게이트웨이 EOF 즉시 종료).
  7. 프론트 res.ok 가드 + start/poll 흐름 + CHAT_HISTORY 대화이력 전달.

잔여

  • Gemini 무료티어 레이트리밋: 연타 테스트 시 blip(재시도로 대부분 흡수, 정상사용 무영향). 지속 시 유료 키 또는 백오프 상향.
  • 게이트웨이 POST 프록시 ~5s 바닥은 게이트웨이(한선씨) 프록시 릴레이 이슈 — gateway 세션 영역(jobId 패턴으로 우회됨).

Gemini 패턴 일괄적용 (2026-06-11, 울트라 5에이전트 병렬)

사용자: "일괄 적용" + "API 연타 금지를 기본 에티켓 선언(연타=2진법적 행위)".

에티켓 선언 (전 세션 적용)

메모리 feedback_api_call_etiquette: 외부 API 연타 금지가 기본 에티켓. 연타=2진법적(crude on/off). 검증은 최소횟수·간격, 백오프 재시도, 타임아웃, 동일키 동시호출 자제. → 워크플로우 에이전트도 Gemini 무호출(헬스200+grep로만 검증).

적용 결과 (5/5 성공, 롤백 0)

서비스파일thinkingBudget:0재시도타임아웃헬스비고
crowny-aiengine/gemini-router.js✓(per-model)✓(15s)200https.request SSE, pro→flash 강등체인 보존. grounding=systemInstruction有
crowny-aimed상담게이트웨이.js200(:9906)포트 9906(9904는 분석서버 별개). grounding present
crowny-mindengine/gemini-bridge.js(node impl)정본=한선씨 VM(mind.toau:7750), node는 부차 → 이원화 별도정리 필요
crowny-mptiserver.js✓(기본0 보장)200+stack에 .env 적재 추가 → gemini:true 복구
crowny-reportengine/llm-router.js200callOpus(Anthropic) 미변경, mock fallback 보존
전부 백업(.bak-gemini) 후 적용, node -c 구문통과, 헬스200 검증. Gemini 실호출 없이(에티켓) grep+health로만.

후속(별도)

  1. crowny-mind: 한선씨 VM vs node server.js 이원화 정리(같은 7750 경합). 정본 확정 필요.
  2. 그라운딩 없는 서비스(mpti는 prompt 인라인): 환각 위험 시 도메인 시스템컨텍스트 보강 검토.
  3. jobId+폴링은 tiomta만 적용 — 게이트웨이 뒤 다른 AI 서비스도 멀티초 응답이면 동일 패턴 권장.