← Docs hub

서버 중심 사용자 정보·관심사 관리 설계

조회와 반환 형식

getVoicePersonalization(voiceId) 요청은 AI-Agent → DeviceAgent → IoTAgent → 서버로 전달한다. 서버 조회 결과는 역방향으로 voicePersonalizationResult 콜백에 담아 전달한다. Binder 호출의 정수 반환값은 관심사 목록이 아니다.

구간 관심사 필드 실제 타입
서버 ↔ IoTAgent interestCodes JSON 문자열 배열
IoTAgent ↔ DeviceAgent ↔ AI-Agent interestCodes Bundle의 ArrayList<String>
AI-Agent 내부 조회 함수 currentServerInterests(voiceId) List<String>

AI-Agent의 메모리 보관은 서버에서 받은 응답의 후처리이며 로컬 DB 조회가 아니다. 현재는 requestId·voiceId·만료 등을 확인한 응답 한 건을 잠시 보관한다. currentServerInterests를 답변 프롬프트에 소비하는 호출은 아직 없다. 소스의 IoTAgent 송신은 샘플 MQTT 브리지이므로 실제 AWS 운영 연동 완료와 구분한다.

관심사는 서버에 저장하고, AI-Agent는 필요할 때 조회한다. 초기 보이스 등록 직후와 이후 App 설정에서 모두 변경할 수 있다. 화자 프로필·임베딩은 기기 파일로 보관한다. 대화내역 기능은 다음 차수로 제외한다.

2026-09-17 작업본에는 샘플 Backend 저장소, 신규 Binder/MQTT 조회 경로, 모바일 연동을 반영했다. 제품 AWS 계정 인증·권한·임베딩 Cloud 저장은 아직 별도 통합 대상이다. 설치된 기기나 공개 샘플 서버가 자동으로 갱신된 것은 아니다.

1. 데이터별 관리 주체

데이터 원본 관리 기기 역할
계정·개인정보·접근 권한 Backend 필요한 최소 정보만 수신; 계정 ID를 화자 키로 사용하지 않음
계정 ↔ deviceId ↔ voiceId 연결 Backend 등록 ID 전달; 서버가 인증된 등록 요청에 연결
닉네임·관심사 제품 Backend 샘플 서버는 voiceId별 닉네임·동의·관심사 저장. 발음 설정은 외부 계약에서 제외
voiceId 발급·기준 임베딩 AI-Agent UUID 발급, 로컬 저장·화자 매칭
등록 임베딩 서버 사본 Backend 등록 시 DeviceAgent를 거쳐 전달하는 요구 유지
대화내역 다음 차수 현재 저장·조회·이벤트 없음

관심사를 바꾸는 창구는 모바일 App이다. 기기 등록 App의 개인화 사용 여부 선택은 관심사 목록 수정과 다르다. 샘플은 새 프로필에 해당 선택을 기록하고 목록 조회 때 서버에 전달한다. 동의 필드가 없는 예전 프로필은 동의한 것으로 추정하지 않는다. 제품에서는 인증된 계정 동의와 연결해야 한다.

2. 변경·조회 흐름

서버 원본과 기기 조회 구조

구조도 크게 보기

기능 흐름 처리 결과
최초 관심사 등록 App 설정 → 관심사 선택(생략 가능) → 등록 요청 → COMPLETED → Gateway가 실제 프로필·동의 확인 후 저장 화면·저장 상태 명세. 임시 선택값은 서버 재시작 시 유실 가능
관심사 변경 모바일 → 인증된 Backend → 서버 DB 서버 저장 완료와 최신 revision 반환. 기기 저장 완료를 기다리지 않음
모바일 관심사 조회 모바일 → Backend → 서버 DB 기기가 오프라인이어도 서버 값 조회
대화 개인화 정보 조회 AI-Agent → DeviceAgent → IoTAgent → Backend voiceId에 대응하는 허용 정보만 반대 방향으로 반환
화자 파일 저장 AI-Agent → 기기 파일 profile.json 및 reference_embedding.bin

