SPECIFICATION
제5장 협상 메커니즘
5.1 협상 원칙
DTP 구현은 다음 협상 원칙을 강제해야 한다:
- 협상 우선: 어떠한 Fragment 데이터 전송 이전에도 상태가
active인 Agreement가 존재해야 한다. - 무약정 전송 금지: 구현은 Agreement에 의존하지 않는 데이터 전송을 허용해서는 안 된다.
- 양방향 협상: 주단은 데이터 수집 협상을 발의할 수 있고, 종단은 데이터 주입 협상을 발의할 수 있다.
- 동적 조정: 양측은 Agreement가
active상태일 때 매개변수를 조정할 수 있다. - 명시적 종료: 양측은 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가지 유형 중 하나여야 한다 |
targetAgreementId | requestType이 "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여야 한다 |
result | NegotiationResult 중 하나여야 한다 |
agreedParams | result가 accepted 또는 counter_proposal일 때 제공해야 한다 |
agreementId | result가 accepted일 때 제공해야 하며, 새로 생성된 UUID v4여야 한다 |
rejectionReason | result가 rejected일 때 제공해야 한다 |
5.2.4 NegotiationResult
NegotiationResult는 다음 세 값 중 하나여야 한다:
| 값 | 의미 |
|---|---|
"accepted" | 요청 수락 |
"rejected" | 요청 거부 |
"counter_proposal" | 대안 제시 |
구현은 나열되지 않은 결과 값을 반환해서는 안 된다.
5.3 협상 흐름
5.3.1 데이터 수집 협상(Master 발의)
데이터 수집 협상은 다음 흐름을 따라야 한다:
- Master가 Request_Frame을 전송한다(
requestType = "collection",requestorRole = "master"). - Slave는 Response_Frame으로 회신해야 하며, 다음 세 결과 중 하나를 포함한다:
"accepted":proposedParams에 따른 전송에 동의. Response_Frame에 새로 생성된agreementId를 포함해야 한다."rejected": 전송 거부.rejectionReason에 컴플라이언스 제약(예: DLP 정책)을 명시해야 한다. 비컴플라이언스 사유로 거부해서는 안 된다."counter_proposal": 대안 매개변수 제시.agreedParams에 수정된 매개변수를 제공해야 한다.
- Slave가
counter_proposal로 회신하면, Master는 새로운 Request_Frame을 전송하여 수락, 거부 또는 협상을 계속할 수 있다. - Master는 Slave의 각 데이터 수집 요청에 대한 응답 결과를 영속화하여 기록해야 한다.
5.3.2 데이터 주입 협상(Slave 발의)
데이터 주입 협상은 다음 흐름을 따라야 한다:
- Slave가 Request_Frame을 전송한다(
requestType = "injection",requestorRole = "slave"). - Master는 Response_Frame으로 회신해야 하며, 다음 세 결과 중 하나를 포함한다:
"accepted": 데이터 제공에 동의.agreedParams에 필터링된 데이터 범위(최소화 데이터셋)를 명시해야 한다. Response_Frame에 새로 생성된agreementId를 포함해야 한다."rejected": 데이터 제공 거부.rejectionReason에 사유를 명시해야 한다(권장)."counter_proposal": 다른 범위 또는 형식의 데이터 제공.agreedParams에 대안을 명시해야 한다.
- Master는 데이터 주입 결정에서 완전한 결정권을 가져야 하며, 요청을 강제로 수락해서는 안 된다.
5.3.3 협상 타임아웃
구현은 Request_Frame에 대한 타임아웃 임곗값을 설정해야 한다. 임곗값 내에 상대측의 Response_Frame을 받지 못하면:
- 요청측은 Request_Frame을 재전송해야 하며(권장), 재시도 횟수는 구현이 설정한 상한을 초과해서는 안 된다.
- 재시도 상한에 도달하면 요청측은 협상을 종료하고 상위 애플리케이션에
AGREEMENT_NEGOTIATION_FAILED오류(3003)를 통지해야 한다.
5.4 약정 매개변수(AgreementParams)
AgreementParams는 다음 필드를 포함해야 한다:
interface AgreementParams {
dataType: string;
dataRange: string;
transferMode: TransferMode;
frequency: number | null;
validityPeriod: number;
priority: Priority;
}
| 필드 | 타입 | 규범적 요구사항 |
|---|---|---|
dataType | string | 비어 있지 않아야 한다. 데이터 유형을 식별 |
dataRange | string | 비어 있지 않아야 한다. 데이터 범위를 설명 |
transferMode | TransferMode | 아래 표의 3가지 값 중 하나여야 한다 |
frequency | number | null | 단위 Hz. transferMode = "one_time"일 때 null이어야 하며, 다른 모드에서는 양수여야 한다 |
validityPeriod | number | 단위 밀리초. 양의 정수여야 한다 |
priority | Priority | 아래 표의 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 |
negotiating | Response_Frame이 accepted 반환 | active |
negotiating | Response_Frame이 rejected 반환 | (종료) |
active | 하위 연결 단절 | suspended |
active | termination 유형 Request_Frame 수신 | terminated |
active | validityPeriod 타임아웃 | terminated |
suspended | 연결 회복 및 CAP 재검증 통과 | active |
suspended | 영속화 타임아웃 | terminated |
terminated | (종료 상태) | (없음) |
5.5.3 일회성 약정의 자동 종료
transferMode = "one_time"이며 데이터 전송이 완료되면:
- 송신측은 마지막 Fragment 이후에
requestType = "termination"인 Request_Frame을 통해 해당 약정을 종료해야 한다. - 수신측은 모든 Fragment를 수신하고 확인한 후 약정 상태를
terminated로 설정해야 한다.
5.6 다중 약정 동시성
DTP 구현은 단일 세션 내에서 active 상태의 여러 약정을 동시에 유지하는 것을 지원해야 한다.
구현은 다음을 충족해야 한다:
- 각 Fragment는 자신의 Agreement_ID를 통해 구체적인 약정에 연결된다.
- 서로 다른 약정의 Fragment는 전송 스트림에서 교차될 수 있다.
- 다중 약정의 실제 전송 방식(직렬 또는 병렬)은 하위 Transport_Adapter의 능력에 따라 결정된다.
- 구현은 단일 세션 내 활성 약정의 최대 개수를 16개 미만으로 제한해서는 안 된다. 임의 개수를 지원해야 한다(권장).
5.7 관찰자 협상 제약
관찰자(Observer) 역할은 다음을 충족해야 한다:
- Request_Frame을 전송해서는 안 된다. 전송을 시도하면 DTP_Engine은 해당 작업을 거부하고
OBSERVER_WRITE_DENIED오류(8002)를 반환해야 한다. - 어떠한 Response_Frame의 결정 권한도 받아서는 안 된다.
- 데이터 프레임의 읽기 전용 사본은 받을 수 있다.
- 관찰에 참여할 때 제어자에 의해 명시적으로 권한이 부여되어야 한다.
