# P2P 입금 UX 확정 설계 — 오입금 방지

**작성**: 2026-08-22 · **상태**: 오너 검토 완료, 화면 설계 확정 · **범위**: `widget-ui` 구매자 위젯
**동반 문서**: `P2P_DEPOSIT_FLOW_MAP.md`(전체 플로우 설명서)
**선행 문서**: `P2P_MANUAL_CONFIRM_DISPUTE_RULES.md`, `P2P_MATCHING_ARCHITECTURE.md`

> **이 재설계의 목적은 하나다 — 오입금을 막는 것.**
> 화면을 예쁘게 만드는 작업이 아니라, **사용자가 잘못된 금액을 잘못된 계좌로 보내는 경로를
> 화면에서 제거하는** 작업이다. 모든 결정은 이 기준으로 판정한다.

---

## 1. 무엇을 막으려 하는가 — 실측된 오입금 패턴 2종

오너 보고 기준. 두 패턴 모두 **분할 매칭**에서 난다.

### 패턴 1. 전액을 첫 계좌로 (가장 잦다)

10만원 주문이 5만/5만 두 계좌로 나뉘었을 때 **첫 계좌에 10만원을 전부 보낸다.**

- 결과: 첫 레그는 5만 약정에 10만 도착(초과), 둘째 레그는 미입금.
- **총액은 맞다.** 돈은 전부 시스템 안에 들어와 있고 한 판매자에게 몰려 있을 뿐이다.
- 사용자의 앵커는 자기가 사려던 총액이다. 계좌 옆에 총액이 떠 있으면 그 숫자를 친다.

### 패턴 2. 약정보다 적게 보냄

5만 약정에 4만을 보낸다. 오타·수수료 착각 등.

### 진짜 범인 — sticky 요약 카드 (전수 조사로 확인)

패턴 1 의 원인은 "총액이 화면에 있다"가 아니라 **총액이 레그 금액보다 크게, 그것도 스크롤 내내
따라다니게** 배치돼 있었다는 것이다.

| 항목 | 위치 | 크기 |
|---|---|---|
| 주문 **총액** | `p2p.vue:371` sticky 요약 카드 | **20px / weight 700** |
| 레그별 **보낼 금액** | `p2p.vue:470` 카드 안 | 15px |

스크롤하면 요약 카드가 `position:fixed; top:0` 로 고정되는데(CSS 2926-2940), 이때 숨기는 것은
**수수료 행과 예상수령 행뿐**(`v-if="!summaryPinned"`)이고 **총액은 계속 보인다**(폰트만 20→17px).

⇒ 2번째 계좌 카드를 보는 순간 상단 고정 바에 `138,000원`, 카드에 `46,000원`.
**보내면 안 되는 숫자가 보낼 숫자보다 컸다.**

보조 요인: `p2p.vue:412` "모든 건을 같은 계좌에서 보내주세요"(보내는 쪽 얘기)가 받는 계좌가
여러 개인 화면에 떠서 오독을 부른다. 총액 `371` 에는 **라벨 span 자체가 없어** 그 숫자가 무엇인지
구분이 더 약하다.

---

## 2. 확정 원칙 8

### 원칙 1 — 이체 화면에 총액이 존재하지 않는다

총액은 **매칭 결과 확인 화면에서 한 번만** 본다. 이체 화면에는 그 레그 금액 하나만 존재한다.
sticky 요약 카드를 이체 화면에 띄우지 않는다. "아직 남았다"는 총액이 아니라 `1 / 3` 로 전달한다.

⚠️ **부정형도 금지.** "전액 138,000원을 보내면 안 됩니다"처럼 총액을 부정형으로 적는 것도
그 숫자를 다시 심는다. 숫자 없이 **"전액을 보내면 안 됩니다"** 로 쓴다.

### 원칙 2 — 다음 레그 계좌는 DOM 에 없다

접는 게 아니라 렌더하지 않는다. **잘못 보낼 대상이 화면에 존재하지 않아야 한다.**
홈 카드 목록에도 계좌번호를 넣지 않는다 — 계좌는 이체 화면에만 있다.

### 원칙 3 — 금액이 계좌보다 크다

오입금은 계좌가 아니라 금액에서 난다. 시각 위계를 뒤집는다.