Backend는 deviceId를 인증된 접속 정보와 대조하고 계정·기기·voiceId 연결을 검증한다. 기기가 보내는 voiceId만 믿고 임의 계정 정보를 반환하지 않는다. 음성 매칭은 계정 인증을 대체하지 않는다.

3. 신규 Binder 계약

기존 로컬 getVoiceProfileInterests와 방향·의미가 달라 새 메서드를 사용한다. 아래 이름은 AI-Agent·DeviceAgent·IoTAgent 작업본의 Contract 상수에 반영했다.

기능 송신 → 수신 method 방식
서버 정보 조회 요청 AI-Agent → DeviceAgent getVoicePersonalization sendModuleCommand(input, output)
외부 조회 중계 DeviceAgent → IoTAgent getVoicePersonalization onModuleCallback(Bundle)
조회 결과 수신 IoTAgent → DeviceAgent voicePersonalizationResult sendModuleCommand(input, output)
조회 결과 전달 DeviceAgent → AI-Agent voicePersonalizationResult onModuleCallback(Bundle)

요청 필드

필드 Bundle 타입 정의
contractVersion String voice-personalization-v1
method String getVoicePersonalization
requestId String 새 UUID; 결과 대응·재전달 식별
voiceId String 인식된 등록 화자 UUID
issuedAtMs Long 생성 Unix 밀리초
expiresAtMs Long AI-Agent: issuedAtMs + 5,000. 중계 수신 상한 10,000ms. 만료 요청 거절

결과 필드

필드 Bundle 타입 정의
contractVersion String voice-personalization-v1
method String voicePersonalizationResult
requestId String 원 요청 ID
voiceId String 원 요청의 화자 ID
success Boolean 정보 조회 성공 여부
reasonCode String 성공은 빈 문자열; 실패는 아래 코드
personalizationEnabled Boolean 성공 시 필수. 서버가 허용한 개인화 여부
interestCodes ArrayList<String> 성공·개인화 허용 시 서버 관심사 목록; []는 미설정
revision Long 성공 시 필수. 서버가 증가시키는 사용자 정보 버전
expiresAtMs Long 항상 필수. 원 요청의 만료 시각 그대로; 서버에서 늘리지 않음

현재 서버 결과: PROFILE_NOT_FOUND, BACKEND_UNAVAILABLE. 성공 reasonCode는 빈 문자열이다. 실패 시 관심사 데이터는 포함하지 않는다. 개인화 비허용은 success=true/personalizationEnabled=false/interestCodes=[]이다. 네트워크 단절·만료는 현재 5초 후 결과를 사용하지 않는 방식이며 별도 실패 콜백을 보장하지 않는다. 제품의 권한 거절 코드는 인증 Backend 통합 때 추가한다. 이름·발음 갱신은 이번 Binder 응답에 포함하지 않는다.

DeviceAgent는 caller 검증 후 요청은 IoTAgent로, 결과는 AI-Agent로 보낸다. Registration App으로 결과를 보내지 않는다. Int 반환은 중계 수락 여부이지 서버 조회 성공이 아니다.

4. 서버·MQTT 연결과 모바일 API

모바일의 GET/PUT /voice-profiles/{voiceId}/interests?deviceId=... 경로를 유지하고 기기 DB에서 샘플 서버 DB로 변경했다. 저장은 허용 코드 10종의 전체 교체이며 빈 배열은 비우기다. 최초 등록 완료 후 목록을 갱신하면 기기에서 확인한 프로필만 샘플 서버에 생성한다. 그 뒤 관심사 GET/PUT은 기기에 MQTT 요청을 보내지 않는다.

