우리가 만드는 것
다음 5분 안에 사용자가 질환과 단계별로 임상 시험을 검색하고 카드에 결과를 표시하고 결과를 페이징하는 간단한 웹 앱을 만들게 됩니다.Clinical Trials API는 ClinicalTrials.gov을 개발자 친화적인 인터페이스로 감싸는 REST API입니다. 구조화된 자격 요건 기준(나이, 성별, 상태, 검체 값과 같은 카테고리로 파싱됨 - 정규식이 필요 없음), 위도/경도를 이용한 지리적 반경 검색, 새로운 시험을 위한 HTTP 웹훅 알림, 커서 기반 페이징, 집계 통계를 제공합니다. 신용카드 없이 무료 티어 제공. FDA에서 매일 업데이트되는 220개국 이상의 480,000개 이상의 시험. 모든 것이 하나의 API로 구동됩니다. 기본적인 HTML/JavaScript 지식과 무료 RapidAPI 계정이 필요합니다.
단계 1: API 키를 얻으시오 (30초)
- 가서https://rapidapi.com/capifactory-capifactory-default/api/clinical-trials-api
- 무료 플랜에서 "구독"을 클릭하세요 (신용카드가 필요 없습니다)
- 대시보드에서 X-RapidAPI-Key를 복사하세요
그것이 다입니다. API 호출을 준비되었습니다.
단계 2: 첫 번째 API 호출을 만드세요
터미널을 엽니다 및 이 curl 명령어를 실행하세요 (YOUR_API_KEY를 바꿔주세요):
curl --request GET \
--url 'https://clinical-trials-api.p.rapidapi.com/v1/trials/search?query=breast+cancer&phase=Phase+2&status=Recruiting&limit=3' \
--header 'X-RapidAPI-Key: YOUR_API_KEY'
다음과 같은 내용이 보일 것입니다:
{
"success": true,
"data": [
{
"nct_id": "NCT04589845",
"title": "Atezolizumab and Chemotherapy for Triple-Negative Breast Cancer",
"brief_summary": "This phase II trial studies how well atezolizumab works with chemotherapy...",
"condition": "Breast Cancer",
"phase": "Phase 2",
"status": "Recruiting",
"enrollment_count": 280,
"last_updated": "2026-05-15",
"locations": [
{
"facility": "Dana-Farber Cancer Institute",
"city": "Boston",
"state": "MA",
"country": "United States"
}
]
}
],
"pagination": {
"total": 847,
"limit": 3,
"next_cursor": "eyJvZmZzZXQiOjN9",
"has_more": true
}
}
847개의 일치 트라이얼이 정리된 JSON 형식으로 내부 페이징과 함께 반환됩니다. 스크래핑, 파싱, 파이프라인 유지보수 없습니다.
3단계: 테스트 검색 앱 만들기
단일 HTML 파일 (index.html)을 만들고 이 코드를 붙여넣으세요:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Clinical Trial Search</title>
<style>
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; max-width: 800px; margin: 40px auto; padding: 0 20px; background: #f5f5f5; }
h1 { color: #1a1a2e; }
.search-box { display: flex; gap: 10px; margin-bottom: 20px; flex-wrap: wrap; }
input, select, button { padding: 10px 15px; border: 1px solid #ddd; border-radius: 6px; font-size: 14px; }
input { flex: 1; min-width: 200px; }
button { background: #1a56db; color: white; border: none; cursor: pointer; font-weight: 600; }
button:hover { background: #1647b8; }
.trial-card { background: white; border-radius: 8px; padding: 20px; margin-bottom: 15px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); }
.trial-card h3 { margin: 0 0 8px 0; color: #1a1a2e; font-size: 16px; }
.trial-meta { display: flex; gap: 15px; font-size: 13px; color: #666; margin-bottom: 8px; flex-wrap: wrap; }
.badge { padding: 2px 8px; border-radius: 12px; font-size: 12px; font-weight: 600; }
.badge-recruiting { background: #d4edda; color: #155724; }
.badge-phase { background: #cce5ff; color: #004085; }
.summary { font-size: 14px; color: #444; line-height: 1.5; }
.pagination { display: flex; gap: 10px; align-items: center; margin-top: 20px; justify-content: center; }
.loading { text-align: center; padding: 40px; color: #666; }
.error { text-align: center; padding: 20px; color: #dc3545; background: #f8d7da; border-radius: 8px; }
.nct { color: #1a56db; font-family: monospace; font-size: 14px; }
.location { font-size: 12px; color: #888; margin-top: 6px; }
</style>
</head>
<body>
<h1>Clinical Trial Search</h1>
<p style="color: #666; margin-bottom: 20px;">Powered by <a href="https://rapidapi.com/capifactory-capifactory-default/api/clinical-trials-api">Clinical Trials API</a> -- 480K+ FDA trials, free tier, no credit card.</p>
<div class="search-box">
<input type="text" id="query" placeholder="Search condition or keyword (e.g., breast cancer)" value="breast cancer">
<select id="phase">
<option value="">All Phases</option>
<option value="Phase 1">Phase 1</option>
<option value="Phase 2" selected>Phase 2</option>
<option value="Phase 3">Phase 3</option>
<option value="Phase 4">Phase 4</option>
</select>
<select id="status">
<option value="">All Statuses</option>
<option value="Recruiting" selected>Recruiting</option>
<option value="Not yet recruiting">Not Yet Recruiting</option>
<option value="Active not recruiting">Active, Not Recruiting</option>
<option value="Completed">Completed</option>
</select>
<button onclick="searchTrials()">Search</button>
</div>
<div id="results"></div>
<script>
const API_KEY = 'YOUR_RAPIDAPI_KEY'; // Replace with your key
const BASE_URL = 'https://clinical-trials-api.p.rapidapi.com';
let currentCursor = null;
let currentQuery = null;
async function searchTrials(cursor = null) {
const query = document.getElementById('query').value;
const phase = document.getElementById('phase').value;
const status = document.getElementById('status').value;
const params = new URLSearchParams({ query, limit: '5' });
if (phase) params.append('phase', phase);
if (status) params.append('status', status);
if (cursor) params.append('cursor', cursor);
const resultsDiv = document.getElementById('results');
resultsDiv.innerHTML = '<div class="loading">Searching 480K+ clinical trials...</div>';
try {
const r = await fetch(`${BASE_URL}/v1/trials/search?${params}`, {
headers: { 'X-RapidAPI-Key': API_KEY }
});
if (r.status === 401) {
resultsDiv.innerHTML = '<div class="error">Invalid API key. Get your free key at <a href="https://rapidapi.com/capifactory-capifactory-default/api/clinical-trials-api">rapidapi.com/clinical-trials-api</a></div>';
return;
}
if (!r.ok) {
resultsDiv.innerHTML = `<div class="error">API error: HTTP ${r.status}</div>`;
return;
}
const body = await r.json();
if (!body.success) {
resultsDiv.innerHTML = `<div class="error">${body.error?.message || 'Unknown error'}</div>`;
return;
}
currentCursor = cursor;
currentQuery = { query, phase, status };
renderResults(body);
} catch (e) {
resultsDiv.innerHTML = `<div class="error">Network error: ${e.message}</div>`;
}
}
function renderResults(body) {
const resultsDiv = document.getElementById('results');
const pagination = body.pagination;
let html = `<p style="color: #666; margin-bottom: 15px;">Found <strong>${pagination.total.toLocaleString()}</strong> trials. Showing ${(currentCursor ? 'next page' : 'first')} ${body.data.length} results.</p>`;
body.data.forEach(trial => {
const loc = trial.locations && trial.locations[0] ? `${trial.locations[0].facility}, ${trial.locations[0].city}, ${trial.locations[0].state}` : '';
html += `
<div class="trial-card">
<h3>${trial.title}</h3>
<div class="trial-meta">
<span class="nct">${trial.nct_id}</span>
<span class="badge badge-phase">${trial.phase}</span>
<span class="badge badge-recruiting">${trial.status}</span>
${trial.enrollment_count ? `<span>${trial.enrollment_count} participants</span>` : ''}
</div>
<p class="summary">${(trial.brief_summary || '').substring(0, 200)}${(trial.brief_summary || '').length > 200 ? '...' : ''}</p>
${loc ? `<p class="location">${loc}</p>` : ''}
</div>
`;
});
html += '<div class="pagination">';
if (currentCursor) {
html += `<button onclick="searchTrials(null)">First Page</button>`;
}
if (pagination.has_more) {
html += `<button onclick="loadNextPage('${pagination.next_cursor}')">Next Page (${pagination.total - (currentCursor ? parseInt(currentCursor.match(/\d+/)?.[0] || 0) : body.data.length)} remaining)</button>`;
} else if (body.data.length > 0) {
html += '<span style="color: #666;">All results loaded.</span>';
}
html += '</div>';
resultsDiv.innerHTML = html;
}
function loadNextPage(cursor) {
document.getElementById('query').value = currentQuery.query;
document.getElementById('phase').value = currentQuery.phase;
document.getElementById('status').value = currentQuery.status;
searchTrials(cursor);
}
// Search on load
searchTrials();
</script>
</body>
</html>
4단계: 실행하기
- 줄 ~70에서
YOUR_RAPIDAPI_KEY을 실제 API 키로 바꿔주세요 - 브라우저에서
index.html을 열어보세요 (파일을 두 번 클릭하세요) - 작동하는 임상 시험 검색 앱을 가지고 있습니다
"알츠하이머", "당뇨병"을 검색해 보거나 기본값인 "유방암"을 남겨두세요 -- 실제 FDA 시험 데이터가 한 초 안에 표시됩니다.
다음은 무엇인가요?
- 지리적 반경 검색 엔드포인트 (
/v1/trials/nearby)를 추가하여 HTML5 지리적 위치 기반으로 "나에게 가까운 시험" 기능을 구축합니다 - 구조화된 자격 요건 표시를 호출하여
/v1/trials/{nct_id}/eligibility사용자가 시험 카드를 클릭할 때 (프로 티어: $19/월) POST /v1/alerts을 통해 새로운 시험 기준이 사용자의 저장된 검색 기준과 일치할 때 웹훅 알림을 설정하여 알림을 받으세요- Vercel, Netlify 또는 GitHub Pages에 배포하여 실시간 데모를 만드세요
- Tailwind CSS로 스타일링하여 전문적인 모습으로 만드세요
API
- 무료 티어: 하루 100 요청, 기본 검색, 근처 검색, 통계, 조건 브라우저, 3개 저장 알림
- 프로: $19/월 -- 10,000 요청, 구조화된 자격 요건 파싱, 25개 웹훅 알림, 이메일 지원
울트라: $49/월 -- 50,000 요청, 무제한 알림, 우선 지원
문서: https://rapidapi.com/capifactory-capifactory-default/api/clinical-trials-api/docs
RapidAPI에서 구독하세요 - 무료 티어, 신용카드가 필요 없습니다.
이 API로 무언가를 만들면 나를 태그해 주세요 - 만드신 것을 보고 싶어요. 댓글에 질문을 남기면 답변해 줄게요.











