← Docs hub

SoC TaskManager Before/After Change Model

이 장은 SoC 업체 설명용 문서다. 핵심은 “기존 DeviceAgent 구조에 TaskManager layer를 왜 추가하는지”, “구조가 어떻게 바뀌는지”, “이 변경으로 어떤 이점이 생기는지”를 한 번에 설명하는 것이다.

SoC TaskManager Before After Change Model

1. 설명 대상

이 문서는 아래 상황에서 사용한다.

대상 설명 목적
SoC/DeviceAgent 업체 기존 구조에 어떤 layer를 추가해야 하는지 이해
Cloud/On-device 개발자 DeviceAgent가 어떤 형태의 task/event/reason contract를 제공해야 하는지 이해
내부 리뷰어 단순 LLM 연동이 아니라 SoC 실행 프레임워크화 작업임을 확인

2. 기존 DeviceAgent 구조

현재 DeviceAgent는 이미 많은 기능을 수행한다. 주요 진입과 실행 경로는 다음 source에서 확인된다.

apps/DeviceAgent/app/src/main/java/com/sk/airbot/deviceagent/DeviceAgent.java
apps/DeviceAgent/app/src/main/java/com/sk/airbot/deviceagent/main/api/MainApi.java
apps/DeviceAgent/app/src/main/java/com/sk/airbot/deviceagent/app/AppCmd.java
apps/DeviceAgent/app/src/main/java/com/sk/airbot/deviceagent/framework/command/*.java

대표 흐름:

External method / Bundle
-> DeviceAgent
-> MainApi.executeMethod(...)
-> 개별 command/domain handler
-> AppCmd.sendModuleCommand_* 또는 AppCmd.sendModuleCallback_main(...)

소스에서 확인되는 기존 구조의 특징:

코드 위치 역할 TaskManager 관점의 해석
DeviceAgent.java 외부 method와 Bundle을 받아 MainApi.executeMethod(...)로 전달 기존 외부 entry
MainApi.java executeMethodInternal(...)에서 main state, blocked status, FrameworkCommandBridge, 기능별 method를 처리 실제 legacy 실행 중심
FrameworkCommandBridge / framework/command/*.java 청정/이동/설정 등 일부 기능을 command handler로 분리 domain handler는 유지 대상
CleanOperationCommandHandler.java setAirCleanerOperation 내부 조건, IoT report, policy gate, executor 수행 TaskManager가 대체하면 안 되는 domain logic
AppCmd.java module command/callback 전송 기존 callback path, TaskManager event도 이 경로를 사용

이 구조는 단일 기능 호출에는 동작한다. 하지만 Cloud LLM, MQTT 서버, 앱, 예약, 로컬 음성처럼 source가 늘어나고 복합명령이 들어오면 아래 문제가 생긴다.

문제 설명
source별 실행 경로 분산 Cloud/MQTT/App/예약이 각자 직접 method를 호출하면 정책과 이벤트가 달라진다.
복합명령 순서 관리 어려움 “거실 이동 -> 청정 -> 안방 이동” 같은 순차 task의 상태와 실패 처리가 호출자 쪽으로 밀린다.
실패 이유 구조화 부족 자연어 메시지나 기능별 callback만으로는 replan/retry/report 판단이 어렵다.
terminal event 보장 부족 accepted task가 최종적으로 완료/실패/취소됐는지 공통적으로 확인하기 어렵다.
프레임워크화 어려움 기능 함수는 많지만 admission, queue, workflow, reason, event bus가 한 layer로 묶이지 않는다.

3. 추가되는 TaskManager Layer

TaskManager layer는 기존 domain 기능을 대체하지 않는다. 기존 기능 앞에 공통 실행 관문을 추가한다.

Cloud / MQTT / App / Local Voice / Internal Schedule
-> submitTask / submitWorkflow
-> TaskManager
-> validation / policy / queue / workflow
-> TaskExecutorRegistry
-> 기존 domain handler 또는 SoC domain executor
-> onTaskEvent

핵심 source:

apps/DeviceAgent/app/src/main/java/com/sk/airbot/deviceagent/task/TaskManager.java
apps/DeviceAgent/app/src/main/java/com/sk/airbot/deviceagent/task/TaskPolicyRegistry.java
apps/DeviceAgent/app/src/main/java/com/sk/airbot/deviceagent/task/TaskBundleValidator.java
apps/DeviceAgent/app/src/main/java/com/sk/airbot/deviceagent/task/TaskExecutorRegistry.java
apps/DeviceAgent/app/src/main/java/com/sk/airbot/deviceagent/task/TaskExecutorBootstrap.java
apps/DeviceAgent/app/src/main/java/com/sk/airbot/deviceagent/task/TaskReasonContract.java
apps/DeviceAgent/app/src/main/java/com/sk/airbot/deviceagent/task/DevicePlanningContextProvider.java

실제 연결 방식:

MainApi.executeMethod(method, indata, outdata)
  if TaskManager.handleControlMethod(method, indata, outdata, factory):
      return
  TaskManager.executeLegacy(method, indata, outdata, legacyRunnable)

즉 TaskManager는 기존 기능을 우회하거나 삭제하는 방식이 아니다. submitTask, submitWorkflow, getTaskStatus 같은 TaskManager API만 먼저 처리하고, 나머지는 기존 executeMethodInternal(...)로 보낸다.

4. 변경되는 구조

기존 변경 후
명령 유입 method 단위 직접 호출 source-agnostic task/workflow 등록
실행 전 검증 기능별/분산 처리 TaskBundleValidator, policy, state/resource check
실행 순서 호출자가 관리 TaskManager workflow가 currentStepIndex와 subtask 상태 관리
domain 연결 개별 handler 직접 호출 TaskExecutorRegistry를 통해 executor binding
실패 이유 기능별 error/toast/callback TaskReasonContractreason_code, reason_params
결과 통지 분산 callback onTaskEvent 공통 event
상위 연동 Cloud 중심으로 오해 가능 Cloud/MQTT/App/예약 모두 같은 framework 사용

4.1 실행 path 비교

단일 청정 명령

기존:

method = setAirCleanerOperation
-> MainApi.executeMethodInternal(...)
-> FrameworkCommandBridge.tryHandle(...)
-> CleanOperationCommandHandler.handleSetAirCleanerOperation(...)
-> AppCmd.sendModuleCommand_iot(...)
-> domain policy/executor

TaskManager 적용 후:

method = submitTask
taskMethod = setAirCleanerOperation
source = cloud_a2a | mqtt_server | app_remote
-> TaskManager.submitTask(...)
-> validation: action/mode/speed/operation 확인
-> policy: cleaning queue, ASYNC, timeout, cancelMethod
-> executor: CleaningAmpTaskExecutor 또는 legacy adapter
-> CleanOperationCommandHandler / domain manager
-> onTaskEvent

차이:

복합 이동/청정 명령

기존:

호출자가 setMoveTo, setAirCleanerOperation, setMoveTo를 직접 순서대로 호출해야 함
각 단계 실패 시 어느 단계가 실패했는지 공통 payload가 약함

TaskManager 적용 후:

method = submitWorkflow
subTasks:
  1. setMoveTo(positionName=거실)
  2. setAirCleanerOperation(action=1, mode=...)
  3. setMoveTo(positionName=안방)
-> currentStepIndex/currentStepMethod 갱신
-> WORKFLOW_STEP_STARTED / WORKFLOW_STEP_COMPLETED
-> 실패 시 parent workflow reason_code 기록

5. 기대 이점

이점 설명
source 확장성 MQTT 서버가 들어와도 새 실행 경로를 만들지 않고 같은 submitTask/submitWorkflow를 사용한다.
복합명령 대응 여러 기능을 workflow로 묶고, step별 진행/완료/실패를 추적할 수 있다.
실패 대응 명확화 PATH_BLOCKED, ROOM_NOT_FOUND, LOW_BATTERY 같은 구조화 reason으로 retry/replan/report를 분기한다.
Cloud 비용 절감 RUNNING, PROGRESS, COMPLETED는 로컬/서버 상태 갱신으로 처리하고, 판단이 필요한 실패만 Cloud replan으로 올린다.
업체 검증 가능성 API sample, event trace, reason code, logcat evidence로 완료 여부를 검증할 수 있다.
장기 프레임워크화 DeviceAgent 내부 기능 묶음에서 SoC 실행 layer로 분리할 수 있다.

5.1 정량/정성 효과

관점 기존 변경 후 기대효과
신규 source 추가 source마다 command path와 callback 정책을 새로 맞출 위험 source trace만 추가하고 같은 TaskManager API 사용
복합명령 호출자가 순서/실패/재시도를 직접 관리 workflow가 step 상태와 terminal event를 관리
장애 분석 기능별 log/callback을 찾아야 함 taskId, workflowName, reason_code로 추적
서버 연동 Cloud/MQTT/App이 각자 다른 형태를 요구할 수 있음 공통 onTaskEvent payload를 source별로 소비
테스트 기능 단위 수동 테스트 위주 API, workflow, reason, trace, logcat evidence로 분리 검증
장기 유지보수 기능이 늘수록 직접 호출/분기 증가 policy/validator/executor registry에 method 추가

6. 업체 구현 관점의 핵심 요구

업체는 “기존 command handler를 모두 버리고 새로 만들라”가 아니라 아래 순서로 연결하면 된다.

  1. 기존 MainApi.executeMethod(...) 기반 기능은 유지한다.
  2. 외부 source는 직접 기능 method를 호출하지 않고 submitTask 또는 submitWorkflow로 들어오게 한다.
  3. TaskManager가 validation, policy, queue, workflow를 먼저 처리한다.
  4. 실제 기기 동작은 TaskExecutorRegistry를 통해 기존 domain handler 또는 새 domain executor에 위임한다.
  5. 모든 task는 accepted 이후 terminal event를 보장한다.
  6. 실패는 자유 문자열이 아니라 reason code와 params로 제공한다.
  7. Cloud source는 replan 후보를, MQTT/App/예약 source는 ack/status/report/retry 정책을 각각 적용한다.

6.1 업체가 특히 조심해야 할 부분

주의점 이유
TaskManager에 domain business logic을 중복 구현하지 않기 기존 handler에 이미 lock mode, policy gate, cleaning transaction, map/movement 조건이 있음
get/status 조회를 무조건 queue task로 만들지 않기 get 계열은 DIRECT 또는 planning context query로 처리하는 편이 안전
workflow 등록 시점에 모든 step 조건을 미리 확정하지 않기 1번 step 완료 후 기기 상태가 바뀌므로 2번 step 조건은 실행 직전에 확인해야 함
Cloud LLM 전용 field로 고정하지 않기 MQTT/App/예약 source도 같은 API를 타야 하므로 source, external_command_id 계열 trace 필요
COMPLETED마다 Cloud 호출하지 않기 정상 진행/완료는 상태 갱신이고, 판단이 필요한 실패만 상위 판단 후보
자유 자연어 reason만 제공하지 않기 업체/서버/Cloud가 동일하게 처리하려면 reason code와 params가 필요

7. 업체 설명 한 문장

이번 변경은 DeviceAgent에 Cloud LLM 전용 기능을 붙이는 작업이 아니라, 기존 직접 method 호출 구조 앞에 TaskManager 실행 layer를 추가해 Cloud/MQTT/App/예약/로컬 음성 명령을 하나의 SoC task framework로 수용하는 리팩터링이다.