soulwise_persons
앨범 항목이에요. userId, status, deletedAt에 인덱스가 있어요. 먼저 소프트 삭제하고, 개인식별정보(PII)는 30일 후에 완전 삭제해요.
엔지니어, PM, 기자, 파트너십 스카우트를 위한 내용이에요. 전체 파이프라인, 네 개의 MongoDB 컬렉션, EDA 이벤트, V-Model의 엄밀함, 성능 목표, 보안, 접근성까지 한 페이지에 담았어요.
각 단계에는 서비스, 계약, 이벤트가 있어요.
사용자 동작 — '언니를 위한 오늘의 챕터 생성하기' — 또는 일요일 9시 요약처럼 예약된 크론, 혹은 6시간마다 갱신되는 날씨 같은 것이에요.
작업은 soulwise-chapter-generation이라는 BullMQ 큐에 도착하며, 28초의 엄격한 제한 시간이 적용돼요. 오래 걸리는 작업은 종료되고 사용자에게 '다시 시도하세요'로 보고돼요.
ChapterGenerationService가 네 가지 요소로 이루어진 프롬프트 — 인물 맥락, 점성술, 신호, 주기 — 를 하나의 입력으로 모아요. 원본 사용자 개인정보(PII)는 그대로 프롬프트에 들어가지 않으며, 모든 것이 먼저 정제돼요.
AI_GENERATION_ADAPTER 심볼 토큰을 통해 AI 제공자를 호출하며, 제공자는 교체할 수 있습니다. 응답은 진행 전에 길이, 형식, 안전성을 검사합니다.
네 가지가 진행됩니다. 위기 분류기가 위기 관련 표현을 확인하고, 어스펙트 칩 추출기가 1~3개의 점성술 칩을 뽑아내며, 안티클레임 필터가 금지된 표현을 제거하고, 본문은 플랫폼이 관리하는 키로 AES-256 암호화됩니다.
해당 아티팩트는 알맞은 MongoDB 컬렉션(챕터, 저널 항목, 공명)에 저장되며, 빠른 조회를 위해 userId와 personId 인덱스가 적용됩니다. 먼저 소프트 삭제를 하고, 개인정보(PII)는 30일 후에 완전 삭제됩니다.
데이터베이스 커밋 이후 EventEmitter2 이벤트(CHAPTER_COMPLETED, JOURNAL_CREATED)가 발생합니다. 알림 모듈이 이를 받아 받은편지함 항목을 만들고, 선택적으로 푸시를 전송합니다(하루 1회로 제한되며, 방해 금지 시간은 존중됩니다).
프런트엔드는 인증된 API 호출을 통해 아티팩트를 가져옵니다. 허브는 새로운 콘텐츠로 다시 렌더링됩니다. 사용자가 오프라인 상태였다면 캐시가 어제의 화면을 보여주고, 다시 연결되면 새 아티팩트가 나타납니다.
각 컬렉션이 처리하는 쿼리에 맞게 인덱싱되어 있어요.
앨범 항목이에요. userId, status, deletedAt에 인덱스가 있어요. 먼저 소프트 삭제하고, 개인식별정보(PII)는 30일 후에 완전 삭제해요.
AI가 작성한 챕터로, 본문은 암호화되어 있어요. personId, userId, generatedAt에 인덱스가 있어요. 빠른 필터링을 위해 어스펙트 칩은 별도의 배열로 저장돼요.
사용자가 작성한 성찰 기록으로, 본문은 암호화되어 있어요. userId, personId, createdAt에 인덱스가 있어요. 검색을 위해 본문은 텍스트 인덱싱되어 있어요. 항목마다 '비공개 — Luminara에 제공하지 않음' 플래그가 있어요.
유대마다 4차원 점수를 매겨요. personId에 고유 인덱스가 있어요. 챕터나 저널이 작성된 후 서비스 호출을 통해 다시 계산돼요.
엄격한 규칙: 이벤트는 데이터베이스 커밋 이후에만 발생합니다. 모듈 간 의존성은 Symbol 주입 토큰을 통해 처리하며, forwardRef는 사용하지 않습니다. 기능 모듈 사이의 서비스 간 직접 임포트는 허용하지 않습니다.
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 계약에 따라 동작하며, 푸시 예산과 방해 금지 시간을 준수합니다.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일이며, 리프레시 시 로테이션이 이루어집니다. PII는 하드 삭제 전 30일의 기간을 둔 소프트 삭제를 적용합니다.
prefers-reduced-motion 설정을 전역으로 존중합니다 — GSAP 애니메이션은 투명도만 변하는 페이드로 전환됩니다. 모든 상호작용 요소에 VoiceOver 및 TalkBack 레이블이 적용되어 있습니다. 매 릴리스 전에 iOS와 Android에서 수동으로 검증합니다.
상위 명세가 기능을 새로 구축하기 때문이며, 기존 모듈 안에서 다시 구축하면 v1 경험을 깨뜨리거나, 분기한 뒤 나중에 병합해야 합니다. 새 모듈은 v1을 그대로 유지하고, v2를 검증할 수 있게 하며, 준비가 되면 깔끔하게 마이그레이션됩니다.
기존 My Zodiac AI 백엔드가 MongoDB 위에서 동작합니다. 전환한다면 이 기능과 무관한 인프라 결정을 내려야 합니다. 또한 문서 모델은 챕터와 저널 항목에 잘 맞습니다 — 중첩되고, 길이가 다양하며, 블롭으로 암호화되는 구조이죠.
BullMQ는 Redis 위에서 동작하며, Redis는 세션과 속도 제한을 위해 이미 스택에 포함되어 있습니다. 새 인프라가 필요 없습니다. 내장된 재시도, 타임아웃, 관찰성 기능이 별도의 구성 없이 챕터 생성에 필요한 요구사항을 충족합니다.
내부 저장소에 있습니다. 이 페이지의 수치와 계약 내용은 상위 V-Model 산출물을 풀어 설명한 것입니다. My Zodiac AI 블로그 클러스터에 공개된 엔지니어링 블로그 글('cosmic-story-v2' 태그)에서 구축의 특정 부분을 더 깊이 다룹니다.
Soulwise가 새로운 흐름을 열어가는 지금, 대표 점성술 앱은 이미 여러분 곁에 있어요.
점성술 콘텐츠는 성찰과 즐거움을 위한 것입니다. 여기서 설명하는 Cosmic Story v2 기능은 개발 중이며, 제공 여부는 사전 안내 없이 변경될 수 있습니다.