AI Server Redis 탈피 전략
이 문서는 ai-server가 AWS Redis에 직접 의존하는 현재 구조를 단계적으로 해소하기 위한 아키텍처 전략을 정리합니다.
핵심 목표는 단순히 Redis를 다른 기술로 치환하는 것이 아닙니다.
외부 연산 노드가 AWS private Redis에 직접 붙는 구조를 제거하면서도, local backend와 dev backend가 계속 같은 중앙 상태를 볼 수 있도록 구조를 재정렬하는 것입니다.
구체적인 transport 및 메시지 계약은 AI Agent Relay Protocol 문서를 참조하십시오.
1. 배경
현재 구조에서 ai-node-agent는 AWS Redis에 직접 연결하여 다음 역할을 동시에 수행합니다.
- 실시간 이벤트 브로커
- 작업 진행 상태 저장소
- 노드 heartbeat 저장소
- 관리자 명령 수신 채널
문서 기준 기존 원칙은 Redis Pub/Sub 기반 실시간 파이프라인입니다. ARCHITECTURE.md REALTIME_PIPELINE.md
그러나 실제 운영에서는 다음 문제가 드러났습니다.
ai-server -> AWS Redis경로가 네트워크 품질에 과도하게 민감합니다.progress,heartbeat,node.monitor,prompt_progress저장이 모두 같은 외부 Redis 경로에 묶여 있습니다.- heartbeat 실패가 곧바로
No Active Workers같은 운영 false negative로 이어집니다. - 외부 generation node는 local/dev backend 주소를 안정적으로 알 수 없는 경우가 있습니다.
- 하나의 노드가
local,dev양쪽 큐를 모두 처리해야 하므로, 단일 backend ingress에만 붙는 구조는 요구사항에 맞지 않습니다.
즉 현재 문제는 "Redis가 느리다"보다, 외부 노드가 AWS private Redis에 직접 붙는 방식이 취약하고, 동시에 중앙 rendezvous point의 필요성은 여전히 남아 있다는 데 가깝습니다.
2. 무엇을 유지하고 무엇을 바꾸는가
이 전략의 핵심은 다음과 같습니다.
유지할 것
local backend와dev backend가 같은 중앙 상태를 볼 수 있는 구조- shared Redis가 담당하는 내부 실시간/상태 브리지 역할
- backend가 프론트엔드용 Socket.IO fan-out을 담당하는 구조
바꿀 것
ai-server -> Redis direct accessai-server -> backend 주소 직접 관리- Redis 하나에 얹힌 외부 노드 direct TCP 세션
한 줄로 요약하면:
shared Redis는 유지하되, 외부 노드가 Redis에 직접 붙지 않게 하고, 대신 단일 public relay를 통해 들어오게 만든다가 이 문서의 기본 방향입니다.
3. 현재 Redis 역할
코드 기준 ai-server와 backend는 Redis를 다음과 같이 사용합니다.
3.1 ai-server
- 작업 메타데이터 매핑
prompt_map:*comfy_id_map:*
- 작업 진행 상태 저장
prompt_progress:*
- 출력 결과 임시 저장
prompt_outputs:*
- 노드 heartbeat / 활성 노드 관리
agent_heartbeat:*nodes:active:last_seennodes:known
- 실시간 이벤트 발행
ai-comfyui-events
- 관리자 명령 수신
ai-system-commands
관련 코드:
ai-server/ai_node_agent/ai_node_agent.pyai-server/ai_node_agent/modules/state_manager.pyai-server/ai_node_agent/modules/progress_reporter.pyai-server/ai_node_agent/modules/warmup_manager.py
3.2 backend
- 생성 직후
queued상태 저장 및 발행 - 실시간 이벤트 수신 및 프론트 fan-out
- 프론트 초기 progress 상태 복원
- 관리자용 노드 상태 복원
- active node 판정
- zombie creation 정리
- 완료/실패 시 최종 상태 동기화
관련 코드:
backend-vivid-ai/src/generation/services/generation-queue.service.tsbackend-vivid-ai/src/ai-realtime/ai-realtime.gateway.tsbackend-vivid-ai/src/ai-realtime/handlers/redis-event.handler.tsbackend-vivid-ai/src/generation/services/generation-request-guard.service.tsbackend-vivid-ai/src/creations/creation-cleanup.service.tsbackend-vivid-ai/src/creations/creation-status-sync.service.ts
4. 설계 원칙
새 구조는 다음 원칙을 따릅니다.
ai-server는 AWS Redis private path에 직접 의존하지 않습니다.ai-server는 각 backend 주소를 직접 관리하지 않습니다.local backend,dev backend는 계속 같은 중앙 상태를 바라볼 수 있어야 합니다.- 중앙 rendezvous point는 단일하게 유지하되, 역할은 논리적으로 분리합니다.
- 빠르게 변하는 값과 영속 상태를 같은 transport로 다루지 않습니다.
- 최종 상태의 authoritative source는 DB입니다.
5. 권장 목표 구조
권장 구조는 다음과 같습니다.
핵심 포인트
- 외부 노드는 단일 public relay 주소 하나만 알면 됩니다.
- relay가 받은 이벤트를 shared Redis의 기존 키/채널 모델로 반영합니다.
- local/dev backend는 여전히 shared Redis를 통해 같은 중앙 상태를 봅니다.
- backend 자체를 외부 노드가 직접 알아야 할 필요가 없습니다.
6. 왜 Relay인가
이 프로젝트에서 relay가 필요한 이유는 기술적 취향이 아니라, 운영 요구사항 때문입니다.
6.1 외부 노드는 backend 주소를 안정적으로 알 수 없다
5090서버와 로컬 호스트 머신은 서로 다른 네트워크에 있을 수 있습니다.- 로컬 backend의 공인 진입 주소는 고정적으로 가정하기 어렵습니다.
- 반면 AWS public ingress는 고정적인 단일 진입점으로 유지하기 쉽습니다.
6.2 하나의 노드가 여러 backend와 동시에 논리적으로 연결되어야 한다
local,dev큐를 하나의 노드가 모두 처리할 수 있습니다.- 따라서 "한 노드 = 한 backend" 모델은 맞지 않습니다.
- 중앙 shared Redis를 통해 여러 backend가 같은 노드 상태를 볼 수 있어야 합니다.
6.3 직접 Redis access만 제거하면 된다
현재의 핵심 문제는 shared Redis의 존재 자체가 아니라, 외부 노드가 AWS private Redis에 직접 붙는 경로입니다.
따라서 가장 현실적인 1차 방향은:
- shared Redis는 유지
- ai-server direct Redis access 제거
- public relay 도입
입니다.
7. 역할 분리
물리적으로 Redis나 relay를 여러 개로 쪼개기보다, 단일 relay + 단일 shared Redis를 유지하면서 역할을 논리적으로 분리하는 것이 현재 단계의 권장안입니다.
7.1 Node Presence Plane
대상:
heartbeatnode statusnode.monitorcomfyui_status_update
특성:
- 고빈도
- 중앙에서 모든 backend가 볼 수 있어야 함
- 운영 false negative와 직결됨
7.2 Job Event Plane
대상:
progressexecutingpreview_imagefinalizing
특성:
- 작업 단위 이벤트
creationId,userId,env메타데이터가 중요- 휘발성 realtime과 durable status를 분리해 다룸
7.3 Durable Status Plane
대상:
- 1차:
post_processing,failed,processing_failed - 2차:
completed,artifact_registered
특성:
- 저빈도
- 유실되면 안 됨
- 멱등성 중요
- 최종 authoritative source는 DB
핵심 원칙:
ai-node-agent는 durable 상태를 직접 Redis에 쓰지 않는다.- relay는 durable 상태를 backend domain service로 전달한다.
- backend가 DB 상태 전이를 먼저 확정하고, Redis는 projection/cache로 뒤따른다.
보충:
artifact_registered는 개념적 이름이며, 현재 코드의 외부 fan-out 이벤트명은creation_result_added다.- 즉 결과물 1개가 DB/스토리지 기준으로 등록된 순간을 문서에서는
artifact_registered라고 부르되, 현재 구현은creation_result_added를 그대로 유지한다.
7.4 Control Plane
대상:
CANCEL_JOBWARMUP_UPDATE- 추후 후보:
PAUSE_NODERESUME_NODEDRAIN_NODERELOAD_CONFIG
특성:
- backend -> node 역방향 명령
- 양방향 실시간 채널 또는 별도 durable queue 필요
8. 왜 Single Relay + Single Redis인가
현재 단계에서는 Redis나 relay를 물리적으로 여러 개로 나누는 것보다, 단일 허브를 유지하는 편이 맞습니다.
이유:
- 외부 노드 설정이 단순해집니다.
- 주소 하나만 알면 됩니다.
- local/dev backend가 같은 노드 상태를 보기가 쉽습니다.
- 상태 통합 계층을 따로 만들 필요가 없습니다.
- 운영 복잡도를 제어할 수 있습니다.
즉:
- 물리적 분리는 나중 문제
- 논리적 분리가 먼저
입니다.
예외적으로 나중에 분리할 수 있는 것:
- preview 이미지
- 큰 payload
- control plane 전용 채널
- extreme scale 시 node presence 전용 relay worker
9. Transport 분리: WS + HTTP Hybrid
relay와의 통신은 역할에 따라 WebSocket과 HTTP를 분리하는 것이 권장됩니다.
9.1 WebSocket 권장 대상
heartbeatprogressexecutingnode.monitorcomfyui_status_updatecancel,warmup같은 실시간 제어 명령
이유:
- 고빈도
- 작은 payload
- 연결 1개를 유지하는 편이 자연스러움
- 요청당 HTTP 오버헤드를 줄일 수 있음
9.2 HTTP 권장 대상
completedfailedprocessing_failedpost_processing- 결과 등록
- 재시도/멱등성이 중요한 확정 이벤트
이유:
- 낮은 빈도
- 성공/실패 판단이 중요
- DB/결과 저장과 궁합이 좋음
9.3 권장 조합
ai-server <-> relay: agent 전용 WebSocket 1개ai-server -> relay: 결과/확정 상태용 HTTP
한 줄로 정리하면:
휘발성 실시간 값은 WS, 확정 이벤트는 HTTP 가 권장안입니다.
10. Relay 상세 역할
relay는 단순 프록시가 아니라, 외부 노드와 shared Redis 사이의 정규화 계층입니다.
주요 책임:
- 외부 노드 인증
- 메시지 검증
- 역할별 라우팅
- Redis 키/채널 포맷 변환
- 중복 제거 및 sequence 처리
- rate limit / throttle
10.1 WS ingress 역할
- ai-server 연결 수용
- node session 관리
- heartbeat 수신
- progress / node.monitor 수신
- control plane 역방향 push
10.2 HTTP ingress 역할
completed,failed,processing_failed,post_processing- 결과 등록
- idempotency key 처리
10.3 Redis write adapter 역할
relay는 기존 shared Redis 모델을 되도록 유지합니다.
예:
agent_heartbeat:*nodes:knownnodes:active:last_seenprompt_progress:*ai-comfyui-events
즉 backend를 전면 개편하기 전에 ai-server direct Redis access만 제거하는 것이 1차 목표입니다.
11. Redis 부하 관점
이 구조로 바꾼다고 해서 Redis 부하가 자동으로 크게 줄어드는 것은 아닙니다.
기본적으로:
- heartbeat write 수는 레거시와 비슷합니다.
- progress 저장/발행 수도 naive하게 옮기면 비슷합니다.
하지만 다음 최적화는 가능합니다.
- progress batch
- 동일 값 dedup
- preview 이미지 분리
- 지연된 stale progress discard
즉 Redis 부하는:
- 기본은 비슷
- relay에서 batch/throttle/dedup를 넣으면 더 줄어들 수 있음
입니다.
12. 데이터 저장 전략
12.1 DB에 저장할 것
Creation.statusCreation.updatedAt- 결과물 엔티티
- 최종 실패 원인
- 필요 시 최근 status transition audit
저장 기준:
- 상태 전이처럼 비즈니스 의미가 있는 durable 변화만 기록
- 같은 상태의 반복 업데이트는 no-op 처리
- 결과물 등록은 이미 필요한 insert/update만 수행
12.2 DB에 저장하지 않을 것
- 모든
progresstick - 모든
node.monitor샘플 preview_image- 매
executing이벤트 - 매 heartbeat
12.3 shared Redis 또는 단기 캐시에 둘 것
creationId -> latest transient progressnodeId -> latest node monitornodeId -> last heartbeatnodeId -> active status
12.4 DB 과부하 회피 원칙
- heartbeat는 끝까지 DB에 주기적으로 쓰지 않는다.
processing중간 진행률은 DB에 쓰지 않는다.- 상태 전이가 아닌
updatedAttouch는 최소화한다. - relay는
idempotencyKey와 현재 상태 비교로 중복 durable write를 차단한다. - Redis는 프론트 실시간 표현을 위한 projection으로 유지해 DB read/write 집중을 피한다.
13. 단계별 전환 전략
Phase 1. Realtime Plane 도입
목표:
ai-server -> Redisdirect path 제거ai-server -> backend 직접 주소 의존제거- shared Redis는 유지
변경:
- AWS public relay 추가
- ai-server
heartbeat,progress,executing,node.monitor를 relay WS로 전환 - relay가 기존 Redis 키/채널을 대신 갱신
- backend는 현재 Redis 기반 로직을 최대한 유지
이 단계의 핵심 이점:
- 네트워크 취약 지점을 가장 직접적으로 제거
- local/dev backend 동시 관찰 요구를 유지
- 외부 노드가 backend 주소를 직접 알 필요가 없어짐
현재 상태:
- realtime plane은 구현 완료 상태로 본다
- 남은 것은 end-to-end 생성 흐름 검증이다
Phase 2. Durable Status Plane 1차
목표:
- ai-node-agent가 직접 생성하는 durable 상태의 Redis direct write 제거
- backend가 durable 상태 전이의 진입점이 되도록 정리
변경:
- ai-node-agent는
post_processing,failed,processing_failed를 relay HTTP로 전송 - relay는 backend durable service로 전달
- backend는 DB 상태 전이 후 Redis projection/publish 수행
- 기존 frontend/backend의 Redis fan-out 구조는 유지
핵심 포인트:
- 이 단계에서는 DB 스키마 변경이 필수는 아니다
- 핵심은 상태 전이 책임을
ai-node-agent/Redis에서backend domain service/DB로 옮기는 것이다
Phase 3. Durable Status Plane 2차
목표:
- 최종 결과 확정 흐름을 backend/post-processing 기준으로 통합
변경:
completed는 결과 개수/후처리 완료 조건을 기준으로 backend가 확정artifact_registered는 post-processing worker 또는 backend 내부 서비스에서 durable plane으로 흡수- 결과 일부 등록 시
Creation.status는PROCESSING으로 회귀하지 않고POST_PROCESSING을 유지 - 현재 결과 등록 이벤트명은
artifact_registered대신creation_result_added를 유지 - Redis는 durable source가 아니라 projection/cache라는 원칙을 고정
이 단계에서 고려할 수 있는 추가 작업:
- 필요한 경우
idempotency key저장소 추가 - transition audit log 추가
- post-processing 세부 단계 표준화
Phase 4. Control Plane 정리
목표:
CANCEL_JOB,WARMUP_UPDATE를 relay 중심으로 재구성
권장:
- 1차: relay WS 양방향 control channel
- 대안: relay 뒤 command queue
Phase 5. backend 내부 Redis 역할 축소 여부 판단
목표:
- 필요 시
prompt_progress,agent_heartbeat, transient cache를 Redis 밖으로 단계적으로 이동
이 단계는 선택입니다.
local/dev backend가 shared Redis 모델로 잘 유지된다면, 이 단계는 서두를 필요가 없습니다.
14. 예상 작업 범위
Phase 1 기준
신규 범위:
- public relay service
- relay WS ingress
- relay HTTP ingress
- relay Redis adapter
- agent 인증/토큰 관리
ai-server
- Redis direct heartbeat 제거
- progress/status 전송 경로를 relay로 변경
- control plane 수신 경로 변경
backend
- 기존 shared Redis 소비 로직은 최대한 유지
- 필요한 경우 relay가 만든 이벤트 포맷에 맞는 최소 보정만 추가
범위 평가는 중간 규모입니다.
Phase 2 기준
다음 서비스들이 추가 영향권에 들어갈 수 있습니다.
backend-vivid-ai/src/agent-relaybackend-vivid-ai/src/creations/creation-status-sync.service.tsai-server/ai_node_agent/modules/job_lifecycle_manager.pyai-server/ai_node_agent/modules/state_manager.py- 신규
relay_durable_client.py
범위 평가는 중간~대규모입니다.
Phase 3 이후
다음 서비스들이 추가 영향권에 들어갈 수 있습니다.
backend-vivid-ai/src/generation/services/generation-request-guard.service.tsbackend-vivid-ai/src/creations/creation-cleanup.service.tsbackend-vivid-ai/src/creations/creation-status-sync.service.tsbackend-vivid-ai/src/creations/creation-results.service.ts
범위 평가는 대규모입니다.
15. 리스크와 부작용
relay를 도입하면 다음 리스크가 생깁니다.
- relay가 새로운 SPOF가 될 수 있음
- 홉이 하나 늘어남
- 인증/보안 설계가 필요함
- 중복 이벤트, 순서 역전, 재시도 정책을 직접 관리해야 함
- 운영 포인트가 하나 늘어남
하지만 현재의 ai-server -> AWS private Redis 직결 구조가 만드는 VPN/Redis stall 문제보다, 이 리스크들은 더 통제 가능하다고 판단합니다.
16. 오픈 이슈
다음 항목은 구현 전 확정이 필요합니다.
- relay 인증 방식
- shared token
- mTLS
- 둘 다
- relay를 별도 서비스로 둘지, backend 인근 컴포넌트로 둘지
- control plane을 WS 양방향으로 둘지, queue로 둘지
- progress/event payload의 batch 단위를 어떻게 잡을지
- preview 이미지 전송을 기본 활성화할지 여부
- local/dev backend의 Redis consume filter 기준을 어디까지 엄격히 둘지
17. 권장 결론
현재 시점의 권장 결론은 다음과 같습니다.
- shared Redis 자체를 버리기보다, ai-server의 direct Redis access만 먼저 제거한다.
- 외부 노드는 backend 주소 대신 단일 public relay 주소만 알도록 만든다.
- relay는 shared Redis의 외부 ingress 역할을 맡고, 기존 Redis 키/채널 모델을 최대한 유지한다.
- 실시간 휘발성 이벤트는 WS, 확정 이벤트는 HTTP로 분리한다.
- durable status의 최종 진실은 DB로 두고, Redis는 projection/cache로 유지한다.
- DB에는 상태 전이만 기록하고, heartbeat/progress 같은 고빈도 값은 끝까지 DB에 쓰지 않는다.
- Redis와 relay는 물리적으로 여러 개로 쪼개기보다, 단일 허브를 유지하고 역할만 논리적으로 분리한다.
이 방식은 현재 요구사항인
- 여러 backend 동시 관찰
- 외부 노드의 불안정한 backend 주소 문제
- shared central state 유지
- Redis direct path 제거
를 가장 현실적으로 동시에 만족시키는 전략입니다.