제3장
WIA-SOCIAL 공공문서 API는 REST (Representational State Transfer) 아키텍처 스타일을 따릅니다. RESTful API는 간단하고 직관적이며 HTTP 프로토콜의 표준 메서드를 활용하여 리소스를 관리합니다. 공공문서 시스템에서 리소스는 문서, 사용자, 발급 기관, 검증 요청 등입니다.
| 원칙 | 설명 | 공공문서 적용 예시 |
|---|---|---|
| 클라이언트-서버 분리 | 클라이언트와 서버의 독립적 진화 | 모바일 앱, 웹 포털이 동일한 API 사용 |
| 무상태성 | 각 요청은 독립적이며 필요한 모든 정보 포함 | JWT 토큰 기반 인증, 세션 상태 없음 |
| 캐시 가능성 | 응답은 캐시 가능 여부를 명시 | 공개 문서는 CDN 캐싱, 민감 문서는 캐시 금지 |
| 계층화 시스템 | 클라이언트는 중간 계층 인식 불필요 | 로드 밸런서, API 게이트웨이, 방화벽 투명 적용 |
| 통일된 인터페이스 | 일관된 URL 패턴과 HTTP 메서드 사용 | /documents/{id}, GET/POST/PUT/DELETE |
| 주문형 코드 (선택) | 서버가 클라이언트에 실행 코드 전송 가능 | 문서 뷰어 JavaScript 플러그인 |
WIA-SOCIAL API는 리소스 중심의 URL 구조를 사용하며, 명사를 사용하여 리소스를 표현하고 HTTP 메서드로 작업을 정의합니다.
BASE_URL: https://api.wia-social.org/v1
# 문서 관리
GET /documents # 문서 목록 조회
POST /documents # 새 문서 생성
GET /documents/{documentId} # 특정 문서 조회
PUT /documents/{documentId} # 문서 업데이트
DELETE /documents/{documentId} # 문서 삭제 (soft delete)
GET /documents/{documentId}/pdf # PDF 다운로드
GET /documents/{documentId}/qr # QR 코드 생성
# 문서 검증
POST /documents/{documentId}/verify # 문서 진위 검증
GET /documents/{documentId}/verification-log # 검증 이력 조회
POST /documents/verify-qr # QR 코드로 검증
# 문서 유형별 특화 엔드포인트
POST /documents/birth-certificates # 출생증명서 발급
POST /documents/drivers-licenses # 운전면허증 발급
POST /documents/passports # 여권 발급
# 사용자 관리
GET /users/{userId}/documents # 사용자의 문서 목록
POST /users/{userId}/documents/share # 문서 공유
GET /users/{userId}/shared-with-me # 나와 공유된 문서
# 발급 기관
GET /authorities # 발급 기관 목록
GET /authorities/{authorityId} # 특정 기관 정보
GET /authorities/{authorityId}/stats # 기관 통계
# 인증 및 권한
POST /auth/login # 로그인
POST /auth/logout # 로그아웃
POST /auth/refresh # 토큰 갱신
GET /auth/profile # 사용자 프로필
# 검색 및 필터링
GET /search?q={query}&type={type} # 문서 검색
GET /documents?status=active&sort=date # 필터링 및 정렬
| 메서드 | 용도 | 멱등성 | 예시 |
|---|---|---|---|
| GET | 리소스 조회 | ✓ | GET /documents/123 |
| POST | 새 리소스 생성 | ✗ | POST /documents (새 문서 발급) |
| PUT | 리소스 전체 업데이트 | ✓ | PUT /documents/123 (전체 교체) |
| PATCH | 리소스 부분 업데이트 | ✗ | PATCH /documents/123 (일부 수정) |
| DELETE | 리소스 삭제 | ✓ | DELETE /documents/123 |
| HEAD | 헤더만 조회 | ✓ | HEAD /documents/123 (존재 확인) |
| OPTIONS | 지원 메서드 조회 | ✓ | OPTIONS /documents (CORS) |
| 코드 | 의미 | 사용 시나리오 |
|---|---|---|
| 200 OK | 성공 | GET, PUT, PATCH 성공 |
| 201 Created | 생성 성공 | POST로 새 문서 발급 성공 |
| 204 No Content | 성공, 응답 본문 없음 | DELETE 성공 |
| 400 Bad Request | 잘못된 요청 | 유효성 검증 실패, 필수 필드 누락 |
| 401 Unauthorized | 인증 실패 | 토큰 없음 또는 만료 |
| 403 Forbidden | 권한 없음 | 타인의 문서 접근 시도 |
| 404 Not Found | 리소스 없음 | 존재하지 않는 문서 ID |
| 409 Conflict | 충돌 | 중복 문서 발급 시도 |
| 429 Too Many Requests | 속도 제한 초과 | API 호출 한도 초과 |
| 500 Internal Server Error | 서버 오류 | 예기치 않은 서버 에러 |
공공문서 API는 OAuth 2.0 및 JWT (JSON Web Token) 기반 인증을 사용합니다. 민감한 개인 정보를 다루므로 강력한 인증과 세분화된 권한 관리가 필수적입니다.
// JWT Header
{
"alg": "RS256",
"typ": "JWT",
"kid": "wia-key-2025-01"
}
// JWT Payload
{
"sub": "user-123456789",
"name": "홍길동",
"email": "hong@example.com",
"role": "CITIZEN",
"permissions": [
"documents:read:own",
"documents:create:birth-certificate",
"documents:share:own"
],
"authority": null,
"iat": 1705301400,
"exp": 1705387800,
"iss": "https://auth.wia-social.org",
"aud": "https://api.wia-social.org"
}
// JWT Signature
RSASHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
privateKey
)
| 역할 | 권한 | 설명 |
|---|---|---|
| CITIZEN | 자신의 문서 조회, 공유 요청 | 일반 시민 |
| OFFICER | 문서 발급, 수정, 검증 | 정부 기관 담당자 |
| SUPERVISOR | 문서 승인, 감사 로그 조회 | 부서장급 |
| ADMIN | 시스템 관리, 사용자 관리 | 시스템 관리자 |
| AUDITOR | 읽기 전용 전체 접근, 로그 분석 | 감사관 |
| VERIFIER | 문서 검증만 가능 | 제3자 검증 기관 |
API 남용 방지와 공정한 리소스 분배를 위해 속도 제한을 적용합니다. WIA-SOCIAL은 Token Bucket 알고리즘을 사용하여 유연하고 효율적인 속도 제한을 구현합니다.
HTTP/1.1 200 OK
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 987
X-RateLimit-Reset: 1705305000
X-RateLimit-Resource: documents
X-RateLimit-Used: 13
# 한도 초과 시
HTTP/1.1 429 Too Many Requests
Retry-After: 3600
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1705305000
{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "시간당 요청 한도를 초과했습니다. 1시간 후 다시 시도하세요.",
"details": {
"limit": 1000,
"remaining": 0,
"resetAt": "2025-01-15T10:30:00Z"
}
}
}
API는 요구사항이 변경되고 새로운 기능이 추가됨에 따라 시간이 지남에 따라 진화합니다. 버전 관리 전략은 기존 클라이언트에 대한 중단을 최소화하면서 이러한 진화를 관리합니다.
WIA-SOCIAL 표준은 URL 경로에 주요 버전 번호를 포함하는 것을 권장합니다(/api/v1/, /api/v2/). 이 접근 방식은 버전을 명시적이고 쉽게 검색할 수 있게 만듭니다. 다른 버전은 독립적으로 배포하고 확장할 수 있습니다. 클라이언트는 자신의 속도에 맞춰 새 버전으로 업그레이드할 수 있습니다. 더 이상 사용되지 않는 버전은 명확한 일정으로 단계적으로 폐지될 수 있습니다.
주요 버전 내에서 변경 사항은 하위 호환되어야 합니다. 선택적 필드 추가는 안전합니다. 새 엔드포인트 추가는 안전합니다. 유효성 검사 완화는 안전합니다. 그러나 필드 제거, 유효성 검사 강화, 응답 형식 변경 또는 의미 변경은 호환성을 깨뜨리며 새로운 주요 버전이 필요합니다. 신중한 API 설계는 주요 변경 사항을 최소화하여 주요 버전 증가 빈도를 줄입니다.
중단 변경 사항을 도입할 때 이전 버전은 전환 기간(일반적으로 정부 API의 경우 12-24개월) 동안 사용 가능한 상태로 유지되어야 합니다. 폐기 경고는 응답 헤더, 문서 및 개발자 커뮤니케이션에 나타납니다. 폐기 기간 동안 두 버전이 병렬로 작동합니다. 마감일 이후에는 이전 버전이 종료됩니다. 중요한 보안 수정 사항은 전환 기간 동안 더 이상 사용되지 않는 버전으로 백포트될 수 있습니다.
v1.0 출시: 2023-01-01
- 초기 릴리스
v1.1 출시: 2023-06-01
- 백신 접종 증명서 지원 추가 (하위 호환)
- /api/v1/documents/{id}/qr-code 엔드포인트 추가
v2.0 출시: 2024-01-01
- OAuth 2.0으로 인증 변경 (중단 변경)
- 오류 응답 재구성 (중단 변경)
- v1 폐기 시작 (12개월 전환 기간)
v2.1 출시: 2024-06-01
- 생체 인식 데이터 엔드포인트 추가 (하위 호환)
v1.0 종료: 2025-01-01
- v1 API 더 이상 사용 불가
- 모든 클라이언트는 v2+ 사용 필수
대량의 문서 데이터를 효율적으로 조회하기 위해 커서 기반 페이지네이션과 다양한 필터링 옵션을 제공합니다.
# Offset-based Pagination (간단하지만 대용량 데이터에 비효율적)
GET /documents?limit=20&offset=0
GET /documents?limit=20&offset=20
# Cursor-based Pagination (권장)
GET /documents?limit=20
# 응답에 nextCursor 포함
{
"data": [...],
"pagination": {
"nextCursor": "eyJpZCI6MTIzLCJjcmVhdGVkQXQiOiIyMDI1LTAxLTE1In0=",
"prevCursor": null,
"hasMore": true
}
}
# 다음 페이지
GET /documents?limit=20&cursor=eyJpZCI6MTIzLCJjcmVhdGVkQXQiOiIyMDI1LTAxLTE1In0=
# 필터링 및 정렬
GET /documents?type=BIRTH_CERTIFICATE&status=ACTIVE&sort=-createdAt&limit=50
# 날짜 범위 필터
GET /documents?fromDate=2025-01-01&toDate=2025-01-31
# 복합 쿼리
GET /documents?q=홍길동&type=PASSPORT&status=ACTIVE&sort=-issueDate
일관된 오류 응답 형식은 클라이언트의 오류 처리를 간소화합니다. WIA-SOCIAL은 RFC 7807 (Problem Details for HTTP APIs) 표준을 따릅니다.
{
"type": "https://api.wia-social.org/errors/validation-error",
"title": "입력 데이터 검증 실패",
"status": 400,
"detail": "필수 필드가 누락되었거나 형식이 올바르지 않습니다.",
"instance": "/documents/birth-certificates",
"timestamp": "2025-01-15T10:30:00Z",
"errors": [
{
"field": "dateOfBirth",
"message": "생년월일은 필수 항목입니다.",
"code": "REQUIRED_FIELD_MISSING"
},
{
"field": "fullName",
"message": "이름은 최소 2자 이상이어야 합니다.",
"code": "MIN_LENGTH_VIOLATION",
"value": "홍",
"constraint": { "minLength": 2 }
}
],
"traceId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
| 오류 코드 | HTTP 상태 | 설명 |
|---|---|---|
| VALIDATION_ERROR | 400 | 입력 데이터 검증 실패 |
| AUTHENTICATION_FAILED | 401 | 인증 실패 또는 토큰 만료 |
| PERMISSION_DENIED | 403 | 접근 권한 없음 |
| RESOURCE_NOT_FOUND | 404 | 요청한 리소스가 존재하지 않음 |
| DOCUMENT_ALREADY_EXISTS | 409 | 중복 문서 발급 시도 |
| RATE_LIMIT_EXCEEDED | 429 | API 호출 한도 초과 |
| INTERNAL_SERVER_ERROR | 500 | 서버 내부 오류 |
효과적인 캐싱은 API 성능을 극적으로 향상시키고 서버 부하를 줄입니다. HTTP는 API가 적절한 헤더와 설계 패턴을 통해 활용해야 하는 내장 캐싱 메커니즘을 제공합니다.
Cache-Control 헤더는 캐싱 정책을 지정합니다. 공개(public) 콘텐츠는 모든 중간 프록시에서 캐시될 수 있습니다. 개인(private) 콘텐츠는 클라이언트 브라우저에서만 캐시되어야 합니다. Max-age는 콘텐츠가 신선한 상태로 유지되는 기간을 지정합니다. No-cache는 캐시된 콘텐츠를 사용하기 전에 재검증을 요구합니다. No-store는 민감한 데이터에 대한 캐싱을 완전히 금지합니다.
ETag(엔티티 태그)는 조건부 요청을 가능하게 합니다. 서버는 응답에 해시 또는 버전 식별자를 포함하는 ETag 헤더를 포함합니다. 클라이언트는 후속 요청에서 ETag와 함께 If-None-Match 헤더를 포함합니다. 리소스가 변경되지 않은 경우 서버는 본문 없이 304 Not Modified를 반환하여 대역폭을 절약합니다. Last-Modified 및 If-Modified-Since 헤더는 타임스탬프를 사용하여 유사한 기능을 제공합니다.
서로 다른 리소스는 서로 다른 캐싱 특성을 가집니다. 문서 콘텐츠는 발급 후 거의 변경되지 않으므로 공격적인 캐싱(몇 시간 또는 며칠)을 허용합니다. 문서 상태는 변경될 수 있으므로(해지) 더 짧은 캐시 시간(몇 분)이 필요합니다. 실시간 검증은 캐시를 완전히 우회해야 합니다. API는 변경 빈도 및 일관성 요구 사항에 따라 적절한 캐시 기간을 설정해야 합니다.
WIA-SOCIAL API는 RESTful 원칙을 준수하며, 명확한 엔드포인트 구조, 강력한 인증 및 권한 관리, 효율적인 속도 제한, 표준화된 오류 처리를 제공합니다. 이러한 설계는 개발자가 쉽게 이해하고 통합할 수 있는 API를 만들며, 동시에 보안과 성능을 보장합니다. 다음 장에서는 이 API를 실제로 구현하는 방법을 TypeScript, Python, Java 예제와 함께 살펴보겠습니다.