← Docs hub

SKIX Blueprint — 재구성 전 상세 설계 이력

보존 문서 — 현재 목표 설계로 사용하지 않는다. 2026-09-10 재구성 직전의 상세 설명과 그림을 원문 보존했다. 초기 MR7 분석, 이후 추가된 설계, 당시 구현 기록이 함께 있으므로 아래의 “현재”는 각각 작성 당시를 뜻한다. DeviceAgent 내부 집중 배치, 범용 Task 제출 API 등 초기 안은 현재 Blueprint의 하이브리드 배치·도메인별 접수 경계로 대체한다. 최신 구현·검증 여부는 진행 현황에서 확인한다.

2026-10-02 설계 통합 안내: 이후 논의한 SDK/서버 namespace, 소비 앱과 Domain의 책임, Task 수명, 내부 Service 초기화, 팀원 기능 정합과 AOSP 빌드 연결 기준은 현재 Blueprint의 통합 기준에 반영했다. 아래 과거 설계를 최신 구현 상태로 읽지 않는다.

보존 내용 안내

찾는 자료 원문 내 구역
초기 MR7 구조 비교 초기 위치 분석
Manager/API·정책·Task 설계 근거 아래 “SKIX 프레임워크 구조”
MQTT 연결·중복·재전송·세션 계약 아래 “외부 사용 방식과 호환성”
UI 세션·앱 내부 구조 아래 “참고 자료”
기존 소스 분석·전환 방식 비교 아래 “적용 및 전환 계획”

이 페이지는 AOSP 위에 올라가는 SKIX 프레임워크의 목표 구조와 설계 기준을 다룬다. 실제 리팩터링 진행 상황의 정본은 리팩터링 진행 현황이다. 구현 커밋·테스트 결과·제품 연결 여부·남은 작업은 진행 현황에 기록하고, 이 설계안과 분리해 관리한다. 특정 외부 로봇 SDK의 호환성 검토는 별도 문서에서 진행하며 이 설계의 필수 구현 범위로 취급하지 않는다.

역할 해설: AI Agent와 프레임워크 — 누가 실행하고 누가 작업을 관리하나. TTS 엔진을 프레임워크로 옮기는 것이 아니라, AI Agent의 실행과 프레임워크의 도메인·Task·자원 관리를 분리한다.

연결·관측 계약: 제공자 연결 세대와 TTS 전달 상세. 서비스 준비와 장치 연결 준비를 구분하고, 이전 연결의 관측을 새 작업에 적용하지 않는 경계를 설명한다.

최신 내부 기반: Resource·Capability·Task Runtime 상세 구조. 현재 7개 서비스 조립, 폴더별 책임, 자원 반환 후 미확인 상태, 기능 조회와 실행 승인의 차이를 확인한다.

폴더 중심으로 보기: skix-framework/base/ 폴더·모듈·역할 SVG · 모듈별 담당 업무와 실제 소스 설명. 상위 지능 서비스는 외부의 상황 해석·계획 수정 역할을 뜻하며, 특정 제품명이나 필수 프로토콜명이 아니다.

전체 구성요소 상세 구조도 — 전체 계층·도메인 15개·소스와 구동 위치 에서 실제 소스와 아직 연결 전인 목표를 구분해 볼 수 있다.

처음 읽는 경우 SKIX 전체 구조 — 처음 보는 안내서에서 요청·판단·실행·결과 환류를 먼저 보고, 세부 비교는 전체 구조 Atlas에서 본다.

이 문서는 전체 설계 근거를 보존하는 상세 Blueprint다. 빠르게 구조와 현재 구현 상태를 파악하려면 먼저 SKIX 리팩터링 한눈에 보기를 읽고, 실제 반영 여부는 리팩터링 진행 현황에서 확인한다.

문서 적용 기준

이 문서는 구현 상태가 다른 항목을 한 구조 안에서 다루므로 다음 세 기준을 구분한다.

표기 의미
현재 기준선 현재 제품 브랜치에서 확인되는 DeviceAgent, Binder, 도메인 실행기와 앱 호출 구조
병합 후보 task_manager 작업본에 구현돼 있으나 제품 브랜치 반영과 회귀 검증이 남은 기능
목표 계약 현재 코드와 병합 후보를 바탕으로 확정해야 할 공개 Manager, 상태, 보안과 생명주기 계약

아래 구조도와 API 이름은 별도 표시가 없으면 목표 계약을 뜻한다. 현재 동작 사실과 목표 설계를 혼동하지 않도록 구현 근거가 확인된 항목만 현재 기준선 또는 병합 후보로 표기한다.

설계 배경과 목표

SKIX 프레임워크의 역할

핵심 정의
Android AOSP 위에서 기기 상태, 안전 정책, 공유 자원, 공개 API, 실행 과정과 결과 전달을 일관된 계약으로 제공하는 단일 namuh 기기 내부 제품 프레임워크다.

구성 맡는 일 맡지 않는 일
호출 앱·PUI·IoT·예약 어떤 기능과 화면을 사용할지 결정 내부 상태와 안전 규칙을 임의로 변경하지 않음
SKIX 프레임워크 현재 상태, 공통 정책, 자원 충돌과 공개 API 관리 특정 제품 장면과 UX를 독점하지 않음
TaskManager 작업(Task)과 작업 흐름(Workflow)의 순서, 취소, 실패와 완료 관리 자연어 해석과 실제 모터·센서 제어를 하지 않음
DeviceAgent와 도메인 기능 기기 기능의 실제 실행 전체 제품의 작업 흐름을 각각 관리하지 않음

SKIX 프레임워크는 Android의 Manager/Service 구조 위에 제품 실행 제어의 핵심 원리인 상태 관찰·안전 정책·공유 자원 조정, 비동기 작업 생명주기와 물리 완료 근거를 결합한다. 기기 기능을 여러 호출 채널이 안전하게 공유하는 실행 기반이다.

공통 프레임워크가 필요한 이유

공통 관리 대상 분산될 때 발생하는 문제 프레임워크의 역할
기기 상태 앱마다 현재 위치·동작 상태를 다르게 판단 출처와 최신성이 포함된 공통 상태 제공
안전·제품 정책 호출 채널에 따라 허용 결과가 달라짐 동일한 정책 판정과 거부 사유 제공
공유 자원 이동·화면·음성·센서 사용이 충돌 소유권과 우선순위를 공통 조정
기능 계약 같은 기능도 입력과 결과 형식이 달라짐 기능 명세와 공개 API 계약 통일
실행 결과 명령 접수와 실제 완료가 혼동됨 진행 상태와 물리 완료 증거 연결

호출 채널별 적용 방식

호출 장면 기존 실행 방식 프레임워크 적용 방식 적용 효과
PUI에서 청정 시작 PUI가 setAirCleanerOperation을 직접 호출 submitTask(taskMethod=setAirCleanerOperation) 관리형 단일 Task로 변환하고 기존 청정 실행기를 사용 호출 채널과 관계없이 청정의 진행·취소·실제 종료를 같은 생명주기로 관리하기 위해
앱에서 이동 후 청정하고 복귀 앱이 callback과 상태를 직접 연결해 다음 기능 호출 앱은 Workflow 하나를 제출하고 TaskManager가 완료 순서를 관리 앱마다 순서·실패·취소 처리를 반복 구현하지 않게 됨
IoT에서 단일 설정값 변경 MQTT가 기존 기능을 직접 실행 기존 MQTT 계약 유지 기존 서버와 기기 계약을 바꾸지 않아도 됨
IoT에서 장기 작업 제출 서버가 진행 확인·재시도·취소를 별도로 구현 관리형 Task로 제출하고 상태 이벤트 수신 연결이 끊겨도 기기 내부에서 작업 상태와 최종 결과를 관리할 수 있음
제품 반복 예약 기존 ScheduleManager가 예약·활성 상태와 실행 장면을 함께 관리 SkixScheduleManager가 등록·반복·활성 상태를 관리하고, 실행 시점에는 Task·Workflow를 TaskManager에 제출 예약 관리와 매회 실행의 진행·취소·실패를 분리하기 위해
Task 1회 지연 호출자나 기능별 타이머가 지연 후 기능을 직접 호출 TaskManager가 한 번 실행할 Task의 시작 시점을 관리하고 제품 예약을 새로 만들지 않음 단기 지연 실행을 제품 반복 예약 목록과 섞지 않고 취소·만료·실행 결과까지 추적하기 위해
Workflow 단계 지연 앞 단계 callback 뒤 호출자가 타이머를 시작 TaskManager가 앞 단계 완료를 확인한 뒤 지정된 시간 후 다음 단계를 실행 단계 간 상대 시간을 실제 완료 시점과 연결하기 위해
상위 Planner가 동적 계획 생성 Planner나 중간 서비스가 기기 기능을 단계별로 직접 호출 Planner는 무엇을 할지 결정하고 TaskManager가 허용된 실행을 관리 계획 판단과 물리 실행·안전·완료 판정을 분리할 수 있음

실행 요청 단위 선택 기준

기능 하나라도 완료 확인·취소·시간 제한이 필요하면 관리형 단일 Task로 제출한다.

구분 사용하는 경우 관리 범위
직접 호출 조회·상태 전달·표현 갱신처럼 별도 작업 생명주기가 필요 없는 요청 기존 호출 경로와 도메인 정책 유지
관리형 단일 Task 청정·이동·복귀처럼 기능은 하나여도 진행 조회·취소·시간 제한·완료 근거가 필요한 동작 TaskManager가 접수부터 최종 상태까지 관리
작업 흐름 (Workflow) 이전 단계의 실제 완료 후 다음 단계를 실행해야 하는 복합 동작 Task 간 순서·의존관계·실패·보상 처리
제품 예약 (Product Schedule) 사용자가 조회·수정·삭제할 반복·요일·시각 기반 제품 예약 Schedule Service가 예약 생명주기를 관리하고 실행 시점마다 Task·Workflow 제출
Task 1회 지연 (Scheduled Task) 30분 뒤 청정처럼 한 번만 지연해 실행하는 작업 TaskManager가 시작 시점·취소·만료와 실행 결과를 관리
단계 상대 지연 (After Step Delay) 이동 완료 30초 뒤 측정처럼 앞 단계 완료를 기준으로 기다리는 경우 Workflow가 완료 근거를 받은 시점부터 지연을 계산해 다음 단계 실행
동적 계획 (Planner Plan) 현재 상태와 목표에 따라 실행 단위를 동적으로 구성하는 경우 Planner가 허용된 기능으로 Task·Workflow를 만들고 TaskManager가 실행

SKIX 프레임워크 구조

AOSP 경계에서 시작해 호출 창구, 공통 제어, TaskManager와 도메인 실행 순서로 구성한다.

기술 용어 뜻
Binder / AIDL Android 프로세스 사이에서 요청과 결과를 주고받는 통신 방식
Manager / Service 앱이 사용하는 호출 창구와, 실제 상태·정책을 소유하는 실행부
Task 시작부터 완료·실패·취소까지 상태를 추적하는 작업 한 개
작업 흐름 (Workflow) 여러 작업의 순서와 조건을 묶은 실행 계획
기능 명세 (Capability) 기능의 입력, 사용 조건, 실행기와 완료 기준을 적은 명세
StateMirror 위치·배터리·동작 상태를 한 형식으로 읽는 공통 최신본
완료 근거 (Evidence) 도착·도킹·측정 완료처럼 실제 작업 종료를 증명하는 사건
단일 책임 주체 상태 기록이나 실행 판단을 최종 확정하는 한 곳

전체 구조

Android AOSP와 SKIX Product Framework 전체 구조

