Skip to content

Commit 5739aec

Browse files
SOIVclaude
andcommitted
feat(web,docs): Phase 1.5.6 UX 품질 기준 완료
- 텍스트 톤 통일: notice 문자열 영문/mock 표기 → 한국어 ("Login successful" → "로그인 성공", "Logged out." → "로그아웃 되었습니다." 등) - docs/ui/04-qa-checklist.md 신규 작성 - 핵심 플로우 QA 체크리스트 30항목 (로그인·관리자·딥링크·개인화) - 반응형 브레이크포인트 정의 (768/860/540/980/900px) 및 체크 항목 - 에러/빈 상태/권한 거부 일관성 매트릭스 - E2E 시나리오 9개 (핵심 5 + 확장 4) - 접근성 QA 체크리스트 (키보드 탐색, ARIA, 명도 대비, 포커스 가시성) - 피드백 톤 가이드 (notice 문구 기준표, 에러 규칙, confirm 문구) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 38a5c0a commit 5739aec

3 files changed

Lines changed: 281 additions & 11 deletions

File tree

apps/web/src/main.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ function App({ installMode }: { installMode: InstallMode }) {
288288
setCurrentUser({ email });
289289
sessionStorage.setItem(SS.auth, "true");
290290
sessionStorage.setItem(SS.email, email);
291-
setNotice("Login successful (mock).");
291+
setNotice("로그인 성공.");
292292
// 첫 방문 온보딩
293293
try {
294294
if (localStorage.getItem(LS.firstVisitShown) !== "true") setIsFirstVisit(true);
@@ -345,7 +345,7 @@ function App({ installMode }: { installMode: InstallMode }) {
345345
setIsPinModalOpen(false);
346346
sessionStorage.setItem(SS.admin, "true");
347347
sessionStorage.setItem(SS.pinVerified, "true");
348-
setNotice("관리자 인증 완료 (mock). 30분간 유효합니다.");
348+
setNotice("관리자 인증 완료. 30분간 유효합니다.");
349349
navigate("admin");
350350
};
351351

@@ -363,7 +363,7 @@ function App({ installMode }: { installMode: InstallMode }) {
363363
setLoginAttempts(0);
364364
setLoginLockedUntil(null);
365365
setSessionExpired(expired);
366-
setNotice(expired ? "" : "Logged out.");
366+
setNotice(expired ? "" : "로그아웃 되었습니다.");
367367
navigate("login");
368368
};
369369

@@ -461,7 +461,7 @@ function App({ installMode }: { installMode: InstallMode }) {
461461
setPinVerifiedAt(null);
462462
sessionStorage.removeItem(SS.pinVerified);
463463
}
464-
setNotice(next ? "Admin authority enabled (mock)." : "Admin authority disabled.");
464+
setNotice(next ? "관리자 권한이 부여되었습니다." : "관리자 권한이 해제되었습니다.");
465465
return next;
466466
});
467467
}}

docs/v2_FINANCIAL-LEDGER/roadmap/01-development-plan.md

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -217,13 +217,13 @@ Control 전체 목록과 상태 관리는 별도 문서에서 관리:
217217
#### 1.5.6 UX 품질 기준
218218
**예상 기간: 2일**
219219

220-
- [ ] 데스크톱/모바일 반응형 기준 확인
221-
- [ ] 에러/빈 상태/권한 거부 상태 일관성 점검
222-
- [ ] 핵심 플로우 QA 체크리스트 작성
223-
- [ ] "설치 -> 로그인 -> 홈 -> 설정" E2E 시나리오 정의
224-
- [ ] 접근성 QA 체크리스트 작성 (focus order, aria label/role, 대비, 키보드 전용 조작)
225-
- [ ] 텍스트/피드백 톤 가이드 통일 (성공/실패/경고 문구 일관성)
226-
- [ ] E2E 확장 시나리오 정의 (설치 실패 복구, 비밀번호 복구, 관리자 PIN 만료 재인증)
220+
- [x] 데스크톱/모바일 반응형 기준 확인 (브레이크포인트 정의: 768px Drawer, 860px padding, 540px bottom sheet, 980px admin 단일 컬럼, 900px 로그인 단일 컬럼)
221+
- [x] 에러/빈 상태/권한 거부 상태 일관성 점검 (`docs/ui/04-qa-checklist.md` 섹션 3 참고)
222+
- [x] 핵심 플로우 QA 체크리스트 작성 (`docs/ui/04-qa-checklist.md` 섹션 1)
223+
- [x] "설치 -> 로그인 -> 홈 -> 설정" E2E 시나리오 정의 (`docs/ui/04-qa-checklist.md` 섹션 4.1 S-02)
224+
- [x] 접근성 QA 체크리스트 작성 (`docs/ui/04-qa-checklist.md` 섹션 5 — 키보드 탐색, ARIA, 명도 대비, 포커스 가시성)
225+
- [x] 텍스트/피드백 톤 가이드 통일 (notice 문자열 한국어 통일, `docs/ui/04-qa-checklist.md` 섹션 6)
226+
- [x] E2E 확장 시나리오 정의 (`docs/ui/04-qa-checklist.md` 섹션 4.2 — 잠금 복구, PIN 만료 재인증, 임시 비밀번호, 개인화 첫 화면)
227227