서버 파일은 VOICE_PROFILE_PERSONALIZATION_DB로 지정한다. 기본값은 ~/.local/share/voice-profile-sample/personalization.db이며 (deviceId, voiceId)로 분리한다. 이는 시험용 범위 키이지 계정 인증이 아니다. nickname-only API는 HTTP 410, 미등록 ID는 404, 잘못된 코드/개인화 비허용 저장은 400이다. 기존 모바일 호출자는 실제 voiceId를 사용해야 한다.

신규 Binder를 JSON으로 변환할 때 Long은 정수, Boolean은 boolean, ArrayList는 배열로 보존한다. 계정 토큰·원본 음성·임베딩은 개인화 조회 요청에 넣지 않는다.

방향 토픽 발행 / 구독 메시지
조회 요청 skmg/airbot/{deviceId}/v1/request/voicePersonalization/{requestId} IoTAgent 발행 / Backend 구독 요청 필드 JSON
조회 결과 skmg/airbot/{deviceId}/v1/command/voiceProfileEnrollment Backend 발행 / IoTAgent 구독 action=personalizationResult, payload=결과

두 방향 모두 QoS 1, retain=false. 현재 실제 발행 코드는 VoiceProfileMqttTestBridge 경로다. 제품 AWS IoT Core의 인증서·정책·Backend consumer 및 송신 연결은 별도로 구현·검증해야 한다.

{
  "contractVersion": "voice-personalization-v1",
  "method": "getVoicePersonalization",
  "requestId": "request-1",
  "voiceId": "voice-1",
  "issuedAtMs": 1789632000000,
  "expiresAtMs": 1789632005000
}
{
  "action": "personalizationResult",
  "payload": {
    "contractVersion": "voice-personalization-v1",
    "method": "voicePersonalizationResult",
    "requestId": "request-1",
    "voiceId": "voice-1",
    "success": true,
    "reasonCode": "",
    "personalizationEnabled": true,
    "interestCodes": [
      "WEATHER",
      "HEALTH"
    ],
    "revision": 2,
    "expiresAtMs": 1789632005000
  }
}

위 시각은 메시지 형식 예시다. 실제 전송 때는 현재 시각과 그로부터 5초 뒤를 넣는다.

5. AI-Agent 조회·캐시 규칙

  1. 한 턴의 voiceId를 확정한다. unknown에는 다른 화자의 정보를 붙이지 않는다.
  2. 관심사 기능이 켜진 경우 새 턴의 voiceId로 비동기 조회한다. 음성 응답을 기다리게 하지 않는다.
  3. 결과의 requestId·voiceId가 현재 요청과 모두 일치하는지 확인한다. 이전 화자·종료한 대화의 응답으로 현재 문맥을 덮어쓰지 않는다.
  4. 새 요청을 시작할 때 이전 결과를 비운다. 같은 요청의 중복 응답은 한 번만 받는다. 결과도 원 요청 만료 시각까지만 읽을 수 있다.
  5. 개인화 비허용·프로필 삭제·턴 정리·서비스 종료 시 결과를 무효화한다. 서버 계정 해제 이벤트 연계는 제품 통합 대상이다.

관심사 결과는 프로세스 메모리에 하나만 유지하며 영구 저장하지 않는다. 기능 설정은 기존 persist.sys.debug.deviceagent.LlmManager.voiceInterestEnabled=true를 사용한다. 이번 변경은 조회 결과를 AI-Agent까지 전달·보관하는 경로이며, LLM 프롬프트에 관심사를 자동 주입하는 변경은 아니다. currentServerInterests(voiceId)는 유효 결과만 반환한다. 오프라인 화자 식별과 일반 대화는 별개로 유지한다.

서버 정보 변경 후 즉시 기기에 반영해야 한다면 무효화 이벤트가 추가로 필요하다. TTL만 사용하는 동안에는 만료 전까지 오래된 캐시가 사용될 수 있으므로 즉시 동기화라고 표현하지 않는다.

6. 기존 구현 전환