그림 1. Android 위에서 동작하는 SKIX 제품 프레임워크 전체 구조
호출 앱의 Android 기본 API 경로와 SKIX 제품 기능 경로, Binder/AIDL, 공통 제어, DeviceAgent 실행, HAL·하드웨어와 callback 반환을 한 장에 연결한다. 원본 SVG 열기

<a id="mr7-current-position"></a>

2026-09-04 기준 MR7 초기 구조 대응 — 과거 분석

아래 오버레이와 표는 초기 분석 시점의 기록이며 현재 구현 상태가 아니다. 이후 공통 런타임·Task 소유권·typed Binder 구현을 포함한 최신 상태는 리팩터링 진행 현황에서 관리한다.

MR7 = Product Interface + Domain Framework 기반 구현
Framework Control Plane + Managed Execution Plane 미구현

Blueprint 원본 전체 구조 위에 MR7 대칭·유사·다름·미구현을 표시한 오버레이

원본 도형을 내부에 그대로 포함한 독립형 MR7 구조 대응 SVG
배경은 위의 Blueprint 전체 구조를 단일 SVG 안에 그대로 포함하며, 그 위에만 대칭(역할과 경계가 직접 대응), 유사(일부 대응), 다름(책임이 다름), 미구현 배지를 얹었다. 빨간 점선은 현재 요청이 중앙 SKIX Product Framework Service authority를 우회하는 경로다. 외부 SVG 중첩 참조가 없어 위키의 <img> 삽입 환경에서도 전체 구조와 오버레이가 함께 보인다. 독립형 오버레이 SVG 열기

MR7의 주 작업은 SkixManager·BaseManager·typed managers가 있는 Product Interface Layer와 ModuleCommandDispatcher·domain handlers가 있는 Domain Framework Plane이다. 현재 요청은 두 영역 사이에서 중앙 제어·관리형 실행 계층을 건너뛰는 현재 경로를 사용한다. 따라서 typed API와 handler 분리는 유지하되, 이것을 Framework Control Plane이나 Managed Execution Plane의 완성으로 해석하면 안 된다.

원본 Blueprint 위치 MR7 대응 판정 읽어야 할 차이
02A SKIX Client SDK / Manager API SkixManager, BaseManager, typed managers 대칭 앱 호출 창구 역할은 목표와 같은 방향
03 Binder / AIDL IDeviceControl.sendModuleCommand(Bundle) 유사 IPC 경계는 있으나 typed/versioned 계약은 아님
04 SKIX Product Framework Service 중앙 authority 없음 다름 상태·정책·자원·Task·완료 판단이 한 서비스 경계로 형성되지 않음
04의 State·Policy·Task·UI session 대응 owner 없음 미구현 이름이 비슷한 기존 helper를 목표 authority로 간주하면 안 됨
05 DeviceAgent Domain Execution ModuleCommandDispatcher, domain handlers 대칭 실제 제품 실행 owner 분리는 유지할 기반
06 Android Runtime / Native / Device Integration 기존 vendor/device 호출과 callback 유사 연동은 존재하지만 공통 TaskState·Evidence 계약으로 닫히지 않음

SKMLauncher2의 Fragment·ViewModel·Repository 비교는 전체 리팩터링 위치가 아니다. MVVM 분석은 Experience/Consumer의 앱 내부 사용 사례이며, Product Interface를 어떤 방식으로 소비하는지 보여 주는 확대도다. 코드별 정합성, 현재 우회 호출과 수정 순서는 MR7 정합성 감사 문서에서 확인한다.

설계와 감사 이후 실제 소스 반영 상태, 검증 결과, MR6 task_manager 이식 진행은 SKIX 제품 프레임워크 리팩터링 진행 현황에서 계속 관리한다. 서비스 라이프사이클과 도메인 상태 감사는 이 Blueprint의 lifecycle/state 원칙이 MR7 소스에서 어떻게 분리되고 있는지 추적한다. 도메인별 Bundle 계약 상수화는 기존 문자열 wire 계약을 base/compatibility에 모으고 typed Manager와 Agent가 같은 원본을 쓰는 진행 상태를 추적한다.

구조 표현은 Android 공식 문서의 AOSP Architecture, Platform Architecture, AIDL Overview를 기준으로 삼았다. Android가 제공하는 Manager·System Service·HAL 경계는 유지하고, 그 위에 SKIX 제품 상태·정책· 작업 생명주기와 실제 완료 근거를 추가한다.

앱이 요청하고 제품 실행 계층이 수행하는 흐름

앱 요청에서 제품 실행 결과까지의 역할 흐름

그림 1-A. 요청 구조화, Binder 전달, 기기 실행과 결과 반환
앱 프로세스는 요청과 화면 상태를 구조화하고 제품 실행 서비스는 상태·정책·Task와 실제 완료 근거를 관리한다. 원본 SVG 열기

SKIX Application Architecture Framework는 Android·Jetpack 사용 규칙과 앱 구조를 AAR·템플릿· 검증 도구로 제공한다. SKIX Product Runtime Framework는 Manager·Binder Service를 통해 기기 상태, 정책, Task와 UI 세션을 실제로 소유한다. 응용 프로그램 아키텍처 표준에서 UiAction·UiState, 제한적인 UiEffect, ViewModel, UseCase, Repository와 제품 실행 모듈의 역할을 정의한다.

AOSP 위에서의 위치

AOSP 위의 SKIX 리팩터링 프레임워크

그림 2. AOSP 위의 SKIX 프레임워크 내부 계층
제품 인터페이스, 공통 제어 계층, TaskManager와 도메인 프레임워크의 위치를 보여준다. 원본 SVG 열기

현재 DeviceAgent가 놓인 위치

DeviceAgent는 /system/priv-app의 플랫폼 서명 상시 실행 앱이자 Binder 제품 서비스다. 이는 현재 구현 기준선이고, 목표는 AOSP system_server의 얇은 SkixFrameworkSystemService와 독립 system_ext Runtime을 결합한 하이브리드다. 부팅·root Binder·권한·runtime death는 전자가, Task·Workflow·Policy·State·Evidence·도메인 권위는 후자가 담당한다. DeviceAgent는 provider·legacy gateway로 축소한다. 구조·SVG·부팅·복구 상세 현재 확인한 manifest의 .DeviceAgent는 exported=true이고 서비스 전체에 적용되는 signature permission이 선언돼 있지 않다. 일부 명령은 Binder.getCallingUid()를 개별 검사하지만 일반 명령 전체를 보호하는 공통 관문은 아니다. 플랫폼 서명으로 설치됐다는 사실은 호출자 접근 제어를 대신하지 않는다. 공개 Manager API를 연결하기 전에 서비스 권한, UID·패키지·인증서 검증과 메서드별 허용 범위를 제품 Runtime Binder 진입점에서 공통 적용해야 한다.

Android 호출 창구(Manager)와 실행 서비스(Service)의 분리

Android Application Framework의 구조처럼 앱이 쓰는 호출 창구(Manager)와 실제 상태·정책을 관리하는 실행 서비스(Service)를 Binder 경계로 분리한다. 호출 앱은 공개 Manager API를 사용하고, 실제 상태와 정책은 기기 안의 서비스 한곳이 책임진다.

Android Manager와 Service 패턴을 적용한 SKIX 계층

그림 3. 호출 창구와 실행 서비스의 책임 분리
호출 앱의 Manager, Binder 계약, 제품 프레임워크 서비스와 기기 도메인의 경계를 보여준다. 원본 SVG 열기

위치 실행 책임
경험·호출 계층 (Experience and Consumer Layer) 시스템 앱·PUI·IoT·예약·승인 파트너·선택적 Planner의 제품 경험 구성
제품 인터페이스 계층 (Product Interface Layer) UI 공통 AAR, Manager/Client API, Binder와 공통 요청·결과·이벤트 계약
프레임워크 제어 계층 (Framework Control Plane) 상태 프레임워크, 정책 엔진, 자원 조정기, 기능 레지스트리와 서비스 상태
관리형 실행 계층 (Managed Execution Plane) TaskManager, 작업 흐름, 실행 일정, 실행기, 완료 근거와 중간 저장점
도메인 프레임워크 계층 (Domain Framework Plane) 이동·청정·UI·Vision·Wellness·Security 등 입력 형식이 명확한 도메인 연결부
기기 연결 계층 (Device Integration Plane) DeviceAgent, 연동 Agent, AIDL/HIDL HAL, MCU·센서·하드웨어

Manager는 호출 앱이 쓰기 쉬운 요청을 만들고 서비스 연결·재연결과 결과 전달을 담당한다. Manager는 호출 창구로 남고 Service가 기기 상태와 정책을 소유한다. Manager가 잠시 저장한 값이 기기의 새로운 기준 상태가 되어서는 안 된다.

AudioManager, PowerManager, DisplayManager, WindowManager, UiModeManager, AlarmManager처럼 Android가 이미 제공하는 기능은 Application과 SKIX Service가 Context.getSystemService()로 직접 사용한다. AOSP 기본 Framework를 다시 구현하지 않는다. SKIX는 그 위에 제품 의미, 공통 상태·정책, 작업 추적 정보와 물리 완료 근거를 추가한다.

필요한 호출 창구와 실행 서비스

Manager는 호출 편의와 Binder 연결 대리부를 제공하고, Service는 최종 상태와 판단을 소유한다. 구성요소 이름은 목표 구조의 책임 명칭이다.

표의 State Service, Policy Service, Task Service는 1차 단계에서 각각 별도 APK나 프로세스를 뜻하지 않는다. 초기 배치는 DeviceAgent 프로세스의 하나의 제품 Runtime Binder 진입점 뒤에 논리 모듈로 둔다. 별도 프로세스는 장애 격리, 독립 업데이트 또는 파트너 보안 경계가 실제로 필요하다는 근거가 생겼을 때만 분리한다.

구분 1차 배치 분리 검토 조건
호출 앱 Skix*Manager와 공통 Client AAR 앱별 독립 배포 유지
Binder 경계 DeviceAgent의 제품 Runtime Binder 진입점 하나 별도 인증서 파트너 공개, 독립 OTA, 장애 격리 요구
내부 실행 책임 상태·정책·자원·Task·UI 세션을 논리 모듈로 분리 측정된 안정성·성능·보안 이점이 있을 때만 프로세스 분리
구분 구성요소 호출 측 역할 Service 책임 필요한 이유
필수 기반 SkixFramework Client Core Service 탐색, 연결·재연결, 버전 확인, 결과 알림 전달 공통 Binder 연결 규약 제공 Manager마다 연결·재연결 코드를 중복하지 않기 위해
필수 기반 SkixDeviceStateManager / State Service 위치·도킹·배터리·동작 상태 조회·구독 단일 상태 원본, 출처, 시각, 최신성, 공개 범위 관리 앱마다 서로 다른 현재 상태를 판단하지 않게 하기 위해
필수 기반 SkixCapabilityManager / Capability Service 지원 기능·입력 형식·사용 가능 조건 조회 기능·정책·자원·실행기·완료 근거 연결 호출 전에 실제 수행 가능 여부를 알기 위해
필수 기반 SkixExecutionPolicyManager / Execution Policy Service 실행 허용 여부와 공개 가능한 판단 사유 조회 안전·보안·제품·사용자 동의 정책 합성 호출 채널마다 실행 기준이 달라지는 것을 막기 위해
필수 기반 SkixExecutionEventManager / Execution Event Service 상태·Task·UI 실행 이벤트와 완료 근거 조회·구독 이벤트 순서·추적 정보·공개 범위·제한 재전달 관리 요청부터 실제 결과까지 같은 실행 흐름으로 추적하기 위해
필수 기반 SkixFrameworkHealthManager / Framework Health Service 프레임워크 구성요소의 준비·성능 저하·복구 상태 조회 Binder 연결 종료, 오래된 상태, 재연결과 안전 정지 관리 연결 장애를 기기 기능 실패와 구분하기 위해
관리형 실행 SkixExecutionResourceManager / Execution Resource Service 실행 자원의 점유 상태와 대기 이유 조회 이동·카메라·화면·오디오 점유권과 충돌 조정 동시에 사용할 수 없는 기기 자원의 오동작을 막기 위해
관리형 실행 SkixTaskManager / Task Service Task·Workflow 제출, 조회, 취소와 완료 구독 실행 허용 판정, 대기열, 순서, 시간 제한, 취소와 완료 판정 장기·복합 작업의 생명주기를 한곳에서 관리하기 위해
제품 확장 SkixUiManager / SkixUiService 안정된 화면 ID로 세션 시작·갱신·종료·복귀 요청 UI 실행 문맥, 전면 화면 소유권, 제품 장면과 겹쳐 표시 조정 Launcher와 호출 앱의 화면 충돌을 막기 위해
제품 확장 SkixScheduleManager / Schedule Service 반복·요일·시각 예약 등록·조회·삭제 저장, 재부팅 후 재등록, 시작 조건과 Task 제출 제품 예약과 작업 흐름 내부 지연을 구분하기 위해

