본문으로 이동
SK-INTELLIX / ENGINEERING전체 모듈 Atlas ↗

신규 기능 구현 절차

이 페이지는 현재 구현의 확장 지점과 개발 제안을 연결합니다. 예제 요구사항은 가상이며 해당 기능을 이미 구현했다는 뜻이 아닙니다. 기준은 quber/mr7 @ 7695c9a8. DA/는 apps/DeviceAgent/app/src/main/java/com/sk/airbot/deviceagent/, LA/는 apps/SKMLauncher2/app/src/main/java/com/sk/airbot/skmlauncher/입니다.

01 / COMMAND새 명령·옵션요청 계약과 정책 입구02 / SETTING재부팅 후 유지할 설정저장 · 적용 · 복원 · 소비자03 / SCHEDULE새 예약 기능등록에서 Launcher 실행까지
신규 명령·이벤트의 정책 등록

제품 차단 정책은 메서드 이름을 열거하며, callback 전달도 메서드별 수신자 목록을 확인합니다. 새 이름을 추가했다면 두 목록을 반드시 검토해야 합니다. 아래 01과 04에서 실제 파일과 실패 증상을 확인하세요.

04 / 새 완료 이벤트와 수신자 연결 →

먼저 결정할 계약

결정할 것 개발 전에 적을 내용 구현 위치에 미치는 영향
노출 입구 화면 / 클라우드 / SDK / 예약 중 실제 지원 채널 producer와 callback consumer의 작업 범위
입력 method, 필수·선택 key, 타입, 단위, 기본값, 허용 범위 MainApi parser와 내부 파라미터, 구버전 호환
정책 product mode, lock/privacy/night, battery/station, 현재 실행 기능 StateManager + 해당 도메인, 예약/WSS는 별도 판정
실행 수명 즉시 완료 또는 장시간 작업; 중복 요청·선점·취소 기존 manager 확장 또는 독립 실행 객체 필요성
상태 메모리 상태 / 영속 설정 / 보고 이력 중 무엇인지 transaction / preferences / DB의 소유자
결과 수락·진행·완료·실패·취소의 정의, 누가 받는지 callback 라우팅, UI/IoT mapping, 실제 장치 확인
복원 재부팅 후 설정만 복원할지, 작업도 재개할지 초기화·알람·장치 재연결 경로와 검증

기존 시스템에 통일된 requestId·완료 상태 모델이 이미 있다고 가정하지 않습니다. 상관 ID, 중복 제거, timeout이 필요하다면 요구사항으로 명시하고 producer부터 consumer까지 함께 설계해야 합니다.

01 · 새 명령 또는 기존 명령에 옵션 추가

예제 요구사항: 앱과 클라우드에서 특정 청정 옵션을 요청할 수 있게 한다. 이름과 값은 제품 요구사항으로 확정해야 하며, 아래는 구현 순서입니다.

순서 직접 수정 또는 분석할 곳 구현할 것 / 결정할 것 놓치면 보이는 증상
1. 기존 옵션인지 판정 DA/data/Constants.java:16, DA/data/AirCleaningParameter.java:23, DA/main/api/MainApi.java:523 기존 setAirCleanerOperation의 mode/speed/position 확장인지 새 method인지 결정. 기존 코드값은 재사용 의미를 바꾸지 않음 기존 앱의 같은 값이 다른 동작을 수행
2. producer 연결 앱은 해당 repository, 클라우드는 apps/IotAgent/app/src/main/java/com/sk/airbot/iotagent/mqtt/topic/CmdTopic.java:359 외부 입력을 Bundle 계약으로 변환. 모든 채널 지원이 요구되지 않으면 해당 producer만 변경 UI에만 추가되고 cloud/예약에서 옵션 유실
3. 일반 진입 DA/DeviceAgent.java:263 → DA/main/api/MainApi.java:150 기존 Stub은 method 읽고 executeMethod 호출. 새 method는 MainApi 분기, 옵션은 해당 기존 분기의 파싱·검증 확장 호출 수락 뒤 기능 선택이 되지 않음
4. 제품 차단 DA/event/StateManager.java:149 · checkBlockedStatus UPGRADE/VITALSIGN 및 Live View의 이름 목록에 새 명령을 포함할지 판정. 기존 이름의 옵션 확장도 정책 의미 점검 새 이름만 업데이트 중 실행 가능해짐
5. 도메인 허용 DA/policy/CmdPolicyManager.java:471 · DA/cleaning/AirCleaningPolicy.java:60 시작/변경/정지에 적용할 정책과 현재 동작의 선점 방식 결정 허용 판단은 맞지만 기존 이동/보안과 충돌
6. 실행·상태 DA/cleaning/BaseCleaningManager.java:213 · DA/cleaning/CleaningTransaction.java:68 Basic/Moving 선택, 파라미터 복사·저장, 정지/재개, 장치 출력까지 연결 파라미터는 전달됐지만 실행에 미반영·재개 시 유실
7. 표시·보고 DA/cleaning/BaseCleaningManager.java:596 · DA/report/CleaningReportManager.java startAirClear callback, 상태 조회, 완료/중단 보고의 추가 의미를 consumer와 맞춤 실제 동작과 UI/보고서가 다름