```
금액   34px · weight 500 · 경고 톤 블록 안
계좌   19px · mono
은행/예금주  14px · secondary
```

### 원칙 4 — 금액을 세 번 반복한다

앱을 떠나기 직전과 돌아온 직후에 금액이 눈에 남아야 한다.

1. 금액 블록 — `50,000원`
2. 복사 버튼 라벨 — `계좌 복사 · 50,000원`
3. 완료 체크 문구 — `위 계좌로 **50,000원**을 보냈습니다`

"확인했습니다" 같은 빈 문구는 무의식적으로 눌린다. **숫자가 문장 안에 박혀 있어야** 한 번 읽는다.

### 원칙 5 — 홈은 하나다

**진행 현황 화면이 매칭 직후부터 결과 직전까지 계속 홈**이다. 이체·확인 대기·분쟁·증빙이 전부
이 목록 위에서 벌어진다. 목록을 덮는 전체화면은 **이체 하나뿐**이고 그것도 반드시 홈으로 돌아온다.

근거: 2026-08-22 사고 A — 2건 분쟁 상태에서 증빙을 1건만 내고 화면이 닫혔다. 서버는 이미 레그
단위로 완전히 분리돼 있었고, 막은 것은 위젯 내비게이션이었다(전체화면이 목록을 덮고 복귀 경로 없음).
**홈이 하나면 그 실수를 구조적으로 반복할 수 없다.**

### 원칙 6 — 하단 버튼은 지금 할 일이 있을 때만 둔다

하단 전폭 버튼은 "지금 눌러야 할 것" 자리다. 돈이 걸린 채 기다리는 화면에 `닫기` 가 거기 있으면
**포기 버튼처럼 보인다.**

| 화면 | 하단 |
|---|---|
| 견적 확정 | `취소` / `거래 시작` |
| 매칭 결과 확인 · 진행 중 | `그만두기` / `입금 시작`·`이어서 입금` |
| 이체 (체크 전) | `그만두기` / `다음 계좌로`(비활성) |
| 이체 (체크 후) | `다음 계좌로` 전폭 — **그만두기 사라짐** |
| 확인 대기 · 검토 대기 | **없음.** 조용한 링크 `나중에 확인하기` |
| 결과(인정) | `확인` |
| 결과(취소) | `닫기` |

### 원칙 7 — 진행 위치를 클라이언트에 저장하지 않는다

`localStorage`·`sessionStorage`·컴포넌트 `ref` 에 "현재 몇 번째"를 저장하지 않는다.
**항상 서버 상태(`matches[].status`)에서 파생**한다. 새로고침·재진입 복원이 공짜로 따라온다.

### 원칙 8 — 원화가 주, USDT 는 부기

**원화 결제다.** 총액도 매칭별 금액도 원화를 크게 쓰고 USDT 는 아래 작은 글씨로 붙인다.
결과 화면에서도 마찬가지다. USDT 를 크게 노출할 이유가 없다.

---

## 3. 화면별 확정 설계

화면 정렬은 **`matchCode` 오름차순 고정**. 재진입 시 `1/3` 순서가 뒤바뀌면 안 된다.

### 3-1. 견적 확정

기존 `p2p-confirm` 개편. 표시 항목 4줄 + 안내 블록.

| 항목 | 표기 |
|---|---|
| 결제 금액 | `138,000원` |
| **최소 받는 금액** | `92.41 USDT` + 부제 `거래 상대에 따라 이보다 더 받습니다` |
| 적용 환율 | `1,468 KRW / USDT` + 부제 `시장가 1,452 + 1.1%` |
| 수수료 (1.5%) | `2,070원` |

**추가 확정 2건**

1. **분할 가능성을 미리 알린다** — `거래 상대에 따라 여러 계좌로 나눠 보내게 될 수 있습니다.
   계좌는 매칭이 끝난 뒤 알려드립니다.` 지금은 이 말이 없어서 사용자가 **한 계좌를 예상하고**
   시작한다. 패턴 1 의 심리적 출발점이다.
2. **"정해진 시간"을 30분으로 명시** — 기존 문구는 시간을 말하지 않는다.

**"받을 USDT" → "최소 받는 금액"** 으로 바꾼다. 실제로 하한값(LP 실효환율 기준)인데 확정처럼
읽히던 문구다. P2P 로 붙으면 더 받는다.

