Cosmic Story v2 아키텍처 — 심층 분석.

엔지니어, PM, 기자, 파트너십 스카우트를 위한 자료예요. 전체 파이프라인, 네 개의 MongoDB 컬렉션, EDA 이벤트, V-Model의 엄격함, 성능 목표, 보안, 접근성까지 — 모두 한 페이지에 담았어요.

  • Soulwise-story는 기존 cosmic-story 모듈과 함께 동작하는 새로운 NestJS 모듈이에요. 기능 모듈 간 직접 임포트는 전혀 없어요.
  • 네 개의 MongoDB 컬렉션: soulwise_persons, soulwise_chapters, soulwise_journal_entries, soulwise_resonances. 본문은 AES-256로 암호화하며, 각 컬렉션이 처리하는 쿼리에 맞게 인덱싱했어요.
  • BullMQ 큐를 통한 비동기 생성으로, 타임아웃은 28초예요. 이벤트는 데이터베이스 커밋 이후에만 EventEmitter2로 발행되므로, 유령 받은편지함 항목이 생기지 않아요.
  • V-모델 명세: 요구사항 119개, 누락 없음. 백엔드 커버리지 목표는 서비스 구문 기준 85%이고, 프런트엔드는 Pinia 스토어 기준 90%예요.

다시 살펴보는 파이프라인, 이번에는 엔지니어링 세부 사항과 함께

각 단계에는 서비스, 계약, 이벤트가 있어요.

  1. 트리거

    '언니를 위한 오늘의 챕터 생성' 같은 사용자 동작이거나, 일요일 9시 요약처럼 예약된 cron, 또는 6시간마다 갱신되는 날씨 정보 같은 거예요.

  2. 작업은 soulwise-chapter-generation이라는 BullMQ 큐에 들어가며, 28초의 강제 타임아웃이 적용돼요. 오래 걸리는 작업은 중단되고 사용자에게 '다시 시도'로 안내돼요.

  3. 구성

    ChapterGenerationService가 네 가지 요소로 된 프롬프트(인물 맥락, 점성술, 신호, 주기)를 하나의 입력으로 조합해요. 원본 사용자 개인정보(PII)는 그대로 프롬프트에 들어가지 않으며, 모두 먼저 정제돼요.

  4. 생성

    AI_GENERATION_ADAPTER 심볼 토큰을 통해 AI 공급자가 호출되며, 이 공급자는 교체할 수 있습니다. 응답은 진행하기 전에 길이, 형식, 안전성을 검사합니다.

  5. 후처리

    네 가지 작업이 진행됩니다. 위기 분류기가 위기 관련 표현을 검사하고, 애스펙트 칩 추출기가 1~3개의 점성술 칩을 추출하며, 안티클레임 필터가 금지된 표현을 제거하고, 본문은 플랫폼이 관리하는 키로 AES-256 암호화됩니다.

  6. 저장

    산출물은 적절한 MongoDB 컬렉션(챕터, 저널 항목, 공명)에 기록되며, 빠른 조회를 위해 userId와 personId 인덱스가 적용됩니다. 먼저 소프트 삭제가 이루어지고, 개인정보(PII)의 하드 삭제는 30일 후에 진행됩니다.

  7. 알림

    데이터베이스 커밋 이후 EventEmitter2 이벤트(CHAPTER_COMPLETED, JOURNAL_CREATED)가 발생합니다. 알림 모듈이 이를 받아 받은편지함 항목을 생성하고, 선택적으로 푸시를 전송합니다(하루 한 번으로 제한되며, 방해 금지 시간을 준수합니다).

  8. 노출

    프런트엔드는 인증된 API 호출을 통해 산출물을 가져옵니다. 허브는 새로운 콘텐츠로 다시 렌더링됩니다. 사용자가 오프라인 상태였다면 캐시가 어제의 화면을 제공하고, 다시 연결되면 새 산출물이 나타납니다.

트리거에서 노출까지 일곱 단계로, 각 단계는 실제로 하는 일을 따서 이름이 붙어 있어요.

네 개의 컬렉션

각 컬렉션이 응답하는 쿼리에 맞게 인덱싱했어요.

soulwise_persons

앨범 항목. userId, status, deletedAt에 인덱스를 둡니다. 먼저 소프트 삭제하고, PII는 30일 후 하드 삭제해요.

soulwise_chapters

AI가 작성한 챕터, 본문은 암호화돼요. personId, userId, generatedAt에 인덱스를 둡니다. 빠른 필터링을 위해 어스펙트 칩은 별도의 배열로 저장해요.

soulwise_journal_entries

사용자가 작성한 성찰, 본문은 암호화돼요. userId, personId, createdAt에 인덱스를 둡니다. 검색을 위해 본문은 텍스트 인덱싱돼요. 항목마다 '비공개 — Luminara에 제공하지 않음' 플래그가 있어요.

soulwise_resonances

관계별 4차원 점수예요. personId에 고유 인덱스를 둡니다. 챕터나 저널이 기록된 후 서비스 호출을 통해 재계산해요.

EDA 이벤트

