---
template: flow-doc@1
doc_id: 01-analysis-flow
title: site 진료·손해 분석 절차군
config: ../_meta/template-config.yaml
last_verified: 767d1e44
flows:
  - id: analysis-request
    actor: 일반회원
    status: conditional-enabled
    status_source: ./00-ia.md#site-analysis-analyze
    evidence: [S-route, S-component, S-test]
    limitations:
      - 절차의 단계 순서는 라우트 등록과 컴포넌트 정독에서 역산했다. 런타임 통과 기록은 대조하지 않았다
      - 구독 판정 함수가 참을 내는 실제 계정 분포는 DB 에만 있고 이 창에 없다
    refs:
      - ./00-ia.md#site-analysis
      - ./00-ia.md#site-analysis-customer
      - ./00-ia.md#site-analysis-analyze
      - ./00-ia.md#site-analysis-analyze-success
    anchors:
      - insuniverse-site/front/src/App.tsx:393
      - insuniverse-site/front/src/App.tsx:395
      - insuniverse-site/front/src/pages/analysis/analyze/AnalyzePage.tsx:19
      - insuniverse-site/front/src/features/analyze/ui/AnalyzeForm.tsx:122
      - insuniverse-site/front/src/features/subscribe/hooks/useCheckSubscription.ts:49
  - id: analysis-result-view
    actor: 일반회원
    status: conditional-unknown
    status_source: ../06-vendors/04-messaging.md#messaging:__bridge__:platform
    unknown_reason: 결과 열람의 마지막 단계인 PDF 저장이 웹뷰 브리지로 갈리는데, 브리지 존재 판정이 빌드 환경변수 `REACT_APP_BRIDGE_NAME` 과 실행 단말의 웹뷰 주입에 달려 있고 그 값이 이 저장소에 없다. 웹과 웹뷰 중 어느 경로가 배포에서 실제로 도는지 동결 트리만으로 판정할 수 없다
    evidence: [S-route, S-component, S-constant]
    limitations:
      - PDF 산출물의 내용 정합은 이 문서가 판정하지 않았다. 이 문서는 어느 경로로 저장되는가만 쓴다
      - 이탈 전수는 미검증. 이동 대상은 이 흐름에 귀속된 파일의 큰따옴표 리터럴 호출에서만 유도했다
    refs:
      - ./00-ia.md#site-analysis-list
      - ./00-ia.md#site-analysis
      - ../06-vendors/04-messaging.md#messaging:__bridge__:platform
    anchors:
      - insuniverse-site/front/src/App.tsx:400
      - insuniverse-site/front/src/pages/analysis/list/AnalysisListPage.tsx:1
      - insuniverse-site/front/src/pages/analysis/list/detail/DownloadPdf.tsx:299
      - insuniverse-site/front/src/features/analysisListView/hooks/useAnalysisCard.ts:69
  - id: analysis-loss-invite
    actor: 일반회원
    status: conditional-enabled
    status_source: ./00-ia.md#site-analysis-loss
    evidence: [S-route, S-component]
    limitations:
      - 초대받은 사람이 걷는 두 화면은 로그인 주체가 아니다. 이 흐름의 actor 는 초대를 보내는 쪽이며 그 사실을 전제에 적었다
      - 동의 화면과 인증 화면 사이의 서버 상태 전이는 site 코드만으로 판정할 수 없다
    refs:
      - ./00-ia.md#site-analysis-loss
      - ./00-ia.md#site-analysis-loss-list
      - ./00-ia.md#site-loss-analysis-param
      - ./00-ia.md#site-loss-analysis-auth-param
    anchors:
      - insuniverse-site/front/src/App.tsx:295
      - insuniverse-site/front/src/App.tsx:397
      - insuniverse-site/front/src/pages/analysis/loss/LossAnalysisInvitePage.tsx:1
      - insuniverse-site/front/src/pages/analysis/loss/LossAnalysisFlowPage.tsx:1
  - id: analysis-admin-view
    actor: 관리자
    status: active-prod
    status_source: ./00-ia.md#site-admin-view-member-param
    evidence: [S-route, S-component]
    limitations:
      - 이 여섯 화면은 admin 콘솔이 iframe 으로 여는 표면이다. 그 iframe 을 여는 쪽의 절차는 `docs/30-admin/` 소유이며 이 문서는 site 쪽 표면만 쓴다
      - 이탈 판정 근거 없음 — 레이아웃이 네비게이션을 렌더하지 않고 상세 화면의 되돌리기는 히스토리 기반이라 대상 라우트를 지정하지 않는다
    refs:
      - ./00-ia.md#site-admin-view-member-param
      - ./00-ia.md#site-admin-view-b2c-param
      - ./00-ia.md#site-admin-view-client-param
      - ./00-ia.md#site-admin-view-member-sub-param
      - ./00-ia.md#site-admin-view-b2c-sub-param
      - ./00-ia.md#site-admin-view-client-sub-param
    anchors:
      - insuniverse-site/front/src/App.tsx:336
      - insuniverse-site/front/src/App.tsx:340
      - insuniverse-site/front/src/layouts/AdminViewLayout.tsx:21