228228
### 마일스톤 1.5 완료 기준
229229
- ✅ 모듈 없이도 Core UI Shell이 정상 동작
@@ -253,6 +253,7 @@ Control 전체 목록과 상태 관리는 별도 문서에서 관리:
253253
| 2026-04-15 | 관리자/사용자 홈 분리 완료. HomeView에 `isAdmin` prop 추가 — 관리자 로그인 시 Admin Overview 배너(활성 사용자·설치 모듈·시스템 상태 카드) 표시, Admin 패널 바로가기 버튼 제공. 관리자 PIN 세션 30분 자동 만료 구현 — `pinVerifiedAt` 타임스탬프 기반 setTimeout, 만료 시 notice 표시 및 AdminView 재인증 게이트 자동 복원. |
254254
| 2026-04-15 | Phase 1.5.4 Main Home 잔여 항목 완료. 글로벌 네비게이션 상세 규격 확정 (메뉴 순서·아이콘·키보드 탐색). 모바일 Drawer 구현 — 768px 이하 햄버거 버튼 + 슬라이드인 오버레이 사이드바 + 배경 클릭 닫기. 딥 링크 라우팅 — 비인증 상태에서 앱 route 직접 진입 시 로그인 후 원래 route로 자동 복귀. 첫 로그인 온보딩 배너 — localStorage 기반 1회 표시, 닫기 버튼으로 영구 dismiss. |
255255
| 2026-04-15 | Phase 1.5.5 일반 설정 저장 UX 완료. SettingsView dirty state 감지, 저장 로딩 피드백, 미저장 변경 시 브라우저 confirm 경고 구현. |
256+
| 2026-04-15 | Phase 1.5.6 UX 품질 기준 완료. 텍스트 톤 통일(notice 문자열 한국어). 반응형 브레이크포인트 정의(768/860/540/980/900px). `docs/ui/04-qa-checklist.md` 작성 — 핵심 플로우 QA 30항목, 반응형 체크, 에러/빈 상태/권한 거부 일관성 매트릭스, E2E 시나리오 9개(핵심 5 + 확장 4), 접근성 체크리스트(키보드/ARIA/명도/포커스), 피드백 톤 가이드. |
256257
| 2026-04-15 | Phase 1.5.5 관리자 대시보드 / 일반 설정 잔여 항목 완료. Settings '로그인 후 첫 화면' 개인화 옵션 추가(fs_startup_route). AdminView master-detail 패널 시스템 도입 — 섹션 클릭 시 오른쪽 패널 전환. 보안 설정 패널에 PIN 변경 폼 구현(현재/새 PIN 유효성 검증, 성공 화면). 감사 로그 패널에 전체 로그(10건) + 필터 탭(전체/로그인/설정/PIN) 구현. |
257258