Manager별 대표 API

공개 API는 get/set/config를 일률적으로 제공하지 않는다. Task·UI·Schedule은 실행 요청을 받지만, 상태·정책·이벤트·건강 정보는 조회와 구독이 기본이다. 모든 요청과 결과는 임의의 setConfig(Bundle) 대신 버전이 붙은 명확한 형식을 사용한다.

제품 기능과 관리형 실행 API
공개 Manager 대표 API 사용 의도 내부 Service에 남기는 권한
SkixTaskManager submitTask(TaskRequest) · submitWorkflow(WorkflowRequest) · getTask(taskId) · listTasks(TaskQuery) · cancelTask(taskId, reason) · observeTask(taskId, listener) 단일 Task와 여러 단계 작업 흐름을 제출하고, 진행·취소·완료를 같은 식별자로 관리한다. 진행률 갱신, 실제 완료 근거 기록, 강제 종료와 대기열 복구
SkixDeviceStateManager getSnapshot(StateQuery) · getState(StateKey) · observeState(StateFilter, listener) · getFreshness(StateKey) 위치·도킹·배터리·이동·청정 등 기기 상태의 최신본과 출처·갱신 시각을 제공한다. 센서와 도메인 어댑터의 상태 기록·정정. 일반 앱의 임의 상태 변경은 공개 API에서 제공하지 않음
SkixCapabilityManager listCapabilities(CapabilityFilter) · getCapability(capabilityId) · checkAvailability(capabilityId, context) · validateRequest(capabilityId, input) 기기가 지원하는 기능, 필요한 입력, 현재 사용 가능 여부와 완료 근거를 실행 전에 확인한다. 기능 등록·변경, 실행기·정책·자원·완료 근거 연결
SkixUiManager startUiSession(UiRequest) · updateUiSession(sessionId, UiUpdate) · finishUiSession(sessionId, reason) · getActiveUiSession() · observeUiSession(listener) 화면을 Activity 이름이 아닌 안정된 UI 대상과 세션으로 열고, 앱의 UiSessionRepository가 수신할 상태를 제공한다. SkixUiService, UiSessionController, 전면 표시 소유권, 화면 실행·복귀, 제품 장면과 겹쳐 표시 조정
SkixScheduleManager createSchedule(ScheduleSpec) · updateSchedule(scheduleId, ScheduleSpec) · getSchedule(scheduleId) · listSchedules(ScheduleQuery) · setScheduleEnabled(scheduleId, enabled) · deleteSchedule(scheduleId) · previewNextRun(scheduleId) 반복·요일·시각 기반 제품 예약을 저장하고 다음 실행 시점과 활성 상태를 관리한다. 재부팅 후 재등록, 실제 알람 연결, 실행 시점의 Task 제출과 실패 복구
실행 판단과 관측 API
공개 Manager 대표 API 사용 의도 내부 Service에 남기는 권한
SkixExecutionPolicyManager checkExecutionAllowed(ExecutionRequest request, Executor executor, ExecutionPolicyCallback callback) · registerPolicyChangeListener(PolicyScope scope, Executor executor, PolicyChangeListener listener) · unregisterPolicyChangeListener(PolicyChangeListener listener) 실행 판정은 callback의 ExecutionPolicyDecision으로 반환한다. result, reasonCode, reasonSummary, unmetConditions, retryable, policyVersion을 함께 제공한다. 시스템·제품 정책 원문, 합성 규칙, 정책 설치·변경, 우회 방지와 상세 진단 정보
SkixExecutionResourceManager getResourceState(resourceId) · checkResourceAvailability(ResourceRequirement) · getOccupancySummary(resourceId) · getWaitReason(requestId) · observeResourceState(listener) 이동·카메라·헤드·오디오·화면처럼 동시에 사용할 수 없는 실행 자원의 점유 여부와 대기 원인을 보여준다. 사용권 부여·회수·선점과 상세 점유 주체는 Service 내부에 둔다. 일반 앱에는 공개 가능한 점유 요약만 제공
SkixExecutionEventManager observeExecutionEvents(EventFilter, listener) · getExecutionHistory(EventQuery) · getLastEvent(traceId) 여러 도메인에 걸친 실행 이력과 진단 이벤트를 추적한다. Task의 현재 상태와 최종 결과는 SkixTaskManager에서 조회한다. 도메인 이벤트 발행, 순서 보장, 원본 완료 근거와 제한된 진단 정보. 일반 앱의 완료 이벤트 발행은 제공하지 않음
SkixFrameworkHealthManager getFrameworkHealth() · getComponentHealth(componentId) · runSelfCheck(scope) · observeHealth(listener) · requestRecovery(componentId) SKIX Service와 연동 구성요소가 준비·저하·복구 중인지 확인하고 진단 결과를 제공한다. 자동 재연결·안전 정지·복구 정책 수행. requestRecovery는 시스템 권한 호출자만 허용

Execution은 Task 실행의 허용·자원·이벤트, Framework는 SKIX 구성요소의 건강 상태를 뜻한다. 정책 변경 구독은 register...Listener와 unregister...Listener를 짝으로 제공하고, callback 실행 스레드는 호출자가 Executor로 지정한다. 판정 사유는 최초 callback에 포함하므로 별도 decisionId 재조회 API를 만들지 않는다. 합성된 정책 원문과 내부 규칙 조회는 권한 있는 진단 도구에만 제공한다.

Task 생명주기의 권위 원본은 SkixTaskManager 하나다. SkixExecutionEventManager는 감사와 장애 분석을 위한 횡단 이벤트를 제공할 뿐, Task의 최종 상태를 별도로 확정하지 않는다.

프레임워크 핵심 구조

공통 구성요소와 역할

핵심 구성 쉽게 말하면 소유 책임 대표 출력
제품 인터페이스 (Product Interface Layer) PUI·앱·IoT 요청을 같은 형식으로 받는 입구 동작·작업 흐름·상태 조회와 결과 형식 정리 버전이 붙은 요청·결과
기능 레지스트리 (Capability Registry) 기기가 할 수 있는 기능과 사용 조건을 모아 둔 기능 명세서 입력·전제 조건·정책·자원·실행기·완료 증거 연결 CapabilityDescriptor
상태 프레임워크 (State Framework) / StateMirror 위치·배터리·동작 상태의 공통 최신본 도메인의 단일 상태 기록을 출처·시각·최신성과 함께 제공 StateSnapshot
정책 엔진 (Policy Engine) 지금 실행해도 되는지 판단 접근·안전·제품·개인정보 보호·동의 정책 합성 PolicyDecision
자원 조정기 (Resource Arbiter) 동시에 쓸 수 없는 기기 자원의 교통정리 이동·카메라·헤드·화면·오디오의 대기·선점·해제 관리 ResourceLease
생명주기 관리기 (Lifecycle Supervisor) 연결된 서비스가 정상인지 감시 준비·장애·재연결·안전 정지 관리 ComponentHealth
TaskManager 허용된 작업을 끝까지 관리 대기열·순서·시간 제한·취소·종료 상태 소유 TaskSnapshot
완료 근거 변환부 (Evidence Adapter) 호출 응답과 실제 완료를 구분 API 접수 응답이 아닌 도킹 결과 알림 같은 물리 근거를 공통 형식으로 변환 EvidenceRecord
도메인 연결 계층 (Domain Framework Plane) 공통 계약을 기존 기능 호출로 바꾸는 연결부 형식이 명확한 요청을 기존 Manager와 도메인 이벤트로 연결 도메인 실행 결과
이벤트·완료 근거 연결망 (Event and Evidence Fabric) 요청과 결과를 같은 작업으로 묶는 흐름 상태·작업·UI 결과 알림에 같은 추적 ID 부여 FrameworkEvent

안전 기준은 호출 앱이 완화할 수 없다

정책은 호출 앱마다 따로 판단하지 않는다. 시스템 안전 기준, 제품 기준, 호출 앱의 허용 범위와 현재 기기 상태를 차례로 적용하고 가장 엄격한 조건을 최종 결과로 사용한다.

System 책임과 호출 앱 자유도를 함께 유지하는 정책 구조

그림 4. 계층형 정책 합성
시스템 안전 기준부터 현재 기기 상태까지 네 조건을 순서대로 확인하고 실행 여부를 결정한다. 원본 SVG 열기

실행 요청
  1. 시스템 안전 기준을 지키는가?
  2. 제품 사양에서 허용한 동작인가?
  3. 호출 앱에 이 기능을 사용할 권한이 있는가?
  4. 현재 기기 상태가 실행 가능하고, 필요한 사용자 동의를 받았는가?

네 조건을 모두 통과해야 실행한다.
하나라도 통과하지 못하면 사유와 함께 거부하거나 조건이 충족될 때까지 보류한다.

상태 조회와 실행 정책의 경계

Client의 상태·정책 조회는 사전 안내다. 화면 제어와 요청 구성에는 사용할 수 있지만, 조회 직후 기기 상태가 달라질 수 있으므로 실행 권한이나 성공 보장이 되지 않는다.

판정 시점 프레임워크 책임
요청 전 조회 현재 상태·기능 사용 가능 여부·거부 사유를 Client에 제공
요청 접수 호출자 권한, 입력, 기기 정책과 자원 충돌 판정
실행 직전 상태 최신성을 확인하고 최신 기기 상태로 다시 판정
장기·복합 실행 접수 시점, 실행 직전, 작업 흐름의 각 단계와 관련 상태 변경 때 재판정

상태가 오래됐거나 정책 조건이 바뀌면 실행을 보류·거부하고, 진행 중 위반이 생기면 정책에 따라 일시 정지·취소·안전 정지한다. 기존 직접 명령도 같은 정책 관문을 통과하며 Client가 우회 값을 지정할 수 없다. 도메인 고유 안전 규칙은 최종 방어선으로 남는다.

예를 들어 제품 정책이 “이동 중에는 헤드 틸트 관찰 동작을 허용하지 않는다”라면 Client가 이동 전 허용 상태를 조회했더라도, 실행 시점에 이동 중이면 프레임워크가 요청을 막는다. 이동 도메인의 주행 자세와 모터 안전 규칙도 별도로 유지한다.

상태·정책·자원을 함께 확인한다