### 3-2. 매칭 대기

전용 화면이 아니라 **진행 현황 화면의 빈 상태**(레그 0개).

- 스피너 + `거래 상대를 찾고 있어요`
- 카운트다운(파트너 설정 시) + 결제 금액 요약
- **결말을 알린다** — `시간 안에 못 찾으면 자동으로 취소되고 결제는 진행되지 않습니다.`
- 하단: `그만두기` 1개

⚠️ **미확정** — 대기 중 `그만두기` 가 서버에서 실제로 되는지 확인되지 않았다(비동기 매칭).
매칭 후 취소(`cancelAllMatches`)는 있으나 대기 상태 취소 경로는 미확인. **서버와 맞춘 뒤 확정.**

### 3-3. 진행 현황 — 하나의 화면, 세 얼굴 (홈)

**매칭 직후부터 결과 직전까지 이 화면이 홈이다.** 제목·상단 요약·하단 버튼이 상태에 따라 바뀌고,
목록의 배지와 인라인 액션이 레그마다 달라진다.

| 상태 | 제목 | 상단 요약 | 하단 |
|---|---|---|---|
| **A. 매칭 직후** | `3곳으로 나눠 보내주세요` | `보낼 금액 138,000원` | `그만두기` / `입금 시작` |
| **B. 일부만 보냄** | `2곳 더 보내야 해요` | **`남은 금액 88,000원 / 138,000원`** | `그만두기` / `이어서 입금` |
| **C. 전부 보냄** | `입금 확인을 기다리고 있어요` | (없음) | 없음 — 조용한 링크만 |

⚠️ **상태 B 의 상단 숫자는 남은 금액이 주(主)다.** 총액만 크게 떠 있으면 중간에 다시 총액을
보내는 사고가 난다(패턴 1 의 변형).

**1곳 매칭이면 상태 A 의 성격이 바뀐다.** 나눠 보낼 게 없으므로 경고가 아니라 **매칭 완료 통지**가
된다 — `거래 상대를 찾았어요` / `아래 한 계좌로 전액을 보내면 됩니다`. 진행 표시(`1/1`)도
"전액을 보내면 안 됩니다" 경고도 합계 줄도 **전부 없앤다**. 화면을 건너뛰지는 않는다 — 건너뛰면
"매칭이 끝났다"는 신호가 사라진다.

#### 레그 카드 — 상태별 배지와 액션

| 레그 상태 | 배지 | 인라인 액션 | 계좌 |
|---|---|---|---|
| `CREATED` (내 차례) | — | **`이 계좌 입금하기`** (강조, 다음 차례 1건만) | 숨김 |
| `CREATED` (대기) | `이체 대기` | 없음 | 숨김 |
| `BANK_PENDING` | `확인 중` + `4분 경과` | 없음 | 숨김 |
| `BANK_PENDING` 10분 초과 | `확인 지연` + `14분 경과` | 없음 (사유 문장만) | 숨김 |
| `BANK_CONFIRMED`/`SETTLED` | `확인 완료` | 없음 | 숨김 |
| `DISPUTED` · 내 차례 | `자료 필요` | **`자료 올리기`** (카드 안 펼침) | 숨김 |
| `DISPUTED` · 상대/관리자 차례 | `검토 중` | 진행 기록(인라인) | 숨김 |
| `FAILED`/`CANCELLED` | `취소됨` | 없음 | 숨김 |

**다음 차례 레그만 강조하고 버튼을 단다.** 나머지 미이체 레그는 배지만 있고 액션이 없다 —
계좌 세 개를 동시에 열어두지 않는다.

**경과 시간을 카드마다 표시한다.** 레그마다 확인 시점이 다른 게 정상이라는 걸 숫자로 보여주는 게
"확인 중입니다"만 반복하는 것보다 낫다. 기준은 상단에 `보통 10분 안에 끝납니다` 하나로 잡는다.

⚠️ 경과 시간은 **서버 시각(이체 신고 시각)에서 계산**한다. 클라이언트 타이머로 재면 새로고침 때
0 으로 돌아간다.

