제3장

API 개요 및 아키텍처

3.1 RESTful API 설계 원칙

WIA-SOCIAL 공공문서 API는 REST (Representational State Transfer) 아키텍처 스타일을 따릅니다. RESTful API는 간단하고 직관적이며 HTTP 프로토콜의 표준 메서드를 활용하여 리소스를 관리합니다. 공공문서 시스템에서 리소스는 문서, 사용자, 발급 기관, 검증 요청 등입니다.

REST 설계 원칙

원칙 설명 공공문서 적용 예시
클라이언트-서버 분리 클라이언트와 서버의 독립적 진화 모바일 앱, 웹 포털이 동일한 API 사용
무상태성 각 요청은 독립적이며 필요한 모든 정보 포함 JWT 토큰 기반 인증, 세션 상태 없음
캐시 가능성 응답은 캐시 가능 여부를 명시 공개 문서는 CDN 캐싱, 민감 문서는 캐시 금지
계층화 시스템 클라이언트는 중간 계층 인식 불필요 로드 밸런서, API 게이트웨이, 방화벽 투명 적용
통일된 인터페이스 일관된 URL 패턴과 HTTP 메서드 사용 /documents/{id}, GET/POST/PUT/DELETE
주문형 코드 (선택) 서버가 클라이언트에 실행 코드 전송 가능 문서 뷰어 JavaScript 플러그인

3.2 API 엔드포인트 구조

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 # 필터링 및 정렬

3.3 HTTP 메서드 및 상태 코드

HTTP 메서드 사용

메서드 용도 멱등성 예시
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)

HTTP 상태 코드

코드 의미 사용 시나리오
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 서버 오류 예기치 않은 서버 에러

3.4 인증 및 권한 부여

공공문서 API는 OAuth 2.0 및 JWT (JSON Web Token) 기반 인증을 사용합니다. 민감한 개인 정보를 다루므로 강력한 인증과 세분화된 권한 관리가 필수적입니다.

JWT 토큰 구조

// 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자 검증 기관

3.5 속도 제한 (Rate Limiting)

API 남용 방지와 공정한 리소스 분배를 위해 속도 제한을 적용합니다. WIA-SOCIAL은 Token Bucket 알고리즘을 사용하여 유연하고 효율적인 속도 제한을 구현합니다.

📊 속도 제한 정책

Rate Limit 헤더

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"
    }
  }
}

3.6 API 버전 관리 전략

API는 요구사항이 변경되고 새로운 기능이 추가됨에 따라 시간이 지남에 따라 진화합니다. 버전 관리 전략은 기존 클라이언트에 대한 중단을 최소화하면서 이러한 진화를 관리합니다.

URL 기반 버전 관리

WIA-SOCIAL 표준은 URL 경로에 주요 버전 번호를 포함하는 것을 권장합니다(/api/v1/, /api/v2/). 이 접근 방식은 버전을 명시적이고 쉽게 검색할 수 있게 만듭니다. 다른 버전은 독립적으로 배포하고 확장할 수 있습니다. 클라이언트는 자신의 속도에 맞춰 새 버전으로 업그레이드할 수 있습니다. 더 이상 사용되지 않는 버전은 명확한 일정으로 단계적으로 폐지될 수 있습니다.

하위 호환성

주요 버전 내에서 변경 사항은 하위 호환되어야 합니다. 선택적 필드 추가는 안전합니다. 새 엔드포인트 추가는 안전합니다. 유효성 검사 완화는 안전합니다. 그러나 필드 제거, 유효성 검사 강화, 응답 형식 변경 또는 의미 변경은 호환성을 깨뜨리며 새로운 주요 버전이 필요합니다. 신중한 API 설계는 주요 변경 사항을 최소화하여 주요 버전 증가 빈도를 줄입니다.

폐기 정책

중단 변경 사항을 도입할 때 이전 버전은 전환 기간(일반적으로 정부 API의 경우 12-24개월) 동안 사용 가능한 상태로 유지되어야 합니다. 폐기 경고는 응답 헤더, 문서 및 개발자 커뮤니케이션에 나타납니다. 폐기 기간 동안 두 버전이 병렬로 작동합니다. 마감일 이후에는 이전 버전이 종료됩니다. 중요한 보안 수정 사항은 전환 기간 동안 더 이상 사용되지 않는 버전으로 백포트될 수 있습니다.

API 버전 타임라인 예시

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+ 사용 필수

3.7 페이지네이션 및 필터링

대량의 문서 데이터를 효율적으로 조회하기 위해 커서 기반 페이지네이션과 다양한 필터링 옵션을 제공합니다.

페이지네이션 방식

# 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

3.8 오류 처리

일관된 오류 응답 형식은 클라이언트의 오류 처리를 간소화합니다. 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 서버 내부 오류

3.9 캐싱 및 성능

효과적인 캐싱은 API 성능을 극적으로 향상시키고 서버 부하를 줄입니다. HTTP는 API가 적절한 헤더와 설계 패턴을 통해 활용해야 하는 내장 캐싱 메커니즘을 제공합니다.

Cache-Control 헤더

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 예제와 함께 살펴보겠습니다.

🤔 복습 질문

  1. REST 아키텍처의 6가지 제약 조건을 나열하고, 각각이 공공문서 API에서 어떻게 적용되는지 설명하세요.
  2. GET과 POST의 멱등성 차이를 설명하고, 이것이 API 설계에 왜 중요한지 논의하세요.
  3. JWT 토큰의 Header, Payload, Signature 각 부분의 역할을 설명하세요.
  4. Offset 기반 페이지네이션과 Cursor 기반 페이지네이션의 장단점을 비교하세요.
  5. Rate Limiting이 필요한 이유와 Token Bucket 알고리즘의 작동 원리를 설명하세요.