진입점 · 인증(첫 로그인 또는 PIN 잠금) → 프로젝트 목록·선택 → 도면·개소·섹션 다운로드·오프라인 캐싱(홈 요약 포함)
- 로그인 폼 — Phase 1 공통 인증 IF-CM-AUTH-001(POST /api/auth/login)을 그대로 쓴다. 기기에 저장된 로그인 정보가 있으면 이 폼을 건너뛰고 PIN 잠금부터 연다 — 앱을 완전히 껐다 켜도 로그인이 풀리지 않는다 (②·③·⑦)
- PIN 잠금 (pin-lock 상태) — 저장된 로그인 정보가 있으면 프로젝트 목록보다 먼저 PIN 숫자 4~6자리를 받는다. NFR-SC-FS-002 「앱 시작 시 매번 인증」을 이 관문이 받는다. 기기 안에서만 확인하고 서버로 보내지 않는다. 5회 틀리면 30초 잠금 (②·③·⑤)
- PIN 설정 (최초 1회) — 아이디·비밀번호로 로그인한 직후 그 자리에서 PIN 을 두 번 받아 저장한다. 건너뛰지 못한다 (③·⑤)
- 다른 계정으로 로그인 — PIN 을 잊었을 때의 유일한 길이다. 저장된 로그인 정보를 지우고 로그인 폼으로 되돌린다. PIN 만 따로 되찾는 길은 두지 않는다 (③·⑤)
- 프로젝트 카드 목록 — Project.project_id·Project.name 바인딩. 카드를 탭하면 도면·개소·섹션을 다운로드한 뒤 SCR-FSM-007로 자동 진입한다 (③·⑤)
- 캐시 상태 배지 — Drawing.cached_path 유무. 도면 본문을 받아 두었는지 보여준다 — 받아 둔 도면만 오프라인에서 열린다 (③)
- 최근 동기화 표시 — Project.last_sync_at (③)
- 로컬 저장 용량 표시 — "로컬 저장된 데이터 크기 표시"(FR-FS-006) 요구는 있으나 구체 필드는 소스에 없어 미확정이다 (③)
- 로그아웃 — 프로젝트 목록 머리에 [동기화 현황]과 나란히 둔다. 누르면 확인 창이 뜨고, 못 보낸 실측이 있으면 몇 건인지 알리되 로그아웃을 막지는 않는다. 생김새는 시안(#882)·구현(#892)이 정하고 여기서는 자리만 잡는다 (③·⑤)
- POST
/api/auth/login— 로그인 인증. Phase 1 공통 인증 IF-CM-AUTH-001 을 그대로 쓴다(앱 실측, §12 ⑦) - POST
/api/auth/refresh— 저장된 재발급 토큰으로 인증을 갱신한다. 서버가 400·401·403 으로 물리치면 저장된 로그인 정보를 지우고 로그인 폼으로 되돌린다(§12 ⑤) - GET
/api/pm/projects— 참여 중인 프로젝트 카드 목록 조회, 다운로드 대상 선정 - GET
/api/fs/projects/{projectId}/sections?updatedAfter=&cursor=&limit=— 프로젝트 부호(섹션)·설계 기준값을 오프라인 캐시로 받는다 — IF-FS-SECTION-001 (§5.9.5). 응답은{projectId, items[], serverTimestamp, nextCursor, hasMore, payloadSha256}이고 항목마다designBaseline·baselineSource가 온다(2026-08-17 서버 대조 — §5.9.5 응답 예시와 같다). 한꺼번에 받는 번들 주소는 두지 않는다 — 프로젝트는 IF-PM-PRJ-001, 도면은 IF-FS-DRAWING-001 로 나눠 받는다
2PIN 잠금 — 앱을 켤 때마다 거치는 관문
저장된 로그인 정보가 있을 때 프로젝트 목록보다 먼저 뜬다. 아이디·비밀번호는 다시 묻지 않는다
장갑 낀 손을 고려해 숫자판을 크게 둔다 — 생김새는 시안(#882)이 정하고 여기서는 자리만 잡는다
틀렸을 때 (pin-error 상태)
5회 틀렸을 때 (pin-locked 상태) — 입력칸이 막힌다
PIN 을 잊었을 때의 유일한 길이다 — 저장된 로그인 정보를 지우고 로그인 폼으로 되돌린다. PIN 만 따로 되찾는 길은 두지 않는다
1로그인
저장된 로그인 정보가 있으면 이 폼을 건너뛰고 PIN 잠금(pin-lock 상태)부터 연다
3로그인에 성공하면 그 자리에서 PIN 을 정한다 (최초 1회, 건너뛰지 못한다)
5프로젝트 선택 — 카드 목록
동기화 현황 9로그아웃7최근 동기화자리
최근 동기화자리
최근 동기화자리
8로컬 저장 용량 표시 자리
로그아웃 확인 창 — 위 [로그아웃] 을 누르면 뜬다
프로젝트 다운로드 중
도면 · 개소 · 섹션(기준값 포함) 다운로드 중 — 완료 후 SCR-FSM-007로 자동 진입
프로젝트 선택
프로젝트 선택 (로컬 캐시만 표시)
전역(프로젝트 무관) · 측정기 페어링·배터리·자동재연결 · 모든 화면 상태바의 BLE 칩에서 진입
- 상태바 BLE 칩(현재) — 프로젝트 진입 전후 어디서나 하단(상태바) 칩으로 접근하는 전역 화면이다 (①)
- BLE 스캔 목록 — 신호 강도 30dBm 이상인 근처 측정기만 표시한다 (③, FR-FS-001)
- 연결 상태 카드(device_id) — 연결됨·끊김·약함 표시. 장치 선택 → 자동 페어링, 앱 재시작 시 이전 장치 자동 재연결 (③·⑤)
- 배터리 레벨 — 20% 이하 주황 "배터리 부족", 5% 이하 빨강 "배터리 거의 없음" 경고 (⑤, FR-FS-009)
- N/A이 화면은 안드로이드 BLE 스캔·페어링 SDK로 기기와 직접 통신하며 서버 REST API를 호출하지 않는다. 페어링 이력·기기 등록을 서버에 남길지는 §12 미확정.
2BLE 스캔 목록 (신호 30dBm 이상만 표시)
3연결 상태 (device_id)
4배터리 82%
신호 강도 4/5 바
연결 끊김
3회 실패 시 사용자 개입 요청
프로젝트 하위 · 개소별 업무상태 리스트 — SCR-FSM-007 도면 뷰어의 리스트형 대체 진입(fallback)
- 필터 칩(부호별) — Section.section_code 기준 동(섹션)별 필터, 다중 선택 가능, 기본값 "전체" (③·⑤, FR-FS-003)
- 개소 리스트 행 — Area.label. 행을 한 번 탭하면 곧장 SCR-FSM-004로 이동한다. 목적지는 SCR-FSM-007 마커 탭과 같으나 걸음 수가 다르다 — 도면 뷰어는 두 걸음이고 이 목록은 한 걸음이다. 목록에는 겹쳐 눌릴 마커가 없어 헛짚을 자리가 없기 때문이다(#1370) (③·⑤)
- 업무상태 배지 — Area.biz_status. 배색은 SCR-FSM-007이 정한 규칙을 재인용한다 — 업무상태 여섯을 색 셋으로 옮기고 재측정은 빨강이 아니라 회색이다(다시 재야 하므로, 2026-08-14 앱 실물 확정). 앱이 「재측정」을 실측대기와 같은 묶음으로 옮겨 그린다(
bizStatusBadge). AN12-1 FR-FS-008 이 적던 「앱 내 빨강 배지」도 이 회색으로 바로잡았다(2026-08-22, #1361) (⑤) - 정렬 옵션 — 개소명·진행 상태·측정 시간순 정렬을 제공한다 (③, FR-FS-003)
- 진행률 바 자리 — 프로젝트별·동별 진행률(파생 표시) — "진행률 바 표시" 요구만 있고 구체 필드는 소스에 없다 (③, FR-FS-003)
- GET
/api/fs/projects/{projectId}/areas?updatedAfter=&cursor=&limit=— 개소 목록·업무상태 증분 동기화 — IF-FS-AREA-001 (§5.4.5 승격 절). 주소에 프로젝트 축이 들어간다 — 승격 전 잠정 표기와 다르다(DE24-1 §5.4.5 「경로가 placeholder 와 다르다」, 2026-08-17 서버 대조)
4정렬: 개소명순(자리) · 필터: 업무상태별 · 동(섹션)별
5진행률 바 자리
네트워크 복구 시 최신 목록으로 갱신
개소 하위 · 재는 쪽(내측만·외측만·둘 다) 먼저 고르기 + W·H 기본 + 보조 라벨 자유 추가, 선택→측정→자동입력(BLE) 순차, 수동 입력 상시 병행, ±10% 검증(도면값 있는 항목), 재측정 · 미서기 개소는 환풍구 유무·위치(모듈→코너) 지정 + 환풍구 가로·세로 자동 항목 · 항목마다 사진·도면 위치 남기기(선택)
- 재는 쪽 고르기 (#842) — 측정 항목 목록보다 먼저 「내측만·외측만·둘 다」를 고른다(fs_measurement.side_mode). 고른 값에 따라 항목 목록이 만들어진다 — 「둘 다」면 W·H·보조 항목이 두 벌로 늘고 환풍구 가로·세로는 한 벌 그대로다. 개소 단위로 남기는 까닭은 「둘 다 재기로 했는데 한쪽이 아직 안 왔다」와 「애초에 한쪽만 재기로 했다」를 사무실이 가를 수 있어야 해서다 (③·⑤)
- 항목별 쪽 배지 (#842) — 항목 줄마다 내측·외측 배지가 붙는다(fs_meas_dim.dim_side). 도면값은 안팎 구분 없이 한 벌이고 두 줄이 그것을 나눠 쓴다 — 도면값은 「만들 창호의 치수」라 개구부를 어느 면에서 쟀느냐와 축이 다르기 때문이다. 편차는 두 줄에서 각각 계산돼 각각 ±10% 경고를 받는다. 내측값과 외측값이 다른 것 자체는 경고가 아니다 — 어느 쪽을 쓸지는 사무실 검토(SCR-FS-002)가 정한다 (③·⑤)
- 사진·위치 열 — 항목 줄마다 붙은 사진·메모 수와 도면 위치 표시 여부를 한 자리에서 보인다. 붙은 것이 없으면
📷0, 위치를 안 찍었으면○다. 둘 다 선택이다 — 없어도 저장·전송된다 (③·⑤) - 도면 위치 찍기 (2026-08-07 결정) —
📍를 누르면 도면 태깅 전용 화면(SCR-FSM-009)이 전체화면으로 열린다. 개소에 달린 도면 가운데 하나를 골라 원도면 그대로 위에 찍는다. 저장 전에도 찍을 수 있고 로컬에 쌓였다가 측정과 함께 올라간다. ⛔ 종전 「그림틀」(앱이 그리는 창호 사각형에서 상·중앙·하를 고르던 방식, #843)은 폐기했다 — 그 그림은 미서기 연창 격자로만 그려져 커튼월 같은 다른 구조에서 쓸 수 없다 (③·⑤) - 측정 항목 리스트 — W(폭)·H(높이) 기본 상시 + 보조 라벨(사용자 추가). 데이터 바인딩 MEAS_DIM.dim_type을 사용자 정의 라벨로 확장(기존 W/H/대각선 고정 라벨에서 확장 — 구조설계 반영 후속 필요) (③)
- 항목 선택(arming) — 행을 탭하면 그 항목이 "측정 대기"로 하이라이트된다(한 번에 하나만 선택) (③·⑤)
- 측정 버튼 — 선택된(armed) 항목에 대해 BLE 측정을 트리거하고, 수신값(StandardMeasurement{dimType,value_mm,ts})이 그 항목에 자동 입력된다. 다음 항목을 다시 선택→측정→자동입력하는 순차 흐름이다 (⑤, FR-FS-002)
- 수동 입력 필드 — 어느 항목이든 BLE 연결 여부와 무관하게 키보드 또는 음성으로 항상 입력할 수 있다(BLE는 보조 수단) (③·⑤, FR-FS-002)
- + 보조 수치 추가 — 사용자가 라벨을 직접 입력해 행을 늘리거나 삭제한다(예: 대각선·W1·W2·H1·H2). 도면 기준값이 없는 보조 항목은 편차를 표시하지 않는다(도면값을 별도 입력하면 계산 — 확정 필요) (③·⑤)
- 재측정 이력 자리 — 동일 개소 재측정 시 새 측정 세션으로 이력이 누적된다 — 덮어쓰기가 아니다 (③·⑤)
- 되돌아온 개소 띠와 반려 사유 (#1449 신설) — returned 갈래다.
Area.biz_status = 재측정인 개소로 들어오면 3열 표 위에 되돌아온 건임을 알리는 띠를 두고 사무실이 적은 반려 사유를 그대로 보인다. 현장에서 다시 잴 때 읽어야 하는 글이라 동기화 현황(SCR-FSM-008)에만 두지 않는다 — 두 화면을 오가며 외우게 하지 않으려는 것이다. 낫표로 묶어 그대로, 석 줄까지 보이고 넘치면 그 줄을 눌러 편다. 사유가 없으면 띠는 그대로 두고 사유 줄만 비운다. 입력도 저장도 막지 않는다 (③·④·⑤) - 환풍구 유무 토글 — 개소 제품이 미서기창일 때만 노출. 기본 꺼짐, 켜면 아래 위치 지정 2단계가 열리고 측정 항목에 환풍구 가로·세로가 자동 추가된다 (③·⑤)
- 환풍구 위치 STEP 1(모듈) — 미서기 연창 격자(OPT-LAY, 제품 설계정보)를 그리드로 보여주고 환풍구가 들어갈 모듈을 고른다 (③·⑤)
- 환풍구 위치 STEP 2(코너) — 선택 모듈의 편창 칸(좌창/우창, 3편창이면 좌·중·우)별 4코너(좌상·좌하·우상·우하)를 체크박스로 지정한다. 여러 곳 동시 가능, 2편창=8·3편창=12 선택지. 편창 칸 수·격자는 제품 설계정보에서 온다 — 스키마 확정 후속 갭 (③·⑤)
- POST
/api/fs/measurements— BLE·수동으로 입력한 실측값(재는 쪽·항목별 쪽·도면 위치·W·H·보조항목·환풍구 치수) 서버 전송
| 5라벨 | 2쪽 | 도면값 | 실측값 | 편차 | 3사진·위치 |
|---|---|---|---|---|---|
| W(폭) | 내측 | 1800mm | 1795mm | -0.3% | 📷2 4 |
| 6H(높이) | 내측 | 1500mm | 측정 대기 | (자리) | 📷0 ○ |
| 대각선(보조) | 내측 | 도면값 없음 | 2338mm | — (도면값 없음) | 📷1 |
| W(폭) | 외측 | 1800mm | 1812mm | +0.7% | 📷1 |
| H(높이) | 외측 | 1500mm | 수동입력 자리 | — | 📷0 ○ |
| 대각선(보조) | 외측 | 도면값 없음 | 수동입력 자리 | — | 📷0 ○ |
| 환풍구 가로자동 | 구분 없음 | — | 측정/수동 | — | 📷0 ○ |
| 환풍구 세로자동 | 구분 없음 | — | 측정/수동 | — | 📷0 ○ |
10재측정 이력 자리
| 라벨 | 도면값 | 실측값 | 편차 | 입력방식 |
|---|---|---|---|---|
| W(폭) | 1800mm | 수동입력 자리 | (자리) | 수동 |
| H(높이) | 1500mm | 수동입력 자리 | (자리) | 수동 |
| 라벨 | 도면값 | 실측값 | 편차 | 입력방식 |
|---|---|---|---|---|
| W(폭) | 1800mm | 1795mm | -0.3% | BLE |
| H(높이) | 1500mm | 1650mm | +10.5% 초과 | BLE |
되돌아온 개소 — 사무실이 반려한 건 (#1449 신설)Area.biz_status = 재측정 · SCR-FSM-008 「되돌아온 건」 카드로 들어온 자리
| 라벨 | 도면값 | 실측값 | 편차 | 입력방식 |
|---|---|---|---|---|
| W(폭) | 1800mm | 1795mm | -0.3% | BLE |
| H(높이) | 1500mm | 1650mm | +10.5% | BLE |
입력도 저장도 막지 않는다 — 띠와 사유를 보이기만 한다(§4-1 원칙)
측정 하위 · 개소·측정 부속정보(선택) · 개소 완료(들어온 자리로 되돌림)·뒤로(실측 입력)
- 사진 썸네일 슬롯 — PHOTO. 최대 5장, 업로드 전 최대 2MB/장으로 자동 압축한다. 썸네일을 누르면 크게 보기 겹창이 뜬다 (#1417 신설) — 어두운 전체 바탕에 사진 한 장(긴 변 1440화소)과 [지우기]·[닫기] 를 두고, 사진 바깥을 눌러도 닫힌다. ➕ 캡션 줄 아래·단추 줄 위에 「무엇이 문제인가」 칩 넷과 「한 줄 설명」 입력칸(최대 500자)을 둔다 (#1517 확정) — 지금 보는 사진의 값을 보이고, 고치면 그 사진에만 담기며, 좌우로 넘기면 두 칸도 그 사진의 값으로 바뀐다. 화면 번호를 따로 주지 않고 이 화면의 상태(photo-viewer)로 둔다. 지우기는 크게 보기 안에만 있고 한 번 되묻는다 — 목록 칸에는 지우기를 두지 않는다(장갑 낀 손으로 잘못 눌러 사진을 잃는 것을 막는다) (③·④·⑤, FR-FS-010)
- 개소 완료·뒤로 버튼 (#1417 확정) — [개소 완료](종전 「저장」)는 이 개소를 마치고 들어온 자리로 되돌린다 — 개소 목록(SCR-FSM-003)에서 들어왔으면 목록으로, 도면 뷰어(SCR-FSM-007)에서 들어왔으면 뷰어로 간다. [← 뒤로]는 측정값을 고치러 실측 입력(SCR-FSM-004)으로 돌아간다. 이 화면에는 저장할 것이 남아 있지 않아 「저장」이라는 이름을 걷었다 — 측정값은 SCR-FSM-004 가 이미 저장했고, 사진은 붙일 때마다 곧바로 담기며, 메모는 어느 쪽으로 나가도 담긴다. 부속정보는 선택이라 사진·메모 없이 눌러도 된다 (③·⑤)
- 카메라·갤러리 버튼 — 촬영 또는 갤러리에서 선택한다 (③, FR-FS-010)
- 메모 입력 — MEMO. 최대 500자, 텍스트 또는 음성→텍스트 변환을 지원한다(장갑 착용 대응) (③·⑤, FR-FS-011)
- 무엇이 문제인가 — 태그 고르기 (#847) — 「손상」·「불균형」·「기타」 셋 가운데 하나를 고른다(fs_attachment.issue_tag, 저장 값은 DAMAGE·IMBALANCE·OTHER). 비워 둘 수 있다 — 기본값이 「없음」이라 안 골라도 저장·전송된다. ➕ 사진 크게 보기에도 같은 칩을 그대로 둔다 — 이름을 나누지 않는다 (#1517 확정). 찍기 전(이 자리)과 찍은 뒤(크게 보기) 어느 쪽에서도 값을 보고 바꿀 수 있고 두 자리가 같은 값을 함께 쓴다. 셋을 고정하고 늘리지 않으며, 안 맞는 것은 「기타」가 받는다. 둘이 함께 보이면 사진을 한 장 더 붙인다 — 여러 개를 받으려면 중간 표가 필요한데 검토자가 「무엇이 문제인가」를 아는 데는 하나로 충분하다. 사진과 메모가 같은 칸을 쓴다. 사무실 검토(SCR-FS-002)가 이 태그로 목록을 거른다 (③·⑤, FR-FS-011)
- 촬영 시간 메타 자리 — 사진 메타정보로 촬영 시간을 자동 기록한다(fs_attachment.taken_at, 단말 로컬 시각). 서버가 받은 시각은 created_at 에 따로 남는다 (③)
- 사진 한 줄 설명 (#847 · #1417 확정 · #1517 로 자리 옮김) — 사진마다 한 줄 적는 칸을 둔다. 자리는 이 화면 아래 입력 칸이 아니라 사진 크게 보기(photo-viewer) 안이다 (#1517 확정) — 아래 칸에 두면 [촬영]을 누르는 그 순간의 값만 붙어 찍은 뒤에 적은 글이 사라진다. 크게 보기 안의 칸은 지금 보는 사진의 값을 보이고 좌우로 넘기면 그 사진의 값으로 바뀐다. 칸은 태그와 상관없이 늘 보인다 — 태그가 「기타」일 때만 「무엇인지 한 줄 적어 주세요」 안내 문구가 더 붙는다. 갈리는 것은 안내이지 칸이 아니다(#1417). 「기타」일 때만 칸을 보이면 「손상」·「불균형」을 고른 사진에 설명을 붙일 자리가 없어진다. 비어 있어도 저장된다 — 사진 자체가 이미 무엇을 찍었는지 보여 준다. 새 칸을 만들지 않고 메모가 쓰던 fs_attachment.memo_text 를 사진 행에서도 쓴다 — 2000자 칸이 이미 있고 검사 제약이 사진 행의 메모 글을 막지 않는다. 글자 수 제한은 메모와 같은 500자다 (③·⑤)
- 무엇을 찍었나 — 측정 항목 잇기 (#843) — 사진·메모 하나에 측정 항목 하나를 잇는다(fs_attachment.meas_dim_id). 고르개에는 그 개소의 측정 항목이 화면에 보이는 그대로(항목 이름 + 쪽 배지) 나열되고 맨 위에 「개소 전체(항목 없음)」가 있다. 기본값이 「개소 전체」라 아무것도 고르지 않아도 종전과 똑같이 저장된다. 사진 한 장은 항목 하나만 가리키고, 한 항목에 사진 여러 장은 된다. 사진 위에 화살표·동그라미를 찍지 않는다 — 좌표 칸을 새로 만들어야 하고 장갑 낀 손으로 사진 위 한 점을 찍는 것이 느리다. SCR-FSM-004 의 편차 초과 줄에서 [사진]을 눌러 들어오면 그 항목이 미리 골라진 채 열린다 — 강제가 아니라 권함이다 (③·⑤)
- 동기화 대기열 등록 — 네트워크가 연결되면 사진·메모가 측정 자료와 함께 자동으로 동기화 대기열에 들어간다 (⑤)
- 항목별 모아보기 (2026-08-07 신설) — 개소 전체 사진 묶음 위에 그 개소의 측정 항목(fs_meas_dim)을 줄줄이 늘어놓고 줄마다 📷 붙은 사진·메모 수와 📍 도면 위 위치 여부를 붙인다. 비어 있는 줄은 「비었음」으로 눈에 띄게 한다 — 어느 항목이 비었는지 현장을 뜨기 전에 채우라고 두는 자리다(사무실에서 되묻는 것을 줄이는 것이 이 요구의 목적이다). 줄을 누르면 그 항목이 「무엇을 찍었나」 고르개에 골라진 채로 사진을 붙일 수 있다. 강제는 아니다 — 비어 있어도 저장·전송된다(「저장을 막지 않는다」 원칙). 측정 항목이 하나도 없으면 상태 empty 로 「아직 잰 항목이 없습니다」를 적고 개소 전체 사진 묶음만 보인다 (③·④·⑤)
- POST
/api/fs/measurements/{measurementId}/attachments— 사진·메모 첨부 — 측정 등록 뒤 별도 주소로 올린다(최대 5장·500자). 어느 측정 항목을 찍은 것인지도 함께 보낸다(선택,measDimId). 특이사항 갈래(선택,issueTag= DAMAGE·IMBALANCE·OTHER)와 사진 한 줄 설명(선택,memoText— #847 로 사진 행에도 받는다)을 함께 보낸다 (IF-FS-ATTACH-001 §5.9.4, 설계선행)
10항목별 모아보기이 개소의 측정 항목
1사진 첨부개소 전체 · 최대 5장
8무엇을 찍었나선택
4메모최대 500자
5무엇이 문제인가선택
7한 줄 설명은 이 자리에 없다 — 사진을 눌러 뜨는 크게 보기 안에서 사진마다 따로 적는다 (#1517 확정)
6촬영 시간 메타 자리
10항목별 모아보기로컬 자료
10항목별 모아보기이 개소의 측정 항목
1사진 첨부개소 전체 · 최대 5장
잰 항목이 없어 「무엇을 찍었나」 고르개는 두지 않는다 — 개소 전체 사진만 붙는다
단말 설정 · 로컬 저장·배치 push 동작·정책 · SCR-FSM-008 동기화 현황의 [저장·동기화 설정] 에서 진입 (#881 4단계 결정)
- 동기화 상태 표시 — MEASUREMENT.sync_status(draft/pending/synced/failed) (③)
- 로컬 저장 건수 표시 자리 — 최소 500건 이상 보관 — 구체 표시 필드는 소스에 없어 미확정이다 (③, FR-FS-004)
- 로컬 저장 항목 리스트 — 전송완료 항목을 보여준다 (③)
- 일괄 전송 버튼(배치 push) — 네트워크 복구 시 백그라운드에서 자동 동기화하며, gzip 압축 배치 최대 500건을 30초 이내 완료 목표로 한다 (⑤, NFR-PF-FS-003)
- [보낸 자료 정리] (#1436 확정) — 손으로 지우는 자리를 이 화면에 둔다. 누르면 전송이 끝난 건의 사진만 지우고 측정값·메모는 남긴다. 지우기 전에 한 번 되묻고, 그 창에 「사진 N장을 지웁니다 · 측정값과 메모는 그대로 둡니다」를 적는다. 시안 f006 의 「더보기에서 고릅니다」는 따르지 않는다 — 이 화면 위 막대에 더보기 단추가 없다 (③·⑤)
- 저절로 지우기 (#1436 확정) — 사진은 전송이 끝나고 30일이 지나면 저절로 지운다. 측정값과 메모는 저절로 지우지 않는다 — 지우면 앞 회차 값 되살리기와 재측정 이력이 함께 없어진다. 이쪽은 되묻지 않고 규칙을 이 화면에 글로 적어 둔다 (③·⑤)
- 지워진 사진 자리 (#1436 확정) — 사진을 지운 자리는 비우지 않고 「기기에서 지웠습니다 — 사무실에서 볼 수 있습니다」로 적는다. 빈 자리로 두면 「사진을 안 찍었다」로 읽힌다 (③)
- 재시도 정책 — 전송이 실패하면 간격을 늘려 가며 최대 5회까지 다시 보낸다(지수 백오프). 실제 값은 착수 시 확정한다 (⑤)
- POST
/api/fs/measurements— 네트워크 복구 시 쌓인 실측 전송 — 배치·gzip 지원 여부는 서버 계약 확인 필요
2로컬 저장 건수 표시 자리
로컬 저장 항목
6전송이 끝나고 30일이 지난 사진은 저절로 지웁니다. 측정값과 메모는 그대로 둡니다.
온라인 복구 시 자동 백그라운드 동기화
프로젝트 하위, 허브 진입 · 프로젝트 도면 여러 장(층별 평면도·입면도·창호일람표·보조 도면)에서 먼저 도면을 고른다 — 측정대상 도면과 참조 전용 도면이 섞여 있다
- 도면 유형 필터 — Drawing.drawing_kind. 전체 / 평면도 / 입면도 / 창호일람표 / 기타. 유형별로 좁혀 본다. 값은 도면을 올릴 때 고르고, 안 고르면 서버가 기타(OTHER)로 담는다 (③)
- 측정대상 도면 행 — Drawing.drawing_kind·Drawing.file_name. 이름은 「종류 + 파일 이름」으로 보인다 — 사람이 붙이는 이름 칸은 두지 않는다. "측정 대상 N개소" 배지가 붙은 도면만 위치 측정 대상이고, 그 여부는 앱이 개소로 센다. 탭하면 도면 뷰어로 이동한다 (③·⑤)
- 측정 진행 배지 — 도면별 개소 측정 진행(완료/전체). 측정 위치(개소)와 갯수는 견적설계 대조검증(PRC-ES-08 · SCR-ES-019)에서 설계자가 평면도에 사전 마킹·확정한 값이다 — 측정자는 위치를 새로 만들지 않는다 (⑤)
- 참조 도면 행 — 창호일람표·입면도·보조 도면 등 측정에 관여하지 않는 도면(개소 0건). "참조 전용" 배지, 탭하면 뷰어에서 열람만(측정 마커 없음). 딱지는 「측정 대상 N개소」와 「참조 전용」 둘뿐이다 — 「측정 없음」은 개소 0건이라 참조 전용과 갈리지 않는다 (③·⑤)
- 캐시 상태 — Drawing.cache_status. 오프라인 조회 가능 여부 (③)
- 상태 — 오프라인 목록 — 캐시된 도면만 목록에 보이고 캐시되지 않은 도면은 흐리게 둔다. 조회 자체는 계속된다 (③·⑤)
- 목록 하단 단축 버튼(「{도면 이름} 열기」) — 측정대상 도면 중 맨 위(첫 번째) 도면을 곧장 여는 단축 버튼. 목적지는 그 행을 탭한 것과 같다(도면 뷰어). 화면 하단은 장갑 낀 손으로 엄지가 닿는 유일한 자리라, 스크롤·행 조준 없이 들어가는 경로를 하나 둔다. 글자 차례는 「열기 · 이름」 — 이름이 길면 반대 차례로는 "열기"가 먼저 잘린다 (⑤, #1341)
- GET
/api/es/projects/{projectId}/drawings— 프로젝트 도면 목록 조회 후보 — ES 대조검증이 쓰는 도면 소스 재사용 가능성(FS 전용 Pull API는 미구현이라 확정 아님) - GET
/api/fs/projects/{projectId}/drawings— 도면 목록 조회 — 모바일 증분 동기화(updatedAfter/cursor)·캐시 파라미터는 아직 없다
1도면 유형 필터
2측정대상 도면 (탭 → 도면 뷰어)
4참조 도면 (측정 없음 · 열람만)
5도면별 캐시됨 — 오프라인 조회 가능
도면 목록 불러오는 중…
아직 내려받은 도면이 없습니다 — 프로젝트를 다시 선택하거나 동기화하세요
도면 목록에서 고른 한 장 · 도면 위 측정 위치(개소) 마커 — 설계자가 대조검증(PRC-ES-08)에서 사전 확정한 위치. 마커 탭 두 걸음(고르기 → 다시 눌러 들어가기) → 실측 입력. 섹션(부호) 필터·핀치줌
- 선택 도면 헤더 — Drawing.name(예: 1층 평면도). [← 도면 목록]으로 돌아가 다른 도면을 고른다 (③·⑤)
- 측정 위치 출처 — 도면 위 개소 마커는 설계자가 견적설계 대조검증(PRC-ES-08 · SCR-ES-019)에서 평면도에 사전 마킹·확정한 설치 위치다. 측정자는 이 위치를 탭해 실측만 입력한다 — 위치·갯수를 바꾸지 않는다 (⑤)
- 섹션 필터 바 — Section.section_code. 칩 다중 선택, 기본값 "전체" — 선택한 부호의 개소 마커만 도면 위에 남긴다 (③·⑤)
- 도면 캔버스(선 도면) — Drawing.cached_path(받아 둔 본문 파일)·Drawing.bounds_*(도면 범위 mm). 서버가 미리 그려 둔 그림이 아니라 선 도면(벡터) 본문을 받아 앱이 직접 그린다(#1018). 받아 두면 오프라인에서도 조회할 수 있다 (③)
- 개소 마커(오버레이) — Area.marker_x/marker_y·Area.label·Area.biz_status(마커 색·모양). 탭은 두 걸음이다 — 처음 누르면 그 마커가 골라지고 개소 정보판이 뜨며, 정보판이나 같은 마커를 다시 누르면 SCR-FSM-004로 이동한다. 겹쳐 있는 마커에서 헛짚어 엉뚱한 개소로 들어가는 것을 막는 걸음이다(#1370). 골라진 마커는 뒤집어 그린다 — 흰 채움에 3dp 테두리다. 도면의 빈 자리를 누르면 골라 둔 것을 놓는다 (③·⑤)
- 개소 정보판(고른 마커 위 카드) — 첫 줄은 개소 부호·개소 이름(예: AW01-2 · 1층 로비), 둘째 줄은 섹션 부호·업무상태·잰 항목 수(예: AW01 · 측정중 · 측정 3항목)다. 잰 기록이 없으면 그 칸을 아예 비운다. 누르면 SCR-FSM-004로 간다. 화면 밖으로 나가지 않게 가두고, 마커 위에 자리가 없으면 아래로 뒤집는다 (③·⑤, #1370) — 마커 6
- 핀치줌 제스처 — 두 손가락으로 확대·축소, 더블탭하면 기본 배율로 되돌아간다 (③·⑤)
- 하단 전역 칩(BLE·동기화) — SCR-FSM-002·SCR-FSM-008이 소유한 상태만 노출하고, 탭하면 해당 화면으로 이동한다 (③)
- 상태 — 오프라인 — 로컬 캐시로 조회를 계속하고 마커 탭·실측 진입을 막지 않는다 (③·⑤)
- 상태 — 본문 못 받음 — 대신 보여 줄 낮은 화질 그림이 없다. 앱이 선 도면을 직접 그리므로 본문을 못 받으면 도면 자체를 그리지 못한다. 마커 좌표는 그대로 남아 개소 목록에서는 계속 보인다 (③·⑤)
- 상태 — 그릴 것이 없는 도면 — 본문은 받았으나 도면 범위(bounds)가 없거나 무한대다. 변환기가 시작값을 그대로 둔 원래 빈 도면이라 앱 결함이 아니다. 이런 도면은 받아 두지 않는다 (④)
- 마커 색과 동기화 상태는 다른 축 — 마커 색은 업무 상태를 뜻하므로 동기화가 밀려도 색이 바뀌지 않는다 (③·⑤)
- 마커 색·모양 규칙 — 여섯을 셋으로, 그 위에 모양 하나 — 측정중은 파란색(#1B6F8D·찬 동그라미), 완료·검증완료·승인완료는 초록색(#2F7A51·체크), 실측대기·모르는 값은 회색(#5D737B·빈 동그라미), 재측정은 같은 회색에 느낌표다. 재측정은 빨강이 아니라 회색 — 다시 재야 하는 개소라 아직 안 잰 개소와 할 일이 같고, 갈라 보이는 것은 색이 아니라 모양이다. 잠정안이 아니라 앱 실물이다(2026-08-22 확인, #892). 이 그림은 흑백이라 두 회색이 같은 명암으로 그려져 있다 (⑤)
- GET
/api/es/drawings/{drawingId}/json— 고른 도면의 선 도면 본문을 받아 갈 주소(IF-ES-DRAWING-JSON-001 · §5.4.23). 본문은 이 주소가 알려 준 저장소 주소에서 따로 내려받고, 도면 범위(bounds)는 그 본문 안에서 읽는다 — 응답에는 배율·범위 칸이 오지 않는다(2026-08-14 실측). 목록은 SCR-FSM-007 이 부르는/api/fs/projects/{projectId}/drawings를 그대로 쓴다 - GET
/api/fs/projects/{projectId}/areas?updatedAfter=&cursor=&limit=— 도면 위 개소 마커(좌표·라벨·업무상태) — IF-FS-AREA-001 (§5.4.5). 마커 좌표 정본은 section_placement
4손가락 두 개로 확대·축소 · 더블탭으로 원래 배율
5하단 전역 칩
앱 전체는 세로 고정, 도면 뷰어(007)만 가로 회전 허용(Android sensorLandscape) · 위 세로 007 프레임과 동일 데이터 — 배치만 재구성(캔버스 확대 + 필터·전역 칩 상단 이동)
- 상단 필터·전역 칩 바 — 가로 모드에서는 섹션 필터·전역 칩(BLE·동기화)이 상단/측면으로 재배치된다 (⑤, 2026-07-07 Approach A)
- 도면 캔버스(확대) — 가로 회전 시 도면 캔버스가 넓어진다. 앱 나머지는 세로 고정이고 007만 예외로 가로 회전을 허용한다(Android
sensorLandscape) (⑤) - 개소 마커 — 위 세로 007 프레임과 동일 데이터, 배치만 재구성한 것이다 (③·⑤)
- 복귀 안내 — 세로로 되돌려도 축소된 배치로 계속 동작한다 — 화면 방향 규정은 현재 AN12-1 요구사항·NFR 어디에도 없어 이식성(NFR-PT)·사용성(UX) NFR 후속 반영 후보로만 남긴다 (⑤)
- 상태 — 가로 보기 — 핀치줌으로 확대·축소하고 더블탭으로 되돌린다. 세로로 되돌려도 위 007 프레임처럼 도면이 축소된 배치로 계속 동작한다. 지금 AN12-1 요구와 NFR 이 이 동작을 규정하지 않아 이식성·UX NFR 후속 반영이 남았다 (③·⑤)
- GET
/api/fs/projects/{projectId}/areas?updatedAfter=&cursor=&limit=— 가로 모드도 007-view 와 같은 개소 데이터를 쓴다 — IF-FS-AREA-001 (§5.4.5)
측정 항목 하위 · 2026-08-07 신설 — 측정 항목 하나가 원도면 어디를 잰 값인지 도면 위에 직접 찍는 전체화면. SCR-FSM-004 항목 줄의 📍 로 들어와 찍거나 그만두면 그 자리로 되돌아온다 · 개소에 달린 도면 가운데 하나를 골라 길게 눌러 한 점 · 찍은 자리는 도면 mm 로 보인다
- 머리말 — 무엇을 찍는 중인가 — SCR-FSM-004 가 넘긴 항목 이름과 쪽 배지를 그대로 잇는다(예 「내측 W(폭)」). 어느 줄에서 눌러 들어왔는지 잊지 않게 하는 자리다 (③)
- 도면 고르개 — Drawing.drawing_id·Drawing.file_name. 개소에 달린 도면에서 한 장을 고르고 그것이 fs_meas_dim.tag_drawing_id 가 된다. SCR-FSM-007 도면 목록이 쓰는 그 목록을 그대로 쓴다 — 이 화면 전용 조회를 새로 만들지 않는다. 처음 열 때는 그 개소 마커가 찍혀 있는 도면을 미리 골라 둔다 (③·⑦)
- 도면 캔버스(전체화면) — Drawing.cached_path(받아 둔 선 도면 본문)·Drawing.bounds_*(도면 범위 mm). 원도면 그대로 그리고 개소 마커를 함께 얹어 「이 개소가 어디인가」를 잃지 않게 한다 — 앱이 선 도면을 직접 그리는 것이고 서버가 미리 그려 둔 그림을 얹는 것이 아니다. 손가락 두 개로 확대·축소, 더블탭으로 기본 배율 — SCR-FSM-007 도면 뷰어와 같은 조작이다 (③·⑤)
- 찍은 점 — 길게 눌러 찍는다 — fs_meas_dim.tag_x_mm·tag_y_mm. 짧게 누르기와 끌기는 팬·줌이 이미 쓰고 있어 길게 누르기 하나만 찍기에 배정한다. 한 항목에 한 점이고 다시 찍으면 앞의 점이 옮겨 간다 — 여러 자리를 남기려면 측정 항목을 줄로 늘려 각각 찍는다 (③·⑤)
- 찍은 자리 좌표 — 도면 mm —
X 12,340 Y 8,720처럼 도면 mm 로만 적는다. 화면 픽셀은 사용자에게 보이지 않는다 — 확대 배율에 매달린 값이라 적어 두면 뜻이 없다. ⚠️ 좌표계는 도면좌표이고 개소 마커·부호 배치와 같은 축이다. 견적설계가 영속 저장에 쓰는 배치 좌표(ESTIMATE_LINE.canvas_x_mm)도 같은 도면좌표라 섞어도 밀리지 않는다(#962 결정). 섞지 말아야 할 상대는 화면 픽셀(캔버스좌표) 이다 — 줌·팬에 매달린 값이라 도면 mm 로 환산하지 않고 쓰면 줌 배율만큼 어긋난 자리에 찍힌다. 다만 눈금자 section_dimension.offset_mm 는 섹션좌표로 영속하는 예외다 (③·⑤) - [지우기]·[확인] — [지우기]는 도면 번호·X·Y 셋을 함께 지운다. [확인]은 찍은 자리를 그 항목 줄에 붙이고 004 로 돌아가며, 점을 안 찍었으면 잠근다 — 도면만 고른 상태는 찍은 자리가 없는 것과 같다 (③·⑤)
- [✕ 닫기] — 아무것도 바꾸지 않고 004 로 돌아간다. 찍다 만 점은 버린다. 이 화면은 저장하지 않는다 — 좌표는 로컬에 쌓였다가 004 의 저장·전송 때 측정과 한 요청으로 함께 올라간다 (②·⑤)
- 왜 전용 전체화면인가 — 폰에서 측정 표와 도면을 함께 띄우면 창 한 짝이 점 하나만 하게 그려져 장갑 낀 손으로 못 찍는다. 전체화면이면 크게 확대해 찍을 수 있어 터치 대상 최소 48dp 요구(NFR-US-FS-001)를 지킨다 — 그것이 이 화면을 따로 세운 유일한 까닭이다 (①)
- 상태 — loading — 고른 도면의 본문을 아직 받는 중. 「도면 받는 중…」 (④)
- 상태 — offline — 네트워크 단절(NFR-RL-FS-001, 5초 내 자동 감지). 캐시된 도면만 고르개에 남기고 안 받아 둔 도면은 「내려받지 않음」으로 잠근다. 캐시된 도면에서는 찍기가 그대로 된다 (④)
- 상태 — empty — 이 개소에 딸린 도면이 0건. 찍을 자리가 없으므로 캔버스를 그리지 않고 [✕ 닫기]만 둔다 (④)
- 상태 — error(도면 범위 없음) — 받아 둔 본문에 도면 범위(bounds)가 없거나 무한대라 mm 를 낼 수 없다. 찍기를 잠근다 — 그럴듯한 엉뚱한 mm 를 내놓는 것보다 못 찍는 편이 낫다. 절취 사각형·배율 메타는 어느 응답에도 오지 않아 막는 조건이 아니다(2026-08-14 실측) (④·⑤)
- GET
/api/fs/projects/{projectId}/drawings— 도면 고르개가 쓰는 목록(IF-FS-DRAWING-001 · §5.9.2) — SCR-FSM-007 이 이미 부르는 그 조회를 그대로 쓴다. 변환이 끝난 도면만 내려와 못 그릴 도면이 섞이지 않는다 - POST
/api/fs/measurements— 찍은 좌표(dims[].tagDrawingId·tagXMm·tagYMm)가 실려 가는 계약(IF-FS-MEAS-001 · §5.9.1) — 이 화면이 직접 부르지 않는다. SCR-FSM-004 가 저장·전송할 때 측정과 함께 올린다
5찍은 자리 — X 12,340mm · Y 8,720mm (도면 mm)
찍은 자리 — X 12,340mm · Y 8,720mm
11이 개소에 달린 도면이 없습니다
전역 · pending/failed 목록·수동 재시도 · 모든 화면 상태바의 동기화 칩에서 진입
- 상태바 동기화 칩(현재) — 모든 화면 상태바의 동기화 칩에서 진입하는 전역 화면이다 (①)
- pending 목록 — MEASUREMENT.sync_status=pending. 서버에 아직 전송되지 않은 대기 중 실측 건을 보여준다 (③)
- failed 목록 + 재시도 버튼 — sync_status=failed(5회 재시도 후 실패). 버튼을 누르면 해당 건을 즉시 재전송한다 (③·⑤, NFR-RL-FS-003)
- 재측정 배지 자리 — Area.biz_status=재측정. 서버 검증 실패·거절(FCM 수신) 시 완료→재측정으로 역행한다. 배지 색은 회색(#9E9E9E)이다 — 「다시 재야 하는 개소」는 「잘못된 개소」가 아니라 「할 일이 남은 개소」라 실측대기와 같은 색으로 둔다(SCR-FSM-007 ⑤ 마커 색 표) (③·⑤, FR-FS-008)
- 되돌아온 건 카드 (#1449 신설) —
Area.biz_status = 재측정인 개소를 카드로 보인다. 줄 차례는 ① 개소 이름과 「재측정」 딱지 ② 「사무실이 반려했습니다 · 다시 재 주세요」 ③ 마지막 회차의 편차 ④ 반려 사유 다. 사유는GET /api/fs/measurements/{measurementId}의rejectReason이고 낫표로 묶어 그대로 보인다 — 앱이 줄이거나 바꿔 적지 않는다. 사유가 없으면 그 줄을 비운다(「사유 없음」을 넣지 않는다). 카드를 누르면 그 개소의 실측 입력(SCR-FSM-004)으로 가고 그 화면이 returned 갈래로 열린다 — 화면이 「다시 재 주세요」라고 하면서 그리로 가는 길을 주지 않던 자리다 (②·③·⑤) - 위쪽 요약 카드 (#881 3단계 신설) — 아래 두 목록의 건수를 위쪽에 모아 보인다(전송 대기 N건 · 전송 실패 N건). 목록을 끝까지 내리지 않고도 「얼마나 남았나」를 읽는 자리다. 새로 세는 값이 아니라 두 목록의 길이를 그대로 보인다 (③)
- [모두 다시 보내기] (#881 3단계 신설) — 대기와 실패를 함께 보낸다. 실패만 보내면 대기 건이 남아 사람이 두 번 눌러야 하고, 이 화면의 이름이 이미 「모두」다. 5회 재시도로 실패한 건도 사람이 손으로 누른 것이므로 다시 보낸다. 누르는 동안 이 단추와 각 줄의 [재시도] 를 함께 잠근다 (③·⑤)
- 묶음 전송 진행 막대 (#881 3단계 신설) — [모두 다시 보내기] 를 누른 동안에만 보인다. 세는 것은 건수(보낸 건수 / 보낼 건수)이지 바이트가 아니다 — 사진이 섞여 크기가 들쭉날쭉해 바이트로 세면 막대가 멈춘 것처럼 보인다 (③·⑤)
- [저장·동기화 설정] (#881 4단계 신설) — 탭하면 SCR-FSM-006 오프라인 저장·동기화로 들어간다. 이 화면은 「지금 무엇이 안 갔나」(건별 목록·재시도)를 보이고, 그쪽은 「이 단말이 어떻게 담고 보내나」(동기화 단계·로컬 저장 용량·동기화 뒤 로컬 삭제)를 보인다. 동기화에 관한 문을 하나로 둔다 — 전역 칩 → 008 → 006 한 길이다 (②·③)
- MISSING
— (만들지 않음)— 수동 재시도 전용 주소는 두지 않는다 — fs_measurement.client_uuid UNIQUE(V250)가 재전송 멱등을 이미 담당한다. 같은 POST 를 다시 보내면 된다 (§5.9.1) - POST
/api/fs/notification/token— 푸시 수신 단말 등록·갱신 — IF-FS-NOTIF-REGISTER-001 (본문은 §6.5.2, 자리 신호는 §5.4.3). 응답은{tokenId, userId, deviceId, registeredAt, active}로 정본 §6.5.2 예시와 같다(2026-08-17 서버 대조). 해지는 같은 주소의DELETE ?deviceId=이고 줄을 지우지 않고active=false로 끈다
동기화 현황 — pending·failed 동시 예시(참고용 기본 화면 · 문서 ④의 3개 variant sync-pending/sync-failed/synced 중 하나가 아님)
4재측정 배지 자리 — 회색(#9E9E9E)
되돌아온 건 카드 (#1449 신설)Area.biz_status = 재측정 · 누르면 그 개소의 실측 입력(SCR-FSM-004)으로 간다
넷째 줄 = 반려 사유. 낫표로 묶어 사무실이 적은 글을 그대로 보인다 — 앱이 줄이거나 바꿔 적지 않는다. 사유가 없으면 이 줄을 비운다 — 「사유 없음」 같은 대신 글을 넣지 않는다
7묶음 전송 진행 막대 — 보낸 건수 / 보낼 건수 (누르는 동안에만 보인다)
전송 대기 12건
전송 실패 2건 (5회 재시도 후)