필수 작업 산출물: 입력 계약 표, 허용/차단 표, 상태 전이와 취소 정의, 변경 파일 목록, 결과 확인 로그 지점. 새 Manager와 AIDL 변경은 자동 필수가 아닙니다.

최소 회귀: 기존 필드만 보내는 앱 → 기존 동작 유지 / 옵션 누락 → 정한 기본값 / 잘못된 값 → 명시한 거절 / lock·UPGRADE·Live View → 기대한 차단 / START 후 STOP → 실제 정지와 결과 일치. 청정의 현재 조기 IoT 전달과 정책의 반환값 쟁점은 정책 근거를 확인합니다.

02 · 새 영속 설정 추가

예제 요구사항: “청정 옵션의 기본값”을 설정 화면에서 바꾸고 재부팅 뒤에도 유지한다. 이는 가상 요구사항이며 현재 해당 key가 있다는 뜻은 아닙니다.

순서 위치 작업 영향과 검사
1. 저장 계약 DA/data/pref/SettingPreferences.java:26 · SettingsPreferencesKey key, 타입, 기본값, 기존 기기에서 key가 없을 때의 값 정의 string/int/boolean 혼용 금지; 기존 저장 파일 호환
2. 저장·런타임 적용 DA/settings/Settings.java · 기존 setVoiceRecognitionEnable:462 / setLanguage:806 참고 setter/getter와 적용 대상 분리. 저장 전후 적용 순서는 기능 특성에 맞게 결정 값만 저장하고 실행 객체는 이전 값인 상태 방지
3. 초기화·reset DA/settings/Settings.java:86 · initSettings / :231 · resetSettings 초기화에서 key를 읽어 필요한 동작 적용; reset 대상이면 기본값 복원 추가 재부팅·공장 초기화·부분 초기화 결과
4. API·UI DA/main/api/MainApi.java와 해당 Launcher repository/ViewModel GET/SET, 값 검증, 화면 저장/조회, 외부 변경 갱신 UI 진입 직후와 외부 변경 직후 같은 값
5. 소비자 해당 executor와 정책의 getter 사용처 시작할 때 읽을지 즉시 실행 중 동작에 적용할지 정의 수동/예약/클라우드 요청마다 일관성
6. 알림 DA/settings/Settings.java:1063 · settingChanged / refreshPui 기존 settingChanged 경로 사용 여부와 수신 후 재조회 확인 저장 성공·적용 완료·화면 갱신을 각각 확인

실제 저장소 함정: DA/provider/DeviceAgentProvider.java:38의 query는 Setting/SKM 저장소를 구분하지만 :64의 insert와 :96의 update는 SKMPreferences에 씁니다. ContentResolver로 썼다고 Settings가 사용하는 SettingPreferences key가 바뀐다고 가정하면 안 됩니다. provider 계약을 확장할 때는 기존 호출자와 권한·호환성을 별도 분석합니다.

권장 검증: key 없는 기존 설치 → default / 정상 값 저장 후 재부팅 / 잘못된 타입 / 반복 SET / 기능 실행 중 SET / UI와 cloud의 GET / reset 후 예상값. 설정값 자체와 적용된 장치 상태를 별도로 관찰합니다.

03 · 새 예약 유형 추가

예제 요구사항: 새 사용자 기능을 지정한 시간에 실행한다. 기존 청정 예약의 옵션만 늘리는 경우에는 새 type이 필요한지 먼저 판단합니다.

예약은 저장·알람·허용·Launcher 실행의 네 구간입니다.

DB 저장 성공이나 알람 수신만으로 개발 완료를 판단하지 않습니다. 새 type의 실행 객체가 등록되어야 최종 기능 요청까지 이어집니다.

