0.9.0 까지가 "감지하는 시스템"이었다면 1.0.0 은 "감지에 대응하는 시스템"이다. 그 차이를
만드는 것은 e00ad69 의 통보 경로이고, 이 커밋은 그것을 실제로 납품 가능한 형태로 만든다.
VERSION 0.9.0 -> 1.0.0
릴리스 규칙 위반 3건 수정 (rules/release-versioning.md)
- 산출물 파일명에 버전·날짜가 없었다. move-detect-cafe24.zip / 2_pi_install-<arch>.tar.gz
는 같은 날 두 번 빌드하면 구분이 안 되고, 현장이 무엇을 돌리는지 파일명으로 답할 수
없었다. 이제 move-detect-cafe24-<VERSION>-<YYYYMMDD>.zip /
move-detect-pi-<VERSION>-<YYYYMMDD>-<arch>-<abi>-<hailo>.tar.gz.
- 두 빌드 스크립트가 VERSION 파일이 없으면 "unknown" 으로 넘어갔다. 무버전 산출물은
빌드머신을 떠나는 순간 커밋과 대조할 방법이 사라진다 — 이제 exit 1 로 거부한다.
- deploy/README.md 의 stale 파일명 표기 갱신.
납품 동봉물 (skill delivery-audit: "설명서 + 점검 리포트 동봉")
- CHANGELOG.md 신설. 업그레이드 절차와 알려진 제약(모델 미확보 3종)을 명시.
- 역할별 사용 설명서를 패키지에 동봉. 운영자/안전관리자/시스템관리자 3역할 14절 + FAQ 6항,
실제 화면 캡처 8장을 base64 로 박은 단일 HTML(665KB). 폐쇄망에서 메일·USB 로 돌아다녀도
도판이 깨지지 않아야 하므로 단일 파일이다.
생성물은 커밋하지 않는다 — 소스(manual.json + shots/)만 두고 패키저가 매번 빌드한다.
커밋된 사본은 화면이 바뀐 뒤에도 최신처럼 보이고, 구 UI 캡처가 남은 매뉴얼은 납품물
자체의 결함이다.
- 감사 리포트를 '납품점검-리포트.md' 로 동봉. 무엇을 점검했고 무엇이 잔여인지 패키지가
스스로 답하지 못하면, 인수인계 몇 달 뒤 그 답을 아는 사람이 남지 않는다.
README-UPLOAD 에 크론 안내 신설 (누락이었다)
설치 안내서에 자동 실행 등록이 아예 없었다. 이 릴리스의 핵심인 통보가 크론 없이는 한 건도
나가지 않는데, 운영자가 읽는 유일한 문서가 그 사실을 말하지 않았다.
8번(알림 켜기: 크론 2개 + --dry-run 선행 + 경광등 우선) / 9번(설치 점검 /setup) 추가,
마지막 체크리스트에 3항목 추가.
부수 수정
- 셸 스크립트에 CRLF 가 섞여 bash 가 여는 중괄호에서 죽었다(빌드 자체가 불가). LF 로 정규화.
cafe24 스크립트에는 bash -n 가드가 이미 있어 이번에 실제로 잡았고, Pi 쪽에는 없어서
그대로 지나갈 뻔했다 — tests/test_deploy_artifacts.py 에 CRLF·bash -n 가드 추가.
산출물
dist/move-detect-cafe24-1.0.0-20260818.zip
dist/move-detect-pi-1.0.0-20260818-aarch64-cp311-hailo8.tar.gz
검증: pytest 통과(skip 3 = 하드웨어·환경) · PHPUnit 224 (skip 0).
매뉴얼 실렌더 확인(목차 정합·도판 8장·콜아웃). 패키지 내부 검증: 버전 스탬프 1.0.0,
마이그레이션 8/8 동봉, config.php 는 CHANGEME 템플릿, tools/ 는 www 밖에만,
웹 루트 PHP 는 index.php/_preflight.php 뿐.
9.9 KiB
카페24 업로드 안내
이 폴더의 내용물을 카페24 FTP 최상위에 그대로 올리면 됩니다.
고칠 파일은 config.php 하나뿐입니다.
1. 올리는 위치 (제일 중요)
폴더 2개만 올리면 됩니다. move_detect_app 과 www.
/ <- FTP 최상위
├── (기존 사이트 파일) <- 건드리지 않습니다
├── move_detect_app/ <- [올리기 1] 통째로. 웹에서 안 보입니다
│ ├── config.php 여기만 고칩니다
│ ├── src/
│ ├── vendor/
│ ├── storage/snapshots/ 사진 저장
│ └── schema.sql DB 넣고 나면 지웁니다
└── www/ <- 원래 있던 폴더 (다른 사이트가 씀)
├── (기존 사이트 파일) <- 건드리지 않습니다
└── move_detect/ <- [올리기 2] 이 폴더만 새로 생깁니다
├── index.php
├── .htaccess
├── _preflight.php
└── assets/
접속 주소는 https://내도메인/move_detect/ 입니다.
README-UPLOAD.md(이 파일)는 올릴 필요 없습니다.
왜 move_detect_app 을 www 밖에 두나: config.php 에 DB 비밀번호가, storage/snapshots/
에 작업자 사진이 들어갑니다. www 안에 있으면 같은 www 를 쓰는 다른 사이트 주소로 접근될
수 있습니다. 한 폴더로 묶은 건 최상위에 있는 남의 파일(vendor/, config.php 같은 흔한
이름)과 겹쳐 덮어쓰는 사고를 막기 위해서입니다.
업로드가 끝나면 FTP 클라이언트에서 권한을 지정하세요. zip 과 FTP 는 유닉스 권한을 옮기지 못하므로, 패키지에 넣어둔 권한은 올리는 순간 사라집니다.
| 대상 | 권한 |
|---|---|
move_detect_app/config.php |
600 (DB 비밀번호가 들어있습니다) |
move_detect_app/storage/snapshots/ |
750 |
_preflight.php 가 실제 권한과 노출 여부를 확인해줍니다.
2. config.php 고치기
DB 세 줄만 카페24 관리자 페이지의 MySQL 정보로 바꿉니다.
'db_dsn' => 'mysql:host=localhost;dbname=여기에_DB이름;charset=utf8mb4',
'db_user' => '여기에_MySQL아이디',
'db_pass' => '여기에_MySQL비밀번호',
나머지 값은 그대로 두면 됩니다. 비밀번호는 메일/메신저/깃에 올리지 마세요.
3. DB 만들기
처음 설치(빈 DB)
- 카페24 관리자 → phpMyAdmin 열기
- 이 앱용 DB 선택
- Import(가져오기) 탭 →
schema.sql선택 → 실행 - 표 11개가 생겼는지 확인
- 서버에서
schema.sql삭제 — 남겨둘 이유가 없습니다
schema.sql 은 항상 최신 상태입니다. 처음 설치라면 아래 마이그레이션은 실행하지 마세요
(이미 반영되어 있어 충돌합니다).
이미 쓰던 DB 업그레이드(기존 데이터 있음)
⚠️ 기존 DB에
schema.sql을 다시 Import 하면CREATE TABLE충돌로 실패합니다. 대신 마이그레이션을 실행하세요.
반드시 아래 순서대로, 아직 적용하지 않은 것부터 전부 실행합니다. 하나라도 건너뛰면
그 컬럼·표를 쓰는 요청이 전부 500 이 됩니다. 순서가 중요한 이유는 뒤 파일이 앞 파일이 만든
표 이름(move_ 접두사)을 전제하기 때문입니다.
| 순서 | 파일 | 무엇이 바뀌나 |
|---|---|---|
| 1 | 2026-07-17-p1-9-p3-2b.sql |
site / event_uuid 컬럼 + 인덱스, 기존 이벤트 site 백필 |
| 2 | 2026-07-20-move-table-prefix.sql |
모든 표 이름에 move_ 접두사 부여 (이 단계를 건너뛰면 이후 전부 실패) |
| 3 | 2026-08-06-zone-rules.sql |
존 점유 규칙(rules_json) |
| 4 | 2026-08-06-heatmap-spatial.sql |
히트맵 좌표(spatial_x, spatial_y) |
| 5 | 2026-08-06-false-positive-tag.sql |
오탐 태그 컬럼 |
| 6 | 2026-08-07-improvement-actions.sql |
개선 조치 표(move_actions) |
| 7 | 2026-08-08-actions-site.sql |
개선 조치의 현장(site) 스코프 |
- phpMyAdmin → 해당 DB → SQL 탭
- 위 표의 순서대로 파일 내용을 하나씩 붙여넣고 실행합니다 (각 파일 첫머리에 적용 조건이 주석으로 적혀 있습니다)
- 각 파일 맨 아래 검증 쿼리로 컬럼·표가 생겼는지 확인
- 전부 끝난 뒤에 새 코드를 배포합니다
이미 적용한 마이그레이션을 다시 실행하면 "Duplicate column" 같은 오류가 납니다 — 재실행은 안전하지 않으니, 어디까지 적용했는지 기록해 두세요. 어디까지 했는지 모르겠으면 phpMyAdmin 의 Structure(구조) 탭에서 위 표의 컬럼·표가 있는지 하나씩 확인하면 됩니다.
4. HTTPS 켜기
카페24 관리자에서 무료 SSL 인증서를 켭니다.
선택이 아니라 필수입니다. 로그인 세션 쿠키가 cookie_secure=true 라서,
HTTP 로는 브라우저가 쿠키를 아예 안 보냅니다 → 로그인이 안 됩니다.
5. 점검하기
브라우저에서 엽니다:
https://내도메인/move_detect/_preflight.php
전부 OK 여야 합니다. 실패한 줄에 무엇을 하면 되는지 적혀 있습니다.
특히 이 둘은 카페24 요금제에 따라 없을 수 있고, 없으면 카페24에 문의해야 합니다:
| 항목 | 없으면 생기는 일 |
|---|---|
| Argon2id | 로그인 페이지가 즉시 죽습니다. 제일 흔한 실패 원인입니다. |
| gd | 이벤트는 저장되는데 사진만 조용히 사라집니다. 에러도 안 납니다. |
확인이 끝나면 www/move_detect/_preflight.php 를 지우세요.
6. 관리자 계정 만들기
앱에 회원가입 기능이 없습니다. 첫 계정은 직접 넣습니다.
비밀번호 해시를 만듭니다(로컬 PC 에서 실행 — 평문이 phpMyAdmin 기록에 남지 않게):
php -r "echo password_hash('여기에_진짜_비밀번호', PASSWORD_ARGON2ID), \"\n\";"
phpMyAdmin → SQL 탭:
INSERT INTO move_users (username, password_hash, role, site_scope, failed_attempts, locked_until)
VALUES ('admin', '여기에_해시_붙여넣기', 'admin', NULL, 0, 0);
7. 라즈베리파이(장비) 등록
장비마다 비밀키를 하나씩 만들어 DB 에 넣습니다.
php -r "echo bin2hex(random_bytes(32)), \"\n\";"
INSERT INTO move_devices (device_id, name, secret, config_version)
VALUES ('pi-01', '3라인 낙상 카메라', '여기에_비밀키_붙여넣기', 1);
같은 값을 파이 쪽 /etc/move-detect/edge.env 의 DEVICE_SECRET 에 넣습니다.
CAFE24_URL 에는 https://내도메인/move_detect 를 넣습니다. (앱이 서브폴더에 있으므로
뒤의 /move_detect 까지 반드시 포함해야 합니다.)
비밀키는 메일/메신저로 보내지 마세요.
8. 알림 켜기 (자동 실행 등록) — 이걸 안 하면 알림이 안 갑니다
여기까지만 하면 시스템은 감지는 하지만 아무에게도 알리지 않습니다. 화면을 보고 있는 사람에게만 보입니다. 새벽에 넘어진 작업자를 아무도 모른 채 아침을 맞게 됩니다.
카페24 관리자 페이지 → 자동실행관리(크론) 에서 아래 두 개를 등록하세요.
| 주기 | 실행할 명령 | 하는 일 |
|---|---|---|
| 1분마다 | /usr/bin/php /home/<계정>/move_detect_app/tools/dispatch_alerts.php |
알림 발송 · 미확인 경보 상위 통보 · 실패 재시도 |
| 하루 1회 (새벽) | /usr/bin/php /home/<계정>/move_detect_app/tools/maintain.php |
사진 보존기간 정리 · 기록 용량 관리 |
<계정> 자리에는 카페24 FTP 계정명을 넣습니다. 경로가 헷갈리면 FTP 로 접속했을 때
move_detect_app 폴더가 보이는 그 위치입니다.
처음 켤 때는 반드시 시험 발송부터
잘못된 수신자 목록으로 첫 발송을 하면 그 현장에서는 두 번 다시 이 기능을 켜지 않게 됩니다. 크론에 넣기 전에 아래를 한 번 실행해 누구에게 무엇이 갈지만 확인하세요 (아무것도 보내지 않습니다).
php /home/<계정>/move_detect_app/tools/dispatch_alerts.php --dry-run
알림 경로 설정
로그인 후 상단 [시스템 설정] → 통보 경로 에서 등록합니다.
- 현장 경광등을 가장 먼저 설정하세요. 라즈베리파이가 직접 울리므로 인터넷이 끊겨도 동작하는 유일한 경로입니다. 정전·회선 장애 때 오히려 위험이 높아지는 시간대에 유일하게 살아 있는 알림입니다.
- 메일·웹훅은 그 위에 얹는 보조 수단이고, 위 크론이 돌아야 나갑니다.
config.php의public_base_url이 비어 있으면 디스패처는 실행을 거부합니다 — 열리지 않는 링크가 담긴 알림을 보내는 것보다 안 보내는 편이 낫기 때문입니다.
9. 설치 점검 화면
로그인 후 https://내도메인/move_detect/setup 을 엽니다.
각 단계는 실제 상태를 조회해서 표시하므로, 체크가 켜졌다면 그 단계는 정말로 동작하고 있는 것입니다. 장치 등록 · 장치 통신 · 카메라 감지 · 위험구역 · 통보 경로 순서대로 확인하세요.
10. 마지막 확인
https://내도메인/move_detect/login이 열린다- admin 으로 로그인되고 대시보드가 뜬다
schema.sql을 서버에서 지웠다www/move_detect/_preflight.php를 서버에서 지웠다https://내도메인/move_detect_app/config.php가 안 열린다 (열리면 위치가 잘못된 것)- 자동실행(크론) 2개가 등록되어 있다 — 없으면 알림이 나가지 않습니다 (8번)
[시스템 설정] → 통보 경로에 최소 1개가 '사용' 상태다 (현장 경광등 우선)/setup화면의 모든 단계에 체크가 켜져 있다 (9번)