제5장
Phase 2: API 인터페이스 설계
알츠하이머 치료 시스템의 RESTful API와 GraphQL 스키마 설계, 인증 체계, 그리고 다양한 프로그래밍 언어에서의 구현 방법을 다룹니다.
1. API 아키텍처 개요
WIA 알츠하이머 치료 표준의 API 인터페이스는 환자 데이터의 안전한 수집, 저장, 분석을 가능하게 하는 핵심 계층입니다.
이 API는 의료기관의 전자건강기록(EHR) 시스템, 연구기관의 데이터 분석 플랫폼, 그리고 환자 모니터링 애플리케이션을
통합하는 허브 역할을 수행합니다.
API 설계는 FHIR R5 표준과의 호환성을 유지하면서도, 알츠하이머 질환 특화 데이터 모델을 지원합니다.
이를 통해 NAD+ 수치, 인지 평가 점수, 바이오마커 농도 등 질환별 특수 데이터를 효율적으로 관리할 수 있습니다.
아키텍처 설계 원칙
API 설계 시 다음 원칙을 준수합니다: (1) RESTful 원칙에 따른 리소스 중심 설계,
(2) 의료 데이터 표준(FHIR, HL7) 준수, (3) 확장 가능한 스키마 구조,
(4) 강력한 인증 및 권한 관리, (5) 실시간 데이터 조회 지원.
2. REST API 엔드포인트 설계
알츠하이머 치료 시스템의 REST API는 환자 평가, 치료 추적, 권장사항 생성을 위한 세 가지 핵심 엔드포인트 그룹으로 구성됩니다.
2.1 환자 평가 엔드포인트
환자의 인지 기능, NAD+ 수치, 바이오마커 데이터를 제출하고 조회하는 엔드포인트입니다.
// POST /api/v1/assessments - 새로운 평가 제출
POST https://api.wia-alzheimers.org/v1/assessments
Content-Type: application/json
Authorization: Bearer {access_token}
{
"patient_id": "PT-2025-001234",
"assessment_date": "2025-01-15T09:30:00Z",
"cognitive_tests": {
"mmse": {
"total_score": 24,
"orientation": 8,
"registration": 3,
"attention_calculation": 4,
"recall": 2,
"language": 7
},
"moca": {
"total_score": 22,
"visuospatial": 4,
"naming": 3,
"attention": 5,
"language": 2,
"abstraction": 2,
"delayed_recall": 3,
"orientation": 6
}
},
"biomarkers": {
"nad_plus": {
"whole_blood": 45.2,
"unit": "μM",
"method": "HPLC-MS/MS"
},
"plasma_abeta42": 320,
"plasma_abeta40": 1850,
"plasma_ptau181": 2.8,
"plasma_nfl": 18.5
}
}
// 응답
{
"assessment_id": "ASSESS-2025-001234-001",
"status": "completed",
"risk_score": 0.72,
"stage": "MCI",
"created_at": "2025-01-15T09:31:23Z"
}
2.2 치료 추적 엔드포인트
NAD+ 부스터(NR/NMN) 보충, 항아밀로이드 치료 등의 개입을 추적하고 모니터링합니다.
// GET /api/v1/treatments/{patient_id} - 치료 이력 조회
GET https://api.wia-alzheimers.org/v1/treatments/PT-2025-001234
Authorization: Bearer {access_token}
// 응답
{
"patient_id": "PT-2025-001234",
"treatments": [
{
"treatment_id": "TRT-2025-001234-NR",
"type": "nad_booster",
"agent": "nicotinamide_riboside",
"dosage": "1000mg",
"frequency": "daily",
"start_date": "2025-01-01",
"adherence": 0.94,
"adverse_events": []
},
{
"treatment_id": "TRT-2025-001234-LEQ",
"type": "anti_amyloid",
"agent": "lecanemab",
"dosage": "10mg/kg",
"frequency": "biweekly",
"start_date": "2025-01-10",
"infusions_completed": 3,
"aria_monitoring": {
"last_mri": "2025-01-12",
"aria_e": false,
"aria_h": false
}
}
]
}
2.3 권장사항 엔드포인트
AI 기반 분석을 통해 개인화된 치료 권장사항을 생성합니다.
// POST /api/v1/recommendations - 권장사항 생성
POST https://api.wia-alzheimers.org/v1/recommendations
Content-Type: application/json
Authorization: Bearer {access_token}
{
"patient_id": "PT-2025-001234",
"assessment_id": "ASSESS-2025-001234-001",
"include_clinical_trials": true
}
// 응답
{
"recommendation_id": "REC-2025-001234-001",
"generated_at": "2025-01-15T09:32:00Z",
"interventions": [
{
"priority": 1,
"type": "nad_booster",
"agent": "NR",
"dosage": "1000mg/day",
"rationale": "NAD+ 수치 45.2μM은 정상 하한(50-60μM) 미만.
NR 보충으로 24주 내 30-50% 증가 예상.",
"evidence_level": "1A",
"monitoring": "4주마다 NAD+ 측정"
},
{
"priority": 2,
"type": "anti_amyloid",
"agent": "lecanemab",
"rationale": "Aβ42/40 비율 0.173은 아밀로이드 양성 기준 미달.
레카네맙으로 플라크 부담 감소 가능.",
"evidence_level": "1A",
"contraindications": ["APOE4 동형접합성 확인 필요"]
}
]
}
3. GraphQL 스키마 정의
복잡한 데이터 관계를 효율적으로 조회하기 위한 GraphQL API를 제공합니다.
단일 쿼리로 환자 정보, 평가 결과, 치료 이력, 권장사항을 모두 가져올 수 있습니다.
# GraphQL 스키마 정의
type Patient {
id: ID!
mrn: String!
demographics: Demographics!
assessments(limit: Int = 10): [Assessment!]!
treatments: [Treatment!]!
recommendations: [Recommendation!]!
riskScore: Float!
currentStage: DiseaseStage!
}
type Assessment {
id: ID!
date: DateTime!
cognitiveTests: CognitiveTests!
biomarkers: Biomarkers!
riskScore: Float!
stage: DiseaseStage!
}
type CognitiveTests {
mmse: MMSEScore
moca: MoCAScore
cdrSb: Float
}
type Biomarkers {
nadPlus: NADMeasurement!
plasmaAbeta42: Float!
plasmaAbeta40: Float!
plasmaPtau181: Float!
plasmaNFL: Float!
abetaRatio: Float!
}
type NADMeasurement {
wholeBlood: Float!
unit: String!
method: NADMethod!
measuredAt: DateTime!
}
enum NADMethod {
HPLC_MS_MS
ENZYMATIC_CYCLING
FLUORESCENT_SENSOR
}
enum DiseaseStage {
PRECLINICAL
MCI
MILD_AD
MODERATE_AD
SEVERE_AD
}
# 쿼리 예제
query GetPatientOverview($patientId: ID!) {
patient(id: $patientId) {
id
demographics {
age
sex
apoeGenotype
}
assessments(limit: 5) {
date
cognitiveTests {
mmse { totalScore }
moca { totalScore }
}
biomarkers {
nadPlus { wholeBlood }
abetaRatio
}
}
treatments {
type
agent
startDate
adherence
}
recommendations {
generatedAt
interventions {
priority
type
agent
rationale
}
}
}
}
4. OAuth 2.0 인증 체계
의료 데이터 보안을 위해 OAuth 2.0 프로토콜을 사용한 3단계 인증 시스템을 구현합니다.
| 인증 단계 |
설명 |
토큰 유효기간 |
| 클라이언트 등록 |
API 콘솔에서 애플리케이션 등록 및 Client ID/Secret 발급 |
영구 |
| Authorization Code 발급 |
사용자 동의 후 일회성 인증 코드 발급 |
10분 |
| Access Token 발급 |
인증 코드를 Access Token으로 교환 |
1시간 |
| Refresh Token |
만료된 Access Token 갱신용 장기 토큰 |
90일 |
// OAuth 2.0 인증 플로우
// 1단계: Authorization Code 요청
GET https://auth.wia-alzheimers.org/oauth/authorize?
response_type=code&
client_id=YOUR_CLIENT_ID&
redirect_uri=https://yourapp.com/callback&
scope=patient:read patient:write assessment:read&
state=RANDOM_STATE_STRING
// 2단계: Authorization Code를 Access Token으로 교환
POST https://auth.wia-alzheimers.org/oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&
code=AUTHORIZATION_CODE&
client_id=YOUR_CLIENT_ID&
client_secret=YOUR_CLIENT_SECRET&
redirect_uri=https://yourapp.com/callback
// 응답
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "tGzv3JOkF0XG5Qx2TlKWIA",
"scope": "patient:read patient:write assessment:read"
}
// 3단계: Access Token으로 API 호출
GET https://api.wia-alzheimers.org/v1/patients/PT-2025-001234
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
5. 권한 범위(Scopes) 정의
세분화된 권한 관리를 위해 다음과 같은 OAuth 스코프를 정의합니다.
| Scope |
설명 |
권한 수준 |
| patient:read |
환자 기본 정보 조회 |
읽기 |
| patient:write |
환자 정보 수정 |
쓰기 |
| assessment:read |
평가 결과 조회 |
읽기 |
| assessment:write |
새로운 평가 제출 |
쓰기 |
| treatment:read |
치료 이력 조회 |
읽기 |
| treatment:write |
치료 기록 추가/수정 |
쓰기 |
| biomarker:read |
바이오마커 데이터 조회 |
읽기 |
| recommendation:read |
AI 권장사항 조회 |
읽기 |
| admin:all |
전체 시스템 관리 |
관리자 |
6. 오류 코드 및 처리
표준화된 HTTP 상태 코드와 상세한 오류 메시지를 제공하여 디버깅을 용이하게 합니다.
| HTTP 상태 |
오류 코드 |
설명 |
| 400 |
INVALID_REQUEST |
요청 형식 오류 (누락된 필수 필드, 잘못된 데이터 타입) |
| 401 |
UNAUTHORIZED |
인증 실패 (유효하지 않은 토큰) |
| 403 |
FORBIDDEN |
권한 부족 (스코프 불충분) |
| 404 |
RESOURCE_NOT_FOUND |
리소스 미존재 (환자 ID 또는 평가 ID 없음) |
| 409 |
CONFLICT |
중복된 리소스 (동일 날짜 평가 존재) |
| 422 |
VALIDATION_ERROR |
데이터 검증 실패 (NAD+ 수치 범위 초과) |
| 429 |
RATE_LIMIT_EXCEEDED |
요청 속도 제한 초과 |
| 500 |
INTERNAL_ERROR |
서버 내부 오류 |
// 오류 응답 형식
{
"error": {
"code": "VALIDATION_ERROR",
"message": "NAD+ 수치는 0-200 μM 범위여야 합니다.",
"details": {
"field": "biomarkers.nad_plus.whole_blood",
"provided_value": 350.5,
"valid_range": "0-200"
},
"request_id": "req_2025011509321234",
"timestamp": "2025-01-15T09:32:12Z"
}
}
7. 속도 제한(Rate Limiting)
API 남용 방지와 공정한 자원 분배를 위해 계층별 속도 제한을 적용합니다.
| API 티어 |
분당 요청 |
일일 요청 |
대상 사용자 |
| Free |
60 |
1,000 |
개발자, 연구자 |
| Standard |
600 |
50,000 |
중소형 의료기관 |
| Premium |
6,000 |
1,000,000 |
대형 병원, 연구기관 |
| Enterprise |
협의 |
무제한 |
국가 건강 시스템 |
속도 제한 초과 시
속도 제한을 초과하면 HTTP 429 상태 코드가 반환됩니다. 응답 헤더의
Retry-After 필드를 확인하여 다음 요청 가능 시점을 파악할 수 있습니다.
의료 데이터의 특성상 긴급 상황에서는 Enterprise 지원팀에 문의하여 임시 제한 완화를 요청할 수 있습니다.
8. 다양한 언어 SDK 예제
8.1 Python SDK
# pip install wia-alzheimers
from wia_alzheimers import AlzheimersAPI, Assessment, Biomarkers
# 클라이언트 초기화
api = AlzheimersAPI(
client_id="YOUR_CLIENT_ID",
client_secret="YOUR_CLIENT_SECRET",
environment="production"
)
# 인증
api.authenticate()
# 새로운 평가 제출
assessment = Assessment(
patient_id="PT-2025-001234",
assessment_date="2025-01-15T09:30:00Z",
cognitive_tests={
"mmse": {"total_score": 24},
"moca": {"total_score": 22}
},
biomarkers=Biomarkers(
nad_plus={"whole_blood": 45.2, "unit": "μM", "method": "HPLC-MS/MS"},
plasma_abeta42=320,
plasma_abeta40=1850
)
)
result = api.assessments.create(assessment)
print(f"평가 ID: {result.assessment_id}, 위험도: {result.risk_score}")
# 권장사항 생성
recommendations = api.recommendations.generate(
patient_id="PT-2025-001234",
assessment_id=result.assessment_id
)
for rec in recommendations.interventions:
print(f"{rec.priority}. {rec.agent}: {rec.rationale}")
8.2 JavaScript/TypeScript SDK
// npm install @wia/alzheimers
import { AlzheimersAPI } from '@wia/alzheimers';
// 클라이언트 초기화
const api = new AlzheimersAPI({
clientId: 'YOUR_CLIENT_ID',
clientSecret: 'YOUR_CLIENT_SECRET',
environment: 'production'
});
// 인증
await api.authenticate();
// 환자 데이터 조회
const patient = await api.patients.get('PT-2025-001234');
console.log(`환자: ${patient.demographics.age}세, APOE: ${patient.demographics.apoeGenotype}`);
// 치료 이력 조회
const treatments = await api.treatments.list(patient.id);
treatments.forEach(treatment => {
console.log(`${treatment.agent}: ${treatment.dosage}, 순응도 ${treatment.adherence * 100}%`);
});
// GraphQL 쿼리 실행
const query = `
query ($patientId: ID!) {
patient(id: $patientId) {
assessments(limit: 5) {
date
biomarkers {
nadPlus { wholeBlood }
abetaRatio
}
}
}
}
`;
const data = await api.graphql(query, { patientId: 'PT-2025-001234' });
console.log(data.patient.assessments);
8.3 Java SDK
// Maven: <dependency>
// <groupId>org.wia</groupId>
// <artifactId>alzheimers-sdk</artifactId>
// <version>1.0.0</version>
// </dependency>
import org.wia.alzheimers.AlzheimersAPI;
import org.wia.alzheimers.models.*;
public class AlzheimersExample {
public static void main(String[] args) {
// 클라이언트 초기화
AlzheimersAPI api = new AlzheimersAPI.Builder()
.clientId("YOUR_CLIENT_ID")
.clientSecret("YOUR_CLIENT_SECRET")
.environment(Environment.PRODUCTION)
.build();
// 인증
api.authenticate();
// 평가 생성
Assessment assessment = new Assessment.Builder()
.patientId("PT-2025-001234")
.assessmentDate("2025-01-15T09:30:00Z")
.cognitiveTest("mmse", new MMSEScore(24))
.cognitiveTest("moca", new MoCAScore(22))
.biomarker("nad_plus", new NADMeasurement(45.2, "μM", "HPLC-MS/MS"))
.build();
AssessmentResult result = api.assessments().create(assessment);
System.out.printf("평가 ID: %s, 위험도: %.2f%n",
result.getAssessmentId(), result.getRiskScore());
// 권장사항 생성
Recommendations recs = api.recommendations().generate(
"PT-2025-001234",
result.getAssessmentId()
);
recs.getInterventions().forEach(intervention -> {
System.out.printf("%d. %s: %s%n",
intervention.getPriority(),
intervention.getAgent(),
intervention.getRationale());
});
}
}
8.4 R SDK (통계 분석용)
# install.packages("wia.alzheimers")
library(wia.alzheimers)
# 클라이언트 초기화
api <- AlzheimersAPI$new(
client_id = "YOUR_CLIENT_ID",
client_secret = "YOUR_CLIENT_SECRET",
environment = "production"
)
# 인증
api$authenticate()
# 다중 환자 데이터 조회 (임상시험용)
patient_ids <- c("PT-2025-001234", "PT-2025-001235", "PT-2025-001236")
assessments_df <- api$assessments$batch_get(patient_ids)
# NAD+ 수치 분석
library(ggplot2)
ggplot(assessments_df, aes(x = assessment_date, y = nad_plus_whole_blood)) +
geom_line(aes(group = patient_id, color = patient_id)) +
labs(title = "NAD+ 수치 변화 추이", x = "날짜", y = "NAD+ (μM)")
# 상관관계 분석
cor.test(assessments_df$nad_plus_whole_blood, assessments_df$mmse_score)
챕터 요약: 핵심 요점
- RESTful API 설계: 환자 평가, 치료 추적, 권장사항 생성을 위한 3개 핵심 엔드포인트 그룹 제공. FHIR R5 호환 유지.
- GraphQL 지원: 복잡한 데이터 관계를 단일 쿼리로 조회 가능. 환자 정보, 평가 결과, 치료 이력 통합 조회.
- OAuth 2.0 인증: 3단계 인증 프로세스(클라이언트 등록, Authorization Code, Access Token). 세분화된 권한 스코프 9개 정의.
- 오류 처리: 표준 HTTP 상태 코드와 상세한 오류 메시지. 8가지 오류 유형 정의 및 디버깅 정보 제공.
- 속도 제한: 4단계 티어 시스템(Free, Standard, Premium, Enterprise). 공정한 자원 분배와 서비스 품질 보장.
- 다국어 SDK: Python, JavaScript/TypeScript, Java, R 등 주요 언어 지원. 의료 연구 및 임상 현장에서 즉시 활용 가능.
복습 질문
- REST API의 세 가지 핵심 엔드포인트 그룹은 무엇이며, 각각 어떤 기능을 수행합니까?
- GraphQL이 REST API에 비해 알츠하이머 데이터 조회에 유리한 이유를 설명하세요.
- OAuth 2.0 인증 플로우의 3단계를 순서대로 나열하고, 각 단계에서 발급되는 토큰의 유효기간을 명시하세요.
- HTTP 422 VALIDATION_ERROR는 어떤 상황에서 발생하며, 응답 메시지는 어떤 정보를 포함해야 합니까?
- Standard 티어의 API 사용자는 분당 몇 건의 요청을 보낼 수 있으며, 속도 제한 초과 시 어떻게 대응해야 합니까?
- Python SDK를 사용하여 NAD+ 수치 45.2μM인 환자의 평가를 제출하는 코드를 작성하세요. (필수 필드만 포함)