---

# site 진료·손해 분석 절차군

이 문서는 `insuniverse-site` 에서 **분석을 요청하고 그 결과를 여는** 절차군을 담는다. 화면 구조의 정본은 [화면 인벤토리](./00-ia.md)이고, 권한 규칙·오류코드·한도의 정본은 [총론](../02-access/02-authz-roles.md)이다. 여기서는 순서만 쓴다.

네 흐름이 서로 다른 것을 보여준다. `analysis-request` 는 구독 게이트 뒤에서 요청이 만들어지는 구간, `analysis-result-view` 는 만들어진 결과를 여는 구간과 그 마지막 단계가 웹과 앱 웹뷰로 갈리는 지점, `analysis-loss-invite` 는 요청 주체가 자기가 아니라 초대받은 사람인 구간, `analysis-admin-view` 는 같은 결과를 admin 콘솔이 iframe 으로 여는 site 쪽 표면이다.

**알림톡 링크로 걷는 본인인증과 대기열은 이 문서에 없다.** 그쪽은 [알림톡 본인인증 절차군](./02-alimtalk-certify.md)이고, 구독 구매·변경은 [구독·결제 절차군](./03-subscription-payment.md)이다.

**분석 요청과 교육 화면은 구독 게이트 아래 등록된다.** `App.tsx` 의 라우트 트리가 구독 판정 결과를 조건으로 그 블록 전체를 렌더하며, 구독이 없는 계정에는 라우트 자체가 등록되지 않는다. 그래서 이 문서의 두 흐름 status 가 `conditional-enabled` 다 — 화면이 죽은 것이 아니라 게이트 뒤에 있다는 뜻이다.

## 흐름 목록

| flow id | 목적 | actor | status |
|---|---|---|---|
| analysis-request | 구독 상태에서 진료분석을 요청해 접수 확인까지 받는다 | 일반회원 | conditional-enabled |
| analysis-result-view | 접수된 분석의 결과를 목록에서 열고 필요하면 PDF 로 저장한다 | 일반회원 | conditional-unknown |
| analysis-loss-invite | 손해분석을 다른 사람에게 요청하고 그 진행을 목록에서 본다 | 일반회원 | conditional-enabled |
| analysis-admin-view | admin 콘솔이 iframe 으로 여는 분석 결과 표면을 제공한다 | 관리자 | active-prod |

## 흐름

### analysis-request

**전제**

- 로그인 세션이 있다. 세션 수립 규칙의 정본은 [인증 총론](../02-access/01-authn.md)이다
- 구독 판정이 참이다. 참이 아니면 `/analysis` 이하 라우트가 등록되지 않는다
- 심평원·국세청 기관 API 가 일시 사용중지 상태가 아니다

**절차**