258259
---
Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
# Phase 1.5 QA 체크리스트 & E2E 시나리오
2+
3+
> 이 문서는 Phase 1.5 완료 기준 검증을 위한 QA 체크리스트, E2E 시나리오, 접근성 기준을 정의합니다.
4+
> 실제 API 연결 전까지는 mock 계정(`admin@fieldstack.dev` / `user@fieldstack.dev`)으로 검증합니다.
5+
6+
---
7+
8+
## 1. 핵심 플로우 QA 체크리스트
9+
10+
### 1.1 설치 → 로그인 → 홈 → 설정
11+
12+
| # | 항목 | 예상 결과 | 상태 |
13+
|---|------|-----------|------|
14+
| 1 | `pnpm dev:bypass`로 실행 — 상단에 "DEV BYPASS" pill 표시 | 노란 pill + notice 표시 ||
15+
| 2 | `admin@fieldstack.dev` / `Admin1234!` 로그인 | "로그인 성공." notice, `#home` 이동 ||
16+
| 3 | 홈 화면 — 모듈 0개 상태 Empty UX 표시 | 온보딩 3단계 가이드 + EmptyState 표시 ||
17+
| 4 | 최초 로그인 시 환영 배너 표시 | 파란 gradient 배너 + ✕ 닫기 ||
18+
| 5 | 환영 배너 닫기 → 재로그인 시 미표시 | localStorage 기반 1회 표시 ||
19+
| 6 | Settings 열기 → 테마 변경 → 즉시 반영 | data-theme 토글, FOUC 없음 ||
20+
| 7 | Settings — 변경 없이 저장 버튼 비활성화 | 저장 버튼 disabled ||
21+
| 8 | Settings — 변경 후 저장 → notice 표시 후 모달 닫힘 | "설정이 저장되었습니다." notice ||
22+
| 9 | Settings — 미저장 상태에서 닫기 → confirm 경고 | 브라우저 confirm 창 ||
23+
| 10 | 사이드바 — Home / Marketplace / Settings / Sign Out 동작 | 각 항목 정상 탐색 ||
24+
25+
### 1.2 관리자 흐름
26+
27+
| # | 항목 | 예상 결과 | 상태 |
28+
|---|------|-----------|------|
29+
| 11 | 관리자 로그인 → 홈에 Admin Overview 배너 표시 | 활성 사용자·설치 모듈·시스템 상태 카드 ||
30+
| 12 | 사이드바 Admin 진입 → PIN 인증 모달 | 🔐 모달, 4자리 입력 ||
31+
| 13 | PIN `1234` 입력 → Admin 패널 진입 | "관리자 인증 완료. 30분간 유효합니다." notice ||
32+
| 14 | 잘못된 PIN 5회 입력 → 5분 잠금 | 카운트다운 표시 ||
33+
| 15 | Admin — 보안 설정 클릭 → PIN 변경 폼 표시 | 현재/새 PIN 입력 3단계 ||
34+
| 16 | PIN 변경 — 현재 PIN 불일치 → 에러 | "현재 PIN이 올바르지 않습니다." ||
35+
| 17 | PIN 변경 — 성공 → 성공 화면 | 녹색 확인 화면 ||
36+
| 18 | Admin — 감사 로그 클릭 → 전체 로그 표시 | 10건 + 필터 탭 동작 ||
37+
| 19 | 30분 대기(타이머 mock) → 관리자 세션 만료 notice | "관리자 세션이 만료되었습니다." notice ||
38+
| 20 | 일반 사용자 로그인 → 사이드바에 Admin 진입점 미표시 | Admin 버튼 없음 ||
39+
40+
### 1.3 인증 예외 흐름
41+
42+
| # | 항목 | 예상 결과 | 상태 |
43+
|---|------|-----------|------|
44+
| 21 | 비밀번호 5회 실패 → 30분 잠금 | 잠금 Alert, 폼 disabled ||
45+
| 22 | `otp1234` 비밀번호 → OTP step 전환 | 로그인 내 OTP 입력 단계 ||
46+
| 23 | OTP 인증 완료 → 홈 이동 | "2단계 인증 완료." notice ||
47+
| 24 | `temp1234` 비밀번호 → 강제 비밀번호 변경 화면 | ChangePasswordView 전체 화면 ||
48+
| 25 | ForgotPassword — 이메일 경로 3단계 흐름 | 경로 선택 → 이메일 입력 → 새 비밀번호 설정 → 완료 ||
49+
| 26 | ForgotPassword — 관리자 토큰 경로 흐름 | 이메일+토큰 입력 → 새 비밀번호 설정 → 완료 ||
50+
51+
### 1.4 딥 링크 & 개인화
52+
53+
| # | 항목 | 예상 결과 | 상태 |
54+
|---|------|-----------|------|
55+
| 27 | 비인증 상태에서 `#admin` 직접 진입 → 로그인 후 `#admin` 복귀 | redirectAfterLogin 동작 ||
56+
| 28 | 비인증 상태에서 `#marketplace` 직접 진입 → 로그인 후 `#marketplace` 복귀 | redirectAfterLogin 동작 ||
57+
| 29 | Settings — 로그인 후 첫 화면 "마켓플레이스" 설정 저장 → 다음 로그인 시 `#marketplace` 이동 | fs_startup_route 반영 ||
58+
| 30 | 로그아웃 → "로그아웃 되었습니다." notice | 한국어 notice ||
59+
60+
---
61+
62+
## 2. 반응형 기준
63+
64+
| 브레이크포인트 | 적용 내용 |
65+
|----------------|-----------|
66+
| > 768px (데스크톱) | 사이드바 고정 220px, 본문 margin-left: 220px |
67+
| ≤ 768px (모바일) | 사이드바 숨김, 상단 바 + 햄버거 버튼, 슬라이드인 Drawer |
68+
| ≤ 860px | 본문 padding 20px |
69+
| ≤ 540px | Settings 모달 → 하단 bottom sheet |
70+
| ≤ 980px | Admin columns → 단일 컬럼 |
71+
| ≤ 900px | 로그인 화면 → showcase 영역 숨김, 단일 컬럼 |
72+
73+
### 반응형 체크 항목
74+
75+
| # | 항목 | 기준 | 상태 |
76+
|---|------|------|------|
77+
| R1 | 768px 이하: 햄버거 버튼 표시 + 사이드바 숨김 | shell-mobile-topbar 노출 ||
78+
| R2 | 768px 이하: 햄버거 클릭 → 사이드바 슬라이드인 + 오버레이 | transition 정상 동작 ||
79+
| R3 | 768px 이하: 오버레이 클릭 → 사이드바 닫힘 | closeMobileMenu 동작 ||
80+
| R4 | 540px 이하: Settings → bottom sheet 애니메이션 | slideUp 전환 ||
81+
| R5 | 980px 이하: Admin 2컬럼 → 1컬럼 | 레이아웃 깨짐 없음 ||
82+
| R6 | 900px 이하: 로그인 showcase 숨김 | 로그인 카드만 표시 ||
83+
84+
---
85+
86+
## 3. 에러 / 빈 상태 / 권한 거부 일관성
87+
88+
| 화면 | 에러 상태 | 빈 상태 | 권한 거부 |
89+
|------|-----------|---------|-----------|
90+
| 로그인 | 인라인 에러 텍스트 (버튼 아래) || 잠금 Alert (5회 실패) |
91+
||| EmptyState (모듈 0개) + 온보딩 3단계 ||
92+
| 마켓플레이스 || EmptyState (Phase 3 안내) ||
93+
| Admin ||| 🔒 lock screen + PIN 인증 버튼 |
94+
| Admin > 섹션 || "준비 중" 플레이스홀더 ||
95+
| Settings | 저장 실패 시 notice (미구현 — Phase 1.95+) |||
96+
| 비밀번호 복구 | 단계별 인라인 에러 |||
97+
98+
---
99+
100+
## 4. E2E 시나리오 정의
101+
102+
### 4.1 핵심 시나리오
103+
104+
#### S-01: 최초 로그인 온보딩
105+
```
106+
전제: localStorage 비어 있음 (첫 방문)
107+
1. 앱 열기 → 로그인 화면
108+
2. admin@fieldstack.dev / Admin1234! 입력 → 로그인
109+
3. 환영 배너 표시 확인
110+
4. 배너 ✕ 클릭 → 배너 사라짐
111+
5. 로그아웃 → 재로그인 → 배너 미표시 확인
112+
기대: fs_first_visit_shown = "true" 저장
113+
```
114+
115+
#### S-02: 설치 → 로그인 → 홈 → 설정 핵심 플로우
116+
```
117+
1. pnpm dev:bypass 실행
118+
2. 로그인 (admin@fieldstack.dev)
119+
3. 홈 화면 — Empty UX 확인
120+
4. Settings 열기 → 테마 다크/라이트 전환 확인
121+
5. 언어 변경 → 저장 → notice 확인
122+
6. Sign Out → 로그인 화면 복귀
123+
```
124+
125+
#### S-03: 관리자 PIN 플로우
126+
```
127+
1. admin@fieldstack.dev 로그인
128+
2. 사이드바 Admin → PIN 모달 표시
129+
3. 1111 입력 → 오류 (1/5)
130+
4. 1234 입력 → Admin 패널 진입
131+
5. 보안 설정 클릭 → PIN 변경 폼
132+
6. 현재: 1234 / 새: 5678 / 확인: 5678 → PIN 변경 성공
133+
7. 로그아웃 → 재로그인 → Admin 진입 → PIN 재인증 게이트 확인
134+
```
135+
136+
#### S-04: 딥 링크 복귀
137+
```
138+
1. 로그아웃 상태에서 URL에 #admin 입력
139+
2. 로그인 화면으로 리다이렉트
140+
3. 로그인 완료 → #admin으로 자동 복귀 (PIN 게이트 표시)
141+
```
142+
143+
#### S-05: 비밀번호 복구
144+
```
145+
[이메일 경로]
146+
1. 로그인 화면 → "비밀번호를 잊으셨나요?" 클릭
147+
2. 이메일 경로 선택 → 이메일 입력 → 전송 완료 화면
148+
3. 새 비밀번호 입력 → 완료 → 로그인 화면 복귀
149+
150+
[관리자 토큰 경로]
151+
1. 관리자 토큰 경로 선택 → 이메일 + 토큰 입력
152+
2. 새 비밀번호 입력 → 완료 → 로그인 화면 복귀
153+
```
154+
155+
### 4.2 확장 시나리오
156+
157+
#### S-06: 로그인 잠금 및 복구
158+
```
159+
1. 잘못된 비밀번호 5회 입력 → 30분 잠금 Alert
160+
2. 30분 대기 (또는 타이머 조작) → 잠금 해제
161+
3. 정상 로그인
162+
```
163+
164+
#### S-07: 관리자 PIN 만료 재인증
165+
```
166+
1. 관리자 PIN 인증 완료
167+
2. 30분 경과 (타이머 mock: setTimeout 조작)
168+
3. "관리자 세션이 만료되었습니다." notice 표시
169+
4. Admin 화면 → PIN 게이트 복원 확인
170+
5. PIN 재인증 → Admin 패널 재진입
171+
```
172+
173+
#### S-08: 임시 비밀번호 강제 변경
174+
```
175+
1. 이메일 임의값 / 비밀번호 temp1234 로그인
176+
2. ChangePasswordView 전체 화면 표시 (shell 없음)
177+
3. 정책 체크리스트 확인
178+
4. 새 비밀번호 입력 → 변경 완료 → 홈 이동
179+
```
180+
181+
#### S-09: 개인화 첫 화면 설정
182+
```
183+
1. 로그인 → Settings → 로그인 후 첫 화면: "마켓플레이스" 선택 → 저장
184+
2. 로그아웃 → 재로그인 → #marketplace로 이동 확인
185+
3. Settings → 다시 "홈 화면"으로 변경 → 저장
186+
4. 로그아웃 → 재로그인 → #home으로 이동 확인
187+
```
188+
189+
---
190+
191+
## 5. 접근성 QA 체크리스트
192+
193+
### 5.1 키보드 전용 조작
194+
195+
| # | 항목 | 기준 |
196+
|---|------|------|
197+
| A1 | Tab으로 로그인 폼 전체 탐색 가능 | 이메일 → 비밀번호 → 로그인 버튼 순서 |
198+
| A2 | Tab으로 사이드바 nav 전체 탐색 가능 | Home → Marketplace → Modules → Settings → Admin → Sign Out |
199+
| A3 | 사이드바 nav list 내 ArrowUp/ArrowDown 이동 | Workspace, Modules 섹션 내 순환 |
200+
| A4 | Modal(Settings, AdminPin) — Tab 순환, Esc 닫기 | 포커스 트랩 (Phase 1.5.6 범위 외) |
201+
| A5 | 버튼 Enter/Space 동작 | 모든 `<button>` 요소 |
202+
203+
### 5.2 ARIA 레이블
204+
205+
| # | 항목 | 기준 |
206+
|---|------|------|
207+
| A6 | 사이드바 `aria-label="사이드바 네비게이션"` | AppShell `<aside>` |
208+
| A7 | 주 메뉴 `aria-label="주 메뉴"` | AppShell `<nav>` |
209+
| A8 | 현재 페이지 `aria-current="page"` | 활성 nav 항목 |
210+
| A9 | 모바일 햄버거 `aria-label="메뉴 열기"`, `aria-expanded` | 상태 반영 |
211+
| A10 | 드로어 닫기 버튼 `aria-label="메뉴 닫기"` | ✕ 버튼 |
212+
| A11 | 감사 로그 필터 그룹 `role="group"` | 필터 탭 영역 |
213+
| A12 | 에러 메시지 `role="alert"` | PIN 오류, 로그인 에러 |
214+
| A13 | notice 바 `role="status"`, `aria-live="polite"` | shell-notice |
215+
| A14 | 홈 환영 배너 `role="region"` | home-welcome-banner |
216+
217+
### 5.3 명도 대비
218+
219+
| 요소 | 전경색 | 배경색 | 비고 |
220+
|------|--------|--------|------|
221+
| 본문 텍스트 (`--text`) | `#E2E8F0` | `#0F172A` | WCAG AA 이상 |
222+
| 보조 텍스트 (`--text-muted`) | `#94A3B8` | `#0F172A` | 대형 텍스트 기준 통과 |
223+
| Accent 버튼 | `#fff` | `#3B82F6` | AA 통과 |
224+
| 에러 텍스트 (`--err`) | `#F87171` | `#0F172A` | AA 통과 |
225+
226+
> 라이트 모드 대비는 Phase 1.5.6 범위에서 별도 검증 필요.
227+
228+
### 5.4 포커스 가시성
229+
230+
| # | 항목 | 기준 |
231+
|---|------|------|
232+
| A15 | 모든 interactive 요소 focus ring 표시 | `global.css` `:focus-visible` 2px outline |
233+
| A16 | 모달 열릴 때 첫 interactive 요소로 포커스 이동 | 자동 포커스 (현재 미구현 — Phase 1.5.6 개선 여지) |
234+
| A17 | 모달 닫힐 때 트리거 버튼으로 포커스 복귀 | 자동 복귀 (현재 미구현 — Phase 1.5.6 개선 여지) |
235+
236+
---
237+
238+
## 6. 텍스트 / 피드백 톤 가이드
239+
240+
### 6.1 notice (상단 바 일시 메시지)
241+
242+
| 상황 | 문구 |
243+
|------|------|
244+
| 로그인 성공 | "로그인 성공." |
245+
| OTP 인증 완료 | "2단계 인증 완료." |
246+
| 로그아웃 | "로그아웃 되었습니다." |
247+
| 비밀번호 변경 완료 | "비밀번호가 변경되었습니다." |
248+
| 비밀번호 복구 완료 | "비밀번호가 복구되었습니다. 새 비밀번호로 로그인하세요." |
249+
| 관리자 PIN 인증 완료 | "관리자 인증 완료. 30분간 유효합니다." |
250+
| 관리자 세션 만료 | "관리자 세션이 만료되었습니다. 다시 인증해 주세요." |
251+
| 설정 저장 완료 | "설정이 저장되었습니다." |
252+
| 관리자 권한 부여 (dev) | "관리자 권한이 부여되었습니다." |
253+
| 관리자 권한 해제 (dev) | "관리자 권한이 해제되었습니다." |
254+
255+
### 6.2 에러 메시지 규칙
256+
257+
- 계정 존재 여부 비노출: 이메일/비밀번호 오류를 구분하지 않음
258+
- ✓ "이메일 또는 비밀번호가 올바르지 않습니다."
259+
- ✗ "존재하지 않는 이메일입니다."
260+
- 잠금 상태: 남은 시간 표시
261+
- ✓ "계정이 잠겼습니다. 30분 후 다시 시도하세요."
262+
- PIN 오류: 남은 시도 횟수 표시
263+
- ✓ "PIN이 올바르지 않습니다. (1/5)"
264+
265+
### 6.3 확인 / 경고 대화상자
266+
267+
| 상황 | 문구 |
268+
|------|------|
269+
| 미저장 변경 닫기 | "저장하지 않은 변경사항이 있습니다. 닫으시겠습니까?" |

0 commit comments

Comments
 (0)