5.1 Phase 2 개요
Phase 2는 표준화된 데이터 형식(Phase 1)을 프로그래밍 방식으로 처리할 수 있는 API 인터페이스를 제공합니다. REST 및 GraphQL 엔드포인트를 통해 삭제 요청의 제출, 추적, 관리를 자동화합니다.
Phase 2의 이점
- 자동화: 수동 프로세스 제거, 대량 요청 처리
- 실시간 추적: 요청 상태를 실시간으로 확인
- 통합 용이성: 기존 시스템과 쉽게 통합
- 확장성: 수천 개의 요청도 효율적으로 처리
- 콜백 지원: 완료 시 자동 알림
API 아키텍처
WIA-LEG-009 API는 RESTful 원칙을 따르며, 선택적으로 GraphQL도 지원합니다:
- Base URL:
https://api.example.com/wia/rtbf/v1 - 인증: OAuth 2.0, API Key, JWT
- 형식: JSON (Content-Type: application/json)
- 버전 관리: URL 경로에 버전 포함 (/v1, /v2 등)
5.2 인증 및 권한
API Key 인증
가장 간단한 인증 방식. 요청 헤더에 API 키를 포함:
GET /wia/rtbf/v1/requests
Authorization: Bearer wia_api_key_abc123def456
Content-Type: application/json
OAuth 2.0 인증
더 안전한 인증 방식. Client Credentials Flow 권장:
POST /oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
&client_id=your_client_id
&client_secret=your_client_secret
&scope=rtbf:read rtbf:write
Response:
{
"access_token": "eyJhbGciOiJSUzI1NiIs...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "rtbf:read rtbf:write"
}
권한 스코프
| 스코프 | 권한 |
|---|---|
rtbf:read |
요청 조회 및 상태 확인 |
rtbf:write |
요청 생성 및 수정 |
rtbf:delete |
요청 취소 및 삭제 |
rtbf:admin |
모든 작업 (관리자) |
5.3 핵심 REST 엔드포인트
목적: 새로운 삭제 요청 생성
인증: 필수 (OAuth 2.0 또는 API Key)
요청 본문:
{
"wia_standard": "WIA-LEG-009",
"version": "1.0",
"request_type": "deletion",
"data_subject": {
"email": "user@example.com",
"identifiers": [
{"type": "user_id", "value": "12345"}
]
},
"legal_basis": "GDPR_Article_17_1a",
"scope": {
"data_categories": ["personal_data"],
"include_backups": true
},
"callback_url": "https://your-app.com/rtbf/callback"
}
응답:
202 Accepted
{
"request_id": "rtbf_20250101_abc123",
"status": "pending_verification",
"created_at": "2025-01-01T10:30:00Z",
"estimated_completion": "2025-01-30T23:59:59Z",
"verification": {
"method": "email_otp",
"expires_at": "2025-01-01T11:00:00Z"
},
"links": {
"self": "/wia/rtbf/v1/requests/rtbf_20250101_abc123",
"verify": "/wia/rtbf/v1/requests/rtbf_20250101_abc123/verify"
}
}
목적: 특정 요청의 상태 조회
응답:
200 OK
{
"request_id": "rtbf_20250101_abc123",
"status": "processing",
"created_at": "2025-01-01T10:30:00Z",
"verified_at": "2025-01-01T10:35:00Z",
"progress": {
"total_systems": 5,
"completed_systems": 2,
"percentage": 40
},
"timeline": [
{
"event": "request_created",
"timestamp": "2025-01-01T10:30:00Z"
},
{
"event": "identity_verified",
"timestamp": "2025-01-01T10:35:00Z"
},
{
"event": "deletion_started",
"timestamp": "2025-01-01T11:00:00Z",
"system": "customer_database"
}
]
}
목적: 신원 확인 코드 제출
요청 본문:
{
"verification_code": "123456",
"method": "email_otp"
}
응답:
200 OK
{
"verified": true,
"message": "Identity verified successfully",
"next_status": "processing"
}
목적: 모든 요청 목록 조회 (페이지네이션)
쿼리 파라미터:
page: 페이지 번호 (기본값: 1)limit: 페이지당 항목 수 (기본값: 20, 최대: 100)status: 상태 필터 (pending, processing, completed, failed)email: 데이터 주체 이메일 필터from_date: 시작 날짜 (ISO 8601)to_date: 종료 날짜 (ISO 8601)
응답:
200 OK
{
"requests": [...],
"pagination": {
"page": 1,
"limit": 20,
"total": 150,
"total_pages": 8
}
}
목적: 요청 취소 (처리 전에만 가능)
응답:
200 OK
{
"message": "Request cancelled successfully",
"request_id": "rtbf_20250101_abc123",
"status": "cancelled"
}
목적: 삭제 완료 증명서 다운로드
응답:
200 OK
Content-Type: application/pdf
[PDF 바이너리 데이터]
5.4 요청 상태 머신
요청은 다음 상태를 거쳐 진행됩니다:
┌────────────────┐
│ created │ ← 요청 생성
└────────┬───────┘
│
▼
┌────────────────┐
│ pending_ │ ← 신원 확인 대기
│ verification │
└────────┬───────┘
│
▼
┌────────────────┐
│ verified │ ← 신원 확인 완료
└────────┬───────┘
│
▼
┌────────────────┐
│ legal_review │ ← 법적 검토 (예외 사항 확인)
└────────┬───────┘
│
├──────────────────┐
│ │
▼ ▼
┌────────────────┐ ┌──────────────┐
│ processing │ │ rejected │ ← 법적 사유로 거부
└────────┬───────┘ └──────────────┘
│
▼
┌────────────────┐
│ completed │ ← 삭제 완료
└────────────────┘
또는
┌────────────────┐
│ failed │ ← 기술적 오류로 실패
└────────────────┘
또는
┌────────────────┐
│ cancelled │ ← 사용자가 취소
└────────────────┘
상태 설명
| 상태 | 설명 | 다음 가능 상태 |
|---|---|---|
created |
요청이 생성됨 | pending_verification, cancelled |
pending_verification |
신원 확인 대기 중 | verified, cancelled |
verified |
신원 확인 완료 | legal_review |
legal_review |
법적 검토 진행 중 | processing, rejected |
processing |
삭제 작업 진행 중 | completed, failed |
completed |
삭제 완료 | (종료 상태) |
rejected |
법적 사유로 거부됨 | (종료 상태) |
failed |
기술적 오류로 실패 | processing (재시도) |
cancelled |
사용자가 취소함 | (종료 상태) |
5.5 Webhook 콜백
비동기 처리를 위해 요청 생성 시 callback_url을 제공하면,
상태 변경 시 자동으로 알림을 받을 수 있습니다.
콜백 페이로드
POST https://your-app.com/rtbf/callback
Content-Type: application/json
X-WIA-Signature: sha256=abc123... (HMAC 서명)
{
"event": "request.completed",
"timestamp": "2025-01-30T15:30:00Z",
"data": {
"request_id": "rtbf_20250101_abc123",
"status": "completed",
"completion_details": {
"systems_processed": 5,
"records_deleted": 1523,
"backups_cleaned": 3
}
}
}
콜백 이벤트
request.created: 요청 생성됨request.verified: 신원 확인됨request.processing: 처리 시작됨request.completed: 삭제 완료됨request.failed: 실패함request.rejected: 거부됨
서명 검증 (보안)
import crypto from 'crypto';
function verifyWebhookSignature(payload, signature, secret) {
const hmac = crypto.createHmac('sha256', secret);
const digest = 'sha256=' + hmac.update(payload).digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(digest)
);
}
5.6 GraphQL API (선택 사항)
REST API 외에도 더 유연한 쿼리를 위해 GraphQL을 지원할 수 있습니다.
GraphQL 스키마
type Query {
rtbfRequest(id: ID!): RTBFRequest
rtbfRequests(
page: Int = 1
limit: Int = 20
status: RTBFStatus
email: String
): RTBFRequestConnection
}
type Mutation {
createRTBFRequest(input: CreateRTBFRequestInput!): RTBFRequest
verifyRTBFRequest(id: ID!, code: String!): RTBFRequest
cancelRTBFRequest(id: ID!): RTBFRequest
}
type RTBFRequest {
id: ID!
status: RTBFStatus!
createdAt: DateTime!
dataSubject: DataSubject!
progress: Progress
timeline: [TimelineEvent!]!
}
enum RTBFStatus {
CREATED
PENDING_VERIFICATION
VERIFIED
LEGAL_REVIEW
PROCESSING
COMPLETED
REJECTED
FAILED
CANCELLED
}
쿼리 예시
query GetRequestDetails {
rtbfRequest(id: "rtbf_20250101_abc123") {
id
status
createdAt
dataSubject {
email
}
progress {
totalSystems
completedSystems
percentage
}
timeline {
event
timestamp
system
}
}
}
뮤테이션 예시
mutation CreateRequest {
createRTBFRequest(input: {
requestType: DELETION
dataSubject: {
email: "user@example.com"
identifiers: [
{type: "user_id", value: "12345"}
]
}
legalBasis: "GDPR_Article_17_1a"
scope: {
dataCategories: ["personal_data"]
includeBackups: true
}
}) {
id
status
}
}
5.7 에러 처리
표준 에러 응답
400 Bad Request
{
"error": {
"code": "INVALID_REQUEST",
"message": "The request is missing required fields",
"details": [
{
"field": "data_subject.email",
"issue": "Required field is missing"
}
],
"documentation_url": "https://docs.wia.org/rtbf/errors#INVALID_REQUEST"
}
}
에러 코드
| HTTP | 코드 | 설명 |
|---|---|---|
| 400 | INVALID_REQUEST |
요청 형식 오류 |
| 401 | UNAUTHORIZED |
인증 실패 |
| 403 | FORBIDDEN |
권한 없음 |
| 404 | NOT_FOUND |
요청을 찾을 수 없음 |
| 409 | DUPLICATE_REQUEST |
중복 요청 |
| 422 | VALIDATION_ERROR |
검증 실패 |
| 429 | RATE_LIMIT_EXCEEDED |
요청 한도 초과 |
| 500 | INTERNAL_ERROR |
서버 오류 |
| 503 | SERVICE_UNAVAILABLE |
일시적 서비스 중단 |
5.8 SDK 및 클라이언트 라이브러리
TypeScript/JavaScript SDK
import { WIARTBFClient } from '@wia/rtbf-sdk';
const client = new WIARTBFClient({
apiKey: 'wia_api_key_abc123',
baseUrl: 'https://api.example.com/wia/rtbf/v1'
});
// 요청 생성
const request = await client.createRequest({
requestType: 'deletion',
dataSubject: {
email: 'user@example.com',
identifiers: [{ type: 'user_id', value: '12345' }]
},
legalBasis: 'GDPR_Article_17_1a',
scope: {
dataCategories: ['personal_data'],
includeBackups: true
}
});
console.log(`Request created: ${request.id}`);
// 상태 확인
const status = await client.getRequest(request.id);
console.log(`Status: ${status.status}`);
Python SDK
from wia_rtbf import RTBFClient
client = RTBFClient(
api_key='wia_api_key_abc123',
base_url='https://api.example.com/wia/rtbf/v1'
)
# 요청 생성
request = client.create_request(
request_type='deletion',
data_subject={
'email': 'user@example.com',
'identifiers': [{'type': 'user_id', 'value': '12345'}]
},
legal_basis='GDPR_Article_17_1a',
scope={
'data_categories': ['personal_data'],
'include_backups': True
}
)
print(f'Request created: {request.id}')
# 상태 확인
status = client.get_request(request.id)
print(f'Status: {status.status}')
5.9 다음 단계
이 장에서는 WIA-LEG-009 Phase 2의 API 인터페이스를 상세히 살펴보았습니다. 다음 장에서는 블록체인을 사용한 암호학적 삭제 검증인 Phase 3를 다룹니다.