Google Gemini 기반 AI 페르소나 및 실시간 사용자 채팅 플랫폼
일반적인 HTTP 요청-응답 방식은 AI 생성이 완료될 때까지 사용자가 오래 대기해야 하는 단점이 있었습니다. 타자 치듯 글자가 나타나는 타이핑 효과를 통해 사용자 경험을 개선하고자 했습니다.
GeminiService에서 generateStreamContent를 통해 AI 응답을 청크단위로 수신 Socket.io의 ai-stream 이벤트를 통해 클라이언트로 실시간 전송.// Backend: Chunk 단위 방출 (gemini.service.ts) for await (const chunk of stream) { if (chunk) { fullResponseText += chunk.text; emitter.emit('ai-stream', { text: chunk.text }); // 실시간 전송 } } emitter.emit('ai-stream-done', { fullText: fullResponseText });
채팅방 진입 시마다 RDBMS(PostgreSQL)에서 전체 대화 내역을 조회하면서 I/O 부하가 우려되었습니다.
채팅 내역 조회 시 Redis List를 먼저 확인하고, Cache Miss 발생 시에만 DB를 조회 후 Redis에 적재, 메시지 전송 시 DB 저장과 동시에 Redis rPush를 수행하여 실시간 데이터의 최신성을 메모리상에서 유지하도록 설계했습니다.
DB 저장이 성공한 이후에만 Redis에 푸시하도록 로직 순서를 엄격하게 제어했습니다.
// 개선된 로직 (Pseudo code) try { // 1. DB 저장 (Source of Truth) await this.messageRepository.save(newChatMessage); // 2. DB 성공 시에만 캐시 업데이트 await this.redisClient.rPush(key, JSON.stringify(message)); } catch (error) { // 3. 실패 시 클라이언트에 에러 전파 및 캐시 갱신 중단 this.server.emit('save-error', { ... }); console.error('DB Write Failed'); }