현재 PoC 제품 전환
로컬 set/getVoiceProfileInterests SERVER_OWNED_PERSONALIZATION 실패 결과 반환. DB를 읽거나 쓰지 않음
구형 voice_memory.db 서비스 시작 시 제거. 서버로 업로드하거나 관심사 원본으로 승격하지 않음
로컬 profile.json 이름·발음 등록 부트스트랩 정보와 캐시로 구분; 서버 최신값 우선 적용 경로 구현
화자 등록·임베딩 유지. Cloud 등록 사본·계정 매핑·ACK 연결 필요
단기 대화 DB 이번 차수에서 제거. 프로필·임베딩 파일은 보존
대화 실시간 이벤트 이번 차수 인터페이스에서 제거

7. 구현 순서·검증

범위 작업본 반영 남은 확인
샘플 Backend SQLite 관심사 원본, 전체 교체, revision, 미등록 ID 거절 제품 계정/기기 접근 권한
DeviceAgent AI 요청→IoT / IoT 결과→AI, caller·타입·만료 검사 실제 Binder 왕복
IoTAgent 샘플 MQTT 발행, 결과 JSON→Bundle 변환 AWS 제품 MQTT 연결
AI-Agent 비동기 조회, 늦은/다른 화자/중복 결과 차단, 로컬 관심사 API 중단 실기기 취소·오프라인 시험
모바일 등록 완료·상시 수정 화면 유지, 서버 저장 문구, 다른 화자 조회 결과 차단 새 APK 화면 시험

단위 검증은 서버 재시작 후 유지, 화자/기기별 분리, 목록 교체·비우기, 동의 없음, 미등록 ID, 만료·다른 요청·중복 응답을 포함한다. 계정 권한 시험·실제 Binder 왕복·기기 발화 시험은 단위 테스트 통과와 구분한다.

제품 연동 규칙 읽는 법

아래 8~14절은 현행 코드와 제안 규칙을 나눈다. 제안 규칙은 구현·제품 검토 대상이며, 문서에 추가했다고 APK·서버에 적용된 것은 아니다. 신규 제품 API나 상태 enum이 없는 항목에 임의의 메서드명을 부여하지 않는다. 제품 AWS 계약을 확정할 때 HTTP 오류·이벤트·필드를 함께 버전 관리한다.

<a id="completion-rules"></a>

8. 완료 조건과 화면 전환

단계 판정 주체·근거 현행 코드 제품 제안 규칙·화면
요청 접수 DeviceAgent의 Binder 반환 / IoTAgent의 발행 결과 중계 수락만 의미 ‘요청 중’. 등록 성공으로 표시하지 않음
기기 프로필 생성 AI-Agent의 로컬 파일 저장·식별기 반영 생성 후 commitVoiceProfile 전달 ‘기기에 저장됨’. 서버 완료와 구분
전달 대기 저장 DeviceAgent, accepted=true 암호화 대기 사본 저장; cloudSynced=false이면 DELIVERY_FAILED 경로 ‘서버 연결 확인 필요’. 녹음부터 반복시키지 않음
서버 등록 Backend의 계정·기기·voiceId 연결 및 임베딩 사본 저장 실제 Cloud ACK 미연결. LOCAL_TEST_ACK로 COMPLETED 가능 서버 저장이 확인된 ACK를 AI-Agent에 전달한 뒤 COMPLETED. PUBACK만으로 완료 금지
최초 관심사 화면 모바일, 등록 요청 전 선택 설정 다음 화면에서 선택하고 등록 진행 화면으로 이동. 완료 후 Gateway가 실제 voiceId·동의 확인 제품 서버에서도 소유권·동의·프로필 확인 후 선택값 저장
관심사 저장 Backend 저장 결과 초기는 interestSaveState=SAVED, 상시 수정은 HTTPS PUT 성공으로 확인 ‘저장됨’. 음성 대화에서 활용됐다는 뜻은 아님