기능 명세(Capability)는 단순한 메서드 목록이 아니라 기능의 사용 설명서다. 입력·출력·실행 전 조건, 정책·자원·실행기·완료 근거를 한곳에서 연결한다. 예를 들어 mobility.move_to_room은 등록된 공간과 최신 위치 상태, 이동 자원 점유권, 이동 정책, AMR 실행기와 movement.arrived 완료 근거를 함께 선언한다. 상세 계약은 뒤의 참고 자료에 둔다.

실행 중인 작업을 관리하는 TaskManager

TaskManager는 요청의 의미를 해석하거나 모터를 직접 제어하는 기능이 아니다. 앱·IoT·예약 같은 호출자가 실행할 작업과 순서를 정해 제출하면, TaskManager는 어떤 단계가 실행 중인지, 언제 다음 단계로 넘어갈지, 최종적으로 성공·실패·취소 중 무엇으로 끝났는지 관리한다.

호출자·TaskManager·DeviceAgent의 책임
구분 담당하는 일 담당하지 않는 일
호출자 제품 장면에 맞는 Task·Workflow를 구성하고 실행 요청 물리 동작의 완료를 임의로 확정하지 않음
TaskManager 접수, 대기열, 단계 순서, 시간 제한, 취소, 완료 근거 대기와 최종 상태 관리 사용자 의도 해석과 모터·센서 직접 제어를 하지 않음
DeviceAgent·도메인 실행기 실제 기기 기능을 수행하고 완료·실패 근거를 반환 전체 Workflow의 다음 단계를 임의로 선택하지 않음

여러 기능을 순서대로 실행하거나 실제 완료를 기다려야 할 때 TaskManager가 필요하다. 앱이 안방 이동 → 청정 → 스테이션 복귀 Workflow를 제출했다면 다음과 같이 처리한다.

  1. 이동 Task를 실행하고 AMR의 실제 도착 결과를 기다린다.
  2. 도착 근거가 확인된 뒤에만 청정 Task를 시작한다.
  3. 청정의 완료·취소·실패를 구분하고 다음 단계 실행 가능 여부를 확인한다.
  4. 복귀 Task의 실제 도킹 결과까지 확인한 후 Workflow를 종료한다.
  5. 각 단계와 전체 Workflow의 진행 상태·실패 이유·최종 결과를 호출자에게 전달한다.

현재와 개선 실행 구조 비교

그림 5. 기능은 유지하고 실행 관리를 공통화하는 구조
호출자가 실행 과정을 각각 연결하는 구조와 TaskManager가 작업 생명주기를 관리하는 구조를 비교한다. 원본 SVG 열기

요청 → 계약 검증 → 정책·자원 판정 → 작업 실행 → 물리 완료 근거 → 결과
구성요소 쉽게 말하면 책임
Task 상태 관리 각 작업의 현재 상태를 기록하는 중심부 접수·대기·실행·완료 근거 대기·최종 종료 상태 관리
단계 순서 관리 여러 Task가 실행될 순서를 관리 앞 단계 완료 확인, 의존관계, 병렬 실행과 실패 시 중단 범위
시작 시점 관리 Task를 언제 시작할지 판단 절대 시각, 이전 단계 완료 후 지연, 상태·이벤트 조건
기기 기능 연결 Task와 실제 DeviceAgent 함수를 연결 기능 명세에 맞는 도메인 실행기 선택과 요청 전달
완료 확인 실제 동작이 끝났는지 확인 도착·도킹·청정 종료·앱 세션 종료 같은 기능별 완료 근거 관찰
실패 처리 실패 뒤 허용된 대응 수행 재시도·되돌림·안전 복귀·사용자 확인 중 사양에 맞는 처리
실행 기록 재시작 뒤에도 이어갈 수 있는 정보 보존 진행 상태, 중복 방지 값과 재기동 복구 정보 저장

SKIX 프레임워크 관리형 실행 폐루프

그림 6. 관리형 실행 폐루프
요청 판정부터 Task 실행, 도메인 결과 알림, 물리 근거와 최종 결과까지의 흐름을 보여준다. 원본 SVG 열기

아래 상태는 목표 공개 계약이다. 현재 병합 후보가 사용하는 PENDING, RUNNING, COMPLETED, CANCELLED, FAILED, PARTIAL_FAILED는 내부 상태로 유지하고 공개 Adapter에서 아래 상태로 변환한다.

SUBMITTED → ADMITTED → QUEUED → RUNNING → WAITING_EVIDENCE
                                      └→ SUCCEEDED | FAILED | CANCELLED | TIMED_OUT

SKIX Task 생명주기 상태 전이

그림 7. Task 생명주기와 종료 상태
요청 접수부터 정책·자원 판정, 실행, 물리 완료 근거 확인과 최종 종료까지의 공개 상태 계약을 보여준다. 원본 SVG 열기

전환기에는 다음 매핑을 사용한다. 내부 정보만으로 공개 단계를 확정할 수 없으면 더 구체적인 상태를 추측하지 않고 앞 단계로 표현한다.

병합 후보 내부 값 공개 상태 변환 기준
PENDING SUBMITTED · ADMITTED · QUEUED admission과 queue 정보가 있을 때만 세분화하고, 없으면 SUBMITTED
RUNNING RUNNING · WAITING_EVIDENCE 완료 근거 watcher 대기 여부가 명시될 때만 WAITING_EVIDENCE
COMPLETED SUCCEEDED 기능별 완료 근거 또는 완료 계약이 확인된 경우에만 변환
FAILED + errorCode=timeout TIMED_OUT 현재 후보 구현이 timeout을 FAILED 이벤트로 내보내는 차이를 Adapter에서 정규화
FAILED FAILED timeout이 아닌 최종 실패
CANCELLED CANCELLED 취소가 실제 실행기와 도메인에서 확인된 경우
PARTIAL_FAILED Workflow 결과의 PARTIAL_FAILED Task 하나의 성공 상태로 축약하지 않고 단계별 결과와 함께 반환

공개 이벤트는 eventName에 상태명을 반복하지 않고 TASK_STATE_CHANGED와 state를 분리한다. 호출자는 state를 기준으로 종료 여부를 판단하고, reasonCode와 단계 결과로 원인을 확인한다.

API 반환은 요청 수락을 의미할 뿐 완료가 아니다. 이동은 도착, 복귀는 도킹, 청정은 정의된 종료 상태, Vital Signs는 사용자 측정 완료 또는 취소처럼 기능별 최종 상태 계약을 따른다. 결과 알림은 requestId, workflowId, stepId, taskId, traceId로 원래 Task에 귀속한다.

제품 예약, Task의 1회 지연과 Workflow 내부 시간 조건은 서로 다른 시간선으로 관리한다.

시간 요구 소유 주체 예
제품 예약의 반복·요일·시각 Schedule Service·예약 저장소·AlarmManager 매일 밤 9시 나이트 모드
Task의 1회 지연·절대 시각 TaskManager TaskScheduler 30분 뒤 청정 시작
이전 단계 완료 후 지연 작업 흐름 실행 일정 이동 완료 30초 뒤 측정 시작
상태·이벤트 조건 시작 조건 판정기 도킹되면 업데이트 수행

프레임워크와 Task 생명주기

프레임워크는 Task 상태만 관리해서는 충분하지 않다. 기동 순서, 서비스 연결, 호출자 세션, 도메인 실행과 완료 증거가 각자의 생명주기를 가지며, Task는 이 상태들을 바탕으로 실행 가능 여부와 다음 단계를 결정한다.

프레임워크 서비스와 Task 생명주기의 연결

그림 8. 프레임워크와 Task 생명주기
프레임워크 기동부터 서비스 연결, Task 실행, 물리 완료 근거와 장애 복구까지의 관계를 보여준다. 원본 SVG 열기

생명주기 대표 상태 관리 책임
프레임워크 기동 CREATED → STARTING → READY → STOPPING 구성요소 생성, 의존성 순서, 종료 정리
서비스 연결 DECLARED → BINDING → READY → DEGRADED → RECOVERING bind·재연결, 준비 상태, 기능 사용 가능 여부
호출자 세션 CONNECTED → ACTIVE → DISCONNECTED callback 등록, Binder 연결 종료, 세션·점유권 정리
Task 생명주기 SUBMITTED → QUEUED → RUNNING → WAITING_EVIDENCE → TERMINAL 순서, 취소, 시간 제한, 재시도와 최종 상태
도메인 실행 REQUESTED → STARTED → ACTIVE → STOPPED/FAILED 실제 기능 실행과 도메인 고유 안전 정책
완료 증거 OBSERVED → CORRELATED → ACCEPTED/REJECTED 결과 알림을 원래 Task·단계에 연결하고 완료 여부 판정

서비스 연결 종료가 곧 Task 성공이나 실패를 뜻하지 않는다. 필요한 서비스가 끊기면 구성요소 상태를 DEGRADED 또는 RECOVERING으로 바꾸고, 진행 중 Task는 기능별 안전 정책에 따라 대기, 재시도, 취소 또는 안전 정지한다. 재연결 뒤에도 같은 요청을 중복 실행하지 않도록 Task 기록과 완료 증거의 상관관계를 유지한다.

호출 계층과 기기 실행 기반의 경계

앱·PUI·IoT·예약·AI 같은 호출 애플리케이션은 StateMirror와 기능 명세로 현재 상태와 허용 기능을 확인하고 구조화된 Task·Workflow를 제출한다. 프레임워크는 정책·자원 검증, 실행 관리와 완료 근거 반환을 담당한다. 이 계약을 유지하면 호출 애플리케이션이 바뀌어도 기기 실행 계층은 유지된다.

호출 애플리케이션과 제품 실행 프레임워크의 경계

그림 9. 호출 계층 변화와 제품 실행 제어의 경계
호출자는 공통 실행 계약에 의존하고, 프레임워크는 상태·정책·자원·완료 판정을 일관되게 관리한다. 원본 SVG 열기

외부 사용 방식과 호환성

기존 호출은 그대로 유지하고, 순서·대기·취소·완료 증거가 필요한 관리형 요청만 Task 계약으로 확장한다.

요청 유형 기존 호환 경로 관리형 경로
단순 조회·표현 갱신 기존 조회·상태 전달 메서드 유지 Manager의 상태 조회 또는 추적 없는 직접 호출 사용
단일 기기 동작 전환기에는 기존 실행 메서드 유지 청정·이동·복귀처럼 완료 관리가 필요한 동작은 관리형 단일 Task로 제출
복합·조건·장기 실행 서비스별 연결 코드 작업 흐름과 실행 일정으로 제출
IoT·MQTT 기존 메서드·payload 유지 request.task 또는 버전이 있는 작업 흐름 요청 형식 선택
앱 화면 진입 기존 Intent 변환부 유지 안정된 uiTargetId와 UiSession으로 단계적 이전

MQTT 계약은 전송 계층이 아니라 응용 계약을 확장한다

TaskManager 도입 때문에 MQTT 전체를 교체하지 않는다. broker·Topic·인증·QoS는 유지하고, 기존 단일 명령의 JSON도 그대로 허용한다. 변경되는 범위는 순서·대기·취소·완료 추적이 필요한 요청에 관리 의미를 추가하는 payload와 결과 이벤트다.

기존 MQTT를 유지하면서 Task와 Workflow 계약을 선택적으로 확장하는 구조

그림 10. MQTT 전송 호환성과 관리형 실행 계약
기존 JSON 해석을 유지한 채 단일 Task만 호환 어댑터로 감싼다. 복합 Workflow의 MQTT 공통 해석기는 별도 수용 범위로 구분한다. 원본 SVG 열기

AWS IoT Domain Framework로 Client별 양방향 관계를 연다