엄격한 규칙: 이벤트는 데이터베이스 커밋 이후에만 발생합니다. 모듈 간 의존성은 forwardRef가 아니라 Symbol 주입 토큰을 통해 처리합니다. 기능 모듈 사이에서 서비스 간 직접 임포트는 허용하지 않습니다.

  • SoulwiseEvents.CHAPTER_COMPLETED — SoulwiseEvents.CHAPTER_COMPLETED — 챕터가 암호화되어 저장된 후 발생합니다. Notifications-v2가 이를 수신해 받은 편지함 항목을 생성하고, 선택적으로 푸시를 전송합니다.
  • SoulwiseEvents.JOURNAL_CREATED — SoulwiseEvents.JOURNAL_CREATED — 저널 항목이 암호화되어 저장된 후 발생합니다. Resonance 서비스가 이를 수신해 재계산을 트리거합니다.
  • SoulwiseEvents.PERSON_BIRTH_UPDATED — SoulwiseEvents.PERSON_BIRTH_UPDATED — 사용자의 출생 데이터가 변경된 후 발생합니다. 상호 궁합 캐시가 무효화됩니다.
  • SoulwiseEvents.PUSH_REQUESTED — SoulwiseEvents.PUSH_REQUESTED — notifications-v2 계약에 따라 처리되며, 푸시 예산과 방해 금지 시간을 준수합니다.

V-모델 명세 엄격성

119개의 추적 가능한 요구사항, 누락은 전혀 없습니다. 각 요구사항은 테스트 케이스(UTP, ITP, STP, E2E)로 순방향 연결되고, 사용자 스토리로 역방향 연결됩니다. 사용자 스토리 20개. 기능 요구사항 15개. 비기능 카테고리 12개. 전역 수용 게이트 8개.

성능 계약

챕터 생성은 요청의 95%에서 30초 이내로, BullMQ 작업 소요 시간 분포를 기준으로 측정합니다. API p99 GET 지연 시간은 동시 사용자 1,000명에서 500ms 이내로, k6 부하 테스트로 측정합니다. 프런트엔드 TTI는 시뮬레이션된 4G 환경에서 3초 이내로, Lighthouse CI로 측정합니다.

보안 계약

저널과 챕터 본문은 플랫폼 관리 키를 사용해 AES-256로 저장 시 암호화합니다. 전송 중에는 TLS 1.2+를 적용하고, HTTP→HTTPS 리다이렉트를 사용합니다. JWT 액세스 토큰은 1시간, 리프레시 토큰은 30일의 수명을 가지며, 갱신 시 회전됩니다. 소프트 삭제 후 30일의 유예 기간을 두고 PII를 완전 삭제합니다.

접근성 계약

prefers-reduced-motion을 전역에서 준수해 GSAP 애니메이션은 투명도만 변하는 페이드로 처리됩니다. 모든 상호작용 요소에 VoiceOver와 TalkBack 레이블을 적용했습니다. 매 릴리스 전에 iOS와 Android에서 직접 검증합니다.

cosmic-story를 확장하지 않고 별도의 soulwise-story 모듈을 둔 이유는 무엇인가요?

상위 사양이 기능을 새로 구축하기 때문입니다. 기존 모듈 안에서 다시 만들면 v1 경험이 깨지거나, 분기한 뒤 나중에 병합해야 하는 상황이 됩니다. 새 모듈을 두면 v1은 그대로 유지하면서 v2를 검증하고, 준비되면 깔끔하게 이전할 수 있습니다.

Postgres가 아니라 MongoDB를 선택한 이유는 무엇인가요?

기존 My Zodiac AI 백엔드가 MongoDB 위에서 동작하고 있어, 전환은 이 기능과 무관한 인프라 결정이 되기 때문입니다. 또한 문서 모델은 챕터와 저널 항목에 잘 맞습니다. 중첩되고 길이가 제각각이며 블롭으로 암호화되는 데이터에 적합하지요.

큐로 BullMQ를 선택한 이유는 무엇인가요?

BullMQ는 Redis 위에서 동작하며, Redis는 세션과 속도 제한을 위해 이미 스택에 들어 있습니다. 새 인프라가 필요 없습니다. 내장된 재시도, 타임아웃, 관찰성 기능이 별도의 배관 작업 없이 챕터 생성에 필요한 부분을 모두 충족합니다.

상위 사양은 실제로 어디에 기록되어 있나요?

내부 저장소입니다. 이 페이지의 수치와 계약은 상위 V-Model 산출물을 풀어 정리한 것입니다. My Zodiac AI 블로그 클러스터에 게시된 공개 엔지니어링 블로그 글('cosmic-story-v2' 태그)에서 구축의 특정 부분을 더 깊이 다룹니다.

오늘 My Zodiac AI를 만나보세요

Soulwise가 물결을 열어가는 지금, 우리의 대표 점성술 앱은 이미 여러분의 손안에 있어요.

점성술 콘텐츠는 성찰과 즐거움을 위한 것입니다. 여기서 설명하는 Cosmic Story v2 기능은 개발 중이며, 제공 여부는 예고 없이 변경될 수 있습니다.