제안 규칙: 보이스 등록과 관심사 저장은 별도 완료 단계다. 관심사 선택을 건너뛰어도 보이스 프로필은 유지하고 관심사는 []로 둔다. 개인화 비동의자는 관심사 편집으로 자동 이동하지 않는다. 관심사 저장 실패로 등록된 보이스를 삭제하거나 다시 녹음하지 않는다.

COMPLETED를 중복 수신해도 같은 등록 요청의 화면을 반복해서 열지 않는다. 모바일 종료로 완료 이벤트를 놓쳤다면 서버 목록·등록 작업 상태를 조회해 복구한다. 현재 샘플의 등록 상태 조회는 실행 중 메모리에 의존하므로 서버 재시작을 넘는 복구를 보장하지 않는다.

<a id="recovery-rules"></a>

9. 실패·대기·재연결

아래 시간과 재시도 횟수 중 ‘제안’으로 표기한 값은 제품 초기 운영값이며 현재 구현값이 아니다.

상황 담당·현행 동작 제안 규칙 화면·종료 조건
등록 App Binder 단절 등록 App 연결 상태; 공통 복구 ACK 없음 재연결 후 같은 requestId로 getVoiceProfileEnrollmentState 1회. 10초 내 확인 불가 시 자동 대기 종료 ‘연결을 확인해 주세요’. 사용자가 다시 확인하거나 나가기
start 응답 유실 동일 requestId start 재호출도 녹음 세트 초기화 가능 start 자동 재전송 금지. 상태 조회 후 진행 중이면 복구, 없으면 사용자 확인 후 새 요청 이미 녹음한 세트를 임의로 초기화하지 않음
서버 관심사 조회 단절 AI-Agent 요청 생성 후 5초, 결과 없으면 사용 안 함 현재 턴 자동 재시도 0회. 다음 정상 턴에 새 요청 일반 대화 진행, 서버 대기 때문에 TTS 정지 금지
관심사 PUT 응답 유실 서버에 이미 저장됐을 수 있음 모바일은 입력값 보존, 10초 후 결과 불명 표시. GET으로 저장값·revision 확인 후 사용자 재시도 성공 확인 전 ‘저장됨’ 표시 금지
임베딩 전달 실패 DeviceAgent 대기 사본 존재, 실제 Cloud 재전송 미연결 IoTAgent·Backend 연계 후 1·5·15초 간격 최대 3회 추가 시도. 이후 백그라운드 대기 녹음 재시작 없이 전달 재시도. UI는 30초 후 나가기 허용
기기·Service 재부팅 녹음 세션·PCM은 메모리; 일부 프로필·대기 사본은 영구 저장 녹음 중이었다면 새 녹음. 저장된 프로필과 대기 사본은 작업 ID로 대조 후 전달 복구 중복 voiceId 생성 금지. 복구 불명은 수동 확인
생성 중 취소·늦은 ACK 생성 중 취소 경합 방어 미완성 취소된 작업을 완료 화면으로 되살리지 않음. 이미 저장된 사본은 삭제 절차로 정리 ‘취소 처리 중’과 ‘취소 완료’ 구분
시계 오차 Unix ms 기준 issuedAtMs/expiresAtMs 검사 시간 동기화 전 개인화 조회를 사용하지 않음. 거절을 해결하려고 TTL을 임의 연장하지 않음 일반 대화 유지, 진단에는 만료 여부만 기록

제품 재전송 제안은 같은 작업 ID의 중복 저장 방지가 선행 조건이다. QoS 1은 중복 수신 가능성이 있으며, 제품 Backend가 이미 저장한 등록 요청을 다시 받으면 같은 결과를 반환해야 한다. 이 규칙이 없는 현재 start 경로에 위 재시도 정책을 적용하면 안 된다.

<a id="deletion-consent"></a>

10. 삭제·동의 철회