IotAgent가 단일 AWS IoT Core 연결과 자격 증명을 소유한다. 각 Client Service App은 SkixIotCoreManager를 통해 필요한 domain/channel만 선택한다. Binder 뒤의 SkixIotCoreService는 caller 권한, Client별 구독, publish 전달 상태와 재연결 생명주기를 소유한다. Client가 별도 MQTT 연결을 만들거나 raw Topic을 받는 구조가 아니다.

Client Service App과 Domain별 양방향 AWS IoT Pub/Sub 구조

그림 10-A. AWS IoT Domain Framework 책임 구조 — 기존 MQTT JSON과 Task Contract는 유지한다. 신규 API는 Manager → Binder Service → IotAgentAdapter를 거치며, 기존 제품 handler와 신규 Client callback은 하나의 물리 수신에서 중복 없이 분배한다.

방향 Client 공개 계약 Framework 내부 처리 AWS IoT Core
AWS → Client subscribe(domain, channel, callback) → SubscriptionHandle ClientSubscriptionRegistry가 caller·callback·quota를 격리하고 SubscriptionMultiplexer가 같은 Topic을 병합 exact Topic Physical Subscription
Client → AWS publish(domain, channel, payload, statusCallback) → PublishReceipt schema·QoS·rate·offline queue를 검사하고 publishId의 후속 상태를 callback/query로 추적 MQTT publish와 QoS 1 PUBACK
양방향 요청 request(domain, requestChannel, responseChannel) response 선구독 → correlationId → request publish → 응답/timeout 후 임시 handle 회수 Request/Response Topic pair

SkixIotCoreManager가 공통 진입점이며, CleaningIotManager, MobilityIotManager 같은 전용 Manager는 같은 정책 경로를 쓰는 선택적 wrapper다. Client A와 B가 같은 cleaning.command를 구독해도 Handle A1/B1은 독립적이다. A의 unsubscribe 또는 Binder death는 A1만 닫고 B1은 유지한다.

Client A: subscribe(cleaning.command) → Handle A1  / publish(cleaning.state) → Receipt A2
Client B: subscribe(cleaning.command) → Handle B1  / subscribe(mobility.command) → Handle B2
Physical: cleaning.command Topic 1개 → Framework가 A1·B1 callback으로 독립 fan-out

Client 공개 범위와 Service 내부 통제

구분 담는 정보 경계 원칙
Client 공개 범위 DomainCapability 사용할 수 있는 domain·channel·방향·schema version Client는 허용된 논리 채널만 선택하고 raw Topic과 내부 정책은 알지 않아도 됨
Service 내부 통제 DomainDescriptor Topic template, caller group, quota 상한, schema·QoS 정책 실제 Topic과 정책 변경 권한은 Framework Service가 소유

실행은 시스템 공통 정책, 서명된 Domain 명세, 호출자 권한, 이번 요청의 조건까지 네 조건을 모두 통과해야 허용한다. 계약식은 Root Policy ∩ signed DomainDescriptor ∩ caller grant ∩ operation request다. 내부 DomainDescriptor는 AWS→Client의 subscribeChannels와 Client→AWS의 publishChannels를 분리해, 구독 권한이 발행 권한으로 확대되지 않도록 한다.

새 Domain 추가

기본 경로는 제품 이미지에 포함되는 로컬 built-in descriptor다. 공통 codec을 사용하는 Domain은 descriptor·schema·권한·계약 테스트만 추가하며 Framework Core의 분기문을 수정하지 않는다. 원격 skix-domain-catalog는 이미 설치된 capability의 활성화·축소·회수만 담당하며, 설치되지 않은 실행 코드나 새 하드웨어 기능을 원격 설정만으로 추가할 수는 없다.

발행 상태와 복구

개념 계약은 publish(domain, channel, payload)이고, 실제 API는 statusCallback을 함께 받는다. 상태는 LOCAL_ACCEPTED → QUEUED_OFFLINE → SENT → PUBACKED → RESPONDED로 진행하거나 FAILED로 끝난다. PublishReceipt는 최종 성공이 아닌 접수 시점의 상태다. 후속 결과는 PublishStatusCallback 또는 getPublishStatus()로 확인한다.

연결, 구독, 발행은 서로 다른 생명주기로 관리해 각 장애의 영향 범위를 격리한다. Broker 단절은 logical handle을 유지한 채 복구하고, Client 종료는 해당 구독만 닫으며, 개별 발행 실패는 해당 메시지만 재처리한다. Framework Service가 재시작되면 기존 Binder handle은 무효이므로 Manager가 재bind 후 구독 intent를 다시 제출해 새 handle을 받는다.

Client별 Domain Subscription 생명주기

그림 10-B. 연결·구독·발행 생명주기 — 마지막 logical reference가 없어질 때만 Broker unsubscribe를 수행한다. Broker 재연결, Binder death, Framework Service 재시작의 복구 규칙은 서로 다르며, 필요한 범위만 복구해 정상 Client와 메시지에 장애가 번지는 것을 막는다. 신규 domain 등록 경로는 Catalog SVG, 전체 API·오류·전환 계약은 AWS IoT Domain Framework 상세 설계를 본다.

현재 구현을 세 단계로 구분한다
구분 실제 경로 상태
현재 제품 경로 CmdTopic이 기존 JSON을 기능별 Bundle로 변환 → sendModuleCommand(Bundle) → MainApi 직접 실행 기존 MQTT 요청·응답 유지
TaskManager 적용 구조 CmdTopic이 기존 명령 Bundle을 만든다 → IotTaskManagerBridge.wrapCommand()가 관리형 여부를 판정 → 같은 sendModuleCommand(Bundle) 사용 별도 TaskManager 작업본에 구현
복합 Workflow method=submitWorkflow, subTasks 목록을 DeviceAgent TaskManager가 실행 AAR·Cloud 변환부는 구현되어 있으나 MQTT 공통 해석기 연결은 추가 수용 필요
MQTT JSON
  → CmdTopic의 기존 기능별 해석
  → 기존 method·parameter Bundle 생성
  → IotTaskManagerBridge.wrapCommand()
       request.task 없음       → 기존 직접 실행 Bundle 유지
       request.task {}         → method=submitTask, taskMethod=기존 method
       request.task.managed=false → 기존 직접 실행 Bundle 유지
  → sendModuleCommand(Bundle)
  → MainApi 직접 실행 또는 TaskManager

request.task가 없으면 기존 직접 실행, 빈 {}도 관리형 실행 의도로 처리한다. managed=false이면 기존 직접 실행을 유지한다. 관리형 요청에서 실행 방식·대기열·우선순위·시간 제한을 생략하면 TaskPolicyRegistry의 기능별 기본값을 사용한다. IoT 변환부는 correlationId를 traceId와 함께 보존하고 replyTo도 다음 계층으로 전달한다.

기존 단일 명령

{
  "request": {
    "method": "setMoveTo",
    "payload": {"positionId": "5"}
  }
}

관리형 단일 Task

{
  "correlationId": "iot-20260830-0001",
  "replyTo": "device/reply/command",
  "request": {
    "method": "setMoveTo",
    "payload": {"positionId": "5"},
    "task": {}
  }
}

위 메시지는 내부에서 다음 Bundle 의미로 바뀐다. forceTaskManager는 DeviceAgent 내부 라우팅 표식이며 공개 MQTT 필수 필드가 아니다. IoT 단일 Task는 method=submitTask 자체로 TaskManager 제어 API에 진입한다.

method=submitTask
taskMethod=setMoveTo
source=iot
traceId=iot-20260830-0001
correlationId=iot-20260830-0001
replyTo=device/reply/command

여러 단계를 한 실행으로 관리할 때는 submitWorkflow와 subTasks 목록을 사용한다. 이 Bundle 계약은 DeviceAgent TaskManager와 AAR·Cloud 변환부에 구현되어 있다. 다만 아래와 같은 외부 MQTT JSON을 모든 Topic에서 공통으로 해석하는 연결부는 단일 Task 어댑터와 별도로 수용·회귀 검증해야 한다.

{
  "requestId": "iot-20260830-0002",
  "traceId": "iot-20260830-0002",
  "request": {
    "method": "submitWorkflow",
    "payload": {
      "subTasks": [
        {"taskMethod": "setMoveTo", "positionId": "5"},
        {"taskMethod": "startBasicAirClear"},
        {"taskMethod": "returnToStation"}
      ]
    }
  }
}
MQTT 전달 특성은 구현 상태를 구분한다
항목 현재 확인된 범위 보강할 계약
상관관계 correlationId, traceId, replyTo 보존 Task 진행·최종 이벤트까지 같은 ID 유지
접수와 완료 TaskManager 내부에서 접수와 최종 상태를 구분 MQTT 응답에서도 ACCEPTED와 공개 최종 상태 SUCCEEDED를 분리
중복 수신 추적 ID 필드는 있으나 MQTT 전체 멱등 실행 보장은 별도 검증 필요 requestId로 QoS 1의 재전달 중복 방지
오래된 명령 단일 IoT 어댑터에 ttlMs·expiresAt 해석 없음 실행 전 만료 판정 추가
retain 기존 운영 Topic 정책을 따름 명령은 retain=false, 상태 최신본만 retained Topic 검토
복합 순서 TaskManager가 subTasks 순서를 관리 MQTT 공통 Workflow 해석기와 단계 이벤트 연결
기존 직접 요청과 관리형 요청이 함께 존재하는 동안의 동시성

현재 직접 요청은 기존 DeviceAgent 정책과 도메인 차단 규칙을 사용하고, 관리형 요청은 여기에 TaskManager의 접수·대기열·자원 판정을 추가한다. 두 경로가 새 자원 조정기를 완전히 공유하는 상태는 아니다. 관리형 Workflow가 이동 중일 때 기존 직접 이동 명령이 들어오는 충돌을 막으려면 진입점에서 사용 중 거절, 허용된 선점 또는 관리형 전환 중 하나를 정하고 실행권을 하나만 선택해야 한다.

상세 필드와 결과 알림 규칙은 MQTT Task Contract를 기준으로 하고, 제품 반영 전에는 기존 요청·응답, 단일 관리 Task, 복합 Workflow를 각각 회귀 시험한다.

호출 앱 계약

DeviceAgent 책임 과집중 해소

DeviceAgent를 단순히 여러 클래스로 나누는 것만으로는 과집중이 해소되지 않는다. 상태·정책·자원·작업·UI의 최종 판단권이 계속 한 객체에 남아 있으면 변경 영향과 장애 범위도 그대로다. 책임은 기능 수가 아니라 최종 판단권을 기준으로 나눈다.

Product Framework와 DeviceAgent 책임 분리

그림 11. 프레임워크와 DeviceAgent의 책임 분리
DeviceAgent에 모인 공통 관리 책임을 단일 소유자로 분리하고, 실제 기능 실행과 하드웨어 안전만 실행 경계에 유지하는 구조다. 원본 SVG 열기

TaskManager와 DeviceAgent가 나누어 맡는 일

TaskManager는 작업표와 진행 상태를 관리하고, DeviceAgent는 실제 기기 기능을 수행한다. 상태·정책·자원 서비스는 두 영역이 같은 현재 상태와 안전 기준을 사용하도록 돕는다.

관리 대상 관리하는 곳 실제로 하는 일
현재 기기 상태 각 도메인의 상태 어댑터와 StateMirror 위치·도킹·배터리 같은 원본 결과를 공통 상태로 제공
실행 허용 여부 Policy Engine과 DeviceAgent 도메인 안전 규칙 제품 공통 정책을 확인하고, 실행 직전 하드웨어 조건을 다시 검사
이동·카메라·오디오 등 공유 자원 Resource Arbiter 사용 중인 자원과 대기 요청을 조정하고 충돌을 방지
Task와 Workflow 진행 TaskManager 단계 순서·취소·시간 제한을 관리하고 실제 완료 근거로 작업 종료
화면 세션과 서비스 연결 Ui Service와 Lifecycle Supervisor 화면 소유권, 서비스 준비 상태와 재연결 관리
하드웨어 안전을 지키는 곳 DeviceAgent와 각 도메인 실행기 모터 정지, 이동 자세, 센서 오류처럼 장치와 가까운 안전 동작 수행

