LOCATION_AUTOMATION_DESIGN - zero1ne-26/doc GitHub Wiki
์ฅ์ ๋์ฐฉ ์๋ํ (Location Automation) ์ค๊ณ
์์ฑ์ผ: 2026-08-22 ยท ์ํ: 1์ฐจ ๊ตฌํ ์๋ฃ (orchestration-server
6c0c7e0, ๋ง์ด๊ทธ๋ ์ด์ 085)๊ตฌํ ๋ฒ์: ยง3 ํ ์ด๋ธ 3๊ฐ ยท ยง4 ์คํ ์์ง(
internal/mqttx/arrival_automation.go) ยท Admin REST (/admin/{tasks|events|locations}/:id/automations,/admin/automations[/runs|/:id/fire]) ยท ๋ฐฑ์คํผ์ค(ํ์คํฌ/์ด๋ฒคํธ/์ฅ์ ์์ธ ํธ์ง๊ธฐ, ๋ก๋ด ์ฐ๋ โ ๊ท์น ๋ชฉ๋กยท์คํ ๋ก๊ทธ). ๋ฏธ๊ตฌํ: ยง4.4automation/firedํ ํฝ(FE ์์ ๋ฏธํ์ธ), ยง6-5 ์ธ์ ์ข ๋ฃ ์ ๋๊ธฐ ์ก์ ์ทจ์,leave/dwellํธ๋ฆฌ๊ฑฐ, ยง6-1 ์๋>์๋ ์ฐ์ ์์. ๋ก๋ดํยท๋ฐ๋ ค๋ก๋ด์ ์คํค๋ง ํ์ ์ ๊น์งparams.topic+ payload JSON ์์ ์ ๋ ฅ. 2026-08-22 ์ถ๊ฐ: ยง4.3 ๋๋ฐ์ด์ค ๋ช ๋ น ํ(SQS FIFO, ์๋ฃ ๋๊ธฐยทํ์์์ยท์ก์ ์ฒด์ธ) ๊ตฌํ. 2026-09-12 ์ถ๊ฐ:leave(์ฅ์ ์ดํ) ํธ๋ฆฌ๊ฑฐ ๊ตฌํ (๋ง์ด๊ทธ๋ ์ด์ 114, ยง4 ์ฐธ๊ณ ). Vision์ด ์ธ์ ์์น๋ฅผ ๋ค๋ฅธ ์ฅ์๋ก ๋ฐ๊ฟ ๊ธฐ๋กํ๋ ์๊ฐ ์ง์ ์ฅ์์ ๊ท์น์trigger='leave'๋ก ํ๊ฐํ๋ค. ๊ท์น ๋ชจ๋ธยท์กฐ๊ฑดยท ๋ฐํ ์ ์ฑ ยท์ก์ ยท์คํ ๋ก๊ทธ๋ ๋์ฐฉ๊ณผ ๋์ผํ๋ฉฐ ๋ชจ๋ owner(ํ์คํฌ/์ด๋ฒคํธ/์ฅ์)์ ๋ถ์ผ ์ ์๋ค. ํ์ฒ๋ฆฌ ์ฐ์ถ์ด๋ฏ๋ก ์ก์ ์user_task_commands๋ก ์ถ์ ํ์ง ์๋๋ค(ํ์คํฌ ์๋ ์๋ฃ ๋ฌด๊ด).dwell์ ์ฌ์ ํ ๋ฏธ๊ตฌํ. 2026-09-12 ์ถ๊ฐ (117): ํ์คํฌ ์คํ ๋ฐฉ์tasks.execution_mode=parallel(๊ธฐ๋ณธ, ๋์ ์งํ) |sequential(์์ฐจ). ์์ฐจ ํ์คํฌ์ ๋์ฐฉ ๊ท์นยท์๋ ์์์ ๊ฐ์ ์ฅ์์ ์ ์์ ํ์คํฌ๊ฐ ์ ๋ถ ์ข ๊ฒฐ๋ ๋๊น์ง ๋ณด๋ฅ(skip_reason=waiting_predecessor)๋๊ณ , ์ ํ์คํฌ ์ข ๊ฒฐ ์OnUserTaskFinished๊ฐ ์ฌ์ฉ์๊ฐ ์์ง ๊ทธ ์ฅ์์ ์์ผ๋ฉด ๋๊ธฐ๊ฐ ํ๋ฆฐ ํ์คํฌ์ ๊ท์น๋ง ์ฌํ๊ฐํ๋ค(RunArrivalParams.OnlyTaskIDs). ์ํ ๋ฐํ/๊ฐ์ ์คํ์ ํต๊ณผ. 2026-09-12 ์ถ๊ฐ (119):device_command_logsโ ํ๊ฐ ๋ณด๋ธ ๋ช ๋ น(pub)๊ณผ ๋ก๋ด ์๋ต(sub: ackยทplanยทhub response)์ command_id ๋ก ๋ฌถ์ด ์๋ฌธ ์ ์ฅ.GET /admin/automations/runs/:runId/logs๋ก ์คํ 1๊ฑด์ ์ก์์ ๋ก๊ทธ๋ฅผ ๋ฐ์ ํ์ดํ๋ผ์ธ ์คํ ์ด๋ ฅ์์ ๋จ๊ณ๋ณ๋ก ๋ณธ๋ค. 2026-09-12 ์ถ๊ฐ: ํ์คํฌ ์์ธ ํ ์คํธ ํจ๋ โ ์ธ์ ์ ๊ณจ๋ผ ์ ์ ์กฐ๊ฑด(์ธ์ ํ์ฑยท์ฝ์ค ํฌํจยท๋ฐฐ์ ยท์ํยทํ์ฌ ์์นยท ์์ฐจ ์ ํ์คํฌยท๊ท์นยท์์ดํ ยทSPOT/๋ก๋ดํ ๊ฐ์ฉ์ฑยทํ์ ๋ณ)์ ์ ๊ฒํ๊ณ ๋ฒํผ์ผ๋ก ๋ฐ๋ก ์กฐ์นํ ๋ค ๋์ฐฉ ์๋ฎฌ๋ ์ด์ (Vision ๊ฒฝ๋ก ๋์ผ) ๋๋ ๊ฐ์ ์คํ.GET/POST /admin/tasks/:id/test/{preflight,fix}(internal/handlers/task_preflight.go).์ฌ์ฉ์๊ฐ ํน์ ์ฅ์์ ๋์ฐฉํ ๊ฒ์ Vision ์์น ์ ๋ณด๋ก ๊ฐ์งํ์ ๋, ๊ทธ ์ฌ์ฉ์์๊ฒ ๊ทธ ์ฅ์์ ๋ฐฐ์ ๋ ํ์คํฌ/์ด๋ฒคํธ์ ๋ณด์ ์์ดํ ์ ๋ฐ๋ผ SPOT ยท ๋ก๋ดํ ยท ๋ฐ๋ ค๋ก๋ด ยท Hub ๋ฑ์ ์ด๋๋ฏผ์ด ๋ฏธ๋ฆฌ ์ ์ํ ๋ช ๋ น์ ์๋์ผ๋ก ๋ด๋ฆฌ๋ ๊ธฐ๋ฅ์ ๋ฐ์ดํฐ ๋ชจ๋ธ ยท ์๋ฒ ์คํ ํ๋ฆ ยท ๋ฐฑ์คํผ์ค ํ๋ฉด ๊ตฌ์กฐ ์ ์.
๋ชฉ์ฐจ
- ๋ฐฐ๊ฒฝ๊ณผ ๋ชฉํ
- ํ์ฌ ์๋ ๊ฒ (์ฌํ์ฉ)
- ๋ฐ์ดํฐ ๋ชจ๋ธ
- ์๋ฒ ์คํ ํ๋ฆ
- ๋ฐฑ์คํผ์ค ํ๋ฉด ๊ตฌ์กฐ
- ์ ์ฑ ๊ฒฐ์ ์ฌํญ
- ๋จ๊ณ๋ณ ๊ตฌํ ์์
- ๋ฏธ๊ฒฐ ์ฌํญ
1. ๋ฐฐ๊ฒฝ๊ณผ ๋ชฉํ
- Vision(์นด๋ฉ๋ผ ํธ๋ํน)์
vision/position/person์ผ๋ก ๋ฐฉ๋ฌธ๊ฐ ์ขํยทzone_id๋ฅผ ๊ณ์ ๋ฐํํ๋ค. - ์๋ฒ๋ ์ด๋ฅผ ์ฅ์(
locations)๋ก ๋งคํํดorchestration/{sessionId}/position์ผ๋ก ์ฌ๋ฐํํ๊ณ , ์ฅ์๊ฐ ๋ฐ๋ ์๊ฐ๋งuser_location_history์ ๊ธฐ๋กํ๋ค. - ํ์ฌ "์ฅ์ ๋์ฐฉ ์ ์๋์ผ๋ก ์ผ์ด๋๋ ์ผ"์ ๋๋ฐ ์ด๋ฒคํธ ๋ฐํ 1๊ฐ์ง๋ฟ์ด๋ค.
- ๋ชฉํ: ๋์ฐฉ ์ ์ฌ๋ฌ ๋๋ฐ์ด์ค(SPOT, ๋ก๋ดํ, ๋ฐ๋ ค๋ก๋ด, Hub)์ ๋ช ๋ น์ ์์๋๋ก ์๋ ๋ฐํํ๊ณ , ๊ทธ ๊ท์น์ ์ด๋๋ฏผ์ด ๋ฐฑ์คํผ์ค์์ ์ ์ยทํ์ธยทํ ์คํธํ ์ ์๊ฒ ํ๋ค.
- ํต์ฌ ์ ์ : "๋ฌด์์ ์๋ ์ํํ ์ง"๋ ์ฅ์ ์์ฒด๊ฐ ์๋๋ผ (์ฌ์ฉ์, ์ฅ์, ํ์คํฌ or ์ด๋ฒคํธ) ๋งคํ์ด
๊ฒฐ์ ํ๋ค. ๊ฐ์ "์ง"์ด๋ผ๋ ์ธ์
๋ง๋ค ๋ฐฐ์ ๋ ํ์คํฌยท์ด๋ฒคํธ๊ฐ ๋ค๋ฅด๊ณ (
user_tasks,user_locations.event_id), ๊ฑฐ๊ธฐ์ ๋ณด์ ์์ดํ ์ ๋ฌด๊ฐ ๋ํด์ ธ ์ํ ์ฌ๋ถ๊ฐ ๊ฐ๋ฆฐ๋ค.
1.1 ํ์ ์ ๋ ฅ ์์ฝ
๋์ฐฉ(์ธ์
S, ์ฅ์ L)
โโ S์๊ฒ L์ ๋ฐฐ์ ๋ ํ์คํฌ : user_tasks โ tasks(location_id = L) โ 0..N๊ฐ
โโ S์๊ฒ L์ ๋ฐฐ์ ๋ ์ด๋ฒคํธ : user_locations(S, L).event_id โ 0..1๊ฐ
โโ (๋ณด์กฐ) L ์์ฒด ๊ท์น : ํ์คํฌยท์ด๋ฒคํธ์ ๋ฌด๊ดํ๊ฒ ์ฅ์์ ์ค๋ฉด ํญ์
โโ S์ ๋ณด์ ์์ดํ
: store_purchases(S) (= orchestration/{S}/store/owned)
โ
์ ํ์คํฌ/์ด๋ฒคํธ/์ฅ์์ ๋ถ์ ์๋ํ ๊ท์น ์ค ์กฐ๊ฑด(์์ดํ
๋ฑ)์ ๋ง์กฑํ๋ ๊ฒ๋ง ๋ฐํ
2. ํ์ฌ ์๋ ๊ฒ (์ฌํ์ฉ)
| ์กฐ๊ฐ | ์์น | ์ฌํ์ฉ ํฌ์ธํธ |
|---|---|---|
| ๋์ฐฉ ๊ฐ์ง | internal/mqttx/vision.go recordLocationChange() โ maybePublishArrivalEvent() |
Vision์ ์ฐ์ ์ขํ๋ฅผ "์ฅ์๊ฐ ๋ฐ๋ ์๊ฐ 1ํ"๋ก ์ด๋ฏธ ๋๋ฐ์ด์ค. ์๋ํ ํ ํฌ์ธํธ๋ ์ฌ๊ธฐ ํ ๊ณณ |
| ์ฌ์ฉ์ โ ์ฅ์ โ ํ์คํฌ/์ด๋ฒคํธ ๋งคํ | user_locations(visit_order, event_id, event_published_at), user_tasks(task_id, status) + tasks.location_id |
์ธ์ ์์ฑ ์ ์ด๋ฏธ ํ์ ๋๋ ๋งคํ. ๋์ฐฉ ์ "์ด ์ธ์ ์ด ์ด ์ฅ์์์ ํ ํ์คํฌ/์ด๋ฒคํธ"๋ฅผ ๋ฐ๋ก ์กฐํ ๊ฐ๋ฅ |
| SPOT ๋ช ๋ น ์ ์ UI | task_options / event_options์ spot_action, spot_destination_mode, spot_params + backoffice/.../components/SpotOptionFields.tsx, spotOptions.ts |
"์ ํ์ง๋ฅผ ๊ณ ๋ฅด๋ฉด SPOT ๋ช ๋ น"์ด ์ด๋ฏธ ๊ตฌํ๋จ. ํธ๋ฆฌ๊ฑฐ๋ง "์ ํ โ ๋์ฐฉ"์ผ๋ก ๋ฐ๊พธ๋ฉด ๊ฐ์ ๋ชจ๋ธ. ํ์คํฌยท์ด๋ฒคํธ ์์ธ ํ๋ฉด์ ์ด๋ฏธ SPOT ์ฐ๋ UI๊ฐ ์์ผ๋ฏ๋ก ๋์ฐฉ ์๋ํ๋ ๊ฐ์ ํ๋ฉด์ ๋ถ์ธ๋ค |
| SPOT ๋์คํจ์น | internal/mqttx/spot.go DispatchSpotCommand(), SpotQueue |
์ธ์
โ ๋ฐฐ์ ์ฅ์ โ devices.type='spot' resolve + ํ์ + ack/plan ๋ฆด๋ ์ด ์ ๋ถ ์ฌ์ฌ์ฉ |
| ๋๋ฐ์ด์ค โ ์ฅ์ ๋ฐฐ์ | devices + ์ฅ์ ๋ฐฐ์ , SpotManagement(waypoint label ๋งคํ) |
๋ก๋ดํยท๋ฐ๋ ค๋ก๋ด๋ ๊ฐ์ ๋ฐฉ์์ผ๋ก devices.type๋ง ์ถ๊ฐํ๋ฉด resolve ๊ฐ๋ฅ |
| Hub ๋ช ๋ น ํฌ๋งท | MQTT_SCHEMA-HUB diorama/{device}/request {session_id, scenario_id, command, target, payload, timestamp} |
๋ฒ์ฉ ํฌ๋งท์ด ์ด๋ฏธ ํ์ |
| ๋ณด์ ์์ดํ ํ์ | task_options.required_product_id + ์คํ ์ด ๊ตฌ๋งค(store_purchase.go, orchestration/{sessionId}/store/owned) |
"์ด ์ํ์ ๊ฐ์ง ์ธ์ ๋ง" ์กฐ๊ฑด์ด ์ ํ์ง ๋จ์๋ก ์ด๋ฏธ ์กด์ฌ โ ๊ท์น ์กฐ๊ฑด์ผ๋ก ๊ทธ๋๋ก ํ์ฅ |
| ํ ์คํธ ๊ฒฝ๋ก | ์ฌ์ฉ์ ์์ธ "์์น ํ
์คํธ" ํญ (POST /admin/users/:id/position/test) |
recordLocationChange๋ฅผ ํ๋ฏ๋ก ์๋ํ ๊ท์น๋ ํจ๊ป ๋ฐํ โ ๋ณ๋ ํ
์คํธ ํ๋ฉด ๋ถํ์ |
โ ๏ธ
MQTT_SCHEMA-ROBOT_ARM,MQTT_SCHEMA-COMPANION_ROBOT์ ์์ง ํ ํฝ๋ช ์กฐ์ฐจ ๋น์ด ์๋ ํ ํ๋ฆฟ์ด๋ค. ์ด ๋ ๋๋ฐ์ด์ค๋ ์คํค๋ง ํ์ ์ ๊น์ง "ํ ํฝ + payload JSON ์์ ์ ๋ ฅ"์ผ๋ก ๋ฐ์๋๋ค (ยง5.3 ์ฐธ๊ณ ).
3. ๋ฐ์ดํฐ ๋ชจ๋ธ
3.1 arrival_automations โ ๊ท์น (์ฃผ์ธ์ ํ์คํฌ / ์ด๋ฒคํธ / ์ฅ์)
| ์ปฌ๋ผ | ํ์ | ์ค๋ช |
|---|---|---|
id |
TEXT PK | UUID v7 |
owner_type |
TEXT | task ยท event ยท location โ ๊ท์น์ด ๋ถ๋ ๋์ ์ข
๋ฅ |
owner_id |
TEXT | tasks.id / events.id / locations.id |
task_status_filter |
TEXT | owner_type='task'์ผ ๋: pending(๊ธฐ๋ณธ, ์์ง ์ ํ ํ์คํฌ๋ง) ยท any |
name |
TEXT | ์ด๋๋ฏผ ํ์์ฉ ์ด๋ฆ (์: "์ง ๋์ฐฉ โ ๋ฐ๋ ค๋ก๋ด ์ธ์ฌ + SPOT ์ถ์ข ") |
trigger |
TEXT | arrive(๋์ฐฉ, ๊ธฐ๋ณธ) ยท leave(์ดํ, 114 โ ๋ค๋ฅธ ์ฅ์๋ก ์ด๋ ๊ธฐ๋ก ์ ์ง์ ์ฅ์ ๊ธฐ์ค) ยท wrong_item/right_item(๋ฌผ๊ฑด ์ง์, 103, ํ์คํฌ ์ ์ฉ) ยท option_selected(ํ์ดํ๋ผ์ธ ์ ํ์ง, 118, ์ด๋ฒคํธ ์ ์ฉ) ยท pending_entered(ํ์คํฌ๊ฐ pending ์ด ๋ ์๊ฐ, 152, ํ์คํฌ ์ ์ฉ) ยท dwell (ํฅํ) |
dwell_seconds |
INTEGER | trigger='dwell'์ผ ๋ ์ฒด๋ฅ ๊ธฐ์ค ์ด |
condition_json |
TEXT(JSON) | {"has_children": true|false|null, "first_visit_only": bool, "persona_ids": [], "required_product_ids": [], "required_products_mode": "all"|"any"} โ null/๋น ๊ฐ์ "๋ฌด๊ด" |
fire_policy |
TEXT | once_per_session (๊ธฐ๋ณธ) ยท every_arrival |
cooldown_seconds |
INTEGER | every_arrival์ผ ๋ ์ฌ๋ฐํ ์ต์ ๊ฐ๊ฒฉ (๊ธฐ๋ณธ 30) |
is_active |
INTEGER | 0/1 |
display_order |
INTEGER | ๊ฐ์ owner ๋ด ํ์ ์์ |
created_at, updated_at |
TIMESTAMP |
์ฅ์๋
owner_type์ผ๋ก ์ ๋๋๋ค โtaskโtasks.location_id,eventโ ๊ทธ ์ธ์ ์user_locations.event_id๊ฐ ๊ฐ๋ฆฌํค๋ ์ฅ์,locationโ ์๊ธฐ ์์ . ๊ท์น ํ ์ด๋ธ์location_id๋ฅผ ์ค๋ณต ์ ์ฅํ์ง ์๋๋ค (ํ์คํฌ๊ฐ ๋ค๋ฅธ ์ฅ์๋ก ์ฎ๊ฒจ์ ธ๋ ๊ท์น์ด ๋ฐ๋ผ๊ฐ๋๋ก).
3.2 arrival_automation_actions โ ๊ท์น 1๊ฐ โ ์์ ์๋ ์ก์
N๊ฐ
| ์ปฌ๋ผ | ํ์ | ์ค๋ช |
|---|---|---|
id |
TEXT PK | |
automation_id |
TEXT FK โ arrival_automations (ON DELETE CASCADE) | |
device_type |
TEXT | spot ยท robot_arm ยท companion ยท hub |
action |
TEXT | SPOT: navigate_to/run_scenario/follow/return_home/stop (๊ธฐ์กด SPOT_ACTIONS). Hub: command ๊ฐ. ๋ก๋ดํ/๋ฐ๋ ค๋ก๋ด: ์์ ๋ฌธ์์ด |
params_json |
TEXT(JSON) | SPOT: ๊ธฐ์กด spot_params์ ๋์ผ ๊ตฌ์กฐ (destination์ ์คํ ์ ๋์ ๊ณ์ฐ). Hub: {target, scenario_id, payload}. ๋ก๋ดํ/๋ฐ๋ ค๋ก๋ด: {topic, payload} |
delay_ms |
INTEGER | ์ด์ ์ก์ ๋์คํจ์น ํ ๋๊ธฐ ์๊ฐ (๊ธฐ๋ณธ 0) |
display_order |
INTEGER | ์คํ ์์ |
3.3 automation_runs โ ์คํ ๋ก๊ทธ
| ์ปฌ๋ผ | ํ์ | ์ค๋ช |
|---|---|---|
id |
TEXT PK | |
automation_id |
TEXT FK | |
user_id |
TEXT | ์ธ์
ID (users.id) |
location_id |
TEXT | ๋ฐํ ์ฅ์ |
matched_owner_type, matched_owner_id |
TEXT | ์ด๋ค ํ์คํฌ/์ด๋ฒคํธ ๋งคํ ๋๋ฌธ์ ๋ฐํ(๋๋ ์คํต)๋๋์ง |
fired_at |
TIMESTAMP | Vision ๋ฉ์์ง timestamp ๊ธฐ์ค |
status |
TEXT | fired ยท skipped ยท partial ยท failed |
skip_reason |
TEXT | condition_unmet ยท missing_item ยท task_completed ยท already_fired ยท cooldown ยท inactive ยท no_device |
action_results_json |
TEXT(JSON) | [{device_type, action, status, command_id, error, dispatched_at}] โ ack ๋ฆด๋ ์ด ์์ ์ ๊ฐฑ์ |
3.4 ER ์์ฝ
erDiagram
tasks ||--o{ arrival_automations : "owner_type=task"
events ||--o{ arrival_automations : "owner_type=event"
locations ||--o{ arrival_automations : "owner_type=location"
users ||--o{ user_tasks : assigned
users ||--o{ user_locations : assigned
user_locations }o--o| events : event_id
tasks }o--|| locations : location_id
arrival_automations ||--o{ arrival_automation_actions : contains
arrival_automations ||--o{ automation_runs : fired
users ||--o{ automation_runs : session
devices }o--o{ locations : assigned
4. ์๋ฒ ์คํ ํ๋ฆ
vision/position/person ์์
โโ PublishSessionPosition()
โโ resolveSessionLocationForZone() (๊ธฐ์กด)
โโ recordLocationChange() == (prevLoc, true) (๊ธฐ์กด: ์ฅ์๊ฐ ๋ฐ๋ ์๊ฐ๋ง true; ์ง์ ์ฅ์๋ ๋ฐํ)
โโ maybePublishArrivalEvent() (๊ธฐ์กด: ๋๋ฐ ์ด๋ฒคํธ)
โโ onLeave(session, prevLoc, ts) โ 114: ์ง์ ์ฅ์์ trigger='leave' ๊ท์น์ ์๋์ ๊ฐ์
โ ํ๋ฆ์ผ๋ก ํ๊ฐ (LocationID=prevLoc, ๋์ฐฉ๋ณด๋ค ๋จผ์ ์ ์ฌ,
โ ํ์คํฌ ์๋ ์์ยท์ด๋ฒคํธ ํ์ด๋ฐ ๋ฑ ๋ถ์ ํจ๊ณผ ์์)
โโ runArrivalAutomations(session, loc, ts) โ ์ ๊ท
1. ์ด ์ธ์
ยท์ฅ์์ ๋งคํ์ ์์ง
tasks : user_tasks โ tasks WHERE tasks.location_id = loc (status ํํฐ ์ ์ฉ)
event : user_locations(user, loc).event_id
location: loc ์์ฒด
โ (owner_type, owner_id) ๋ชฉ๋ก์ผ๋ก arrival_automations ํ์ฑ ๊ท์น ๋ก๋
(์ ๋ ฌ: location ๊ท์น โ event ๊ท์น โ task ๊ท์น(visit/display ์))
โ ๏ธ ์ฅ์ ๊ท์น ์ฐ์ (2026-10-06, Run() ๋ด ๊ฒ์ดํธ) โ arrive ํธ๋ฆฌ๊ฑฐ์ location/
event ๊ท์น๊ณผ task ๊ท์น์ด ์์ฌ ์์ผ๋ฉด, location/event ๊ท์น์ ๋จผ์ ํ๊ฐยท
๋์คํจ์นํ๊ณ ๊ทธ ์ก์
์ด ์ ๋ถ ์ข
๊ฒฐ(completed/failed/timeout/skipped)๋
๋๊น์ง task ๊ท์น ํ๊ฐ ์์ฒด๋ฅผ ๋ฏธ๋ฃฌ๋ค(ํด๋ง, ์ต๋ 45์ด โ ๋์ผ๋ฉด ํฌ๊ธฐํ๊ณ
์งํ). ๋จ์ "์ ๋ ฌ ์์"๊ฐ ์๋๋ผ "์ฅ์๊ฐ ๋จผ์ ๋๋์ผ ํ์คํฌ๊ฐ ์์"์ผ๋ก
๊ฐํ๋ ๊ฒ. leaveยท๋ฌผ๊ฑด ์ง์ยทoption_selected ํธ๋ฆฌ๊ฑฐ๋ ์ ์ด์ location๊ณผ
task๊ฐ ์์ด์ง ์์ผ๋ฏ๋ก ์ด ๊ฒ์ดํธ๊ฐ ์ ๊ฑธ๋ฆฐ๋ค
โ ๏ธ ์ธ์
๋จ์ ๊ฒ์ดํธ(2026-10-07, location_gate.go) โ ์ฒซ ๋์ฐฉ์ ๋ณดํต ํ์คํฌ
์๋ฉ๋ณด๋ค ๋จผ์ ์์ ๊ทธ ํ๊ฐ์ task ๊ท์น์ด ์๋ค. ๊ทธ๋์ ๋์ฐฉ์์ ๋
location/event run ์ ์ธ์
๋ณ๋ก ๊ธฐ์ตํ๊ณ , ๋ค๋ฆ๊ฒ task ๊ท์น๋ง ๋๋ ํ๊ฐ
(์๋ฉ ํ ์ฌํ๊ฐยทpending_enteredยท์์ฐจ ํ์)๋ ๊ทธ run ์ด ์ ๋ถ ์ข
๊ฒฐ๋ ๋๊น์ง
(์ต๋ 45์ด) ๊ธฐ๋ค๋ฆฐ๋ค. ์๋ ์คํยทleaveยท๋ฌผ๊ฑด ์ง์ยทoption_selected ๋ ์ ๊ธฐ๋ค๋ฆผ
2. ๊ท์น๋ณ ์กฐ๊ฑด ํ๊ฐ (has_children / first_visit_only / persona / ๋ณด์ ์์ดํ
)
๋ณด์ ์์ดํ
: ์ธ์
์ ๊ตฌ๋งค ๋ด์ญ(store_purchases)์ required_product_ids๊ฐ
์ ๋ถ(all) ๋๋ ํ๋๋ผ๋(any) ์์ด์ผ ๋ฐํ. ์์ผ๋ฉด skipped: missing_item
3. fire_policy ยท cooldown ๊ฒ์ฌ (automation_runs ์ต๊ทผ ํ ์กฐํ)
4. ์ก์
์ display_order ์์ผ๋ก goroutine์์ delay_ms ๋๊ณ ๋์คํจ์น
spot โ DispatchSpotCommand() ์ฌ์ฌ์ฉ (์ธ์
๋ฐฐ์ ์ฅ์์ spot ๋๋ฐ์ด์ค resolve)
hub โ diorama/{device}/request publish
lg โ HA ์ ์/๋ชจ๋. params._lg_condition(2026-10-07)์ด ์์ผ๋ฉด ๊ท์น
์์ ๋ ๊ฐ์ ์ํ๋ฅผ ํ ๋ฒ ์ฝ์ด(์ค๋
์ท) ๋ง์ ๋๋ง ๋ณด๋ด๊ณ , ์ ๋ง์ผ๋ฉด
skipped: lg_condition_not_met. ๋ชจ์์ ๋ฐํ _lg_branches ํ ์ค๊ณผ ๊ฐ๋ค
({appliance_id, feature(๊ธฐ๋ณธ power), op: is|is_not|unknown|any, value})
companion say + _lg_branches[i].lg_command(2026-10-07) โ ๋ฐํ ๋ถ๊ธฐ๋ง๋ค ๊ฐ์ ๋ช
๋ น.
๋ฐํ๊ฐ ์ํ ๋์ ๋ฌถ์ ๋ค์ "๋ถ๊ธฐ ๊ฐ์ ๋ช
๋ น" ๋จ๊ณ(action_id={say}#lg)๋ฅผ
๋ผ์ฐ๊ณ , ๋ฐํ ์ง์ ๊ณ ๋ฅธ ๋ถ๊ธฐ์ ๋ช
๋ น๋ง ๋ฐํ๊ฐ ๋๋ ๋ค ๋ณด๋ธ๋ค(์์ผ๋ฉด skipped).
์คํ ๋ก๊ทธ์ branchยทlg_command ๊ธฐ๋ก, ์ฌ์๋๋ ๊ทธ ๋ช
๋ น๋ง ์ฌ๋ฐ์ก
robot_arm / companion โ params_json.topic ์ผ๋ก payload publish (์คํค๋ง ํ์ ์ ์์)
5. automation_runs ๊ธฐ๋ก (skipped ํฌํจ), ack/response ๋ฆด๋ ์ด ์์ ์ ๊ฒฐ๊ณผ ๊ฐฑ์
4.0 ๋งคํ ๊ธฐ๋ฐ ์ ํ ์์
| ์ธ์ | ์ฅ์ "์ง"์ ๋ฐฐ์ ๋ ๊ฒ | ๋ณด์ ์์ดํ | ๋ฐํ๋๋ ๊ท์น |
|---|---|---|---|
| ์งํธ | ํ์คํฌ "์กฐ๋ช ์ผ๊ธฐ" + ์ด๋ฒคํธ "ํ๋ฐฐ ๋์ฐฉ" | ์์ | ์ด๋ฒคํธ "ํ๋ฐฐ ๋์ฐฉ"์ ๊ท์น(๋ก๋ดํ ์ ๋ฌ)์ ์์ดํ
ํ์ โ missing_item ์คํต(= ์ฆ์ ์ข
๊ฒฐ๋ก ๊ฐ์ฃผ). ์ด๋ฒคํธ ๊ท์น์ด ์ข
๊ฒฐ๋ ๋ค์์ผ ํ์คํฌ ๊ท์น(๋ฐ๋ ค๋ก๋ด ์ธ์ฌ) ํ๊ฐ |
| ์์ | ํ์คํฌ "์กฐ๋ช ์ผ๊ธฐ" | ๊ฐ์ ์ธํธ | ์ด๋ฒคํธ๊ฐ ๋ฐฐ์ ์ ๋์ผ๋ฏ๋ก ์ด๋ฒคํธ ๊ท์น์ ํ๋ณด์๋ ์ ๋ค์ด๊ฐ โ ์ฅ์ ๊ท์น์ด ์์ผ๋ฉด ํ์คํฌ ๊ท์น์ด ๋ฐ๋ก ํ๊ฐ(๊ฒ์ดํธ ๋์์ด ์์) |
| ๋ฏผ์ค | ํ์คํฌ "์กฐ๋ช ์ผ๊ธฐ"(์ด๋ฏธ ์๋ฃ) | ๊ฐ์ ์ธํธ | task_status_filter=pending์ด๋ฉด ํ๋ณด ์ ์ธ โ ์๋ฌด๊ฒ๋ ๋ฐํ ์ ํจ (์ฅ์ ๊ท์น์ด ์์ผ๋ฉด ๊ทธ๊ฒ๋ถํฐ ์ ๋ถ ๋๋ ๋ค์ ํ๊ฐํ์ง๋ง, ์ด ๊ฒฝ์ฐ ์ ์ด์ ํ์คํฌ ํ๋ณด๊ฐ ์์) |
4.1 ๋ณด์ ์์ดํ ์กฐ๊ฑด ํ๊ฐ
- ํ์ ์์ค๋ ์ธ์
์ ์คํ ์ด ๊ตฌ๋งค ๋ด์ญ =
orchestration/{sessionId}/store/owned์ ๋์ผํ ์งํฉ. - ๊ท์น ๋จ์(
condition_json.required_product_ids)์ ์ก์ ๋จ์(params_json.required_product_id, ์ ํ) ๋ ์ธต์ผ๋ก ๋๋ค. ๊ท์น ๋จ์๋ "์์ดํ ์์ผ๋ฉด ๊ท์น ์ ์ฒด ์คํต", ์ก์ ๋จ์๋ "์ด ์ก์ ๋ง ๊ฑด๋๋ฐ๊ณ ๋๋จธ์ง๋ ์งํ" (์: ๊ฐ์ ์์ดํ ์์ ๋๋ง ๋ก๋ดํ ์ ๋ฌ, ๋ฐ๋ ค๋ก๋ด ์ธ์ฌ๋ ํญ์). - ๊ตฌ๋งค๋ ์ธ์
์ค ์ธ์ ๋ ์ผ์ด๋๋ฏ๋ก ๋ฐํ ์์ ์ ์กฐํํ๋ค (์บ์ X).
once_per_session๊ท์น์ด ์์ดํ ๋ถ์ฌ๋กmissing_item์คํต๋ ๊ฒฝ์ฐ๋ "๋ฐํํ ๊ฒ"์ผ๋ก ์น์ง ์์, ์ดํ ์์ดํ ์ ์ฌ๊ณ ๋ค์ ๋์ฐฉํ๋ฉด ๋ฐํ๋๋ค.
4.2 ๋๋ฐ์ด์ค resolve ๊ท์น
- ์ธ์
์ ๋ฐฐ์ ๋ ์ฅ์(
user_locations)์ ๋งคํ๋devices(ํด๋นtype,is_active=1) ์ค ์ฒซ ๋ฒ์งธ. - ์์ผ๋ฉด ์ก์
์
skipped: no device๋ก ๋ก๊ทธ์ ๋จ๊ธฐ๊ณ ๋ค์ ์ก์ ์ ๊ณ์ ์งํํ๋ค (ํ ๋๋ฐ์ด์ค ๋ถ์ฌ๊ฐ ์ ์ฒด ๊ท์น์ ๋ง์ง ์๋๋ก).
4.3 ๋๋ฐ์ด์ค ๋ช ๋ น ํ (SQS FIFO) โ 2026-08-22 ๊ตฌํ
๋ชจ๋ ๋๋ฐ์ด์ค ๋ช
๋ น(SPOTยท๋ก๋ดํยท๋ฐ๋ ค๋ก๋ดยทHub, ์๋ํ/ํ๋ธ๋ฆฟ/์ ํ์ง ์ถ์ฒ ๋ถ๋ฌธ)์
internal/mqttx/device_queue.go์ ๋๋ฐ์ด์ค ๋ช
๋ น ํ๋ฅผ ๊ฑฐ์น๋ค. ๋ฐฑ์๋๋
internal/devicequeue/ โ SQS_ENDPOINT๊ฐ ์์ผ๋ฉด ministack SQS FIFO(device-commands.fifo
-dlq.fifo), ์์ผ๋ฉด ํ๋ก์ธ์ค ๋ด ๋ฉ๋ชจ๋ฆฌ ํ(๊ฐ์ ๊ณ์ฝ).
Enqueue(job) โ SQS FIFO (MessageGroupId = ๋๋ฐ์ด์ค ํค: spot:{robotId} | hub | robot_arm:{topic} | companion:{topic})
consumer โ Receive โ delay_ms ๋๊ธฐ โ MQTT ๋ฐํ โ ์๋ฃ ์ ํธ ๋๊ธฐ(timeout_ms) โ DeleteMessage โ job.next ์ ์ฌ
- ๋๋ฐ์ด์ค ๋จ์ ์ง๋ ฌํ: ๊ฐ์ ๊ทธ๋ฃน์ ์ ์ก์ Deleteํ๊ธฐ ์ ๊น์ง ๋ค์ ์ก์ด ๋์ค์ง ์๋๋ค. ์ธ์ ์ด ๋ฌ๋ผ๋ ๊ฐ์ SPOT์ด๋ฉด ์์๋๋ก. (SQS๋ ํ Receive ๋ฐฐ์น ์์์ ๊ฐ์ ๊ทธ๋ฃน์ ์ฌ๋ฌ ๊ฐ ๋ด์ค ์ ์์ด ์๋น์๋ ๊ทธ๋ฃน๋ณ ๋ฝ์ผ๋ก ํ ๋ฒ ๋ ์ง๋ ฌํํ๋ค.)
- ๊ท์น ์ ์ก์
์ฒด์ธ: ์ฒซ ์ก์
๋ง ํ์ ๋ฃ๊ณ
job.next๋ก ๋ค์ ์ก์ ์ ์ค์ด, ์ ์ก์ ์๋ฃ ํ ์๋น์๊ฐ ๋ค์์ ์ ์ฌํ๋ค โ ๋๋ฐ์ด์ค๊ฐ ๋ฌ๋ผ๋ ์ก์ ์ ์์ฐจ.delay_ms= "์ ์ก์ ์๋ฃ ํ ๋๊ธฐ". - ์๋ฃ ์ ํธ: SPOT
robot/{id}/ack์ข ๊ฒฐ status ยท Hubdiorama/{device}/response.resultยท ๋ก๋ดํ/๋ฐ๋ ค๋ก๋ด์ ์คํค๋ง ํ์ ์ ๊น์งparams.duration_ms(๊ธฐ๋ณธ 3์ด) ๊ฒฝ๊ณผ๋ฅผ ์๋ฃ๋ก ๊ฐ์ฃผ. - ํ์์์:
arrival_automation_actions.timeout_ms(๊ธฐ๋ณธ 30์ด). ๋๊ธฐ๋ฉดtimeout์ผ๋ก ๊ธฐ๋กํ๊ณ ๋ค์์ผ๋ก ์งํ. ๊ฐ์์ฑ ํ์์์์ delay+timeout+์ฌ์ ๋ก ๋๋ ค ์ฌ์ ๋ฌ์ ๋ง๊ณ , ์๋น์๊ฐ ๋ ๋ฒ ์ฃฝ์ผ๋ฉด DLQ. - ์ก์
์ํ:
queued โ dispatched โ completed | timeout | failed(+device_status์ ack ์๋ฌธ)์ดautomation_runs.action_results_json์ ๊ฐฑ์ ๋๊ณ ๋ฐฑ์คํผ์ค ์คํ ๋ก๊ทธยทministack ํ๋ฉด์์ ๋ณด์ธ๋ค. - ์ฐ์ ์์(์๋ > ์๋)๋ ๋ฏธ๊ตฌํ โ ๋ชจ๋ ๊ฐ์ FIFO.
4.4 MQTT ํ ํฝ (์ ๊ท)
| Topic | ๋ฐฉํฅ | QoS | Retained | ์ค๋ช |
|---|---|---|---|---|
orchestration/{sessionId}/automation/fired |
SโC | 1 | X | ๊ท์น ๋ฐํ ์๋ฆผ {automation_id, name, location_id, actions:[{device_type, action, command_id, status}]} โ ํ๋ธ๋ฆฟ์ด "๋ก๋ด์ด ์์ง์
๋๋ค" ๊ฐ์ ์๋ด๋ฅผ ๋์ฐ๋ ์ฉ๋(์ ํ) |
5. ๋ฐฑ์คํผ์ค ํ๋ฉด ๊ตฌ์กฐ
์ฌ์ด๋๋ฐ
โโ ํ์คํฌ ๊ด๋ฆฌ โ ํ์คํฌ ์์ธ (/tasks/:id)
โ โโ ๊ธฐ๋ณธ ์ ๋ณด / ์ ํ์ง(์ต์
๋ณ SPOT ์ฐ๋) (๊ธฐ์กด)
โ โโ [NEW] ๋์ฐฉ ์๋ํ ์น์
โ ๊ท์น์ "์ฃผ ํธ์ง ํ๋ฉด" โ
โโ ์ด๋ฒคํธ ๊ด๋ฆฌ โ ์ด๋ฒคํธ ์์ธ (/events/:id)
โ โโ ๊ธฐ๋ณธ ์ ๋ณด / ์ ํ์ง(์ต์
๋ณ SPOT ์ฐ๋) (๊ธฐ์กด)
โ โโ [NEW] ๋์ฐฉ ์๋ํ ์น์
โ ๊ท์น์ "์ฃผ ํธ์ง ํ๋ฉด" โก
โโ ์ฅ์ ๊ด๋ฆฌ
โ โโ ์ฅ์ ์์ธ (/locations/:id)
โ โโ ๊ธฐ๋ณธ ์ ๋ณด / ํ์คํฌ / ์ฝํ
์ธ (๊ธฐ์กด)
โ โโ [NEW] ๋์ฐฉ ์๋ํ ํญ
โ โโ ์ฅ์ ์์ฒด ๊ท์น (owner_type=location) ํธ์ง
โ โโ ์ด ์ฅ์์ ํ์คํฌยท์ด๋ฒคํธ์ ๋ถ์ ๊ท์น **์ฝ๊ธฐ ์ ์ฉ ์ง๊ณ** (ํด๋ฆญ โ ํด๋น ์์ธ๋ก)
โ
โโ ๋ก๋ด ์ฐ๋ โ ๊ธฐ์กด "SPOT ๊ด๋ฆฌ" ๋ค๋น ํธ๋ฆฌ๋ฅผ ์ด๋ฆ ๋ฐ๊ฟ ํ์ฅ
โโ SPOT ์ฅ์ ๊ด๋ฆฌ (/spot-management) (๊ธฐ์กด, waypoint ๋งคํ)
โโ [NEW] ์๋ํ ๊ท์น ์ ์ฒด (/automations) โ ์ฅ์ยท๋๋ฐ์ด์ค ์ถ read-mostly ๋ชฉ๋ก
โโ [NEW] ์๋ํ ์คํ ๋ก๊ทธ (/automations/runs) โ automation_runs ํ์๋ผ์ธ
โโ ํ
์คํธ (/spot-test) (๊ธฐ์กด + SPOT ์์น ํ
์คํธ)
์ ํ์คํฌ/์ด๋ฒคํธ ์์ธ๋ฅผ ์ฃผ ํธ์ง ํ๋ฉด์ผ๋ก ๋๋ โ ์ํ ์ฌ๋ถ๋ฅผ ๊ฐ๋ฅด๋ ๊ฑด "์ด ์ธ์
์ด ์ด
์ฅ์์์ ๋ฌด์จ ํ์คํฌ/์ด๋ฒคํธ๋ฅผ ํ๋๋"์ด๋ฏ๋ก, ๊ท์น์ ๊ทธ ํ์คํฌ/์ด๋ฒคํธ์ ์์ฑ์ด๋ค.
์ด๋ฏธ ํ์คํฌยท์ด๋ฒคํธ ์์ธ์ "์ ํ์ง๋ฅผ ๊ณ ๋ฅด๋ฉด SPOT ๋ช
๋ น"(SpotOptionFields)์ด ์์ด์, ๋ฐ๋ก
์์ "๋์ฐฉํ๋ฉด ์๋์ผ๋ก" ์น์
์ด ๋ถ์ผ๋ฉด ์ด๋๋ฏผ์ด ํ ํ๋ฉด์์ ์ ํ ์ ๋์ vs ๋์ฐฉ ์ ๋์์
๊ฐ์ด ์ค๊ณํ ์ ์๋ค. ์ฅ์ ์์ธ ํญ์ "์ด ์ฅ์์์ ์ผ์ด๋ ์ ์๋ ๋ชจ๋ ์๋ํ"๋ฅผ ํ๋์ ๋ณด๋
์ง๊ณ + ์ฅ์ ๊ณตํต ๊ท์น ํธ์ง์ฉ. ์ ์ฒด ๋ชฉ๋ก์ ๋๋ฐ์ด์ค ์ถ ์ญ์กฐํ์ฉ ๋ณด์กฐ ๋ทฐ.
5.1 ํ์คํฌ/์ด๋ฒคํธ ์์ธ โ ๋์ฐฉ ์๋ํ ์น์ (์ฅ์ ์์ธ์ ์ฅ์ ๊ท์น๋ ๋์ผ ์ปดํฌ๋ํธ)
โโ ๋์ฐฉ ์๋ํ (์ด ํ์คํฌ๊ฐ ๋ฐฐ์ ๋ ์ธ์
์ด "์ง"์ ๋์ฐฉํ๋ฉด) โโโโ [+ ๊ท์น ์ถ๊ฐ] โโ
โ โ
โ โพ ๋ฐ๋ ค๋ก๋ด ์ธ์ฌ + SPOT ์ถ์ข
[ํ์ฑ โ] [์ํ ๋ฐํ โพ] โ
โ ํธ๋ฆฌ๊ฑฐ: ๋์ฐฉ ยท ๋์: ๋ฏธ์๋ฃ ํ์คํฌ๋ง ยท ์กฐ๊ฑด: ์์ด ๋๋ฐ ๋ฌด๊ด ยท ์ธ์
๋น 1ํ โ
โ ํ์ ์์ดํ
: ์์ โ
โ โโโโโโฌโโโโโโโโโโโฌโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโฌโโโโโโโ โ
โ โ ์์โ ๋๋ฐ์ด์ค โ ๋ช
๋ น โ ํ๋ผ๋ฏธํฐ โ ์ง์ฐ โ โ โ
โ โโโโโโผโโโโโโโโโโโผโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโผโโโโโโโค โ
โ โ 1 โ ๋ฐ๋ ค๋ก๋ด โ greet โ {"voice":"hello"} โ 0 ms โ โโ ๐ โ โ
โ โ 2 โ SPOT โ follow โ mode=start โ 1500ms โ โโ ๐ โ โ
โ โโโโโโดโโโโโโโโโโโดโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโดโโโโโโโ โ
โ [+ ์ก์
์ถ๊ฐ] โ
โ โ
โ โธ (์์ด ๋๋ฐ) ๋ก๋ดํ ๊ฐ์ ์ ๋ฌ [ํ์ฑ โ] [์ํ ๋ฐํ โพ] โ
โ ํ์ ์์ดํ
: ๐ ๊ฐ์ ์ธํธ (all) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- ์น์
ํค๋์ ๊ท์น์ด ๋ฐํ๋๋ ์ฅ์๋ฅผ ๋ช
์ (
tasks.location_id/ ์ด๋ฒคํธ๋ "๋ฐฐ์ ๋ ์ฅ์") - ๊ท์น ์นด๋: ์ด๋ฆ ยท ํธ๋ฆฌ๊ฑฐ ยท (ํ์คํฌ) ์ํ ํํฐ ยท ์กฐ๊ฑด ์์ฝ ยท ํ์ ์์ดํ
์นฉ(์คํ ์ด ์ํ ๋ค์ค ์ ํ, all/any) ยท ๋ฐํ ์ ์ฑ
ยท ํ์ฑ ํ ๊ธ ยท ์ํ ๋ฐํ(์ด ํ์คํฌ/์ด๋ฒคํธ๊ฐ ๋ฐฐ์ ๋ ํ์ฑ ์ธ์
๋ง ๋ชฉ๋ก์ ๋ธ โ ์ ํ ์ ์ฆ์ ์คํ,
automation_runs์manual=true๋ก ๊ธฐ๋ก) - ๊ฐ์ ์ปดํฌ๋ํธ(
ArrivalAutomationEditor)๋ฅผ ์ฅ์ ์์ธ ํญ์ "์ฅ์ ๊ท์น"์๋ ์ฌ์ฌ์ฉ - ์ก์ ํ ์ด๋ธ: ์์ ๋ณ๊ฒฝ(โโ), ์ญ์ , ํ ํด๋ฆญ ์ ์ธ๋ผ์ธ/๋ชจ๋ฌ ํธ์ง
- ๋ง์ง๋ง ์คํ ๊ฒฐ๊ณผ ๋ฐฐ์ง (์ต๊ทผ run์ status) โ ๋ก๊ทธ ํ๋ฉด์ผ๋ก ๋งํฌ
5.2 ์๋ํ ๊ท์น ์ ์ฒด (/automations)
| ์ปฌ๋ผ | ์ค๋ช |
|---|---|
| ์ฃผ์ธ | ํ์คํฌ ยท ์กฐ๋ช
์ผ๊ธฐ / ์ด๋ฒคํธ ยท ํ๋ฐฐ ๋์ฐฉ / ์ฅ์ ยท ์ง ์นฉ โ ํด๋ฆญ โ ํด๋น ์์ธ |
| ์ฅ์ | ์ ๋๋ ์ฅ์ |
| ๊ท์น๋ช | |
| ํธ๋ฆฌ๊ฑฐ / ์กฐ๊ฑด | ์์ฝ (ํ์ ์์ดํ ํฌํจ) |
| ์ก์ | ๋๋ฐ์ด์ค ์นฉ ๋์ด (SPOT ๋ฐ๋ ค๋ก๋ด โฆ) |
| ํ์ฑ | ํ ๊ธ (์ฌ๊ธฐ์๋ ๋ฐ๋ก on/off) |
| ์ต๊ทผ ๋ฐํ | ์๊ฐ + ์ํ ๋ฐฐ์ง |
ํํฐ: ์ฃผ์ธ ์ข ๋ฅ(ํ์คํฌ/์ด๋ฒคํธ/์ฅ์) ยท ์ฅ์ ยท ๋๋ฐ์ด์ค ํ์ ยท ํ์ฑ ์ฌ๋ถ.
5.3 ์ก์ ํธ์ง ํผ (๋๋ฐ์ด์ค ํ์ ๋ณ ๋ถ๊ธฐ)
| ๋๋ฐ์ด์ค | ์ ๋ ฅ | ๋น๊ณ |
|---|---|---|
| SPOT | SpotOptionFields ๊ทธ๋๋ก ์ฌ์ฌ์ฉ (spot_action / spot_destination_mode / scenarioยทvariablesยทfollow mode) |
navigate_to์ destination์ ์ธ์
์ฅ์ โ waypoint label๋ก ๋์ ๊ณ์ฐ(own/next). 2026-09-16๋ถํฐ destination_mode=waypoint์ด๋ฉด ํธ์ง๊ธฐ์์ SPOT์ retained waypoints ๋ชฉ๋ก(+์ฅ์ ๋งคํ)์์ ๊ณ ๋ฅธ params.destination์ ๊ทธ๋๋ก ์ฌ์ฉ โ SPOT ํ
์คํธ ํ๋ฉด๊ณผ ๋์ผ |
| Hub | command, target, scenario_id, payload(JSON) |
diorama/{device}/request ํฌ๋งท ํ์ ๋จ |
| ๋ก๋ดํ ยท ๋ฐ๋ ค๋ก๋ด | ํ ํฝ ๋ฌธ์์ด + payload JSON ์์ ์ ๋ ฅ + โ ๏ธ "์คํค๋ง ๋ฏธํ์ " ๋ฐฐ์ง | ์คํค๋ง ํ์ ๋๋ฉด ๋๋กญ๋ค์ด/ํ์
๋ ํผ์ผ๋ก ๊ต์ฒด. session_id๋ ์๋ฒ๊ฐ ์๋ ์ฃผ์
|
๊ณตํต: delay_ms ์ซ์ ์
๋ ฅ, ์์, ํ์ ์์ดํ
(์ ํ) โ ์ด ์ก์
๋ง ํด๋น ์ํ ๋ณด์ ์ ์คํ.
5.4 ์๋ํ ์คํ ๋ก๊ทธ (/automations/runs)
์๊ฐ ์ธ์
(ํ๋ฅด์๋) ์ฅ์ ์ฃผ์ธ ๊ท์น ์ํ ์ก์
๊ฒฐ๊ณผ
13:36:23 ์งํธ (abc123) ์ง ํ์คํฌยท์กฐ๋ช
์ผ๊ธฐ ๋ฐ๋ ค๋ก๋ด+SPOT fired ๋ฐ๋ ค๋ก๋ด โ ยท SPOT ACCEPTEDโSUCCESS
13:36:23 ์งํธ (abc123) ์ง ์ด๋ฒคํธยทํ๋ฐฐ ๋์ฐฉ ๋ก๋ดํ ๊ฐ์ ์ ๋ฌ skipped missing_item (๊ฐ์ ์ธํธ)
13:35:50 ์งํธ (abc123) ๋งํธ ํ์คํฌยท์ฅ๋ณด๊ธฐ ๋ก๋ดํ ์ํ ์ ๋ฌ skipped no device (robot_arm)
13:20:01 ๋ฏผ์ค (ghi789) ์ง ํ์คํฌยท์กฐ๋ช
์ผ๊ธฐ ๋ฐ๋ ค๋ก๋ด+SPOT skipped task_completed (status filter)
13:20:01 ์์ (def456) ์ง ์ง ๋์ฐฉ โ ๋ฐ๋ ค๋ก๋ด+SPOT skipped already_fired (once_per_session)
- ํํฐ: ์ธ์ ยท ์ฅ์ ยท ๊ท์น ยท ์ํ ยท ๊ธฐ๊ฐ
- ํ ํผ์น๋ฉด
action_results_json์๋ฌธ + ๋ฐํํ MQTT payload - ์ฌ์ฉ์ ์์ธ(
/task-completions/:sessionUuid)์๋ "์๋ํ" ํญ์ผ๋ก ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ์ธ์ ํํฐ ๊ณ ์ ์ผ๋ก ๋ ธ์ถ
6. ์ ์ฑ ๊ฒฐ์ ์ฌํญ
| # | ์ด์ | ์ ์ |
|---|---|---|
| 1 | ์๋ vs ์๋ SPOT ๋ช
๋ น ์ถฉ๋ โ ๋์ฐฉ ๊ท์น์ด follow๋ฅผ ๋ณด๋ธ ์งํ ์ฌ์ฉ์๊ฐ ํ๋ธ๋ฆฟ์์ navigate_to๋ฅผ ๊ณ ๋ฅด๋ฉด? |
์๋(์ฌ์ฉ์ ์ ํ) > ์๋. ์๋ ๋ช
๋ น์ stop ์ธ์ ์งํ ์ค ๋ช
๋ น์ ๋์ง ์๊ณ ํ ๋ค์ ๋ถ๋๋ค. ์ญ์ผ๋ก ์๋ ๋ช
๋ น์ ๋๊ธฐ ์ค์ธ ์๋ ๋ช
๋ น์ ๊ฑด๋๋ธ ์ ์๊ฒ SpotQueue์ source ํ๋ ์ถ๊ฐ |
| 2 | every_arrival ํญ์ฃผ โ Vision์ด ์งโ๋งํธ ๊ฒฝ๊ณ์์ ๊น๋นก์ด๋ฉด ๋์ฐฉ์ด ์ฐ๋ฌ์ ์ฐํ |
๊ท์น๋ณ cooldown_seconds ๊ธฐ๋ณธ 30์ด. once_per_session์ ๊ธฐ๋ณธ๊ฐ์ผ๋ก |
| 3 | ๋๋ฐ์ด์ค ๋ถ์ฌ โ ์ธ์ ์ฅ์์ ํด๋น ํ์ ๋๋ฐ์ด์ค๊ฐ ์์ ๋ | ์กฐ์ฉํ ์คํตํ์ง ์๊ณ automation_runs์ skipped: no device๋ก ๋จ๊น. ๊ท์น ์นด๋์ ๊ฒฝ๊ณ ๋ฐฐ์ง |
| 3b | ํ์คํฌ ์๋ฃ ํ ์ฌ๋์ฐฉ โ ํ์คํฌ๋ฅผ ๋ง์น ๋ค ๊ฐ์ ์ฅ์์ ๋ค์ ์ค๋ฉด? | task_status_filter=pending(๊ธฐ๋ณธ)์ด๋ฉด ํ๋ณด์์ ๋น ์ง โ ์๋ฃ ํ์ ๋ฐํ ์ ํจ. ์๋ฃ ํ์๋ ๋์๊ฐ๊ธธ ์ํ๋ฉด any. ์ด๋ฒคํธ๋ event_published_at๊ณผ ๋ฌด๊ดํ๊ฒ ๋์ฐฉ๋ง๋ค ํ๋ณด(fire_policy๋ก ์ ์ด) |
| 3c | ํ ๋์ฐฉ์ ๊ท์น ์ฌ๋ฌ ๊ฐ โ ํ์คํฌ 2๊ฐ + ์ด๋ฒคํธ 1๊ฐ๊ฐ ๊ฐ๊ฐ SPOT ๋ช ๋ น์ ๊ฐ๊ณ ์์ผ๋ฉด? | ์ ๋ถ ๋ฐํํ๋ ์์๋ location โ event โ task(visit/display ์). SPOT์ SpotQueue๊ฐ ์ง๋ ฌํ. ์์ถฉ(follow vs navigate_to)์ ์ด๋๋ฏผ ์ฑ
์์ผ๋ก ๋๊ณ , ๊ท์น ์ ์ฒด ๋ชฉ๋ก์์ ๊ฐ์ ์ฅ์ยท๊ฐ์ ๋๋ฐ์ด์ค์ ๊ท์น์ด ์ฌ๋ฌ ๊ฐ๋ฉด โ ๏ธ ๋ฐฐ์ง |
| 4 | zone_id='home' ์ธ์คํด์ค ์ ํ โ ์ฒซ ๋ฐฉ๋ฌธ์ STEP์ด ๊ฐ์ฅ ์์ ์ง, ๋ ๋ฒ์งธ๋ถํฐ๋ ์ฒซ ์ธ์คํด์ค๋ก ๋์๊ฐ์ง ์๊ณ ๋๋จธ์ง ์์์ ์ํ (2026-09-27) |
์๋ํ๋ ๋์ผ ์ธ์คํด์ค ๊ธฐ์ค์ผ๋ก first_visit_only ํ๋จ. ์ง-์์นจ/์ง-์ ๋
์ด ๊ฐ์ ๊ท์น์ ๊ณต์ ํ๋ ค๋ฉด ์ฅ์ ์ธ์คํด์ค๋ง๋ค ๊ท์น์ ๋ฐ๋ก ๋๊ฑฐ๋, ํฅํ "zone ๋จ์ ๊ท์น" ์ต์
๊ฒํ |
| 5 | ์ธ์ ์ข ๋ฃ ์ | ์ธ์
์ข
๋ฃ(end-session) ์ ํด๋น ์ธ์
์ ๋๊ธฐ ์ค ์๋ ์ก์
(delay ์ค์ธ goroutine) ์ทจ์ |
| 6 | ์์ดํ
์กฐ๊ฑด๊ณผ once_per_session |
missing_item ์คํต์ ๋ฐํ๋ก ์น์ง ์์ โ ๊ตฌ๋งค ํ ์ฌ๋์ฐฉ ์ ๋ฐํ. ์ํ ๋ฐํ๋ ์์ดํ
์กฐ๊ฑด์ ๋ฌด์ํ ์ง ํ ๊ธ ์ ๊ณต |
| 7 | ์๋ฒ ์ฌ๊ธฐ๋ | delay ์ค์ด๋ ์ก์ ์ ์ ์ค ํ์ฉ (์ ์ ํ์ฅ ํน์ฑ์ ์ ์ด ๋จ์๋ผ ์์ํ ๋ถํ์) |
| 9 | ์ก์ ๋ณ๋ ฌ ์คํ (2026-08-30, ๋ฐ๋ ค๋ก๋ด ์ฑ๋ ๋ชจ๋ธ) | arrival_automation_actions.parallel=1 ์ด๋ฉด ์ ์ก์
์ ์๋ฃ๋ฅผ ๊ธฐ๋ค๋ฆฌ์ง ์๊ณ ์ ์ก์
๊ณผ ๋์์ ์ ์ฌ. ์ฐ์๋ ๋ณ๋ ฌ ์ก์
์ ํ ๋จ๊ณ๋ก ๋ฌถ์ด๊ณ ๋จ๊ณ ์ ์ฒด๊ฐ ์ข
๊ฒฐ๋ผ์ผ ๋ค์ ๋จ๊ณ๋ก. ๋ฐ๋ ค๋ก๋ด ๋ช
๋ น์ ํ ๊ทธ๋ฃน์ด companion:{robot}:{์ฑ๋}์ด๋ผ locomotion(ํ์ฒด)๋ง ์ง๋ ฌ, audio/led/gaze/projection์ ์ค์ ๋ก ๋์์ ๋๊ฐ๋ค(์: ์ ์ค์ฒ โฅ ๋ฐํ). ์ฒซ ์ก์
์ parallel์ ๋ฌด์. ๋ณ๋ ฌ ๊ทธ๋ฃน ์นด์ดํธ๋ ํ๋ก์ธ์ค ๋ฉ๋ชจ๋ฆฌ(์ฌ๊ธฐ๋ ์ ๊ทธ ๋จ๊ณ์ ๋ค์ ์ ์ฌ ์ ์ค โ 7๋ฒ๊ณผ ๋์ผ ์์ค) |
| 9-1 | ๊ธฐ๋ค๋ฆฌ์ง ์๋ ๋จ๊ณ (2026-10-04) | params_json._no_wait=true ๋ฉด ๊ฐ์ด ์ถ๋ฐํ๋ ์๋ฌด๋ ๊ทธ ๋จ๊ณ์ ์๋ฃ๋ฅผ ๊ธฐ๋ค๋ฆฌ์ง ์๋๋ค. ๋๋ก ๋ฐฐ์ก์ฒ๋ผ ์ค๋ ๊ฑธ๋ฆฌ๋ ์ฐ์ถ์ด ๋ค ๋จ๊ณ(๋ก๋ดํยทSPOT)๋ฅผ ๋ถ์ก์ง ์๊ฒ ํ๋ ค๊ณ ๋ฃ์๋ค โ ์ ์๋ Hub(๋๋ก ) โฅ SPOT ๋ฌถ์์ด ์ ๋ถ ๋๋์ผ ๋ก๋ดํ์ด ๋๊ฐ๊ณ , ๋๋ก ack ๊ฐ ํ์์์์ด๋ฉด ์ฒด์ธ์ด ๋ฉ์ท๋ค. ์๋ฒ๋ ์ก์
์ buildChainStages ๋ก "ํ๊บผ๋ฒ์ ์ ์ฌํ ๋ฌถ์"์ผ๋ก ๋๋๊ณ , ๊ทธ ๋ฌถ์์ ๊ธฐ๋ค๋ฆฌ๋ ์ก(= _no_wait ์๋ ๊ฒ)์ด ์ ๋ถ ์ข
๊ฒฐ๋ ๋๋ง ๋ค์ ๋ฌถ์์ ์ ์ฌํ๋ค. ๋ฌถ์์ด ํต์งธ๋ก _no_wait ๋ฉด ๋ค์ ๋ฌถ์์ ๊ฐ์ด ์ ์ฌํ๋ค. ๊ธฐ๋ค๋ฆฌ์ง ์๋ ๋จ๊ณ๋ ์คํจํด๋ ์ฒด์ธ์ ๋ฉ์ถ์ง ์๊ณ (๋ด๋ถ์ ์ผ๋ก _continue_on_failure ์ทจ๊ธ), ์๋ ์ฌ์๋๋ ๊ทธ ๋จ๊ณ๋ง ๋ค์ ๋ณด๋ธ๋ค(RetryRunFrom). ๊ฐ์ ๋ก๋ด์ ๋ค ๋จ๊ณ๊ฐ ๋ ๋ช
๋ น์ ๋ฃ์ผ๋ฉด ๊ทธ ๋ก๋ด ํ์์ ์ฐจ๋ก๋ฅผ ๊ธฐ๋ค๋ฆฐ๋ค โ ๋ณ๋ ฌ ๊ธ์ง ๊ท์น(ยง๊ฐ์ ๋ก๋ด ๋์ ๊ธ์ง)์ ๋ฌถ์ ์์์๋ง ๊ฒ์ฌํ๋ค. ์ด๋๋ฏผ: ๋จ๊ณ ์นด๋ "๋ค ๋จ๊ณ๊ฐ ๊ธฐ๋ค๋ฆฌ์ง ์์" ์ฒดํฌ, ๋ค์ด์ด๊ทธ๋จ์ ์ ์ ๊ฐ์ง๋ก ๋น ์ ธ๋๊ฐ๊ฒ ๊ทธ๋ฆฐ๋ค. ๋ง์ด๊ทธ๋ ์ด์
์์ โ parallel(100) ๊ณผ ๋ฌ๋ฆฌ ์ปฌ๋ผ์ด ์๋๋ผ params_json ์์ฝ ํค๋ค(_continue_on_failure ์ ๊ฐ์ ์๋ฆฌ) |
| 8 | ํ์คํฌ ์๋ ์๋ฃ (2026-08-30) โ ํ์คํฌ๋ ํ๋ธ๋ฆฟ ์ ํ ํ์ ์์ด ๋์ฐฉ ์๋ํ๋ก๋ง ์คํ๋๋ค | owner_type=task ๊ท์น์ด ์ค์ ๋ฐํ(์ํ ๋ฐํ ์ ์ธ)ํ๋ฉด ๊ฐ ์ก์
์ด user_task_commands์ queued๋ก ๊ธฐ๋ก๋๊ณ , ํ๊ฐ ์ก์
์ ์ข
๊ฒฐ(ack/timeout/failed)ํ ๋๋ง๋ค ๊ฐฑ์ โ ์ ๋ถ ์ข
๊ฒฐ๋๋ฉด user_tasks๋ฅผ ์๋ completed ํ๊ณ task/complete์ ๊ฐ์ ํ์ ๋ฐํ. ์คํจยทํ์์์๋ ์ข
๊ฒฐ๋ก ์ผ๋ค. ๋ฐฑ์คํผ์ค ์ธ์
์์ธ(์์น๋ณ ํ์คํฌ)์ ๋ช
๋ น๋ณ ์ํ ํ์. ์๋ ์๋ฃ ํ ํ๋ธ๋ฆฟ task/complete๊ฐ ๋ ์๋ ํฌ์ธํธ ์ฌ์ง๊ธ ์์ |
| 10 | pending_entered ํธ๋ฆฌ๊ฑฐ (2026-10-06, 152) โ ๊ธฐ์กด ํธ๋ฆฌ๊ฑฐ(arrive/leave/๋ฌผ๊ฑด ์ง์/์ ํ์ง)์ ๋์ผํ ๊ท์น ๋ชจ๋ธ(UIยท์กฐ๊ฑดยท๋ฐํ ์ ์ฑ
ยท์ก์
ยท์คํ ๋ก๊ทธยท์ํ ๋ฐํ)๋ก, ํธ๋ฆฌ๊ฑฐ ๊ฐ๋ง ๋ค๋ฅด๋ค. ํ์คํฌ ์ ์ฉ(owner_type='task') โ ์ฅ์ยท์ด๋ฒคํธ์๋ pending ์ํ ๊ฐ๋
์ด ์๋ค |
"๋ด ์ฐจ๋ก" = ๊ด๋๊ฐ์ด ๊ทธ ์ฅ์์ ์๊ณ ์ ํ์คํฌ์ ๋งํ์ง ์์ (2026-10-10). ๋ฐํ ์ง์ ์ธ ๊ณณ: โ ์ธ์
์๋ฉ ์งํ โ ๊ด๋๊ฐ์ด ์ง๊ธ ์๋ ์ฅ์์ pending ์ด๋ฉด์ ์ ํ์คํฌ์ ๋งํ์ง ์์ ํ์คํฌ๋ง(seedPendingEnteredTargets). ์์ ์ ์ฝ์ค ์ ์ฒด ์ฅ์๋ฅผ ํ์ด, ๊ณต์ ์ฒซ ํ์คํฌ์ pending_entered ๊ฐ ๊ด๋๊ฐ์ด ์ง์ ์์ ๋ ๋์ ํ์คํฌ๊ฐ ์๋ ์๋ฃ๋๊ณ ๊ณต์ ์ด๋ฒคํธ๊น์ง ๋ฐํ๋๋ค(์ธ์
01a125b1). โก ์ฅ์ ๋์ฐฉ(onArrival โ fireReadyPendingEntered, ๋์ฐฉ ํ๊ฐ ๋ค๋ผ ์ฅ์ ์ฐ์ถ ๊ฒ์ดํธ๋ฅผ ํ๋ค). โข ์์ฐจ ์คํ(117) ์ฒด์ธ์์ ์ ํ์คํฌ๊ฐ ์ข
๊ฒฐ๋ผ ๋๊ธฐ๊ฐ ํ๋ฆฌ๋ ์๊ฐ(OnUserTaskFinished, ๊ด๋๊ฐ์ด ๊ทธ ์ฅ์์ ์์ ๋). ์ค๋ณต ๋ฐํ๋ ๊ท์น์ fire_policy ๊ฐ ๋ง๋๋ค. ์ฉ๋: detailed ์ฒ๋ผ ํ๋ธ๋ฆฟ์ ๋ช
์์ task/start ์์ด ์๋ํ๋ก๋ง ์์๋๋ ํ์คํฌ ํ์
์ด, ์ฅ์ ๋์ฐฉ(arrive)์ ๋ค์ ๊ธฐ๋ค๋ฆฌ์ง ์๊ณ ๋ "๋ด ์ฐจ๋ก๊ฐ ๋ ์๊ฐ" ๋ฐ๋ก ๋ก๋ด ๋ช
๋ น์ ๋ฐ์ ์ ์๋ค โ ๊ด๋๊ฐ์ด ์ด๋ฏธ ๊ทธ ์ฅ์์ ์ ์๋ ์ฑ๋ก ์์ฐจ ์ฒด์ธ์ ๋ ๋ฒ์งธ ์ดํ ํ์คํฌ๊ฐ ์์๋๋ ๊ฒฝ์ฐ, ๊ทธ ์ฌ๋์ ๋ค์ "๋์ฐฉ"ํ์ง ์์ผ๋ฏ๋ก arrive ๋ง์ผ๋ก๋ ์์ ๋ฐํํ์ง ์์๋ค. ๊ตฌ์ฒด์ ์ผ๋ก ์ธ์ ์ธ์ง๋ ์ด์์๊ฐ ์๋ํ ๊ท์น์ ๋ง๋ค๋ฉฐ ์ ํ๋ค. ์ถ์ : arrive ์ ๋์ผํ๊ฒ user_task_commands ๋ก ์ถ์ ํด ์ก์
์ด ์ ๋ถ ์ข
๊ฒฐ๋๋ฉด ํ์คํฌ๋ฅผ ์๋ completed ํ๋ค(isTrackableTaskTrigger) โ leaveยท๋ฌผ๊ฑด ์ง์์ฒ๋ผ "์ฐ์ถยทํ์ฒ๋ฆฌ"๊ฐ ์๋๋ผ "์ด ํ์คํฌ๋ฅผ ์ํํ๋ผ"๋ ๋ช
๋ น์ด๊ธฐ ๋๋ฌธ |
7. ๋จ๊ณ๋ณ ๊ตฌํ ์์
- ๋ง์ด๊ทธ๋ ์ด์
+ sqlc โ ยง3 ํ
์ด๋ธ 3๊ฐ (
-- +goose Up์ง์์ ํ์). ๋งคํ ์์ง์ฉ ์ฟผ๋ฆฌ:ListUserTasksAtLocation(user, location), ๊ธฐ์กดGetUserLocationByUserAndLocation์ฌ์ฌ์ฉ - ์๋ฒ ์คํ ์์ง โ
internal/mqttx/automation.go:runArrivalAutomations()+recordLocationChangeํ . ๋งคํ ์์ง โ ๊ท์น ๋ก๋ โ ์์ดํ /์ํ ์กฐ๊ฑด โ ๋์คํจ์น. SPOT๋ง ๋จผ์ , ๋ก๋ดํ/๋ฐ๋ ค๋ก๋ด/Hub๋ generic publish - Admin REST โ
/admin/{tasks|events|locations}/:id/automationsCRUD(๊ณตํต ํธ๋ค๋ฌ, owner_type๋ง ๋ค๋ฆ),/admin/automations,/admin/automations/runs,POST /admin/automations/:id/fire?user_id=(์ํ ๋ฐํ) - ๋ฐฑ์คํผ์ค โ
ArrivalAutomationEditor๊ณต์ฉ ์ปดํฌ๋ํธ โ ํ์คํฌ ์์ธ โ ์ด๋ฒคํธ ์์ธ โ ์ฅ์ ์์ธ ํญ(์ฅ์ ๊ท์น + ์ง๊ณ) โ ์ ์ฒด ๋ชฉ๋ก โ ์คํ ๋ก๊ทธ - ๋ฌธ์ โ
MQTT_SCHEMA-ORCHESTRATION_SERVER์automation/firedํ ํฝ, ์ด ๋ฌธ์ ์ํ๋ฅผ "ํ์ "์ผ๋ก - (์คํค๋ง ํ์ ํ) ๋ก๋ดํยท๋ฐ๋ ค๋ก๋ด ํ์ ๋ ํผ ๊ต์ฒด
8. ๋ฏธ๊ฒฐ ์ฌํญ
- ๋ก๋ดํ ยท ๋ฐ๋ ค๋ก๋ด MQTT ์คํค๋ง (๊ฐ ํ ์์ฑ ๋๊ธฐ) โ ํ์ ์ ๊น์ง JSON ์์ ์ ๋ ฅ
-
leaveํธ๋ฆฌ๊ฑฐ โ 2026-09-12 ๊ตฌํ(114). ํ์์์ ๊ธฐ๋ฐ์ด ์๋๋ผ ๋ค๋ฅธ ์ฅ์ ๋์ฐฉ = ์ง์ ์ฅ์ ์ดํ๋ก ํ์ ํ๋ค. ๋ฐ๋ผ์ ๋ง์ง๋ง ์ฅ์(๋ณดํต home)๋ ์ธ์ ์ข ๋ฃ๋ก๋ ์ดํ์ด ๋ฐํํ์ง ์์ โ ์ธ์ ์ข ๋ฃ ์ ๋ฐํ๊ฐ ํ์ํ๋ฉด ยง6-5(์ข ๋ฃ ์ ๋๊ธฐ ์ก์ ์ทจ์)์ ํจ๊ป ๊ฒฐ์ -
dwellํธ๋ฆฌ๊ฑฐ ์ค์ ์์ ํ์ธ -
orchestration/{sessionId}/automation/fired๋ฅผ ํ๋ธ๋ฆฟ์ด ์ค์ ๋ก ์ธ์ง (FE ํ ํ์ธ) - ์ฅ์ ์ธ์คํด์ค ๋จ์ ๊ท์น vs zone ๋จ์ ๊ท์น (ยง6-4)
- ํ์คํฌ ์ ํ์ง(option)๋ณ ๋์ฐฉ ์๋ํ๊ฐ ํ์ํ์ง โ ํ์ฌ๋ ํ์คํฌ ๋จ์. "์ด ์ ํ์ง๋ฅผ ์ด๋ฏธ ๊ณ ๋ฅธ ์ธ์
์ด ๋์ฐฉํ๋ฉด"์
task_option_selections์กฐ๊ฑด์ผ๋ก ํ์ฅ ๊ฐ๋ฅ - ์ด๋ฒคํธ ๊ท์น์ ๋ฐํ ์์ โ ๋์ฐฉ ์ฆ์ vs ๋๋ฐ ์ด๋ฒคํธ ํ์
(
maybePublishArrivalEvent) ์งํ. ๋ก๋ดํ ์ ๋ฌ์ฒ๋ผ "์ด๋ฒคํธ ์ฐ์ถ"์ธ ๊ฒฝ์ฐ ํ์ ๊ณผ ํ์ด๋ฐ์ ๋ง์ถฐ์ผ ํ ์ ์์ - ์์ดํ
"์๋ชจ" ์ฌ๋ถ โ ๋ก๋ดํ์ด ๊ฐ์์ ์ ๋ฌํ๋ฉด ๋ณด์ ๋ชฉ๋ก์์ ์ฐจ๊ฐํด์ผ ํ๋์ง (ํ์ฌ
store/owned๋ ๋์ ๋ณด์ ๋ง ํํ)