사용자 행동 지울 값·유지할 값 현행 코드 제품 제안 규칙
관심사 비우기 서버 목록을 []; 프로필·임베딩·동의 유지 HTTPS PUT [] 지원 다음 유효 조회부터 빈 목록. 보이스 삭제로 해석하지 않음
개인화 동의 철회 관심사 삭제, 개인화 사용 중단; 보이스 식별 동의와 구분 상시 서버 동의 변경 API·기기 통지 미연결 서버가 먼저 조회·편집 차단 후 revision 증가, 기기 snapshot 무효화 통지. 원격 반영 확인 전 ‘기기 적용 대기’
보이스 프로필 삭제 로컬 프로필·임베딩·해당 단기 기록·전달 대기 사본·서버 매핑·임베딩·관심사 기기 삭제 후 샘플 서버 관심사 삭제. 전체 트랜잭션 아님 서버가 신규 조회·사용을 먼저 차단하고 삭제 작업 보관, 기기 삭제 ACK와 서버 삭제 결과 모두 확인
계정·기기 연결 해제 해당 연결의 접근 차단; 다른 사용자 데이터 유지 제품 계정 처리 미구현 권한 해제 즉시 서버 요청 거절. 오프라인 기기 데이터 제거는 재접속 후 확인

제안 삭제 순서: App 본인 확인 → Backend 사용 차단·삭제 작업 보관 → IoTAgent/DeviceAgent가 AI-Agent 삭제 요청 → AI-Agent의 로컬 삭제 결과 → DeviceAgent 대기 사본 제거 확인 → 서버 데이터 제거 → App에 전체 완료. 단계별 실패는 작업 상태에 남기고 성공한 단계를 되돌려 데이터를 복원하지 않는다.

기기가 오프라인이면 ‘서버 접근 차단, 기기 삭제 대기’로 표시한다. 대기 사본 제거 실패를 숨기고 전체 완료로 응답하지 않는다. 삭제 도중 늦게 도착한 commit이 프로필을 다시 만들지 못하도록 삭제된 작업/프로필 식별 기록이 필요하다. 보관 기간은 개인정보 정책 확정 대상이다.

동의 철회는 서버 저장 즉시 이미 생성 중인 답변에서 데이터를 회수할 수 있다는 뜻이 아니다. 제안: 기기에서 철회를 확인하면 진행 중 개인화 추론을 취소하고 일반 응답으로 전환하며, 이를 구현·검증하기 전에는 즉시 철회를 보장하지 않는다. 통신이 끊긴 기기는 현재 요청의 최대 5초 유효기간 후 결과를 사용할 수 없지만, 이미 시작된 추론의 중단까지 보장하는 것은 아니다.

<a id="account-binding"></a>

11. 계정·기기·화자 연결과 권한

주체 제품 제안 책임 허용하지 않을 처리
모바일 App 로그인 계정으로 등록·편집·삭제 요청. 닉네임은 표시값 계정 ID·voiceId 입력만으로 권한 획득
Backend 로그인 계정의 기기 접근권한 확인 → 등록 requestId와 계정·deviceId 연결 → 기기 발급 voiceId를 연결 미등록 기기의 commit 또는 다른 계정 voiceId 수정
IoTAgent·AWS IoT Core 인증서에 연결된 기기와 토픽 deviceId 검증 payload의 deviceId만 믿고 타 기기 요청 처리
DeviceAgent 허용 caller·Bundle 검사 및 대상별 중계 사용자 계정 소유권을 Binder UID 검사만으로 확정
AI-Agent voiceId 발급·임베딩 식별, 허용 조회 결과만 사용 목소리 일치만으로 계정 인증·민감정보 접근 허용

제안 규칙: 관심사 편집은 해당 프로필의 계정 소유자에게만 허용한다. 공유 기기 관리자에게 다른 사람의 관심사 열람 권한을 자동 부여하지 않는다. 기기 관리자의 삭제 권한이 필요하면 별도 권한으로 정의한다. 새 기기에 재등록한 voiceId는 새 기기 연결로 취급하며, 닉네임이 같다는 이유로 이전 화자와 병합하지 않는다.