어떤 책임을 옮기고 무엇을 남기는가

현재 DeviceAgent에 섞인 책임 옮길 위치 분리 후 효과
Binder 진입·callback 등록·연결 종료 Client Core·Framework Service·Lifecycle Supervisor 호출 앱마다 다른 연결·복구 처리 제거
위치·도킹·배터리 등 상태 조회 조합 State Framework·StateMirror 같은 상태의 중복 해석과 오래된 값 사용 방지
여러 기능에 걸친 허용·차단 판정 Policy Engine 제품 정책의 적용 근거와 버전 추적
이동·카메라·화면·오디오 충돌 처리 Resource Arbiter 점유·대기·거절·선점 결과를 한 기준으로 관리
대기열·순서·취소·시간 제한·최종 상태 TaskManager 단일 Task와 Workflow의 생명주기 통합
Launcher 화면 진입과 진행 화면 연결 SkixUiManager·Ui Service 화면 소유권과 Task 진행 상태 연결
연동 서비스 상태와 결과 알림 전달 Lifecycle Supervisor·Event/Evidence 계층 연결 상태와 작업 완료 상태의 혼동 방지
DeviceAgent에 남길 책임 이유
이동·청정·화면·TTS 명령 실행 기존 기능 구현과 하드웨어 연동을 그대로 활용
AMR·Vision·IoT·Update 연동 서비스 호출 도메인별 입력·결과 의미를 가장 잘 아는 실행 경계
이동 중 tilt-down, motor stop, sensor fault 같은 도메인 고유 안전 규칙 하드웨어와 가장 가까운 최종 방어선
원시 결과 알림을 도메인 결과로 변환 실제 완료·실패 이유를 정확히 만드는 책임

이동 중 헤드 틸트 다운, 모터 정지, 센서 오류처럼 하드웨어와 강하게 결합된 규칙은 기존 도메인에 남긴다. 카메라와 이동의 동시 사용, 음성 세션 중 행동, 전면 표시 경쟁처럼 여러 도메인을 조정하는 규칙은 프레임워크가 합성한다.

이동 → 청정 → 복귀에서 DeviceAgent가 실제 완료·실패 근거를 반환하면 TaskManager가 다음 단계, 재시도, 보상 동작 또는 전체 종료를 결정한다.

상태마다 값을 최종 기록하는 곳을 하나만 둔다. 이를 단일 상태 기록 책임이라고 한다. 위치는 이동 결과 알림 담당부, 청정 상태는 청정 결과 알림 담당부가 기록한다. StateMirror는 이 값을 공통 형식으로 읽어 주지만 같은 상태를 별도로 판단하거나 다시 소유하지 않는다. Task 완료도 API 접수 응답이 아니라 물리 결과 알림으로 판정한다.

구현 현황(2026-09-05): b77c2c5에서 이 원칙의 첫 concrete slice인 StateManagerService가 Runtime+State 기본 composition에 연결됐다. typed key/record, source·관측 시각·freshness, READY gate와 immutable snapshot은 JVM에서 검증됐다. 다만 MR6 observation bridge의 producer adapter, 기존 상태와의 dual-publish 동등성, Binder/AOSP/실기기 연결은 아직 완료되지 않았다. 구현·이식 경계와 SVG

안전한 이관 순서

  1. 공통 상태를 먼저 분리: 기존 실행은 유지하고 StateMirror가 읽기 전용 최신본을 제공한다.
  2. 판단을 나란히 비교: Policy·Resource·Task 판정을 실제 실행 없이 기존 결과와 비교한다.
  3. 기능별 실행권 이전: 검증된 기능만 관리형 경로로 전환하며 기존 경로와 동시에 실행하지 않는다.
  4. DeviceAgent를 실행 Facade로 축소: 공통 판단은 제거하고 도메인 명령·근거 변환·하드웨어 안전에 집중한다.
  5. 프로세스 분리는 근거가 있을 때만 수행: 장애 격리·독립 OTA·보안 경계가 필요할 때 Binder Service 분리를 검토한다.

전환 중에는 정책 책임 중복, 기존 대기열과 작업 대기열의 중복 실행, 상태 기록 책임 중복, 결과 알림에서 명령을 다시 호출하는 순환, 하드웨어 안전 장치 완화를 금지한다. 특히 동일 기능의 실행권을 두 경로가 동시에 갖지 않는다.

참고 자료

공개 호출 API와 결과 조회

Manager별 함수는 Manager별 대표 API를 기준으로 한다. 최종 정책, 자원 점유권, 완료 근거와 구성요소 상태는 Service가 소유하며 일반 호출자가 임의로 변경할 수 없다.

호출자 등급 공개 범위
일반 파트너 앱 공개 기능 상태·요약 사유·제한 상태와 서비스 상태
SKIX 시스템 앱·Planner 정책 판단·자원 충돌·형식이 명확한 이벤트·구성요소 상태
개발·관제 도구 추적 정보·정책 버전·점유 책임·원시 근거. 별도 권한과 감사 기록 필요

공통 Client Core는 Service 탐색, 연결·재연결, Binder 연결 종료, 버전 확인과 결과 알림 전달을 공유한다. 각 Manager가 Binder 연결과 상태 캐시를 따로 만들지 않게 하는 SDK 기반이다.

상태·정책·기능 명세 계약

상태 종류와 공통 형식

상태 예 원본 소유자
관찰 상태 (Observed State) 위치·도킹·배터리·청정·개인정보 보호 실제 도메인 결과 알림 책임부
목표 상태 (Desired State) 목표 위치·요청 모드·음량 승인된 Task·제품 설정
파생 상태 (Derived State) 이동 가능·관찰 준비·저전력 보호 결정 규칙 판정기
작업 상태 대기·실행·완료 근거 대기·최종 종료 TaskManager
구성요소 상태 (Component Health) 연결 중·준비·성능 저하·오래된 상태 생명주기 관리기
StateEnvelope
  domain, key, typed_value
  source, captured_at, received_at
  freshness, sequence, confidence
  visibility, correlation_id

기능 명세와 공유 자원

CapabilityDescriptor
  capability_id, version, domain, operation
  input_schema, output_schema
  preconditions, policy_refs, resource_claims
  executor_ref, completion_evidence, failure_reasons
  risk_level, visibility, availability
자원 충돌 예 기본 원칙
이동 기반 이동·회전·복귀 동시 요청 하나의 독점 점유권
헤드 틸트 주행 자세와 Vision 관찰 자세 이동 안전 정책 우선
카메라·Vision LiveView·객체 관찰·개인정보 보호 개인정보 보호와 전면 사용 책임 우선
오디오·TTS 음성 세션·TTS·미디어 오디오 포커스·세션 상태 반영
화면·UI Launcher·Vital Signs·Security UiSession·UI 정책으로 조정

ResourceLease는 점유 주체, 사용 방식, 우선순위, 선점 가능 여부, 획득·만료 시각과 해제 사유를 가진다. 호출 앱은 직접 점유권을 조작하지 않고 작업·UI 요청을 통해 필요한 자원을 선언한다.

UI와 호출 앱 세션

공통 UI AAR와 시스템 화면

공통 UI는 정적 자산을 배포하는 AAR과 실행 중 UI 상태를 조정하는 Service로 분리한다. UI Resource Kit AAR와 UI Foundation AAR는 SKMLauncher2의 공통 자산·구성요소를 공유하되, 화면별 상태나 제품 실행 정책은 포함하지 않는다.

UI 요구 제공 방식 런타임 Manager/Service 역할
색상·글꼴·간격·아이콘 이름 공간이 적용된 UI Resource Kit AAR 정적 자산은 Manager 없이 사용하고 제품 테마 버전·공통 자산 배포는 빌드 계약으로 관리
버튼·팝업·진행률·상태 화면 UI Foundation AAR 공통 구성요소 앱 내부 렌더링은 앱이 소유하고 전역 Popup·Overlay 충돌만 Service가 조정
Task 진행 표시 Task 이벤트 + 공통 진행 구성요소 실행 중 UI 상태와 Task 세션을 같은 식별자로 연결
Vital Signs·Security 화면 진입 안정된 uiTargetId와 UiSession 화면 소유권·복귀·취소를 관리하고 기능 완료는 도메인 증거로 별도 판정

UI AAR는 SKMLauncher2 전체 코드를 공유하지 않는다. 리소스는 skix_ prefix와 이름 공간을 사용하고, 중앙 권한·상태·우선순위가 필요한 요청만 SkixUiManager로 보낸다.

앱 내부 Android UI 구조와 SKIX 제품 UI 조정

SKIX UI 아키텍처 확정안

그림 12. MVVM + UDF 기본형과 제품 UI 세션 경계
앱 내부의 상태 흐름, 선택형 Reducer, 공개 UI API와 제품 UI 세션의 책임을 분리한다. 원본 SVG 열기

앱 내부는 UDF 기반 MVVM을 기본으로 사용한다. UiState는 불변 화면 상태, UiAction은 사용자가 화면에 전달한 입력이다. UiEffect는 유실돼도 업무 결과가 바뀌지 않는 짧은 시각 반응에만 제한한다. 단순 화면은 ViewModel → Repository → Manager로 끝내고, 복잡한 상태 전이에만 선택적 UseCase와 Reducer·StateMachine·Coordinator를 추가한다.

ViewModel은 Binder를 직접 호출하지 않는다. UiSessionRepository는 앱 또는 Client AAR에서 callback을 화면 상태로 변환한다. SKIX UI Framework는 MVVM 구성요소가 아니다. God Manager로 만들지 않는다. 화면별 상태와 사용자 이벤트는 앱이 소유하고, 제품 UI 실행 문맥은 SkixUiService, 기기 작업 상태는 TaskManager가 소유한다.

응용 프로그램 아키텍처 표준에서 구성요소, 복잡도별 확장 기준, 오류·Coroutine·테스트 규칙과 전환 순서를 정의한다.

앱 화면과 제품 UI 서비스 책임 경계

UI Manager·Service 경계 상세 SVG 열기

Launcher 연동 앱의 화면 세션 관리

이 영역을 호출 앱 연동(Client App Integration)으로 정의한다. 패키지·Activity class 직접 결합은 기존 변환부로 감싸고 안정된 대상과 서비스 상태·최종 결과 알림으로 단계적으로 이전한다.

SKMLauncher2와 호출 앱 UI 세션 관리 구조

그림 13. Launcher와 호출 앱의 UI 세션 관리
앱 내부 자유 영역과 프레임워크 소유 경계인 화면·Task 세션·복귀 관계를 보여준다. 원본 SVG 열기