**창을 닫아도 된다고 알린다** — `이 창을 닫아도 확인은 계속됩니다. 나중에 같은 링크로 들어오면
여기로 돌아옵니다.` 수동 확인 레그는 10분 이상 걸릴 수 있어 붙잡고 있으라는 인상을 주면 안 된다.

### 3-4. 순차 이체 — 레그당 1화면

```
┌──────────────────────────────┐
│  [1 / 3]  ▬▬▬▬▭▭▭▭▭▭▭▭   27:52 │
│                              │
│  ┌────── 경고 톤 블록 ──────┐ │
│  │   이 계좌로 보낼 금액     │ │
│  │      50,000원   ← 34px   │ │
│  │   전액을 보내면 안 됩니다  │ │
│  └──────────────────────────┘ │
│  받는 계좌                     │
│  123456-04-567890  ← 19px mono│
│  국민은행 · 홍길동             │
│  [ 계좌 복사 · 50,000원 ]      │
│  ⚠ 본인 명의 계좌에서만        │
│  ☐ 위 계좌로 50,000원을 보냈습니다│
│  실제 이체 없이 체크하면…       │
└──────────────────────────────┘
   [그만두기]  [다음 계좌로(비활성)]
```

- 총액 0회, 레그 금액 3회(블록·복사 버튼·체크 문구).
- 다음 레그 계좌 **DOM 부재**.
- 만료 카운트다운을 둔다 — 주문 거래창이 이 화면에서 흐르는데 남은 시간을 볼 데가 없으면 갇힌다.
  총액이 아니므로 원칙 1 위반이 아니다. 레그 2개 이상일 때만 진행 표시와 함께 노출.
- 마지막 레그의 주 CTA 는 `다음 계좌로` 가 아니라 `입금 완료`.
- 주 CTA = `POST /api/p2p/match/{matchCode}/transfer-done` **그 레그만**. 성공 후 다음 `CREATED`
  레그로, 없으면 홈.
- 같은 계좌로 병합된 그룹(`groupMatchCodes`)은 **한 장으로 묶어** 합산 금액을 보여준다.

#### 이체 완료 확인 팝업 폐지 → 체크박스 (확정)

기존 `popup.show` 2단계 확인을 없애고 **금액이 박힌 체크박스**로 대체한다. 팝업이 체크 직후라
무의식적으로 넘겨졌다.

**다만 결과 고지는 남긴다** — 체크 옆 상시 노출:
`실제 이체 없이 체크하면 분쟁으로 처리되어 취소가 어려울 수 있습니다.`
클릭을 줄이되 경고를 없애지는 않는다.

#### 그만두기 — 체크 여부로 갈린다 (확정)

| 체크 | 하단 | 이유 |
|---|---|---|
| **전** | `그만두기` / `다음 계좌로`(비활성) | 아직 안 보냈으니 중단 가능 |
| **후** | `다음 계좌로` **전폭** | **보냈다고 표시한 순간부터 되돌릴 대상이 아니다** |

체크 후 하단 문구도 바뀐다:
`보냈다고 표시했기 때문에 이 건은 취소할 수 없습니다. 확인이 안 되면 다음 화면에서 신고할 수 있습니다.`
왜 그만두기가 사라졌는지 설명하고, 문제 생겼을 때의 출구도 미리 알린다.

⚠️ **이 규칙이 없으면 위험하다** — 방금 30,000원을 실제로 보내놓고 그만두기를 누르면 그 돈이
취소 대상이 된다.

`전체 보기` 는 두지 않는다. 진행 위치는 상단 `2 / 3` 과 진행바가 대신한다.

#### 그만두기 확인창

```
여기서 그만둘까요?
  이미 보낸 50,000원   →  USDT 로 지급됩니다
  남은 88,000원        →  취소됩니다
  ─────────────────────────────────
  받는 금액이 모자라 원래 결제는 완료되지 않습니다.
  지급된 USDT 는 잔액으로 남습니다.
        [계속 입금]   [그만두기]
```

**"원래 결제는 완료되지 않습니다"가 핵심이다.** 기존 확인 문구는 "보낸 건 지급되고 남은 건
취소됩니다"까지만 말하고 **사용자가 사려던 물건이 어떻게 되는지 침묵**했다.

아무것도 안 보낸 상태(1/N)에서는 "이미 보낸 금액" 줄이 없다 — `거래를 취소할까요?` 로 단순화.

