멧돼지 92%
스마트팜 IoTDesign
컴포넌트 사용법 화면 명세서

스마트팜 IoT Design System · v1 2026-10-14

현장에서 한눈에 읽히는
스마트팜 모니터링 화면

하우스 상태를 3D 공간 위에서 보고, 위험해지기 전에 알림을 받고, 자동으로 대응하는 서비스의 화면 규칙이에요. 모든 미리보기는 화면 명세서(iot.html)와 같은 CSS로 그려지고, 오른쪽 위에서 라이트 · 다크를 바꿀 수 있어요.

사용법 보기컨셉화면 명세서
기초
컴포넌트
패턴
아이콘
테마
라이트 · 다크

시작

기초 · Foundations

색 · 상태 색 · 글자 · 간격 · 모서리 · 표면 · 아이콘 · 모션. 모든 값은 CSS 변수(토큰)이고 라이트 · 다크 두 벌이 있어요.

컴포넌트 · Components

화면 명세서 17개 화면에서 두 번 이상 쓰는 것만 모았어요. 이름 옆 .class 를 그대로 써요.

패턴 · Patterns

컴포넌트를 조합한 화면 규칙 — 앱 껍데기 · 3D 대시보드 · 알림 흐름 · 장비 제어 · 화면 크기 · 문구.

사용법

이 가이드와 화면 명세서는 같은 CSS 한 벌(spec-src/screens.css)을 쓴다. 가이드에서 보이는 모양이 곧 화면 모양이고, 토큰을 바꾸면 둘 다 바뀐다.

파일 구조

    frontend/
    ├── spec-src/                 ← 화면 명세서 원본 (조각)
    │   ├── screens.css           ← ★ 토큰 + 컴포넌트 + 화면 (가이드도 이것을 씀)
    │   ├── icons.html            ← 아이콘 스프라이트 (i-* 89개 · 영상 목업 · 작물)
    │   ├── spec.js               ← 테마 · 앱 껍데기 · 차트
    │   ├── farm3d.js             ← 3D 장면 (Three.js)
    │   └── build.sh              → assets/iot.html
    ├── guide-src/                ← 이 가이드 원본
    │   ├── guide.css · guide.js  ← 문서 화면 (헤더 · 목록 · 코드 상자 · 검색)
    │   ├── pages-*.html          ← 페이지 내용
    │   └── build.sh              → assets/iot_guide.html
    └── assets/
        ├── iot.html              ← 화면 명세서 + 프로토타입 (빌드 결과)
        ├── iot_guide.html        ← 이 페이지 (빌드 결과)
        └── fonts/PretendardVariable.woff2
  

