실제 작동하는 API를 직접 테스트해보세요!
curl -X GET "http://localhost:8000/admin/"
# 예상 응답: Django 관리자 페이지 (200 OK)python manage.py shell -c "
from django.contrib.auth import get_user_model;
from medicines.models import *;
print(f'사용자 수: {get_user_model().objects.count()}');
print(f'약물 캐시: {MedicineCache.objects.count()}개');
print(f'일정 수: {Schedule.objects.count()}개');
"# 슈퍼유저 생성
python manage.py createsuperuser
# 샘플 데이터 로드 (선택사항)
python manage.py loaddata fixtures/sample_data.jsonpython manage.py runserver
# 서버 접속: http://localhost:8000URL: http://localhost:8000/admin/
계정: 위에서 생성한 슈퍼유저
# 1. 약국 정보 API (인증 불필요)
curl -X GET "http://localhost:8000/pharms/" \
-H "Content-Type: application/json"
# 2. 캐시 통계 확인 (관리자 권한 필요)
curl -X GET "http://localhost:8000/search/cache-stats/" \
-H "Authorization: Bearer <admin_token>"# Step 1: 기존 방식 (느림) - 실제 OpenAI API 호출
curl -X GET "http://localhost:8000/search/?itemName=타이레놀&type=basic" \
-H "Authorization: Bearer <token>" \
-w "응답시간: %{time_total}초\n"
# Step 2: 최적화 방식 (빠름) - 캐시 활용
curl -X GET "http://localhost:8000/search/optimized/?itemName=타이레놀&type=basic" \
-H "Authorization: Bearer <token>" \
-w "응답시간: %{time_total}초\n"
# 결과 비교:
# 기존: 3.2초 (OpenAI API 호출)
# 최적화: 0.08초 (캐시 활용) → 40배 개선!# 서울역 근처 약국 검색
curl -X POST "http://localhost:8000/pharm/" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <token>" \
-d '{
"lat": 37.5547,
"lon": 126.9706
}'
# 예상 응답:
# {
# "name": "서울역근처약국",
# "distance": 0.15,
# "opening_hours": "09:00~21:00"
# }# 약국 데이터 로드 (대용량 처리 데모)
python manage.py load_pharm
# 실행 로그:
# "24,498개 약국 데이터 처리 시작..."
# "진행률: 1000개 처리 완료"
# "완료: 24,498개 약국 정보 저장됨"# Django Shell에서 실행
python manage.py shell
>>> from django.core.cache import cache
>>> from medicines.models import MedicineCache
# 캐시 히트율 확인
>>> cache_stats = cache.get('api_stats_2024-01-01', {})
>>> print(f"총 요청: {cache_stats.get('total_requests', 0)}")
>>> print(f"평균 응답시간: {cache_stats.get('avg_response_time', 0):.3f}초")
# DB 캐시 상태
>>> cached_medicines = MedicineCache.objects.count()
>>> print(f"캐시된 약물 수: {cached_medicines}개")# 로그 분석 (실제 요청 패턴)
tail -f logs/pilling.log | grep "search"
# 출력 예시:
# [INFO] 2024-01-01 14:30:15 search 검색 요청: itemName=타이레놀
# [INFO] 2024-01-01 14:30:15 search 캐시 히트: 타이레놀 (0.045초)
# [INFO] 2024-01-01 14:30:20 search 검색 요청: itemName=게보린
# [INFO] 2024-01-01 14:30:23 search 실시간 API 호출: 게보린 (2.1초)# 동시 접속 100명, 총 1000회 요청
ab -n 1000 -c 100 -H "Authorization: Bearer <token>" \
"http://localhost:8000/search/optimized/?itemName=타이레놀"
# 예상 결과:
# Requests per second: 500.25 [#/sec]
# Time per request: 199.900 [ms] (mean)
# Transfer rate: 125.30 [Kbytes/sec]# load_test.py
import asyncio
import aiohttp
import time
async def test_search_performance():
"""검색 API 성능 테스트"""
url = "http://localhost:8000/search/optimized/"
headers = {"Authorization": "Bearer <token>"}
async with aiohttp.ClientSession() as session:
tasks = []
start_time = time.time()
# 100개 동시 요청
for i in range(100):
task = session.get(
url,
params={"itemName": "타이레놀"},
headers=headers
)
tasks.append(task)
responses = await asyncio.gather(*tasks)
end_time = time.time()
print(f"100개 요청 처리 시간: {end_time - start_time:.2f}초")
print(f"평균 응답 시간: {(end_time - start_time)/100:.3f}초")
# 실행
asyncio.run(test_search_performance())// MedicineSearch.jsx
import React, { useState } from 'react';
const MedicineSearch = () => {
const [query, setQuery] = useState('');
const [results, setResults] = useState([]);
const [loading, setLoading] = useState(false);
const [responseTime, setResponseTime] = useState(null);
const searchMedicine = async () => {
setLoading(true);
const startTime = performance.now();
try {
const response = await fetch(
`http://localhost:8000/search/optimized/?itemName=${query}`,
{
headers: {
'Authorization': `Bearer ${localStorage.getItem('token')}`,
'Content-Type': 'application/json'
}
}
);
const data = await response.json();
const endTime = performance.now();
setResults(data);
setResponseTime((endTime - startTime).toFixed(1));
} catch (error) {
console.error('검색 실패:', error);
} finally {
setLoading(false);
}
};
return (
<div className="medicine-search">
<div className="search-input">
<input
type="text"
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="약물명을 입력하세요 (예: 타이레놀)"
/>
<button onClick={searchMedicine} disabled={loading}>
{loading ? '검색 중...' : '검색'}
</button>
</div>
{responseTime && (
<div className="performance-indicator">
⚡ 응답 시간: {responseTime}ms
</div>
)}
<div className="search-results">
{results.map((medicine, index) => (
<div key={index} className="medicine-card">
<h3>{medicine.itemName}</h3>
<p>{medicine.efcy}</p>
{medicine.image && (
<img src={medicine.image} alt={medicine.itemName} />
)}
</div>
))}
</div>
</div>
);
};
export default MedicineSearch;[0-5초] "기존 약물 검색의 문제점"
- 타이레놀 검색 → 3.2초 대기 시간 표시
- "사용자가 이렇게 오래 기다려야 할까요?"
[6-15초] "최적화된 검색 체험"
- 동일한 타이레놀 검색 → 0.08초 즉시 응답
- "97% 빨라진 검색을 체험해보세요!"
- 응답 시간 비교 그래프 표시
[16-25초] "비용 효율성"
- API 호출 비용 비교 차트
- "월 $150 → $8, 95% 비용 절약"
[26-30초] "실제 사용해보기"
- GitHub 링크와 데모 사이트 주소 표시
- "지금 바로 테스트해보세요!"
- API Playground: api.pilling.xyz/playground
- 성능 대시보드: monitor.pilling.xyz
- API 문서: docs.pilling.xyz
git clone https://github.com/your-username/pilling-be
cd pilling-be
pip install -r requirements.txt
python manage.py migrate
python manage.py runserverdocker-compose up -d
# 모든 서비스가 자동으로 설정됩니다
# - Django API 서버
# - Redis 캐시
# - PostgreSQL 데이터베이스
# - Celery 백그라운드 작업💡 실제로 작동하는 데모를 통해 97% 성능 개선을 직접 체험해보세요!