### 3-5. 분쟁 — 버튼을 없애고 시스템이 건다 (확정)

**카드마다 분쟁 버튼을 두지 않는다.** 상시 노출된 버튼은 "이걸 눌러야 진행되나?"로 읽히고,
설명하기도 어렵다. 실제로는 예외 경로다.

| 위치 | 무엇 |
|---|---|
| 카드 | **없음** |
| 목록 하단 | 작은 회색 글씨 `입금했는데 확인이 안 되나요?` — 누르면 안내 후 한 번 더 확인 |
| 지연 카드 | 사유 문장만 — `판매자에게 다시 요청했습니다. 계속 확인되지 않으면 저희가 직접 처리합니다.` |

⚠️ **서버 선행 필요** — 만료 직전까지 확인되지 않은 `BANK_PENDING` 레그를 **시스템이 자동으로
분쟁 전환**해야 한다. 이 안전망 없이는 버튼을 없앨 수 없다.

**근거**: 지금 자동 확인(CODEF) 레그는 스크래핑이 놓치면 30분에 `FAILED` 로 죽고, **죽은 뒤에는
분쟁을 걸 수 없다**(2026-08-14 결정으로 `FAILED`→`DISPUTED` 경로 폐기). 즉 구매자가 30분 안에
직접 누르지 않으면 돈이 묶인 채 고객센터로 넘어간다. 사용자에게 그 부담을 지우지 않는다.

수동 확인 레그는 30분 만료 대상에서 제외되므로 죽지 않는다 — 자동 전환은 자동 확인 레그가 대상이다.

**관리자 큐 부담은 감수한다.** 실제로 걸리는 건 "돈은 들어왔는데 스크래핑이 놓쳤거나 판매자가
확인을 안 한" 건들이고, 어차피 사람이 봐야 한다. 지금은 그게 만료로 조용히 죽었다가 고객센터로
되돌아오는 구조다.

### 3-6. 자료 제출 — 카드 안 펼침 + 요건 명시 (확정)

전체화면(`p2p-dispute`, `p2p-dispute-reviewing`)을 폐지하고 카드가 그 자리에서 늘어난다.
화면 전환이 없으므로 목록이 사라질 일이 없다(사고 A 구조적 차단).

**사진에 보여야 하는 것 4**
- 보낸 날짜와 시각
- **보낸 금액 — `30,000원`** ← 해당 레그 금액을 문장에 박는다. 3건이 걸려 있을 때 맞는 사진을 고르게 한다
- 받는 사람 이름 또는 계좌번호
- 보낸 사람(본인) 이름

**반려되는 것 3** (작은 예시 그림과 함께)
- 일부만 잘라낸 사진
- 금액·이름을 가린 사진
- 흐리거나 편집한 사진

업로드 영역 부기: `화면 캡처 원본 그대로 · 최대 5MB`
설명란(선택) 힌트: `보낸 사람 이름이 계좌 주인과 다르다면 그 이유를 적어주세요`
→ 자동 분쟁의 가장 흔한 원인이 이름 불일치라 여기서 미리 물어 라운드를 줄인다.

**제출 후 화면 전환 없음.** 같은 카드가 `검토 중` 배지로 바뀌고 진행 기록이 쌓인다.
한 번에 하나만 펼친다(다른 카드를 펼치면 이전 것은 닫힌다).

**분쟁 사유를 카드마다 문장으로 쓴다** — 구매자가 왜 이렇게 됐는지 알아야 사고로 읽히지 않는다.

| 원인 | 문구 |
|---|---|
| 자동(입금자명 불일치) | `보내신 분 이름이 달라 자동 확인이 되지 않았습니다.` |
| 판매자 신고 | `판매자가 입금을 확인하지 못했습니다.` |

### 3-7. 검토 대기 (소명 제출 후)

**"내 돈이 지금 어디까지 와 있나"가 이 화면의 핵심이다.**

- 상단: 충전 완료분 / 검토 중 금액을 **갈라서** 표시 (원화 주, USDT 부기)
- 진행 기록 타임라인 — 이체 신고 → 분쟁 접수 → 자료 제출 → 관리자 대조 중 (시각 포함)
- **결과가 어느 쪽으로 나든 어떻게 되는지 미리 쓴다** — 판정을 기다리는 사람이 가장 궁금한 건
  "잘못되면 이미 받은 것도 날아가나"다