고치고 빌드하기

  1. 디자인을 바꿀 때는 가이드 먼저 — 새 컴포넌트 · 토큰은 screens.css 에 넣고, 이 가이드에 페이지(예시 · 명세)를 추가한다.
  2. 두 개 다 빌드 — 같은 CSS 를 쓰므로 가이드와 명세서를 함께 다시 만든다.
  3. 결과 HTML 은 직접 고치지 않는다 — assets/*.html 은 빌드할 때마다 덮어쓴다.
    docker exec smartfarm bash -c "bash /smartfarm/frontend/spec-src/build.sh && bash /smartfarm/frontend/guide-src/build.sh"
  
문서주소 (개발 서버 serve · 5173 → 호스트 55176)
디자인 가이드http://192.168.5.20:55176/assets/iot_guide
화면 명세서http://192.168.5.20:55176/assets/iot

화면 루트 .scr 와 토큰

모든 화면은 .scr 하나로 시작한다. 토큰(색 · 크기 단위) · 글자 · 아이콘 · 버튼 초기화가 여기에 걸린다. 다크는 html.theme-dark 한 줄로 바뀐다 — 화면마다 색을 따로 적지 않는다.

    <html class="theme-dark">            <!-- 없으면 라이트 (기본) -->
    <div class="scr app" data-shell="main" data-title="대시보드">
      <main class="app__main"> … </main>  <!-- 왼쪽 메뉴 · 상단바 · 탭바는 껍데기가 넣는다 -->
    </div>
  
    /* 같은 이름을 라이트 · 다크에서 다시 정의 — 컴포넌트는 이름만 쓴다 */
    .scr, .sf { --bg: #eef1f2; --panel: #ffffff; --fg: #12171b; --brand: #0f9e85; … }
    .theme-dark .scr, .theme-dark .sf { --bg: #0d1113; --panel: #171d21; --fg: #eef2f4; --brand: #2cc9ab; … }
    .card { background: var(--panel); border: 1px solid var(--line); }
  

앱(Vue)으로 옮길 때

  1. screens.css 를 앱 공통 CSS 로 — 토큰 · 컴포넌트 부분(화면 루트 ~ 오버레이)을 src/assets/css 로 옮기고, 화면별(A · B · C …) 부분은 각 view 의 스타일로 나눈다.
  2. 클래스 이름 그대로 — .btn · .st · .kpi 를 템플릿에 그대로 쓴다. 상태는 is-ok · is-caution · is-warn · is-danger · is-fault 클래스 하나로.
  3. 아이콘 — 스프라이트(icons.html)를 index.html 에 한 번 넣고 <svg class="ic"><use href="#i-bell"/></svg> 로 쓴다 (AppIcon 컴포넌트로 감싸도 됨).
  4. 3D — farm3d.js 의 장면 만들기(buildScene) · 라벨(labelItems)을 컴포넌트로 옮긴다. 색은 화면 토큰(--f3d-*)을 읽는다.

컨셉 — Field Clear

농장주가 하우스 밖에서, 폰 한 번 보고 "어느 동 · 어디서 · 무슨 일이 · 무엇을 했는지" 알 수 있어야 한다. 장식보다 읽히는 것이 먼저다.

다섯 가지 원칙

1. 숫자 목록 대신 공간 — 대시보드 가운데는 3D 하우스. 센서 값은 그 위치의 라벨로 붙는다. 이상한 센서는 멀리서도 항상 보인다.
2. 상태는 색 + 아이콘 + 글자 — 정상 · 주의 · 경고 · 위험 · 장애 다섯 단계. 색만으로 전달하지 않는다 (색약 · 햇빛 아래 화면).
3. 큰 숫자, 작은 단위 — 30.6℃ 처럼 값은 크고 굵게, 단위는 작게. 숫자는 자릿수가 흔들리지 않게 고정폭(tabular).
4. 자동이 한 일을 보여준다 — "무엇을 · 왜(규칙) · 결과"를 한 줄로. 사람이 개입할 때는 무엇이 멈추는지 누르기 전에 알려준다.
5. 차분한 바탕, 강조는 하나 — 회청색 바탕 · 흰 판 · 청록(brand) 하나. 빨강 · 주황 · 노랑은 상태에만 쓴다.

모양 요약

요소규칙
바탕라이트 회청색 --bg 위에 흰 판 --panel · 다크 거의 검정 위에 짙은 회색 판. 그라데이션 · 유리 효과는 3D 위에 뜬 도구에만 (뒤가 비쳐야 위치를 잃지 않음)
강조색청록 --brand 하나 — 주 버튼 · 선택 · 자동(규칙) 표시. 농작물 · 식물 느낌이지만 상태 초록(정상)과는 다른 색
글자Pretendard · 제목 800 · 숫자 750~800 · 본문 400~600. 기본 14px × 화면 배율(--u)
모서리둥글지만 각지게 — 판 1em · 버튼 0.75em · 상태 · 칩은 알약(999px)
움직임짧고 조용하게 (0.2 ~ 0.32초). 반복 움직임은 "지금 주의가 필요한 것"(깜빡이는 라벨 · 3D 팬 회전)에만

권장 · 지양

경고30.6℃
권장

상태는 아이콘 + 글자 + 색, 값은 크게 · 단위는 작게.

30.6 ℃
지양

숫자에 색만 칠해 상태를 알리기 — 색을 못 보면 "정상"인지 "경고"인지 모른다.

색

색은 역할 이름(토큰)으로만 쓴다. 값은 라이트 · 다크에서 각각 다시 정의되어 있고, 오른쪽 위 테마를 바꾸면 아래 값도 바뀐다.

바탕 · 판

--bg화면 바탕 ·
--bg-2왼쪽 메뉴 · 탭바 ·
--panel카드 · 드로어 ·
--panel-2판 안의 칸 · 버튼 ·
--panel-3막대 바탕 · 배지 ·
--scrim오버레이 뒤 ·

글자 · 선

--fg제목 · 값 · 본문 ·
--fg-2설명 · 보조 ·
--fg-3라벨 · 시각 · 단위 ·
--line판 테두리 · 구분선 ·
--line-2입력칸 · 진한 선 ·

강조 (brand)

--brand주 버튼 · 선택 ·
--brand-2주 버튼 hover ·
--brand-inkbrand 위 글자 ·
--brand-weak선택 바탕 · 자동 배지 ·
--brand-textweak 위 글자 · 링크 ·
대시보드 자동 · R2

동 · 계열 색

여러 동을 한 차트 · 한 화면에서 비교할 때만 쓴다. 순서가 고정이다 (1동 파랑 → 2동 주황 → 3동 초록). 4동 이상은 같은 색을 다시 쓰지 않고 동 이름 라벨로 구분한다. 상태 색과 섞어 쓰지 않는다.

--zone-11동 · 단일 계열 ·
--zone-22동 ·
--zone-33동 ·
--band-ok차트 적정 범위 띠 ·
--band-peer우수농가 범위 띠 ·

3D 장면 색 --f3d-*

3D 엔진(farm3d)이 화면 토큰을 읽어 그린다 — 테마를 바꾸면 3D 도 다시 그려진다. 숫자를 코드에 적지 않는다.

--f3d-bg하늘 · 배경 ·
--f3d-ground땅 ·
--f3d-frame하우스 골조 ·
--f3d-crop작물 줄 ·
--f3d-heat-*히트맵 낮음 → 적정 → 높음
--f3d-wind바람 화살표 ·
--f3d-rain빗줄기 ·
--f3d-tree뒤편 숲 ·
--f3d-animal야생동물 ·
권장

새 화면도 var(--panel) · var(--fg-2) 처럼 이름으로. 반투명이 필요하면 color-mix(in srgb, var(--panel) 88%, transparent).

지양

#ffffff · rgba(…) 를 화면 CSS 에 직접 쓰기 — 다크에서 흰 판이 그대로 남는다.

상태 색 .is-*

이 서비스에서 가장 중요한 색. 상태 클래스 하나(is-warn)를 붙이면 그 안의 --st 가 바뀌고, 배지 · 점 · 라벨 · 알림 아이콘이 모두 그 색을 쓴다. 항상 아이콘 + 글자와 함께.

단계

정상.is-ok · --st-ok적정 범위 안. 대시보드에서는 동 이름만 (값은 확대해야 보임)
주의.is-caution적정을 벗어나기 시작 · 빠르게 오르는 중 · 예보. 앱 안에만 표시
경고.is-warn기준 초과가 지속 → 자동제어 · 푸시 알림
위험.is-danger작물 피해 직전 · 제어 실패 → 푸시 + 문자 · 미확인 시 전화
장애.is-fault센서 · 장비 통신 두절 · 고장. 값이 아니라 기기 문제 (보라 — 위험 단계와 섞이지 않게)
꺼짐.is-off사용 안 함 · 꺼진 규칙 · 대기

쓰는 법

상태 클래스는 가장 바깥 하나에만 붙인다. 안쪽 아이콘 · 테두리 · 바탕은 var(--st) 를 읽는다.

경고 T2-331.4℃
    .is-ok { --st: var(--st-ok); }   .is-caution { --st: var(--st-caution); }   .is-warn { --st: var(--st-warn); }
    .is-danger { --st: var(--st-danger); }   .is-fault { --st: var(--st-fault); }   .is-off { --st: var(--st-off); }
    /* 바탕은 상태색을 옅게 섞는다 — 라이트 · 다크 모두 같은 식 */
    .st { background: color-mix(in srgb, var(--st) 16%, transparent); }
  

상태 · 아이콘 짝

상태아이콘글자 · 문구
정상i-check정상 · 완료 · 복구
주의i-alert-c (원)주의 · 예보 · 추세
경고i-alert (삼각)경고 · 기준 초과
위험i-octagon (팔각)위험 · 제어 실패
장애i-unplug · i-bug장애 · 통신 두절 · 고장
센서 1 장애주의 · 고온
권장

모양이 다른 아이콘으로 단계를 구분 (원 · 삼각 · 팔각) — 흑백에서도 구분된다.

새 기능
지양

상태가 아닌 곳에 상태 색 쓰기 — 빨강은 "위험"으로만 읽혀야 한다. 삭제 버튼(.btn--danger)만 예외.

글자

글꼴은 Pretendard Variable 하나. 크기는 기본 14px × --u 에 em 배수로 쓴다 — 화면이 커지면(4K) --u 만 바뀌어 전부 같이 커진다.

크기 단계

큰 숫자30.6℃.big-num · 2.6em · 750
KPI 값13회.kpi__value · 1.5em · 800
알림 상세 제목2동 온도 30.6℃.adetail__title · 1.45em · 800
화면 제목대시보드.top__title · 1.3em · 800
패널 제목2동 센서 T2-3.drawer__title · 1.2em · 800
카드 제목오늘 자동제어.card__h · 0.98em · 750
본문30℃ 넘은 상태 2분 지속 → 규칙 R21em(14px) · 400 · 1.45
설명3동 자동제어는 T3-1 · T3-3 평균으로 대체 중.aitem__desc · 0.8em · fg-2
라벨진행 중 알림.kpi__label · 0.8em · 650 · fg-3

숫자

  • 값은 크게 · 단위는 작게 — 단위는 <small> (0.42 ~ 0.72em, 회색). 값과 단위 사이 띄어쓰기 없음: 30.6℃ · 11m/s · 68%
  • 고정폭 숫자 — 값 · 시각은 font-variant-numeric: tabular-nums (.num). 값이 바뀌어도 자리가 흔들리지 않는다.
  • 소수점은 측정 정밀도까지 — 온도 한 자리(30.6), 습도 · 토양 · 개폐율 정수(61%), 풍속 한 자리(3.2m/s), 예보 정수(11m/s).
  • 자간 — 큰 숫자 · 제목은 좁게(-0.03 ~ -0.05em), 본문 -0.01em.
습도61%
30.6℃ 14:12:04

간격

간격은 em 으로 적는다 — 글자 크기(--u)를 따라 같이 커지고 작아진다. 아래 단계 안에서 고른다.

단계

0.3em아이콘 ↔ 글자 (배지 · 칩)
0.5em버튼 묶음 · 목록 항목 사이
0.8em패드 화면의 칸 사이 · 3D 도구 여백
1em모니터 화면의 칸(카드) 사이 · 카드 안쪽 위아래
1.1 ~ 1.3em카드 · 드로어 안쪽 좌우
1.2 / 1.4em본문 바깥 여백 (위아래 / 좌우) · 다이얼로그 안쪽

화면별 여백

위치모니터패드폰
.app__main1.2em 1.4em1em 1.1em0.3em 1em 1.2em
칸 사이 (grid gap)1em0.8em0.9em (세로 쌓기)
.card1em 1.1em (모든 기기 같음)
.drawer__body1.1em 1.3em · 항목 사이 1.1em바텀시트 — 같음

모서리

작은 것일수록 작게, 판일수록 크게. 상태 · 칩 · 스위치처럼 "값 하나"를 담는 것은 알약(999px).

0.45em배지
0.65em입력칸 · 3D 시점 버튼
0.75em버튼 · 세그먼트 · 아이콘 버튼
0.85em알림 항목 · 카메라 영상
1em카드 · KPI · 3D 뷰어
1.2em다이얼로그
1.4em 위폰 바텀시트
999px상태 · 칩 · 스위치 · 3D 라벨

표면 · 그림자

층은 세 개 — 바탕(--bg) · 판(--panel + 테두리 + --shadow-1) · 떠 있는 것(드로어 · 다이얼로그 · 툴팁, --shadow-2). 3D 위에 뜬 도구는 반투명 판으로 뒤가 비친다.

--bg화면 바탕
--panel + --shadow-1카드 · KPI · 기기 카드
--panel-2판 안의 칸 · 알림 항목
--shadow-2드로어 · 다이얼로그 · 툴팁

3D 위 반투명 판

3D 위 도구 · 범례 · 날씨 칩 · 작은 카메라 창은 color-mix(in srgb, var(--panel) 88~90%, transparent) + backdrop-filter: blur(10px). 뒤 3D 가 살짝 비쳐서 "공간 위에 떠 있다"는 것이 보인다. 3D 가 아닌 곳에는 쓰지 않는다.

정상주의경고위험장애

아이콘 개

24 × 24 격자 · 선 두께 1.9 · 둥근 끝 선 아이콘 한 벌. 색은 currentColor — 글자색을 따른다. 스프라이트 한 번 넣고 <use href="#i-이름"/> 로 쓴다. 칸을 누르면 코드가 복사된다.

크기

클래스크기쓰는 곳
.ic--sm1em배지 · 칩 · 글자 사이 (자동 · 3D 표시)
.ic1.25em버튼 · 메뉴 · 카드 제목 · 라벨
.ic--lg1.6em알림 상세 머리 · 빈 화면

장비 · 센서 아이콘

온도습도CO₂토양일사EC 천창측창유동팬보온커튼난방기관수보광등퇴치기

모션

움직임은 어디서 왔는지 · 어디로 갔는지를 알려줄 때만. 곡선은 하나 — cubic-bezier(0.2, 0.8, 0.2, 1) (빠르게 출발해 부드럽게 멈춤).

2동 센서 T2-3

아래에서 올라옴 · 0.32초

무엇시간 · 곡선움직임
메뉴 이동 (본문 교체)240ms · 감속본문만 아래 8px → 제자리 + 페이드. 메뉴 · 상단바는 그대로
드로어 · 패널 열기320ms · 감속오른쪽에서 밀려 들어옴 (폰 = 아래에서). 뒤 오버레이 200ms 페이드
닫기200ms · ease-in들어온 반대 방향으로
3D 시점 이동750ms · easeInOutCubic카메라가 날아감. 사용자가 끌면 바로 멈춤
3D 라벨 깜빡임1.6s 반복주의 이상 · 장애 라벨만 (.is-pulse)
스위치200ms손잡이 이동
권장

반복 움직임은 "지금 봐야 하는 것"에만 — 위험 라벨 깜빡임, 켜진 팬 회전, 퇴치기 소리 고리.

지양

카드가 차례로 튀어나오는 장식 애니메이션 — 상황판처럼 오래 켜 두는 화면에서 눈이 피곤하다.

버튼 .btn

한 화면(또는 한 패널)에 주 버튼(primary)은 하나. 장비를 움직이는 버튼은 동사 + 목표값으로 적는다 (100% 열기).

놀이판

오른쪽에서 값을 바꾸면 미리보기와 코드가 같이 바뀌어요.

html

종류 · 크기

아이콘 버튼

명세

클래스모양쓰는 곳
.btnpanel-2 · 테두리 · 높이 2.6em · 650보조 동작 · 장비 명령 (닫기 · 정지 · 열기)
+ .btn--primarybrand 채움주 동작 하나 (확인했어요 · 저장 · 100% 열기)
+ .btn--danger위험 빨강 채움지우기 · 되돌릴 수 없는 것만
+ .btn--ghost바탕 없음취소 · 덜 중요한 동작
+ .is-onbrand-weak 바탕켜짐 · 끄기 중 지금 상태
.btn--sm / --lg / --block2.1em / 3.2em / 가로 꽉표 안 · 3D 도구 / 다이얼로그 · 폰 아래 고정
.icon-btn2.5em 정사각 · 점 배지(.icon-btn__dot)상단바 알림 · 패널 닫기
권장

누르면 무슨 일이 생기는지 버튼 글자로 — 확인 창의 주 버튼은 질문의 동사 그대로.

지양

주 버튼 두 개 · "확인 / 예" 처럼 무엇을 하는지 모르는 글자.

세그먼트 .seg

화면을 떠나지 않고 보는 것만 바꿀 때 — 3D 표시 항목, 동 고르기, 지금 / 예보. 2 ~ 5개. 그 이상이면 칩.

클래스설명
.segpanel-2 바탕 · 0.2em 안쪽 여백 · 버튼 높이 2em
.seg > button.is-onpanel 흰 판 + 그림자 (하나만)
.seg--full가로 꽉 · 버튼 같은 폭 (패널 안)
[data-ui]화면 안 선택 표시 — 이동 없음 (프로토타입 · 가이드가 is-on 을 옮김)

칩 .chip

목록을 거를 때 — 알림 등급 · 종류, 카메라 분할. 선택된 것은 글자색 반전(.is-on). 개수는 <b> 로.

전체 12미확인 2위험경고장애

입력 · 스위치 .field

입력칸은 라벨을 위에, 단위는 칸 안 오른쪽(.input__unit). 규칙 · 기준값처럼 숫자를 넣는 칸은 적정 범위를 바로 아래 보여준다.

R2 고온 환기 켜짐
클래스설명
.field · .field__label세로 묶음 · 라벨 0.8em 700
.input높이 2.6em · panel-2 · line-2 테두리
.input--select · --focus오른쪽 화살표 / brand 테두리 + 3px 링
.switch (.is-on)2.7 × 1.6em 알약 — 규칙 · 알림 켜고 끄기
.slider개폐율 (천창 · 커튼) — 채움 i + 손잡이 b

상태 배지 · 점 .st

상태를 알리는 기본 단위. 점(.dot)은 글자가 바로 옆에 있을 때만 (범례 · 칩 · 목록).

완료 주의 1 장애 1 경고 정상 위험
클래스설명
.st알약 · 상태색 16% 바탕 · 아이콘만 상태색 · 글자는 fg (읽힘 우선)
.st--lg패널 머리 · 큰 상태
.dot · .dot--ring0.6em 점 / 바깥 링 (지금 진행 중)

배지 .badge

상태가 아닌 정보 — 장비를 지금 누가 움직이는지(자동 · 스케줄 · 수동 · 안전), 개수, 데이터 출처.

자동 · R2 스케줄 수동 안전 R1 미확인 기상청 단기예보
클래스뜻
.badge--auto자동 규칙 · 스케줄이 움직임 (brand)
.badge--manual사람이 직접 — 자동 규칙 1시간 멈춤 (노랑 옅게)
.badge--safe안전 규칙 (강풍 · 강우) — 수동보다 우선 (빨강 옅게)
.src데이터 출처 한 줄 (공공 API · 시뮬레이터)

카드 .card

화면을 나누는 기본 판. 제목 줄(.card__h)은 아이콘 + 제목 + 오른쪽 "더 보기".

오늘 자동제어규칙
14:122동 천창 50% · R2완료
02:14뒤편 퇴치기 30초 · R9 멧돼지완료

KPI 칸 .kpi

라벨 → 큰 값 → 한 줄 설명. 누르면 자세히(알림 센터 · 바람 · 비 3D)로. 3D 로 이어지는 칸은 오른쪽에 .kpi__go 표시.

농장 상태
정상 1주의 1
3동 · 센서 21 · 카메라 4
진행 중 알림 3건 미확인 2 · 경고 1 · 장애 1
외부 날씨3D 24.6℃ 맑음 습도 48% · 북서 3.2m/s
클래스설명
.kpi--alert진행 중 알림이 있을 때 경고색 테두리
.kpi--wx · .kpi__go누르면 3D 에 바람 · 비가 겹침 (A-4)
.wxdir바람이 흘러가는 쪽 화살표 · 위가 북 — --deg 로 돌림

측정값 · 게이지 .metric

값만 보여주지 않고 적정 범위 안에서 어디쯤인지를 같이 — 게이지는 위험 | 주의 | 적정 | 주의 | 위험 다섯 칸.

온도31.4℃
습도61%
CO₂540ppm
1018273340℃

알림 항목 .aitem

한 칸에 "무엇이 · 어디서 · 언제 → 무슨 일 → 자동이 무엇을 했나". 안 읽은 알림(.is-unread)은 상태색 바탕 · 테두리.

경고2동 · 고온14:12

온도 30.6℃ — 천창 50% 자동 열림

30℃ 넘은 상태 2분 지속 → 규칙 R2. 33℃ 넘으면 100% + 유동팬.

확인하기
주의예보13:40

내일 03시 강풍 11m/s 예보

안전 규칙 R1 대기 — 강풍이 감지되면 측창 · 천창이 전부 닫혀요.

권장

제목에 값 + 결과: "온도 30.6℃ — 천창 50% 자동 열림". 설명에 이유(규칙)와 다음 단계.

지양

"이상 감지됨" · "TEMP_HIGH" 처럼 무엇이 얼마나인지 없는 제목.

기록 · 타임라인 .log · .tl

짧은 목록은 .log(시각 · 무엇 · 결과), 하나의 사건 경과는 .tl(점 + 세로선).

13:58
추세 경고 10분 사이 +1.9℃

임계치 전에 먼저 알림

14:10
기준 초과 30.2℃ — 2분 지속
14:12
자동제어 R2 → 천창 50% 열기
14:13
결과 확인 개폐율 50% 도달

표 · 키값 · 안내 .tbl · .kv · .note-inline

센서위치값마지막 수신상태
T2-32동 뒤쪽31.4℃14:20주의
T3-23동 가운데—14:02 (18분 전)통신 두절
지금 → 목표
50% → 100%
자동 규칙 R2 · R3
1시간 멈춤 · 15:21 자동 복귀
강풍 · 강우가 감지되면 안전 규칙이 수동 조작보다 먼저 창을 닫아요.

차트 .chart

선은 2px 하나 + 적정 범위 띠(초록 옅게). 비교는 우수농가 띠(회색). 기준선은 경고색. 마우스를 올리면 세로선 + 시각별 값. 축은 하나만 (두 축 차트 금지).

속성설명
data-chart계열 이름 (쉼표로 여러 개 — 동 색 순서대로)
data-names · data-unit범례 이름 · 단위
data-range적정 범위 띠 (최소,최대)
data-peer우수농가 범위 띠
data-thr · data-marks기준선 값 · 사건 표시 ("14:12 천창 50%")

드로어 · 바텀시트 .drawer

3D 라벨 · 카메라 · 날씨를 누르면 뒤 화면(3D)을 그대로 두고 오른쪽에서 열린다. 폰에서는 같은 마크업이 아래에서 올라오는 바텀시트가 된다 (손잡이 자동).

2동 센서 T2-3

온도 · 2동 뒤쪽 1.5m

주의 · 적정보다 높음 31.4℃
클래스설명
.overlay (.overlay--clear)뒤 어둡게 / 3D 를 보여야 할 때는 투명
.drawer폭 30em · 오른쪽 · 머리 / 몸통(스크롤) / 바닥(버튼)
.drawer--peek폰에서 높이 54% — 위 3D 가 보이게 (바람 · 비 · 야생동물)
폰 (< 600)아래 고정 · 위 모서리 1.4em · 최대 86% · 손잡이

확인 다이얼로그 .dialog

되돌리기 어려운 동작 · 장비 명령 전에만. 제목은 질문, 내용은 지금 → 목표 · 걸리는 시간 · 멈추는 자동 규칙, 주 버튼은 질문의 동사.

2동 천창을 100%까지 열까요?

지금 → 목표
50% → 100%
걸리는 시간
약 40초
자동 규칙 R2 · R3
1시간 멈춤 · 15:21 자동 복귀

메뉴 · 상단바 · 탭바 .side · .top · .tabbar

껍데기는 화면에 적지 않고 data-shell="메뉴키" 로 넣는다 (spec.js). 화면 크기에 따라 같은 메뉴가 왼쪽 메뉴 → 아이콘 레일 → 하단 탭바로 바뀐다 (앱 껍데기 패턴).

모니터링

대시보드 알림2 기기 상태1

대시보드

햇살농원 · 토마토 3동 24.6℃북서 3.2m/s
클래스설명
.nav-i (.is-on)메뉴 한 줄 · 선택은 brand-weak · 배지는 위험(빨강) / 장애(보라)
.top제목 · 농장 · 날씨(누르면 3D 바람 · 비) · 시각 · 알림
.tabbar · .tab폰 하단 5칸: 홈 · 알림 · 제어 · 기기 · 더보기

카메라 영상 .video

16:9 판. 위에 카메라 이름 · LIVE · 시각, 아래에 설명. 알림 순간의 스냅샷도 같은 모양.

LIVECAM-1 · 2동 입구14:20:31
CAM-4 · 뒤편 경계 · 열화상02:14:05
AI 감지 · 멧돼지 92%

3D 라벨 .f3l

3D 엔진이 위치를 계산해 HTML 로 붙인다 (글자가 선명하고 누를 수 있음). 멀리서는 동 대표값 + 이상 센서만, 확대하면 센서 전부. 누르면 센서 상세 · 카메라 영상으로.

2동30.6℃ T2-331.4℃ T3-2두절 CAM-12동 입구 T1-225.6℃
클래스쓰는 곳
.f3l--zone동 대표값 (동 위 크게)
.f3l.is-pulse주의 이상 · 장애 — 깜빡이는 고리
.f3l.is-dim값 없음 · 통신 두절 (점선)
.f3l--cam · --sm · --sel카메라 / 확대 시 일반 센서 / 공간 편집에서 선택

3D 도구 .f3d-tools · .f3d-views · .f3d-wx

3D 모서리에 고정: 왼쪽 위 = 보는 항목, 왼쪽 아래 = 범례, 오른쪽 아래 = 시점(나침반 · 전체 보기 · 회전 · 바람). 날씨 칩은 바람 · 비가 켜졌을 때만.

서남서 11m/s비 8mm/h · 돌풍 15내일 03시 · 예보
정상주의경고위험장애히트맵 낮음 · 높음
N

앱 껍데기 data-shell

모든 메뉴 화면은 같은 껍데기 안에 본문(.app__main)만 바뀐다. 메뉴 이동 때 메뉴 · 상단바는 그대로, 본문만 교체 (앱처럼). 아래 두 화면은 같은 마크업을 1920 · 390 폭으로 그린 것.

전체 12미확인 2경고
경고2동 · 고온14:12

온도 30.6℃ — 천창 50% 자동 열림

장애3동 · 센서14:02

온도 센서 T3-2 통신 두절

주의예보13:40

내일 03시 강풍 11m/s 예보

2동 온도 30.6℃ — 천창 50% 자동 열림

모니터 1920 — 왼쪽 메뉴 · 목록 + 상세 나란히

전체 12미확인 2
경고2동 · 고온14:12

온도 30.6℃ — 천창 50% 자동 열림

30℃ 넘은 상태 2분 지속 → 규칙 R2

장애3동 · 센서14:02

온도 센서 T3-2 통신 두절

주의예보13:40

내일 03시 강풍 11m/s 예보

폰 390 — 탭바 · 목록만 (상세는 눌러서)

마크업

    <div class="scr app" data-shell="alerts" data-title="알림 센터" data-back="main">
      <main class="app__main">
        … 화면 내용만 …
      </main>
    </div>
    <!-- spec.js 가 .side(왼쪽 메뉴) · .top(상단바) · .tabbar(폰) 를 넣는다. data-shell = 켜질 메뉴 -->
  

3D 대시보드 .f3d[data-farm3d]

아래는 실제 3D 엔진이다 — 끌어서 돌리고, 휠로 확대하고, 온도 · 습도 · 히트맵을 바꿔 보세요. 테마를 바꾸면 3D 색도 바뀐다.

3D 불러오는 중…
정상주의경고위험장애히트맵 적정보다 낮음 · 높음

farm3d.js · Three.js r160 — 화면 명세서 A-1 과 같은 장면 (데모 농장 : 연동형 3동 8×50m · 센서 21 · 카메라 4)

규칙

무엇규칙
라벨 양멀리서 = 동 대표값 + 이상 센서 + 카메라. 가까이(확대) = 센서 전부. 폰은 동 이름 · 이상 센서만
장비실제 상태 그대로 움직임 — 천창 개폐율만큼 열림, 켜진 팬 회전, 카메라는 바닥에 비치는 범위
색라벨 테두리 = 상태 색. 히트맵 = 적정보다 낮음(파랑) · 적정(회색) · 높음(빨강) — 상태 색과 다른 축
방향출입구가 남쪽 · 나침반(N)이 시점과 같이 돈다. 바람 화살표는 바람이 흘러가는 쪽
그리기바뀔 때만 다시 그림 (배터리). 시점 이동 750ms, 사용자가 끌면 멈춤
누르기라벨 · 카메라 몸체 → 센서 상세 · 카메라 영상 (드로어, 3D 는 뒤에 그대로)

알림 흐름

알림 하나를 열면 "무엇이 · 왜 · 무엇을 했고 · 결과는 · 누구에게 갔나"가 한 화면에 있어야 한다. 순서: 머리(상태 · 제목 · 메타 · 동작) → 발생 전후 차트 → 타임라인 → 전달 단계.

2동 온도 30.6℃ — 천창 50% 자동 열림

경고2동 · 고온· 14:12 발생 · 8분째· 규칙 R2미확인
알림 전달
앱 푸시 · 김농부, 이반장14:12
위험(35℃↑)으로 오르면 문자5분 미확인
그래도 미확인이면 전화10분
등급전달화면
주의앱 안에만알림 센터 · 3D 라벨 깜빡임
경고앱 푸시+ 대시보드 오른쪽 위 · 알림 배지
위험푸시 + 문자 → 미확인 시 전화+ 상단 알림 점
장애푸시 (기기 담당)기기 상태 · 3D 점선 라벨

장비 제어 .dev

장비 카드 하나에 지금 상태 · 누가 움직이는지(배지) · 왜(한 줄). 사람이 누르면 자동 규칙이 멈춘다는 것을 누르기 전에 확인 창으로 알려준다. 안전 규칙(강풍 · 강우)은 항상 우선.

천창

2동 지붕

자동 · R2
50%열림 · 14:13 도달

30℃ 넘어 R2가 14:12에 열었어요 · 27℃ 아래면 닫힘

보광등

2동

수동
꺼짐15:21 자동 복귀

김농부가 14:21에 껐어요 · 자동 규칙 1시간 멈춤

  1. 명령 — 버튼을 누르면 확인 창(확인 다이얼로그) : 지금 → 목표 · 걸리는 시간 · 멈추는 규칙과 복귀 시각.
  2. 결과 확인 — 명령 후 실제 값(개폐율 · 전류)이 바뀌는지 본다. 2분 안에 안 바뀌면 "제어 실패" 위험 알림.
  3. 복귀 — 1시간 뒤 자동 규칙 복귀. 배지가 수동 → 자동으로 돌아온다.

화면 크기 @container screen

기준은 창(viewport)이 아니라 화면 루트의 폭(컨테이너 쿼리) — 명세서 · 가이드 안의 작은 화면에서도 같은 규칙이 걸린다. 큰 화면은 같은 내용을 키우지 않고 보여주는 양을 늘린다.

폰 세로< 600탭바 · 세로 쌓기 · 드로어 → 바텀시트 · 3D 더 멀리서 · 라벨 줄임 · --u: 1.04px
패드 (세로 · 가로)600 – 1439왼쪽 메뉴 → 아이콘 레일 · 3D + 오른쪽 알림 열 · KPI 4칸 · 알림 목록 + 상세 좁게
모니터 24″1440 – 2199기본 (원본 화면). 대시보드는 스크롤 없이 한 화면
27″ · 32″ 150%≥ 2200+ 카메라 작은 창 · 동별 24시간 차트 · 장비 4열 · --u: 1.12px
32″ 4K 100%≥ 3200배치는 2560 과 같고 글자 · 간격만 --u: 1.6px
    /* 크기는 --u(px) × em — 화면 폭이 커지면 --u 만 바꾼다 */
    .scr { font-size: calc(var(--u) * 14); }
    @container screen (max-width: 599px) { .scr { --u: 1.04px; } }
    @container screen (min-width: 3200px) { .scr { --u: 1.6px; } }
    /* 보이기 · 숨기기 */
    .only-phone · .hide-phone · .only-monitor (≥ 1440) · .only-wide (≥ 2200)
  
권장

폰과 패드에서 버튼 · 토글은 최소 44 × 44px. 장갑 · 젖은 손으로도 누를 수 있게. 마우스 올림(hover)에만 있는 정보를 만들지 않는다.

지양

@media (창 폭) 로 화면 규칙 쓰기 — 명세서 · 가이드 안의 작은 화면에서는 걸리지 않는다.

문구

읽는 사람은 농장주 · 현장 관리자. 시스템 말 대신 농장에서 쓰는 말로, 짧게.

규칙이렇게이렇게 쓰지 않음
장소 → 무엇 → 값2동 온도 30.6℃TEMP_SENSOR_2 HIGH
자동이 한 일 + 이유천창 50% 자동 열림 (R2)제어 명령 전송됨
다음에 일어날 일33℃ 넘으면 100% + 유동팬(없음)
상태 단어는 다섯 개만정상 · 주의 · 경고 · 위험 · 장애심각 · 이상 · 에러 · Critical
시각14:12 · 어제 22:40 · 내일 03시2026-10-13T14:12:00
말투 — 해요체, 짧게센서 연결이 끊겼어요센서와의 통신이 원활하지 않습니다
버튼 = 동사확인했어요 · 100% 열기 · 장비 제어확인 · 예 · 실행
방향북서풍 → 남동쪽으로 (16방위)315°
스마트팜 IoT 디자인 가이드 · v1 2026-10-14

원본 : frontend/guide-src/* + frontend/spec-src/screens.css → bash frontend/guide-src/build.sh

화면 명세서 iot.html 와 같은 CSS 를 쓴다
↑↓ 이동 Enter 열기 Esc 닫기