1. 회원이 `site-analysis` 에서 분석 진입점을 연다.
2. 대상자를 고를 필요가 있으면 `site-analysis-customer` 에서 고른다.
3. `site-analysis-analyze` 로 이동한다. 진입 시점에 기관 사용중지 목록을 조회해 해당하면 안내 팝업을 띄우고 되돌린다 (`AnalyzePage.tsx:19`).
4. 회원이 요청 정보를 제출한다. 구독권이 모자라면 화면이 구독권 변경 경로를 버튼으로 제안한다 (`AnalyzeForm.tsx:122`).
5. 접수되면 `site-analysis-analyze-success` 가 접수 확인을 보여준다.

**분석 요청은 즉시 결과가 아니다.** 4단계의 접수와 결과 열람은 다른 흐름이며 그 사이 상태는 서버가 진다. 이 문서는 그 사이의 서버 상태를 판정하지 않는다.

**권한**

| 층 | 차단성 | 이 흐름에서의 강제 지점 | 실패 시 |
|---|---|---|---|
| 인증 | 차단 | 라우트 트리의 세션 가드가 세션 없는 진입을 로그인 화면으로 보낸다 (`useAuthGuard.tsx:52`) | 로그인 화면으로 이동 |
| 계정 종류 | 차단 | 해당 없음 — site 라우트는 `@Roles` 메타데이터를 갖지 않는다. 계정 종류 판정은 서버 API 층의 축이며 정본은 [역할 총론](../02-access/02-authz-roles.md)이다 | 해당 없음 |
| 쓰기 스코프 | 차단 | 해당 없음 — 조직관리자 읽기전용 가드는 admin 콘솔 요청에만 발화한다 | 해당 없음 |
| 기업 노출 등급 | 차단 | 해당 없음 — 기업 노출 등급 가드는 admin 콘솔의 기업 분석 조회에만 걸린다 | 해당 없음 |
| 메뉴 노출 | 비차단 | 구독 판정이 거짓이면 라우트가 아예 등록되지 않는다. 이것은 메뉴에서 감추는 것보다 강하다 | 등록되지 않은 경로라 진입 자체가 성립하지 않는다 |

**실패·이탈**

| 지점 | 조건 | 결과 |
|---|---|---|
| 1단계 진입 | 구독 판정이 거짓이고 단말이 웹이며 일반 회원이다 | 계속 안내 팝업을 띄우고 `/products` 로 보낸다 (`useCheckSubscription.ts:49`) |
| 1단계 진입 | 구독 판정이 거짓이고 단말이 앱 웹뷰다 | 계속 안내 팝업을 띄우고 `/main` 으로 보낸다 (`useCheckSubscription.ts:36`) |
| 3단계 진입 | 기관 API 가 일시 사용중지다 | 막다름. 안내 팝업을 닫으면 직전 화면으로 되돌린다 |
| 4단계 제출 | 보유 구독권으로 요청할 수 없다 | 계속 `/mypage/subscription/change` 로 가는 버튼을 제안한다 |
| 4단계 제출 | 세션이 만료됐다 | HTTP 401. 세션 만료 처리가 로그아웃으로 이어진다 |

### analysis-result-view

**전제**

- 로그인 세션이 있고 구독 판정이 참이다
- 결과를 볼 분석이 접수돼 있다. 접수는 `analysis-request` 또는 알림톡 본인인증 절차군이 만든다
- PDF 저장을 하려면 단말이 웹 브라우저이거나 브리지가 주입된 앱 웹뷰다

**절차**

1. 회원이 `site-analysis-list` 에서 자기 분석 목록을 연다.
2. 목록의 카드를 고르면 상세 경로로 이동한다 (`useAnalysisCard.ts:69`). 상세 라우트는 `site-analysis` 아래에 접혀 있다.
3. 상세에서 항목별 리포트를 연다.
4. PDF 저장을 누르면 단말에 따라 경로가 갈린다 — 웹은 브라우저 저장, 앱 웹뷰는 브리지 호출이다 (`DownloadPdf.tsx:299`).