- 하단 버튼 없음. 조용한 링크 `나중에 확인하기` + `검토에는 시간이 걸릴 수 있습니다`

#### 단독 페이지일 때 — 돌아오는 길

위젯이 아니라 단독 페이지로 열린 경우 호스트의 X 가 없고, 판정에 상한이 없어 몇 시간이 걸린다.

- `이 페이지를 다시 열면 결과를 볼 수 있어요` + 주문번호 표시·복사
- **`따로 알림은 가지 않습니다`** — 정직하게 쓴다. 지금 구조에서 구매자에게 결과를 알릴 수단이
  없다(판매자는 텔레그램을 받지만 구매자는 아무것도 못 받는다)

⚠️ **한계 명시** — 주소를 복사해 **다른 기기·브라우저에서 열면 복원되지 않는다**(§5 참조).
"주소를 저장해두세요"는 같은 브라우저에서만 유효하다.

### 3-8. 결과 — 인정 / 취소 2종뿐

**분쟁 결과는 `CONFIRM` / `CANCEL` 둘뿐이다.** 관리자 판정 API 가 이 둘 외에는 거부한다.

⚠️ **"자료 반려"는 결과가 아니다.** 분쟁 헤더의 `status` 가 `OPEN` → `WAITING_EVIDENCE` →
`WAITING_JUDGMENT` 사이를 오가는 **진행 중 상태**이고, `result` 는 그동안 비어 있다.
재요청은 몇 번이든 가능하다(라운드 **번호**만 폐기 — `REQUEST_MORE` 이벤트 수로 도출).

#### 결과 화면 공통 규칙 (확정)

1. **원화가 주, USDT 는 부기** (원칙 8)
2. **합산하지 않는다** — `완료된 거래` / `취소된 거래` 섹션을 갈라 **매칭별로 나열**한다.
   "충전된 금액 108,000원 · 2건"처럼 뭉뚱그리면 어느 거래가 어떻게 됐는지 알 수 없다
3. **사유를 명시한다** — 상단 사유 블록 + 해당 카드 안 문장, 두 곳

#### 인정 (CONFIRM)

- `충전이 완료되었어요` + `138,000원` (아래 작게 `100.28 USDT 로 충전되었습니다`)
- `완료된 거래 3건` — 매칭별 카드, 분쟁 건은 `검토 후 확인됨` + `제출하신 이체 확인증으로 입금이 확인되었습니다.`
- `결제가 진행됩니다`

#### 취소 (CANCEL)

- `3건 중 1건이 취소되었습니다`
- **취소 사유 블록** — `분쟁 심사 결과 입금이 확인되지 않아 취소되었습니다. 제출하신 자료로는
  판매자 계좌 입금 내역을 확인할 수 없었습니다.`
- `완료된 거래` 섹션 / `취소된 거래` 섹션 각각 매칭별 나열
- `이 거래는 종료되었습니다` — 잔액으로 남음 + **원래 결제 미완료** + **이 판정은 되돌릴 수 없습니다**
- 하단은 `닫기` 하나. **`부족분 다시 충전` 같은 버튼을 두지 않는다**
- 이의는 조용한 링크 — 재심 경로가 없지만 출구가 아예 없으면 곤란하고, 버튼으로 크게 두면
  재심이 있는 것처럼 읽힌다

#### 재요청(반려) 화면 — 결과가 아니라 진행 중

- `자료를 다시 올려주세요` + **관리자 요청 원문 표시**
- 기한을 **남은 시간으로** 환산 — `5시간 12분 안에 올려주세요` (주황 톤. 빨강 아님)
- `기한이 지나면 지금까지 제출된 자료만으로 관리자가 판정합니다. 자료가 부족하면 취소로 판정될 수 있습니다.`
  ⚠️ **자동 판정이 아니다** — 6h 기한은 표시·참고용이고 스케줄러는 관리자에게 알리기만 한다
- 반려 사유 체크리스트를 다시 보여준다(가림·잘림 금지 등)

---

## 4. 오입금 발생 후 처리 (확정 정책)

### 4-1. 적게 보냄 → 정정 매칭