단계 DeviceAgent 쪽 Launcher / 외부 쪽 완료 확인
타입·필드 DA/schedule/Schedule.java:38 코드, :85 Bundle parser, :211 toBundle LA/data/repository/ScheduleRepository.java:357 목록 모델, :782 parseScheduleIntoBundle 저장→조회→편집→재저장 시 같은 값
CRUD DA/main/api/MainApi.java:2235 addSchedule / :2296 scheduleiot, DA/schedule/ScheduleManager.java LA/data/repository/ScheduleRepository.java:666 editSchedule add/update/remove 및 비활성 처리
DB DA/schedule/db/ScheduleDao.java · ScheduleDbHelper.java cloud schema가 바뀔 때 backend 계약 기존 데이터 유지; 컬럼 변경 때만 migration
알람·재판정 DA/schedule/ScheduleInitRunner.java, DA/schedule/ScheduleAlarmReceiver.java:71 / :134 시간·타임존·요일 입력 규칙 재부팅/시간 변경/삭제 뒤 알람 동작
유형별 정책 Receiver 일반 판정·Security 재판정·UPGRADE 우선 화면에 보이는 예약 가용성과 차단 안내 새 type이 다른 type의 예외를 우연히 상속하지 않는지
실행 전달 DA/schedule/ScheduleAlarmReceiver.java:334 setSchedule Bundle LA/ui/SKMLauncherApp.java:1138 → ReceivedScheduleInfo → LA/data/model/executableSchedule/ExecutableScheduleManager.java:17 등록 / :48 조회 Activity 없음·등록 누락·dialog 조건과 실제 API 호출
실행 확인 DA/main/api/MainApi.java:378 setScheduleExecuted 전달 LA/data/repository/ScheduleRepository.java:622 sendScheduleExecuted / LA/data/model/executableSchedule/ExecutableSchedule.java:105 이 응답의 의미와 실제 장치 완료는 별도로 확인

현재 실행 확인의 정확한 의미: LA/data/model/executableSchedule/ExecutableSchedule.java:105의 executeSchedule은 sendExecutedSchedule(..., true)를 먼저 호출한 뒤 execute(...)를 호출합니다. 따라서 isExecuted=true는 실제 기능 호출에 앞서 송신될 수 있으며, 장치 완료 판정에 사용할 수 없습니다.

작업 순서: 계약 합의 → parser/저장 왕복 → 실제 기능 API 구현 → Launcher 실행 객체 등록 → Receiver 정책 → UI/클라우드 노출 → 재부팅·예외 회귀. 모든 TYPE_* 비교와 문자열 type 비교를 함께 검색합니다.

필수 조합: 구버전 저장 데이터, 알 수 없는 type, 삭제/비활성, night/lock/privacy, station 밖·저전력, 일반/보안 예외, Launcher Activity 없음, API 정책 거절, 실제 기능 실패. 새 예약에도 일반 기능의 정책이 다시 적용되는지 추적합니다.

04 · 새 완료 이벤트 추가

예제 요구사항: 장시간 기능이 실제로 끝났을 때 화면과 클라우드가 결과를 받는다. 아래는 일반 Bundle callback 경로이며 전용 WSS/Streaming 인터페이스는 별도 추적합니다.

순서 근거 파일·메서드 필요한 수정/검토
완료 지점 정의 실제 도메인 executor / 장치 callback 요청 수신·작업 enqueue·장치 응답 중 어느 시점을 완료로 볼지 명시. 실패·취소·timeout도 결정
이벤트 작성 DA/event/StateManager.java:538 · notifyStateChanged 또는 DA/cleaning/BaseCleaningManager.java:596 예시 기존 Bundle의 method와 결과 field 패턴 참고. 새 이벤트 이름과 consumer 계약 작성
주 Handler 전달 DA/app/AppCmd.java:18 → DA/main/MainHandler.java:79 sendModuleCallback_main과 MainHandler의 특수 분기/필터 확인
수신자 정책 DA/app/ModuleCmdCallbackPolicy.java → DA/main/api/MainApi.java:3624 getAvailableCaller(method)가 빈 목록이면 전달되지 않음. 원하는 실제 수신자만 매핑
client 등록 DA/DeviceAgent.java:130 / :180 · registerCallback / registerCallbackByName 실제 caller 이름과 등록된 callback을 확인. 문자열 포함 비교와 legacy not-defined 경로 존재
표시·전송 Launcher 해당 callback 분기 / apps/IotAgent/app/src/main/java/com/sk/airbot/iotagent/IotAgent.java:741 method 소비, UI 상태 갱신, cloud 응답·이벤트 선택
수명 종료 DA/event/StateManager.java:570 · registerDeathMonitor client 종료/재등록, 늦게 온 결과와 새 작업 혼동, 중복 완료 처리