**이 흐름의 status 가 `conditional-unknown` 인 이유는 4단계다.** 브리지 존재 판정은 빌드 환경변수와 실행 단말의 웹뷰 주입 둘 다에 달려 있고 이 저장소에 그 값이 없다. 정본은 [메시징·브리지 벤더 정책](../06-vendors/04-messaging.md)이며 이 문서는 그 판정을 복제하지 않는다.

**권한**

| 층 | 차단성 | 이 흐름에서의 강제 지점 | 실패 시 |
|---|---|---|---|
| 인증 | 차단 | 라우트 트리의 세션 가드 (`useAuthGuard.tsx:52`) | 로그인 화면으로 이동 |
| 계정 종류 | 차단 | 해당 없음 — 목록 조회는 자기 소유 자원이라 역할 분기가 없다 | 해당 없음 |
| 쓰기 스코프 | 차단 | 해당 없음 — 이 흐름은 읽기뿐이다 | 해당 없음 |
| 기업 노출 등급 | 차단 | 해당 없음 — 기업 노출 등급은 admin 콘솔 축이다 | 해당 없음 |
| 메뉴 노출 | 비차단 | 구독 판정이 거짓이면 라우트가 등록되지 않는다 | 진입 자체가 성립하지 않는다 |

**실패·이탈**

| 지점 | 조건 | 결과 |
|---|---|---|
| 1단계 진입 | 구독 판정이 거짓이다 | 계속 구독 안내 팝업으로 갈린다. 갈림은 `analysis-request` 의 이탈 표와 같다 |
| 2단계 이동 | 상세 대상이 없거나 권한 밖이다 | HTTP 403. 목록 화면에 머문다 |
| 4단계 저장 | 앱 웹뷰인데 브리지가 응답하지 않는다 | fail-open 브리지 호출만 하고 화면은 그대로 둔다. 저장 성공 여부를 site 가 확인하지 않는다 |
| 4단계 저장 | 웹 브라우저이고 팝업 차단이 걸렸다 | 막다름. 이 경우의 안내는 이 창에서 관측되지 않았다 |

### analysis-loss-invite

**전제**

- 로그인 세션이 있고 구독 판정이 참이다
- 초대를 보낼 상대의 연락 수단을 알고 있다
- **초대받아 걷는 두 화면의 보행자는 로그인 주체가 아니다.** 링크의 코드만 갖고 지나며, 그 사실이 `config.actors` 축에 값이 없는 자리다 (`docs/_meta/term-requests/50-domain.md` 로 회부했다)

**절차**

1. 회원이 `site-analysis-loss` 에서 손해분석 초대를 만든다.
2. 초대받은 사람이 링크로 `site-loss-analysis-param` 에 들어와 동의한다.
3. 동의하면 `site-loss-analysis-auth-param` 에서 본인인증을 지난다.
4. 초대를 보낸 회원이 `site-analysis-loss-list` 에서 진행 상태를 본다.

**2·3단계는 세션 가드의 비회원 허용 경로다.** 로그인하지 않은 사람이 지나야 하므로 라우트가 세션 가드 밖에 등록돼 있다.

**권한**

| 층 | 차단성 | 이 흐름에서의 강제 지점 | 실패 시 |
|---|---|---|---|
| 인증 | 차단 | 1·4단계에만 걸린다. 2·3단계는 세션 가드 밖 경로다 | 1·4단계는 로그인 화면으로 이동 |
| 계정 종류 | 차단 | 해당 없음 — site 라우트에 역할 메타데이터가 없다 | 해당 없음 |
| 쓰기 스코프 | 차단 | 해당 없음 — 조직관리자 축은 admin 콘솔 요청에만 발화한다 | 해당 없음 |
| 기업 노출 등급 | 차단 | 해당 없음 — admin 콘솔 축이다 | 해당 없음 |
| 메뉴 노출 | 비차단 | 1·4단계는 구독 게이트 아래 등록된다 | 진입 자체가 성립하지 않는다 |