구성요소 책임
ClientRegistry 패키지·인증서·버전·지원 대상·서비스 상태 등록
UiTargetRegistry 안정된 uiTargetId, 인자·결과·권한 관리
UiSessionRepository 앱에서 SkixUiManager callback을 화면별 UiState로 변환
SkixUiService 제품 UI 요청의 Binder Service 진입점과 결과 알림
UiSessionController uiSessionId와 Task·단계·화면 상태의 상관관계 관리
UiLaunchController UI 대상 실행·준비·전면 표시·일시 정지·종료 처리
ForegroundOwnerArbiter 동시에 전면에 표시하려는 세션의 우선순위와 선점 판정
UiSceneCoordinator LCD·대기 화면·밝기·EyeLED를 제품 장면 단위로 조정
UiOverlayCoordinator Toast·Popup·Overlay의 표시 순서와 억제 사유 관리
TaskSessionBinder Task·단계·UiSession·도메인 이벤트 연결
NavigationCoordinator 이전 대상·Launcher 복귀·중단 세션 복원
ClientHealthMonitor 미설치·프로세스 종료·버전 불일치 감지
UiSession: REQUESTED → LAUNCHING → READY → FOREGROUND ↔ PAUSED → DISMISSED
Task:      RUNNING → WAITING_EVIDENCE → SUCCEEDED | CANCELLED | FAILED | TIMED_OUT

화면 READY는 기능 완료가 아니다. Vital Signs는 측정 완료·사용자 취소, Security는 모드 종료·변경, Welcome은 시나리오 종료 증거가 필요하다. TaskSessionBinder가 이를 원래 Task에 연결한 뒤에만 다음 작업 흐름 단계로 진행한다.

외부 설계 원리

외부 사례 확인된 원리 SKIX에 적용하는 부분 그대로 가져오지 않는 범위
Android CarService와 CarManager 앱의 호출 창구와 권한·상태를 소유하는 중앙 서비스를 분리 SKIX Manager/Service, 호출자 권한과 단일 실행 책임 자동차 전용 API와 기동 방식
Android Stable AIDL 구조화된 프로세스 간 계약과 버전별 하위 호환 검사 요청·결과·이벤트 버전 관리와 구버전 호출자 호환 모든 내부 Java 인터페이스의 VINTF 안정화
VHAL의 HIDL→AIDL 전환 기존 방식과 새 방식을 함께 지원하며 단계적으로 전환 기존 Bundle과 신규 계약 병행, 기능별 실행 책임 이전과 되돌림 차량 속성 모델 자체
ROS 2 Actions 오래 걸리는 동작을 요청·진행·결과·취소로 분리 작업 ID, 진행 상태, 취소와 최종 결과 계약 ROS 2 통신 계층과 DDS 이식
ROS 2 Managed Nodes 구성요소의 준비·활성·비활성·오류 상태를 표준화 연결 서비스와 도메인 변환부의 준비·저하·복구 상태 기존 Agent의 전면 재작성
Android WorkManager 조건이 있는 영속 작업, 선후행 연결, 중복 방지와 복구 작업 흐름 의존관계와 재시작 복구 설계 물리 완료·실시간 자원·하드웨어 안전 판정
Kubernetes API와 Controller 원하는 상태와 관찰된 상태를 나누고 차이를 줄여 감 목표 상태와 실제 기기 상태를 구분하는 관측 방식 클러스터 제어 구조 전체
Branch by Abstraction 기존 구현 앞에 호환 경계를 두고 기능별로 점진 교체 호환 변환부, 판단 결과 사전 비교, 기능별 책임 이전 검증 없이 호출 창구만 영구 유지하는 구조
ROS 2 QoS 상태·이벤트별 최신성·보관·전달 기준 상태 종류별 최신성·전달 기준 ROS 통신 설정 자체
AOSP SELinux 정책 시스템 불변 정책과 제품 확장 경계 상위 안전 정책을 하위 호출자가 완화하지 못하는 구조 AOSP 보안 정책의 재구현

적용 및 전환 계획

지금 구조에서 무엇을 바꾸는가

영역 현재 방식 바뀌는 방식 기대 효과
코드 기준 DeviceAgent·SKMLauncher2 코드와 TaskManager 구현 작업본이 별도로 존재 한 출시 기준에서 Manager·Service·도메인 계약을 함께 검증 브랜치마다 기능 계약이 달라지는 문제 감소
기능 호출 DeviceControlProxy와 sendModuleCommand(Bundle) 중심 입력·결과 형식이 명확한 Manager API와 공통 Client Core 제공 잘못된 필드와 호출자별 해석 차이 감소
기기 상태 StateManager와 기능별 상태값을 호출자가 조합 StateMirror가 출처·갱신 시각을 포함한 최신본 제공 앱마다 현재 상태를 다르게 판단하는 문제 방지
결과 이벤트 EventManager와 기능별 결과 알림이 분산 Task·상태·UI 이벤트를 추적 ID로 연결하고 권한별 구독 제공 요청부터 실제 결과까지 한 흐름으로 추적
실행 정책 CmdPolicyManager, PolicyEngine과 도메인 규칙에 분산 공통 제품 정책을 먼저 확인하고 도메인 안전 규칙을 실행 직전에 재확인 호출 채널이 달라도 같은 안전 기준 적용
Task 실행 TaskManager 후보에 대기열·Workflow·시간 실행·완료 처리가 구현 검증된 기능부터 정식 관리형 실행 경로로 전환 순서·취소·시간 제한·실제 완료를 공통 관리
공유 자원 각 기능의 busy/state 값으로 개별 충돌 처리 이동·카메라·오디오·화면의 점유와 대기 원인을 공통 조정 동시 실행 충돌과 임의 선점 방지
서비스 연결 각 앱과 기능이 Android bind·재연결을 개별 처리 공통 Client Core와 Health Service가 준비·장애·재연결 상태 제공 연결 장애와 기능 실패를 구분하고 중복 코드 감소
기능 명세 메서드·실행기·지원 목록이 여러 위치에 분산 기능 입력·조건·정책·실행기·완료 근거를 하나의 명세로 연결 호출 전에 실제 사용 가능 여부 확인
UI Launcher Activity·LCD·EyeLED·Toast/Popup을 직접 조합 UI AAR와 SkixUiManager가 화면 세션·우선순위·복귀 관리 화면 충돌과 패키지명 직접 결합 감소
실패 복구 기능별 재시도와 일부 실행 기록에 의존 실행 기록·중복 방지·재시작·안전 정지 규칙을 공통화 재기동 후 중복 실행과 유실 감소

현재 내부 Manager와 TaskManager 적용 후보는 서명·권한·회귀·실기기 검증 전까지 제품 계약으로 확정하지 않는다.

코드 기준 이행 설계

분석 기준 커밋은 1398d109이며, TaskManager 기능이 있는 별도 작업본은 TaskManager 적용 후보로 구분한다.

전환 방식 비교와 선택

기존 구조를 모두 버리는 전면 재구축보다 단계적 융합을 기본안으로 삼는다. 검증된 기기 기능과 하드웨어 안전 규칙은 유지하고, 공통 상태·정책·자원·작업 관리 책임만 기능 단위로 옮긴다. 처음에는 새 구조는 판단만 하고 실제 실행은 기존 방식이 담당한다.

접근 방식 장점 위험과 한계 판단
전면 재구축 처음부터 일관된 구조를 만들기 쉬움 기존 270개 명령, Binder·MQTT·결과 알림·권한·하드웨어 정책을 동시에 다시 검증해야 함 현재 제품에는 적용하지 않음
호환 호출 창구만 추가 호출 앱 변경이 작고 빠르게 외형을 정리할 수 있음 내부의 책임 집중과 상태·정책 중복은 그대로 남음 짧은 전환 단계로만 사용
단계적 융합 기존 기능을 유지하면서 기능별로 검증·전환·되돌림 가능 일정 기간 기존 구조와 새 구조를 함께 비교해야 함 기본안
유지 → 감싸기 → 판단 결과 사전 비교 → 실행 책임 이전 → 기존 분기 축소

기존 구조와 목표 SKIX를 단계적으로 융합하는 구조

그림 14. 기존 기능을 유지하면서 실행 책임을 옮기는 구조
새 구조는 먼저 판단만 하고 실제 실행은 기존 방식이 담당한다. 결과가 충분히 일치한 기능부터 실행 책임을 옮기며, 문제가 생기면 해당 기능만 기존 경로로 되돌린다. 원본 SVG 열기

구분 대상 처리 원칙
유지 기존 도메인 실행과 하드웨어 안전 규칙 현재 동작을 회귀 기준선으로 사용
감싸기 기존 Bundle, MQTT 단일 명령, 결과 알림 호환 변환부 뒤에서 같은 실행기로 연결
분리 상태 기록, 정책 판단, 공유 자원, 작업 생명주기 최종 책임 주체를 하나로 명시
새로 추가 형식이 명확한 Manager API, 기능 명세, 작업·작업 흐름 계약 버전이 붙은 계약으로 기존 경로와 병행
단계 교체 문자열 명령 분기, 직접 실행이 섞인 정책, 주기 확인 중심의 완료 판단 판단 결과 사전 비교 후 기능별로 책임 이전
후속 축소 사용자가 없어진 기존 분기와 중복 저장소 회귀·실기기 검증과 지원 종료 기간 이후 제거

전환 중에도 같은 요청을 실행하는 곳과 같은 상태를 최종 기록하는 곳은 각각 하나여야 한다. 기능 단위로 실행 책임을 하나만 이전해야 새 대기열과 기존 직접 호출의 중복 실행을 막을 수 있다.

협력사와 먼저 합의할 항목

현재 코드, 병합 후보, 목표 설계를 구분한다

근거 수준 의미 적용
현재 소스 확인 1398d109 소스에 존재하고 현재 구조를 설명할 수 있음 변경 전 기준선과 호환성 판단에 사용
TaskManager 적용 후보 별도 작업본에 구현되어 있으나 제품 기준 검증이 남음 재사용 후보로 평가하고 선택 이식
리팩터링 제안 현재 클래스 책임을 분리하기 위한 목표 설계 API·책임·전환 순서와 완료 조건으로 관리

TaskManager 후보는 기준선 이후 431개 파일이 변경돼 전체 병합하지 않는다. 실행 생명주기, Workflow, Scheduler와 완료 근거를 분리해 기능별로 이식한다.

DeviceAgent 현재 실행 경로

그림 15. 현재 실행 경로와 책임 집중 지점
공개 Binder 진입부터 MainApi, 상태·정책, 연동 서비스 결과 알림과 물리 실행까지 실제 호출 흐름을 보여준다. 원본 SVG 열기

현재 코드에서 먼저 풀어야 할 책임 집중

현재 파일 확인된 규모와 역할 구조적 위험 첫 분리 단위
DeviceAgent.java 573줄. Binder Stub, 결과 알림 목록, 여러 Manager 생성과 연동 서비스 초기화 프로세스 생명주기와 제품 반응이 한 시작점에 결합 ComponentRuntime, ClientSessionRegistry
MainApi.java 4,210줄, 270개 method.equals 명령 분기 문자열 계약, 차단 판정, Bundle 해석과 도메인 실행이 한 변경 범위 LegacyCommandRegistry, 도메인별 CommandHandler
MainApiCleaning.java 6줄의 빈 골격 파일 분리만 있고 책임 분리는 없음 Cleaning handler를 계약 단위로 추출
StateManager.java 707줄. 주·보조 상태, 차단 목록, 모드 전환 부수효과, Binder 연결 종료 상태 원본·정책·하드웨어 효과·세션 정리가 결합 LegacyDeviceModeCoordinator, DeviceStateSnapshotAdapter, ModeTransitionEffects
CmdPolicyManager.java 1,581줄. 상태 수집, 실행 허용 판정, 이동·청정 실행, 일시 정지·재개 판단 코드가 직접 동작을 수행해 정책 검증과 실행 검증을 분리하기 어려움 DeviceFactCollector, OperationAdmissionPolicy, 도메인 변환부
EventManager.java 414줄. 주·보조 상태와 EyeLED 장면·우선순위 조정 이름은 범용 이벤트처럼 보이나 실제로는 표현 상태 조정기 기존 역할 유지 후 LegacyIndicatorCoordinator로 명확화
MainService.java 642줄. 동료 서비스 연결, AMR 결과 알림 해석, 상태 기록, UI·IoT 전달과 오류 반응 원시 결과 알림, 상태 기록, 제품 반응과 완료 근거 생성이 결합 PeerServiceConnector, AmrCallbackDecoder, FrameworkEventHub
AppCmd.java·MainHandler.java Handler 메시지로 AMR·IoT·Update·앱 결과 알림 전달 전송 경로와 도메인 의미가 섞이고 상관관계가 메서드에 의존 형식이 명확한 이벤트 묶음과 추적 ID 변환부
DeviceControlProxy.java 259줄. 연결·재연결, 연결 종료 감지, 결과 알림 등록, 원시 AIDL 노출 호출자 클래스 추정, 버전 분산, Manager별 명확한 계약 부재 공통 호출 라이브러리와 CallerIdentityResolver 연계
IDeviceControl.aidl 결과 알림 4개와 sendModuleCommand(Bundle) 1개 API 버전과 입력 형식이 타입으로 드러나지 않음 기존 AIDL 유지 + 버전이 붙은 명확한 호출 계약 병행