샘플의 (deviceId, voiceId) 키는 시험용 구분일 뿐 위 계정 인증이 구현된 것이 아니다. 권한 거절용 HTTP 상태·reasonCode, 계정 해제 이벤트의 실제 이름·필드는 제품 Backend 계약 확정 및 구현 전까지 기존 Bundle에 임의로 추가하지 않는다.

<a id="interest-update"></a>

12. 관심사 변경 반영과 동시 수정

항목 현재 구현 제품 제안 규칙
초기·상시 저장 초기는 등록 body의 interestCodes를 Gateway가 완료 후 저장, 상시 변경은 HTTPS PUT. 둘 다 동일 서버 저장소의 전체 목록 교체 코드 목록 최대 10종·중복 금지 유지. 저장 결과 확인 후 화면 갱신
revision 저장 시 증가, 읽을 때 반환 저장 요청에 조회 당시 버전 조건을 추가해 동시 수정 감지
동시 수정 후속 DB 저장이 앞선 값을 덮어쓸 수 있음 버전 불일치 시 HTTP 409 제안. 최신 목록을 보여주고 사용자가 다시 선택. 자동 덮어쓰기 금지
대화 적용 매 턴 비동기 조회; 프롬프트 소비 미구현 App 수정은 다음 턴에서 새로 조회한 값부터 적용. 이미 생성·재생 중인 답변은 일반 수정만으로 중단하지 않음
늦은 응답 requestId·voiceId·기한 확인 후 수락 새 턴에 이전 응답 사용 금지. 결과 수신 후 5초를 새로 시작하지 않음
개인정보·동의 철회 원격 무효화 미구현 일반 관심사 수정과 달리 10절의 차단·무효화 절차 적용

버전 조건 필드·409 응답은 제안이며 현행 PUT 스키마가 아니다. 전환 시 모바일과 Backend를 함께 수정하고, 버전 조건 없는 구형 클라이언트의 허용 여부를 명시해야 한다. 현재 revision만 존재한다고 충돌 방지가 구현된 것으로 판단하지 않는다.

<a id="prompt-consumption"></a>

13. AI-Agent가 관심사를 실제로 사용하는 시점

현행: currentServerInterests(voiceId)로 유효 목록을 읽을 수 있으나 LLM 프롬프트 자동 주입은 없다. 조회 성공만으로 개인화된 답변이 나오는 상태가 아니다.

제안 순서: 화자 확정 → 비동기 조회 → LLM 요청을 만들기 직전에 현재 요청·voiceId·동의·기한 확인 → 준비된 목록이 있으면 이번 요청에 한 번만 사용 → 없으면 일반 응답. 관심사를 기다리기 위한 추가 대기시간은 0ms로 두며, 추론 시작 후 도착한 결과로 같은 질문을 재추론하지 않는다.

적용 지점 제안 처리
사용자 질문·제품 명령 사용자 의도와 명령 규칙이 우선. 관심사로 실행 대상·권한 변경 금지
일반 대화·추천 허용 코드에 대응하는 선호 주제로만 사용. 사실·건강 상태·계정 권한으로 해석 금지
데이터 형식 interestCodes 문자열 배열만 구조화된 참고 데이터로 전달. 닉네임이나 자유 텍스트를 시스템 지시문으로 결합하지 않음
화자 변경 A → B A snapshot을 비우고 B 조회. B 결과 없으면 일반 응답
후속 unknown 기존 화자 귀속 정책이 A 유지로 판정한 경우에만 A로 새 조회. 새 대화 unknown에는 미사용
실패·취소·만료 프롬프트에 넣지 않음. 이전 로컬 관심사로 대체하지 않음
로그 requestId·결과 상태·적용 여부·지연만 기록. 관심사 목록·임베딩·계정 토큰을 운영 로그에 기록하지 않음

이 소비 지점은 온디바이스/Cloud 요청 작성부마다 구현해야 한다. 어느 모델 경로에 적용했는지 별도로 검증하며, getter 추가만으로 모든 모델에 적용했다고 표시하지 않는다. 서버가 느려 개인화 적용률이 낮다면 측정 후 사전 조회 정책을 검토하며 무조건 TTL을 늘리지 않는다.