**실입금액으로 매칭을 낮추고 그만큼만 인정한다.** 5만 약정에 4만이 들어오면 4만짜리 거래로
정정되고 차액은 없어진다.

> **오너가 별도로 진행.** 이 문서의 화면 설계 범위 밖이다.
> **다만 결과 화면에 배지가 하나 늘어난다** — `50,000원 → 40,000원으로 정정됨` 처럼 **원래 금액과
> 정정된 금액을 같이** 보여줘야 사용자가 왜 덜 받았는지 안다. 결과 화면은 섹션 구조라 배지만
> 추가하면 들어간다.

### 4-2. 많이 보냄 → 약정액만 처리, 초과분은 사고

**시스템은 약정 정확액만 정산한다.** 초과분에 대해 자동 반환이나 재매칭을 시도하지 않고
**별도 사고로 관리**한다.

⚠️ **화면에 남는 과제** — 8만을 보낸 구매자는 5만어치만 받는다. 화면에서 아무 말도 안 하면
"덜 받았다"로 읽힌다. 최소한 **약정액만 처리되었다는 사실은 알려야** 하고, 초과분은 고객센터
안내로 넘긴다. 문구는 초과 사고 처리 정책이 정해진 뒤 확정한다.

### 4-3. 탐지가 선행돼야 한다 (서버, 미구현)

지금 스크래핑은 **정확히 맞는 금액만** 찾고 아니면 못 찾은 걸로 넘긴다. 그래서 부족인지 초과인지
구분되지 않고 전부 "확인 안 됨" → 분쟁으로 뭉뚱그려진다.

**"같은 입금자명으로 다른 금액이 들어왔다"를 잡아내면** 세 가지가 풀린다.

1. 구매자에게 정확히 말할 수 있다 — `80,000원이 들어왔는데 약정은 50,000원입니다`
2. 분쟁 사유가 `AMOUNT_OVER`/`AMOUNT_SHORT` 로 자동 분류돼 관리자 큐에서 구분된다
3. **초과분이 실제로 판매자에게 갔다는 증거**가 남는다 — 사고 처리의 근거

### 4-4. 예방 한 겹 더 (저비용)

계좌 복사 버튼을 누르는 순간이 은행 앱으로 떠나기 직전 **마지막 방어선**이다.
복사 토스트에 `50,000원만 보내세요` 를 띄운다.

---

## 5. 새로고침·재진입 복원

**설계상 유지된다.** 진행 위치를 저장하지 않고 서버 상태에서 매번 다시 계산하므로(원칙 7),
새로고침하면 같은 화면이 다시 그려진다.

**조건 2**
1. URL 에 주문 식별자가 있어야 한다 — 매칭 시작 시 `history.replaceState` 로 `?p2pOrderCode=` 를
   심는다. 결제 링크(`/p2p/:linkCode`)로도 복원된다
2. `localStorage` 의 `cryptoments_widget_access_token` 이 살아 있어야 한다

**깨지는 경우**
- **주소를 복사해 다른 기기·브라우저에서 열면 복원되지 않는다** (토큰이 없다). 주문번호로 조회할
  수단도 지금은 없다 → §3-7 의 "주소를 저장해두세요"는 같은 브라우저 한정
- 토큰 만료 / 브라우저 데이터 삭제
- ⚠️ **위젯이 iframe 안에서 돌 때 사파리의 서드파티 스토리지 차단에 걸리는지 미확인.**
  새로고침만이 아니라 위젯 전체에 영향이 있는 문제라 별도로 봐야 한다

---

## 6. 서버 의존 항목 — 확인·구현이 필요한 것