**실패·이탈**

| 지점 | 조건 | 결과 |
|---|---|---|
| 2단계 진입 | 링크의 코드가 만료됐거나 없다 | 막다름. 이 경로의 만료 안내 화면은 이 창에서 관측되지 않았다 |
| 3단계 인증 | 본인인증이 실패한다 | 막다름. 인증 화면에 머문다 |
| 4단계 조회 | 아직 아무도 동의하지 않았다 | 계속 빈 목록을 보여준다 |

### analysis-admin-view

**전제**

- admin 콘솔이 이 경로를 iframe 으로 연다. 여는 쪽 절차는 `docs/30-admin/` 소유다
- 경로 파라미터로 조회 대상 식별자를 받는다

**절차**

1. admin 콘솔이 `site-admin-view-member-param` · `site-admin-view-b2c-param` · `site-admin-view-client-param` 중 하나를 iframe 으로 연다.
2. 전용 레이아웃이 네비게이션 없이 본문만 렌더한다 (`AdminViewLayout.tsx:21`).
3. 상세 항목을 열면 `site-admin-view-member-sub-param` · `site-admin-view-b2c-sub-param` · `site-admin-view-client-sub-param` 중 대응하는 화면으로 간다.

**권한**

| 층 | 차단성 | 이 흐름에서의 강제 지점 | 실패 시 |
|---|---|---|---|
| 인증 | 차단 | 이 여섯 라우트는 site 세션 가드 밖이다. 인증은 iframe 을 여는 admin 쪽이 진다 | site 쪽에서는 막지 않는다 |
| 계정 종류 | 차단 | 해당 없음 — site 라우트에 역할 메타데이터가 없다. 판정은 admin 쪽 API 가 진다 | 해당 없음 |
| 쓰기 스코프 | 차단 | 해당 없음 — 이 표면은 읽기뿐이다 | 해당 없음 |
| 기업 노출 등급 | 차단 | 해당 없음 — site 표면에는 가드가 없다. 정본은 [권한 등급 총론](../02-access/03-authz-capabilities.md)이며 발화는 admin API 층이다 | 해당 없음 |
| 메뉴 노출 | 비차단 | 해당 없음 — 네비게이션을 렌더하지 않는 레이아웃이라 메뉴 축이 성립하지 않는다 | 해당 없음 |

**실패·이탈**

| 지점 | 조건 | 결과 |
|---|---|---|
| 1단계 진입 | 파라미터가 가리키는 대상이 없다 | 막다름. 레이아웃이 네비게이션을 렌더하지 않아 화면에서 나갈 경로가 없다 |
| 3단계 이동 | 상세 대상이 없다 | 막다름. 되돌리기는 히스토리 기반이라 대상 라우트를 지정하지 않는다 |

## 플랫폼 차이 (웹 / 웹뷰)

`analysis-result-view` 4단계만 갈린다. 웹 브라우저는 브라우저의 저장 경로를 쓰고, 앱 웹뷰는 브리지 함수를 호출해 앱이 저장한다 (`DownloadPdf.tsx:299`). 브리지 존재 판정은 사용자 에이전트와 빌드 환경변수 이름으로 하며, iOS 는 메시지 핸들러 유무를, Android 는 전역 객체 유무를 본다 (`common.helper.ts:1326`).

`analysis-request` 의 구독 미충족 이탈도 단말에 따라 갈린다 — 웹은 구매 화면으로, 앱 웹뷰는 메인으로 보낸다 (`useCheckSubscription.ts:36`·`:49`). 앱에서 구매 화면으로 보내지 않는 이유는 이 창에서 코드 주석으로 확인되지 않았다.

## 연혁

| 릴리스 | 날짜 | SHA | 변경 요약 |
|---|---|---|---|
| — | 2026-08-27 | 767d1e44 | 최초 저작. 동결 HEAD 의 라우트 트리와 컴포넌트 정독에서 네 흐름을 유도했다 |