<a id="integration-acceptance"></a>

14. 연동 시험과 완료 판정

아래는 실행할 시험표이며 통과 결과가 아니다. 제품 제안 행은 해당 기능 구현 후 수행한다. 각 시험은 APK/서버 버전, deviceId(공유 시 마스킹), requestId, 관측 시각, 송수신 결과, 저장 상태, 화면 결과를 묶어서 기록한다. 화면 캡처만으로 서버 저장 성공을 판정하지 않는다.

ID 시험·적용 범위 기대 메시지·데이터·화면 판정 담당
VP-01 정상 등록, 현행/제품 구분 commit와 ACK, COMPLETED의 voiceId 일치. LOCAL_TEST_ACK는 제품 Cloud 통과에서 제외 AI-Agent·DeviceAgent·Backend
VP-02 최초 관심사 저장, 현행 완료 후 해당 voiceId 편집 → PUT 성공 → GET 동일 목록·revision. 다른 화자 무변경 모바일·Backend
VP-03 상시 변경·비우기, 현행 동일 API로 교체/[] 저장, 재조회 일치, 보이스 유지 모바일·Backend
VP-04 서버 재시작, 현행 저장소 저장한 관심사가 재시작 뒤 유지. 등록 작업 메모리 복구와 구분 Backend
VP-05 정상 조회, 현행 getVoicePersonalization → voicePersonalizationResult의 ID·Long·Boolean·배열 일치 AI-Agent·DeviceAgent·IoTAgent
VP-06 무응답·5초 경계, 현행 기한 직전 수락/기한 도달 후 거절. 결과 수신부터 재계산 금지 AI-Agent
VP-07 다른 화자·취소·중복 응답, 현행 B 턴에 A 결과 미사용, 취소 후 snapshot 없음, 동일 응답 1회 수락 AI-Agent
VP-08 구형 set/get, 현행 SERVER_OWNED_PERSONALIZATION, 로컬 DB 무변경. 앞단 거절은 별도 기록 AI-Agent·DeviceAgent
VP-09 Binder 단절·start 유실, 복구 제안 재연결 후 상태 조회, start 자동 중복 전송 없음, 기존 녹음 미초기화 등록 App·DeviceAgent
VP-10 등록 전달 중 재부팅, 복구 제안 보관된 작업 대조·재전달, 같은 voiceId 중복 생성 없음 DeviceAgent·IoTAgent·Backend
VP-11 삭제 중 기기 오프라인, 제품 제안 서버 사용 차단, 기기 삭제 대기 표시, 재접속 ACK 후 전체 완료 전 구간
VP-12 동의 철회·늦은 commit, 제품 제안 개인화 결과·추론 무효화, 삭제한 프로필 부활 없음 Backend·AI-Agent
VP-13 타 계정/타 기기 ID, 제품 제안 조회·수정·삭제 거절, 데이터 유출 없음 Backend·IoTAgent
VP-14 동시 수정, 제품 제안 동일 revision의 두 요청 중 충돌 감지, 409와 재선택 화면 모바일·Backend
VP-15 관심사 활용, 제품 제안 추론 직전 준비된 값만 적용; 늦으면 일반 응답, 중복 TTS 없음 AI-Agent
VP-16 시계 오차·재연결, 제품 제안 만료 검사 실패 시 개인화 미사용, 시계 정상화 후 새 요청 성공 SoC·IoTAgent·AI-Agent

출시 판정 제안: VP-01의 실제 Cloud 저장과 VP-09~16의 제품 기능을 검증하기 전에는 PoC 연동 완료와 제품 준비 완료를 구분한다. 현행 단위 테스트 통과는 실제 Binder/MQTT 왕복·전원 재부팅·음성 시험을 대체하지 않는다.

연결 문서

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