주의: ModuleCmdCallbackPolicy는 callback 라우팅 정책입니다. caller 문자열 비교를 서명 인증으로 해석하거나 보안 권한 검증의 대체물로 사용하지 않습니다. 동기 Binder 반환값도 새 비동기 완료 이벤트의 보장이 아닙니다.

회귀 검증: 정상 등록된 consumer만 수신 / 미등록·종료된 consumer / 시작 뒤 취소 / 다음 요청 뒤 이전 결과 도착 / 연결 재등록 / 동일 완료 두 번 / 장치 실패 / 정책에서 거절된 요청. 결과 로그는 요청 입력·정책 결과·실행 시작·장치 결과·callback 전달·consumer 처리의 여섯 지점을 연결합니다. 이것은 권장 관측 지점이며 현재 모든 로그가 존재한다는 뜻은 아닙니다.

AIDL·저장·빌드 변경 판단표

바뀌는 것 함께 변경할 범위 변경이 자동으로 필요하지 않은 부분
기존 Bundle에 key 또는 method 문자열 추가 producer/parser/executor/consumer 및 정책 목록 기존 generic AIDL signature
typed Binder 메서드·callback·Parcelable 계약 서비스와 실제 client의 AIDL/SDK 및 호환성 관련 없는 앱
영속 설정 key 추가 기본값·저장·초기화·reset·GET/SET 소비자 예약 DB migration
예약 DB 컬럼/형식 변경 DAO/helper·migration·serializer·기존 데이터 스키마가 그대로인 단순 정책 변경
새 패키지/서비스·권한 Manifest·제품 빌드 선택·연결/해제·권한 검토 단순 도메인 옵션 변경
외부 device protocol 실제 wrapper·전송·수신·단위·timeout와 firmware 계약 호출하지 않는 다른 MCU/HAL 경로

코드에서 영향 범위를 찾는 명령

아래는 저장소 루트에서 실행하는 읽기 전용 검색 예시입니다. 첫 결과만 고치지 말고 producer, consumer, 초기화, reset, 테스트를 분류합니다.

# 명령의 producer / parser / consumer
rg -n 'setAirCleanerOperation|startAirClear' apps
# 새 명령이 지나야 할 공통 제한과 callback 라우팅
rg -n 'checkBlockedStatus|getAvailableCaller|onModuleCallbackLoop' apps/DeviceAgent
# 예약 type와 실행 등록
rg -n 'TYPE_|scheduleTypeCode|setScheduleExecuted|getExecutableSchedule' apps/DeviceAgent apps/SKMLauncher2
# 영속 설정 적용·초기화·reset
rg -n 'SettingsPreferencesKey|initSettings|resetSettings|settingChanged' apps/DeviceAgent

기준 커밋은 git rev-parse quber/mr7로 확인하고, 분석할 파일은 git show quber/mr7:파일경로로 읽습니다. 작업 트리의 미추적 기능을 기준 브랜치의 구현으로 섞지 않습니다.

개발 티켓에 붙일 작업 정의

요구사항 / 지원 입구:
기준 커밋 / 현재 동작 / 변경 후 동작:
입력 method·keys·기본값·호환성:
정책(제품 모드 / 도메인 / 예약·WSS 예외):
직접 수정 파일·메서드 / 연관 검토 파일·판정:
상태 소유자 / thread / 취소·timeout / 영속 여부:
결과 method·수신자·완료 정의 / 실패·중복·지연 결과:
빌드·배포 대상 / 기존 데이터 호환:
단위 검증 결과 / IPC·DB 검증 결과 / 실기기 검증 결과:

문서의 정적 근거는 APK나 실제 동작의 증거가 아닙니다. 구현 시 변경한 모듈의 최소 단위 검증부터 수행하고, IPC/저장/장치 경계를 바꾸면 해당 경계의 통합 검증으로 범위를 넓힙니다.

Connections

세부 개발 지도 45개 작업 · 수정 위치 · 영향 범위 · 기존 구조 Atlas · 개발 지도