PetAI WBS 4.0 백엔드·데이터·보안
목표: 로컬 핵심 플레이를 침범하지 않고, 업데이트·날씨·알림·백업·제한된 친구 기능·구매 복원·분석에 필요한 최소 서버만 제공한다.
주 책임: Backend
협업: Unity, Product, Privacy, DevOps, QA
핵심 원칙: optional backend, data minimization, explicit consent
1. 서버 도입 원칙
- Boot→Home→Template Dialogue→Shared Play→Result→Memory→Save→Restart는 네트워크 없이 동작한다.
- 서버 장애는 핵심 플레이를 차단하지 않는다.
- 대화 원문과 장기 기억은 서버에 저장하지 않는다.
- 동의 없는 정확한 GPS, Health 원시값, 연락처와 광고 식별자는 payload에서 제외한다.
- 날씨 조회는 사용자가 명시적으로 동의한 경우에만 현재 정밀 GPS를 받을 수 있으며, 날씨 응답을 만든 뒤 정밀 좌표를 저장·분석·공유하지 않는다.
- 서버는 로컬 관계 수치와 보상의 권위를 가지지 않는다.
- 친구 기능 장애는 친구 목록·방 방문·스티커만 막고, 홈·관계·공동 플레이·추억은 계속 동작한다.
- 친구 관계는 수락형이며, 연락처 전체 수집·자동 친구 추가·공개 검색을 하지 않는다.
- 각 API는 timeout, cache, stale, signature, rollback, opt-out을 정의한다.
2. 작업분해구조
| WBS | 작업 | 상태 | 선행 | 산출물 | 수용 기준 |
|---|---|---|---|---|---|
| 4.1.1 | API 공통 규약 | READY | 기능 범위 | version/error/retry/idempotency | OpenAPI lint |
| 4.1.2 | Auth 경계 | OPEN | 백업 정책 | install/account option ADR | anonymous path 분리 |
| 4.1.3 | SNS identity 연결 | OPEN | provider·탈퇴 정책 | provider subject→opaque UID, token 폐기 규칙 | raw provider token 저장 0건 |
| 4.1.4 | Friend graph | OPEN | auth | request/accept/remove/block state machine | 수락 전 room 접근 0건 |
| 4.1.5 | Room snapshot delivery | OPEN | room public schema | allowlisted snapshot/version/cache | 대화·기억·정밀 위치 포함 0건 |
| 4.1.6 | Sticker reaction | OPEN | friend graph | approved sticker/revoke/visibility | free text·image·URL payload reject |
| 4.1.7 | Social safety | OPEN | policy | report/block/audit retention | 차단 뒤 조회·반응 0건 |
| 4.1.8 | Tutorial/profile sync | OPEN | account policy | current step/completed/character ID/user nickname/character nickname/first meeting/starter grant migration | 기기 이전 뒤 도입 반복·중복 시작 지급 0건 |
| 4.2.1 | Content manifest | CONDITIONAL | local bundle | version/hash/signature/minApp | 변조 차단 |
| 4.2.2 | Bundle delivery | CONDITIONAL | manifest | CDN/object URL/rollback | 이전 bundle 유지 |
| 4.3.1 | GPS weather proxy | READY | consent UX·provider 결정 | current coordinate→weather grid, consent receipt, cache/source, coordinate discard | provider 장애·권한 거절 시 수동 도시 fallback |
| 4.4.1 | Push registration | CONDITIONAL | consent UX | opaque token/topic | opt-out 즉시 반영 |
| 4.4.2 | Notification schedule | CONDITIONAL | event catalog | type/window/quiet hours | 게임 없이 압박 금지 |
| 4.5.1 | Progress backup | CONDITIONAL | account·crypto | allowlist payload/version | local authority 유지 |
| 4.5.2 | Restore | CONDITIONAL | backup | inspect/preview/confirm | silent overwrite 0건 |
| 4.5.3 | Purchase entitlement | OPEN | BM policy | product/transaction/restore idempotency | 중복 지급·관계·능력치 판매 0건 |
| 4.6.1 | Analytics ingest | CONDITIONAL | consent policy | event allowlist | forbidden field reject |
| 4.6.2 | Retention/delete | CONDITIONAL | legal/product | TTL/delete job/export | deletion audit |
| 4.7.1 | Rate/abuse limits | P2 | endpoint spec | per-endpoint limits | 핵심 local play 무관 |
| 4.8.1 | Monitoring | P2 | deployment | SLO/error budget | 원문 없는 alert |
3. 전송 허용·금지
| 데이터 | 기본 | 조건 |
|---|---|---|
| app/content/schema version | 허용 | 운영에 필요한 범위 |
| coarse device/OS version | 조건부 | 분석 동의, 소수 bucket |
| event ID와 result bucket | 조건부 | 원문·정확 시각 제외 가능 |
| city-level weather key | 조건부 | 위치 권한 없이 수동 도시 fallback |
| current precise coordinate | 조건부 | GPS 날씨 동의가 있는 요청에서만 수신, weather grid 변환 뒤 로그·DB·분석 payload에서 제거 |
| weather consent version·timestamp | 조건부 | 동의·철회 감사와 서버 수락 판단에 필요한 최소값 |
| signed content request | 허용 | 개인정보 없음 |
| 관계 stage bucket | 조건부 | 백업 또는 동의 분석만 |
| opaque UID와 수락된 friend edge | 조건부 | 친구 기능 동의·탈퇴·차단 처리 목적만 |
| 공개한 room snapshot | 조건부 | 가구·복장·승인된 캐릭터 상태만 allowlist |
| 승인 sticker ID와 반응 시각 bucket | 조건부 | 친구 반응 표시·차단·신고 처리 목적만 |
| SNS provider subject | 조건부 | opaque UID 연결 후 최소 보존, 원본 access token 저장 금지 |
| tutorial step, character ID, 사용자·캐릭터 호칭, 첫 만남 시간, starter grant 상태 | 조건부 | 로그인 계정의 기기 이전·도입 반복·중복 시작 지급 방지 목적만 |
| product ID와 정규화 transaction ID | 조건부 | 구매 복원·환불·중복 지급 방지 목적만 |
| 대화 원문 | 금지 | 예외 없음 |
| 장기 기억 원문·embedding | 금지 | 예외 없음 |
| 정밀 GPS·주소의 영구 저장, 이동 이력, 분석 전송 | 금지 | 날씨 1회 조회 뒤 즉시 폐기 |
| Health 원시값 | 금지 | MVP 제외 |
| 사용자 입력 자유문장 | 금지 | 분석·로그에서 제외 |
| 주소록·SNS 친구 목록 전체 | 금지 | 직접 UID·초대 링크·명시 수락만 허용 |
| 결제 수단 번호와 원본 영수증 전문 | 금지 | 플랫폼 결제·검증 서비스에 위임 |
| 로컬 파일 경로·stack trace 전체 | 금지 | 정규화 error code만 |
4. 친구 기능 서버 경계
친구 기능은 소셜 네트워크가 아니라, 서로 아는 사람이 캐릭터와 방을 제한적으로 공유하는 기능이다.
- 친구 추가: SNS 연결, 초대 링크, UID 중 하나로 요청을 만들고 상대가 수락해야 한다.
- 방 방문: 서버는 공개 허용한 room snapshot만 전달한다. 대화, 장기 기억, 관계 수치, 위치, 일정은 snapshot에 넣지 않는다.
- 캐릭터 교류: 클라이언트가 승인된 interaction ID를 요청하고, 각 캐릭터의 공개 상태를 기준으로 미리 만든 연출을 재생한다. 서버가 AI 대화를 만들지 않는다.
- 반응: 승인된 sticker ID만 저장한다. 자유 텍스트, 이미지, 링크, 파일 첨부는 API 수준에서 거절한다.
- 안전: remove, block, report가 같은 우선순위로 제공된다. block 뒤에는 profile, snapshot, sticker, 초대 링크의 접근 권한을 즉시 철회한다.
- 오프라인: 친구 기능은 unavailable 상태를 명확히 보여 주되, 로컬 게임 상태를 바꾸거나 저장을 실패시키지 않는다.
공개 방 상태의 기본값은 비공개다. 사용자는 친구별 또는 전체 친구에게 공개할 수 있으며, 공개를 끄면 CDN cache와 서버 원본의 철회 시점도 기록한다.
4. Content manifest contract
{
"bundleId": "petai-content",
"version": 12,
"schemaVersion": 3,
"minAppVersion": "0.1.0",
"sha256": "hex",
"signature": "base64",
"downloadUrl": "https://...",
"publishedAt": "ISO-8601"
}
클라이언트는 signature와 hash를 검증한 뒤 새 bundle을 staging에 풀고 runtime validator를 통과시킨다. 실패하면 현재 활성 bundle을 유지한다. 서버 응답이 없으면 설치 번들을 사용한다.
5. 날씨 실패 계약
| 상황 | 반환 | 클라이언트 처리 |
|---|---|---|
| fresh cache | cached state | source와 age 기록 |
| provider timeout | stale cache | stale 허용 범위 표시 없이 자연스럽게 사용 |
| cache 없음 | unknown | 중립 환경·대사 |
| 위치 권한 거절·동의 철회 | no-location | 수동 도시 또는 unknown fallback |
| invalid city 또는 coordinate | 400 normalized error | 수동 도시 재선택 |
| rate limit | retry-after | 즉시 반복 금지 |
날씨 정확도를 게임 진행 조건으로 사용하지 않는다. 날씨 보상, 연속 기록, 관계 패널티를 만들지 않는다. GPS 날씨 조회는 foreground 또는 사용자가 허용한 제한적 background refresh에만 수행하며, 위치 이동 감시를 시작하지 않는다.
6. 백업 원칙
- opt-in 이전 업로드 0건
- allowlist field만 직렬화
- 업로드 전 local schema와 backup payload schema를 분리
- restore 전에 diff summary 제공
- primary local save를 즉시 덮어쓰지 않고 import candidate로 검사
- cloud가 최신이라는 이유만으로 자동 선택하지 않음
- 대화 원문·로컬 memory body 제외
- 계정 삭제 시 server copy 삭제와 local 유지 여부를 별도 선택
7. 분석 이벤트 최소안
| 이벤트 | 필수 field | 금지 field |
|---|---|---|
| session_started | app_version, day_bucket | exact last seen |
| home_interaction | target_type, result | coordinates, free text |
| shared_play_completed | content_id, outcome, duration_bucket | raw input timeline |
| memory_opened | source_type, age_bucket | memory body |
| real_action_offered | action_id, accepted | user reason text |
| event_completed | event_id, choice_id | dialogue line |
| error_observed | error_code, feature | stack trace, file path |
8. 장애와 SLO
- manifest API P95 목표 500ms, timeout 2s
- weather proxy P95 목표 1s, timeout 2s
- analytics는 fire-and-forget queue, gameplay blocking 0ms
- backup은 사용자 명시 action에서만 진행 상태 표시
- 모든 retry는 exponential backoff와 jitter
- signature·schema 오류는 retry보다 rollback 우선
- backend 24시간 장애 중에도 Day 0~7 local content 완주
9. 완료 증거
- OpenAPI와 schema validation
- allowlist/denylist payload 자동 테스트
- signature/hash tamper fixture
- timeout·5xx·429·offline·stale cache 통합 테스트
- consent off 상태 network capture 0건
- delete/export/restore 사용자 여정
- log sample의 원문·정확 위치·절대 경로 0건
- backend 미실행 상태 Unity 핵심 플레이 회귀
10. 연결 문서
11. 2026-07-23 서버 범위 보완
| WBS | 서버 책임 | 허용 데이터 | 금지 데이터 | 완료 증거 |
|---|---|---|---|---|
| 4.9 | OAuth 계정 연결 | provider subject, account UID, consent | OAuth access token 장기 보관, 대화 원문 | provider별 unlink/delete/re-auth 테스트 |
| 4.10 | 푸시 발송 | push token, category opt-in, quiet hours, deep link id | 자유 대화 본문, 정밀 위치 | category off 시 network/dispatch 0건 |
| 4.11 | 날씨 프록시 | 조회 순간의 최소 위치 또는 수동 도시, weather response | 좌표 이력, 이동 경로, 친구 공유 | 권한 off/timeout 시 client fallback 계약 |
| 4.12 | 친구·방 snapshot | UID, 요청/수락/차단, 공개 방 snapshot | DM, 이미지, 자유 텍스트, private room data | 수락 전·차단 후 접근 거부 테스트 |
| 4.13 | 결제 검증·복원 | store transaction id, product id, entitlement | 대화/건강/위치와 결합한 프로파일 | restore/refund/duplicate transaction fixture |
| 4.14 | 선택 백업 | 비민감 성장·소유·방·튜토리얼 요약 | memory body, health raw, exact location | export/delete/restore와 conflict 선택 여정 |
11.1 데이터 보존 원칙
- 푸시 목적의 “미접속”은 재방문 정책에 필요한 coarse last-active bucket만 사용하며, 장기 행동 이력을 마케팅 프로필로 만들지 않는다.
- 스트레스 회복 푸시는 기본값 또는 opt-in 여부를 제품에서 결정한 뒤에만 발송한다. 건강 데이터는 회복 판정의 서버 입력이 아니다.
- 이벤트·상품·한정 정책의 기준 데이터는 versioned content manifest로 제공하고, 클라이언트는 오프라인 cache와 schema rollback을 가져야 한다.
자세한 데이터 구분과 사용자 흐름은 최종 기능 정의서를 따른다.