현재 process에서 하이브리드 process로 단계적 전환한다

현재 DeviceAgent는 android.uid.system, persistent=true인 privileged app이지 SystemService가 아니다. 기존 process 논리 경계는 호환 기준선으로 유지하고, 신규 권위 소스는 skix-framework/base로 이동한다. SkixFrameworkService.apk는 격리 Runtime, SkixFrameworkSystemService는 부팅과 전역 Binder를 소유한다.

com.sk.airbot.deviceagent
├─ bootstrap/        DeviceAgent · ComponentRuntime · peer 연결 순서
├─ compat/           LegacyCommandRegistry · LegacyBundleAdapter
├─ identity/         CallerIdentityResolver · ClientSessionRegistry
├─ state/            StateStore · DeviceStateSnapshotAdapter · derived state
├─ policy/           DeviceFactCollector · OperationAdmissionPolicy
├─ event/            FrameworkEventHub · EvidenceNormalizer
├─ task/
│  ├─ api/           TaskControlApi · TaskQueryService
│  ├─ core/          TaskLifecycleReducer · TaskRepository
│  ├─ workflow/      WorkflowEngine · DependencyResolver
│  └─ schedule/      TaskScheduler · TriggerEvaluator
└─ domain/
   ├─ mobility/      MobilityCommandAdapter · MobilityEvidenceAdapter
   ├─ cleaning/      CleaningCommandAdapter · CleaningEvidenceAdapter
   └─ ui/            UiSessionAdapter · UiEvidenceAdapter

기존 RobotMovementController, BaseCleaningManager, ScheduleManager, ErrorHandler는 도메인 동작과 하드웨어 안전 규칙을 계속 소유한다. 새 계층은 이 코드를 복제하지 않고 입력·상태·완료 증거를 정규화한다. 별도 프로세스 분리는 비정상 종료 격리나 독립 OTA의 실측 필요가 확인된 뒤 결정한다.

TaskManager 병합 후보를 다루는 방법

병합 후보에는 TaskManager.java 3,632줄, 실행기 레지스트리, Task 완료 상태 저장소와 관찰기, 작업 흐름·실행 일정, 추적 ID, TaskManagerClient AAR와 테스트가 있다. 이 기반은 버리지 않는다. 다만 큰 클래스를 그대로 옮기면 현재 MainApi와 비슷한 책임 집중이 다시 생기므로, 검증된 기능 단위로 나눠 가져온다.

분류 대상 처리 원칙
선택 이식 Task 기록·대기열, 작업 흐름 의존관계, 실행 일정, 실행기 레지스트리, 완료 증거 저장, 추적 ID 현재 기준 회귀 시험과 함께 작은 모듈로 이식
분해 후 이식 TaskManager.java, 주기 확인 기반 완료 관찰, 입력 정책 해석, 영속 저장 접수·저장·대기열·작업 흐름·스케줄·조회·상태 전이를 별도 책임으로 분리
공개 계약에서 제외 bypassCallerPolicy, 호출자 지정 source, 임의 대기열·우선순위·시간 제한·자원 요구, 메서드 문자열 추정 경로 선택 서버 책임 정책으로 대체하고 내부 시험 기능은 별도 개발 권한으로 격리
별도 검증 재부팅 복구, 중복 방지, PARTIAL_FAILED, 장기 UI·Vital·Security 세션 실기기 최종 완료 근거와 복구 시험 전에는 제품 보장으로 선언하지 않음

목표 Task Service는 다음처럼 분리한다.

구성 단일 책임 주요 입력·출력
TaskControlApi 제출·취소·일시 정지·재개·조회 진입 버전이 붙은 요청과 안정된 결과
TaskAdmissionService 호출자·입력 형식·정책·자원 사전 판정 AdmissionDecision
TaskRepository Task·단계·작업 흐름과 중복 방지 정보 저장 상태 최신본·중간 저장점
TaskQueueDispatcher 대기열 선택과 실행 가능 Task 전달 실행 전달 이벤트
WorkflowEngine 의존관계·조건·실패 정책 평가 실행 가능 단계·작업 흐름 결과
TaskScheduler 절대 시각·이전 단계 후 지연·시작 조건 관리 실행 허용 판정 재진입 이벤트
TaskLifecycleReducer 이벤트와 완료 근거를 유효한 상태 전이로 축약 최종 상태
TaskQueryService 진행률·사유·이력을 권한에 맞게 가공 일반·시스템·개발용 조회 결과

호출자 권한과 정책 책임

현재 Binder service는 앱 고유 signature permission을 요구하지 않는다. 적용 후보의 signature permission 추가는 이식 가치가 있으나, manifest 선언만으로 끝나지 않는다.

Binder UID · PID
  → PackageManager에서 package 집합 확인
  → signing certificate와 선언 permission 확인
  → CallerIdentityResolver가 caller profile 생성
  → 공개 Capability·상태·명령 범위 결정

기존 명령을 끊지 않는 계약 전환

기존 sendModuleCommand(Bundle)와 MQTT 형식은 즉시 제거하지 않는다. LegacyCommandRegistry가 270개 메서드의 입력, 결과, 차단 조건, 결과 알림, 물리 완료 기준과 관리형 전환 여부를 명시한다.

기존 요청
  → LegacyBundleAdapter
  → LegacyCommandRegistry 명세
  → 기존 직접 실행 또는 관리형 작업 중 실행 책임 하나 선택
  → 동일한 기존 결과 Bundle·결과 알림 반환

신규 요청
  → 형식이 명확한 Manager 요청
  → 기능 명세
  → 작업 허용 판정·실행·완료 근거
  → 형식이 명확한 결과·이벤트

IoT 호환성과 관리형 요청 형식은 MQTT 계약을 따른다.

상태와 완료 증거를 옮기는 순서

StateManager를 즉시 교체하지 않고 LegacyDeviceModeCoordinator로 감싼다. 먼저 DeviceStateSnapshotAdapter가 기존 위치·도킹·배터리·이동·청정 상태를 읽기 전용으로 투영한다. 새 상태 저장소는 동일 값을 다시 판단하거나 하드웨어를 제어하지 않는다.

MainService의 연동 서비스 결과 알림은 다음 순서로 분리한다.

AMR·Vision·IoT 원시 결과 알림
  → 도메인 결과 해석기
  → 기존 상태 기록 책임과 제품 반응 유지
  → FrameworkEventHub에 형식이 명확한 이벤트 이중 기록
  → EvidenceNormalizer가 taskId·stepId와 연결
  → TaskLifecycleReducer가 최종 상태 여부 판정

초기에는 기존 결과 알림과 새 형식의 이벤트를 동시에 기록해 누락·순서·지연 차이를 비교한다. 주기적으로 상태를 확인하는 방식은 호환용 보조 장치로만 남기고, 최종 구조는 완료 사건을 받는 방식을 기본으로 한다. 결과 알림이 다시 명령을 호출해 순환하거나, API 접수 응답을 실제 완료로 잘못 처리하는 경로는 차단한다.

단계별 전환과 되돌림

점진 리팩터링 로드맵

그림 16. 실행 책임을 단계적으로 이전하는 경로
기존 실행 유지, 판단 결과 사전 비교, 선택 이식, 도메인 변환부와 실행권 이전을 기능 단위로 진행한다. 원본 SVG 열기

단계 구현 작업 다음 단계 진입 조건 되돌림 방법
0 명령 목록 동결: 270개 메서드의 호출자·입력·결과·결과 알림·차단·완료 목록 생성 대표 기기 형상과 회귀 기준선 확정 변경 없음
1 읽기 전용 상태 투영: 위치·도킹·배터리·이동·청정 최신본 생성 기존 상태와 순서 번호·시각·값 동등 상태 투영 비활성화
2 이벤트·완료 근거 이중 기록: 결과 알림을 형식이 명확한 이벤트·완료 근거로 병행 변환 누락·중복·순서·지연 허용 범위 통과 이벤트 추가 전달 제거
3 판단 결과 사전 비교: 새 정책은 허용·거절·실행 경로 판단만 기록하고 기존 경로가 실제 명령을 한 번만 실행 기존 허용·차단과 차이 검수 완료 새 판정 무시
4 Task 핵심 선택 이식과 분해 대기열·취소·시간 제한·저장 단위 시험 통과 기능별 설정으로 기존 직접 실행
5 이동·청정부터 관리형 실행 전환 기존 경로와 결과 동등성, 중복 실행 0건 기능별 실행 책임 복귀
6 UI·Vital Signs·Security·Welcome 세션 연결 사용자 완료·취소·모드 종료 근거 확인 해당 세션 변환부 해제
7 실행 책임 이전: 새 정책·상태·Task로 최종 실행 책임 이전 장기 시험·업데이트·복구·권한 기준 통과 도메인별 기존 변환부 유지

완료와 배포 기준

검증 축 필수 기준
계약 270개 기존 메서드의 입력·결과 Bundle·결과 알림과 신규 명확한 계약 매핑
동등성 기존 경로와 결과 동등성, 차이가 있으면 승인된 사양 변경으로 분류
물리 실행 이동·복귀·청정·화면 세션의 실기기 물리 완료 증거 확인
생명주기 취소·시간 제한·일시 정지·재개·Binder 연결 종료·프로세스 재기동·중복 요청 검증
권한 플랫폼 서명, 서명 권한, Binder UID·인증서별 허용·거부 시험
성능 기준선 대비 Binder 지연, 대기열 대기, 결과 알림 처리, PSS·스레드·저장소 증가 측정
관측 요청·작업 흐름·단계·Task·완료 근거가 하나의 추적 정보로 연결
배포 기능별 전환 설정과 즉시 가능한 되돌림 절차 보유

컴파일과 JVM 시험은 구조 검증이다. 제품 전환 완료는 동일 서명 APK, 실제 Binder 호출자, 연동 서비스 연결, 센서·모터 결과 알림과 장기 실행 로그가 함께 확인된 시점으로 판정한다.

연결 문서

Keyboard shortcuts

⌘K / Ctrl+KOpen command palette
/Focus search
g hGo to home
g pGo to projects
g sGo to sessions
j / kNext / prev row (tables)
?Show this help
EscClose dialogs

Structured queries

Mix key:value filters with free text in the palette:

type:sessionOnly session pages
project:llm-wikiFilter by project name (substring)
model:claudeFilter by model name (substring)
date:>2026-03-01Sessions after a date
date:<2026-04-01Sessions before a date
tags:rustPages mentioning a tag/topic
sort:dateSort results by date (newest first)

Example: type:session project:llm-wiki date:>2026-04 sort:date