제5장 협상 메커니즘

5.1 협상 원칙

DTP 구현은 다음 협상 원칙을 강제해야 한다:

  1. 협상 우선: 어떠한 Fragment 데이터 전송 이전에도 상태가 active인 Agreement가 존재해야 한다.
  2. 무약정 전송 금지: 구현은 Agreement에 의존하지 않는 데이터 전송을 허용해서는 안 된다.
  3. 양방향 협상: 주단은 데이터 수집 협상을 발의할 수 있고, 종단은 데이터 주입 협상을 발의할 수 있다.
  4. 동적 조정: 양측은 Agreement가 active 상태일 때 매개변수를 조정할 수 있다.
  5. 명시적 종료: 양측은 Agreement를 명시적으로 종료할 수 있다. 종료 후 해당 약정 하의 데이터 전송을 즉시 중단해야 한다.

5.2 협상 프레임 유형

협상은 두 가지 프레임 유형, 즉 Request_Frame과 Response_Frame을 통해 완료해야 한다.

5.2.1 Request_Frame

Request_Frame은 다음 필드를 포함해야 한다:

interface RequestFrame {
  frameType: "request";
  requestId: string;
  requestorRole: "master" | "slave";
  requestType: "collection" | "injection" | "adjustment" | "termination";
  targetAgreementId?: AgreementID;
  proposedParams: AgreementParams;
}
필드규범적 요구사항
frameType리터럴 "request"여야 한다
requestId요청의 고유 식별자여야 한다. UUID v4를 사용해야 한다(권장)
requestorRole"master" 또는 "slave"여야 하며, 요청 발의자를 식별한다
requestType아래 표의 4가지 유형 중 하나여야 한다
targetAgreementIdrequestType"adjustment" 또는 "termination"일 때 제공해야 한다
proposedParams완전한 AgreementParams를 제공해야 한다(제5.4절 참조)

5.2.2 RequestType

의미제약
"collection"데이터 수집 요청requestorRole = "master"가 발의해야 한다
"injection"데이터 주입 신청requestorRole = "slave"가 발의해야 한다
"adjustment"기존 약정 조정targetAgreementId를 제공해야 하며, 대상 약정은 active 상태여야 한다
"termination"기존 약정 종료targetAgreementId를 제공해야 한다

구현은 위 제약을 충족하지 않는 요청을 거부하고 해당 오류를 반환해야 한다(제9장 참조).

5.2.3 Response_Frame

Response_Frame은 다음 필드를 포함해야 한다:

interface ResponseFrame {
  frameType: "response";
  requestId: string;
  result: NegotiationResult;
  agreedParams?: AgreementParams;
  agreementId?: AgreementID;
  rejectionReason?: string;
}
필드규범적 요구사항
frameType리터럴 "response"여야 한다
requestId대응하는 Request_Frame의 requestId여야 한다
resultNegotiationResult 중 하나여야 한다
agreedParamsresultaccepted 또는 counter_proposal일 때 제공해야 한다
agreementIdresultaccepted일 때 제공해야 하며, 새로 생성된 UUID v4여야 한다
rejectionReasonresultrejected일 때 제공해야 한다

5.2.4 NegotiationResult

NegotiationResult는 다음 세 값 중 하나여야 한다:

의미
"accepted"요청 수락
"rejected"요청 거부
"counter_proposal"대안 제시

구현은 나열되지 않은 결과 값을 반환해서는 안 된다.

5.3 협상 흐름

5.3.1 데이터 수집 협상(Master 발의)

데이터 수집 협상은 다음 흐름을 따라야 한다:

  1. Master가 Request_Frame을 전송한다(requestType = "collection", requestorRole = "master").
  2. Slave는 Response_Frame으로 회신해야 하며, 다음 세 결과 중 하나를 포함한다:
    • "accepted": proposedParams에 따른 전송에 동의. Response_Frame에 새로 생성된 agreementId를 포함해야 한다.
    • "rejected": 전송 거부. rejectionReason에 컴플라이언스 제약(예: DLP 정책)을 명시해야 한다. 비컴플라이언스 사유로 거부해서는 안 된다.
    • "counter_proposal": 대안 매개변수 제시. agreedParams에 수정된 매개변수를 제공해야 한다.
  3. Slave가 counter_proposal로 회신하면, Master는 새로운 Request_Frame을 전송하여 수락, 거부 또는 협상을 계속할 수 있다.
  4. Master는 Slave의 각 데이터 수집 요청에 대한 응답 결과를 영속화하여 기록해야 한다.

5.3.2 데이터 주입 협상(Slave 발의)

데이터 주입 협상은 다음 흐름을 따라야 한다:

  1. Slave가 Request_Frame을 전송한다(requestType = "injection", requestorRole = "slave").
  2. Master는 Response_Frame으로 회신해야 하며, 다음 세 결과 중 하나를 포함한다:
    • "accepted": 데이터 제공에 동의. agreedParams에 필터링된 데이터 범위(최소화 데이터셋)를 명시해야 한다. Response_Frame에 새로 생성된 agreementId를 포함해야 한다.
    • "rejected": 데이터 제공 거부. rejectionReason에 사유를 명시해야 한다(권장).
    • "counter_proposal": 다른 범위 또는 형식의 데이터 제공. agreedParams에 대안을 명시해야 한다.
  3. Master는 데이터 주입 결정에서 완전한 결정권을 가져야 하며, 요청을 강제로 수락해서는 안 된다.