| # | 항목 | 상태 | 없으면 |
|---|---|---|---|
| S1 | **만료 직전 자동 분쟁 전환** (`BANK_PENDING` 미확인 레그) | **미구현** | §3-5 의 "버튼 없애기"가 불가능 |
| S2 | 레그별 **이체 신고 시각** (경과 시간 계산용) | 확인 필요 | "4분 경과"가 새로고침 때 0 으로 |
| S3 | 레그별 **정산 USDT 금액** | 확인 필요 | 결과 카드의 USDT 부기 제거 |
| S4 | **취소 사유 문구**(판정 메모 또는 코드) | 확인 필요 | 사유 블록을 일반 문구로 대체 |
| S5 | 분쟁 사유 코드 → 구매자용 문장 매핑 | 확인 필요 | "확인되지 않았습니다"로 뭉뚱그림 |
| S6 | **실입금액 탐지**(부족/초과 구분) | 미구현 | §4 전체가 추측 위에 선다 |
| S7 | 대기 중 취소(`그만두기`) 경로 | **미확인** | §3-2 하단 버튼 재설계 |
| S8 | `disputeWaitingOn`, `groupMatchCodes` 응답 포함 | **확인됨** (`P2pWidgetController:769, 772`) | — |
| S9 | LP 견적 3필드(`lpEffectiveRate` 등) | **확인됨** (`:156-178`) | — |

---

## 7. 현재 구현(`7a735ff`)과의 차이

2026-08-22 에 순차 이체 재설계가 이미 push 되어 있다(배포 ▶ 대기). **이 문서의 확정 설계는
그보다 뒤에 나온 것으로, 다음이 다르다.**

| 항목 | 구현됨(`7a735ff`) | 이 문서 확정 |
|---|---|---|
| 이체 화면 보조 버튼 | `전체 보기` | **`그만두기`** (체크 후 사라짐) |
| 이체 화면 총액 | `전액 138,000원을 보내면 안 됩니다` | **숫자 제거** — `전액을 보내면 안 됩니다` |
| 분쟁 제기 | 카드마다 CTA | **버튼 없음** + 시스템 자동 전환(S1) |
| 매칭 결과 확인 | `p2p-split-notice`(고지만) | **진행 현황 상태 A** 로 통합, 1곳일 땐 매칭 완료 통지 |
| 확인 대기 | 홈에 흡수 | 동일 — 단 **하단 버튼 제거**, 조용한 링크 |
| 자료 제출 요건 | 사진 첨부만 | **필수 4 / 반려 3 명시 + 예시 그림** |
| 결과 화면 | 기존 success/failed 유지 | **인정/취소 2종 재설계** (원화 주, 매칭별 분리, 사유 명시) |
| 대기 화면 하단 | `닫기` 전폭 | **없음** — `나중에 확인하기` 링크 |

---

## 8. 하지 말 것

- 이체 화면에 총액·합계·"총 N원 중" 류 문구를 넣는 것 (**부정형 포함**)
- 홈 카드에 계좌번호를 남기는 것
- 홈 목록을 덮는 전체화면을 새로 만드는 것 (이체 하나만 예외, 그것도 복귀 있음)
- 진행 위치를 클라이언트에 저장하는 것
- 결과 화면에서 매칭을 **합산**해 보여주는 것
- 결과 화면에서 **USDT 를 원화보다 크게** 쓰는 것
- 취소 결과에 사유 없이 "취소되었습니다"만 쓰는 것
- 취소 결과에 `부족분 다시 충전` 같은 후속 액션 버튼을 두는 것
- 체크박스 체크 **후에** `그만두기` 를 남겨두는 것 (실제 보낸 돈이 취소 대상이 된다)
- 판매자 **확인 완료**를 다음 레그 진입 조건으로 삼는 것
  → 레그는 주문 거래창을 공유한다(`legExpiresAt(order)`). 확인은 수동이라 최대 10분이고
    2건이면 20분이 흘러 주문 전체가 만료된다. 게이트는 **"내가 이체했다" 신고까지만**

---

## 9. 미확정 — 후속 논의

| 항목 | 내용 |
|---|---|
| 대기 중 `그만두기` | 비동기 매칭이라 서버 취소 경로 확인 필요 (S7) |
| 초과입금 안내 문구 | 사고 처리 정책 확정 후 |
| 구매자 결과 알림 | 판정 결과를 구매자에게 알릴 수단이 **없다**. 화면으로 풀 수 없는 문제 |
| 기기 이동 복원 | 토큰 없이 주문을 여는 경로 — 보안 설계 선행 |
| 가린 사진 반려 여부 | 계좌번호를 가리는 건 습관적 행동. 화면에서 막을지, 받고 재요청할지 |
| 초과입금 빈도 | "잦다"는 보고만 있고 숫자가 없다. 분쟁 기록에서 금액 불일치 건을 뽑을 수 있는지 확인 |