5.3.3 협상 타임아웃

구현은 Request_Frame에 대한 타임아웃 임곗값을 설정해야 한다. 임곗값 내에 상대측의 Response_Frame을 받지 못하면:

  1. 요청측은 Request_Frame을 재전송해야 하며(권장), 재시도 횟수는 구현이 설정한 상한을 초과해서는 안 된다.
  2. 재시도 상한에 도달하면 요청측은 협상을 종료하고 상위 애플리케이션에 AGREEMENT_NEGOTIATION_FAILED 오류(3003)를 통지해야 한다.

5.4 약정 매개변수(AgreementParams)

AgreementParams는 다음 필드를 포함해야 한다:

interface AgreementParams {
  dataType: string;
  dataRange: string;
  transferMode: TransferMode;
  frequency: number | null;
  validityPeriod: number;
  priority: Priority;
}
필드타입규범적 요구사항
dataTypestring비어 있지 않아야 한다. 데이터 유형을 식별
dataRangestring비어 있지 않아야 한다. 데이터 범위를 설명
transferModeTransferMode아래 표의 3가지 값 중 하나여야 한다
frequencynumber | null단위 Hz. transferMode = "one_time"일 때 null이어야 하며, 다른 모드에서는 양수여야 한다
validityPeriodnumber단위 밀리초. 양의 정수여야 한다
priorityPriority아래 표의 4가지 값 중 하나여야 한다

5.4.1 TransferMode

의미
"one_time"일회성 전송. 데이터 전송이 완료되면 Agreement는 자동으로 종료되어야 한다(권장)
"periodic"주기적 전송. frequency를 설정해야 한다
"streaming"스트리밍 전송. frequency를 설정해야 한다

5.4.2 Priority

의미
"low"낮은 우선순위
"normal"보통 우선순위(기본값)
"high"높은 우선순위
"critical"긴급 우선순위

구현은 여러 약정이 자원을 경쟁할 때 priority에 따라 스케줄링해야 한다(권장).

5.5 약정 생명주기

5.5.1 상태 정의

AgreementStatus는 다음 4가지 값 중 하나여야 한다:

상태의미
"negotiating"협상 진행 중
"active"약정 발효, 데이터 전송 중
"suspended"연결 중단, 약정 일시 중지
"terminated"약정 종료

5.5.2 상태 전이

약정 상태는 다음 전이 규칙을 따라야 한다:

현재 상태트리거 이벤트목표 상태
(없음)Request_Frame 발송negotiating
negotiatingResponse_Frame이 accepted 반환active
negotiatingResponse_Frame이 rejected 반환(종료)
active하위 연결 단절suspended
activetermination 유형 Request_Frame 수신terminated
activevalidityPeriod 타임아웃terminated
suspended연결 회복 및 CAP 재검증 통과active
suspended영속화 타임아웃terminated
terminated(종료 상태)(없음)

5.5.3 일회성 약정의 자동 종료

transferMode = "one_time"이며 데이터 전송이 완료되면:

  1. 송신측은 마지막 Fragment 이후에 requestType = "termination"인 Request_Frame을 통해 해당 약정을 종료해야 한다.
  2. 수신측은 모든 Fragment를 수신하고 확인한 후 약정 상태를 terminated로 설정해야 한다.

5.6 다중 약정 동시성

DTP 구현은 단일 세션 내에서 active 상태의 여러 약정을 동시에 유지하는 것을 지원해야 한다.

구현은 다음을 충족해야 한다:

  1. 각 Fragment는 자신의 Agreement_ID를 통해 구체적인 약정에 연결된다.
  2. 서로 다른 약정의 Fragment는 전송 스트림에서 교차될 수 있다.
  3. 다중 약정의 실제 전송 방식(직렬 또는 병렬)은 하위 Transport_Adapter의 능력에 따라 결정된다.
  4. 구현은 단일 세션 내 활성 약정의 최대 개수를 16개 미만으로 제한해서는 안 된다. 임의 개수를 지원해야 한다(권장).

5.7 관찰자 협상 제약

관찰자(Observer) 역할은 다음을 충족해야 한다:

  1. Request_Frame을 전송해서는 안 된다. 전송을 시도하면 DTP_Engine은 해당 작업을 거부하고 OBSERVER_WRITE_DENIED 오류(8002)를 반환해야 한다.
  2. 어떠한 Response_Frame의 결정 권한도 받아서는 안 된다.
  3. 데이터 프레임의 읽기 전용 사본은 받을 수 있다.
  4. 관찰에 참여할 때 제어자에 의해 명시적으로 권한이 부여되어야 한다.