API로 생물학 데이터베이스 조회하기
이 토픽을 마치면
Python requests 라이브러리로 NCBI와 UniProt API를 호출하고, JSON 응답에서 필요한 데이터를 추출하고, 여러 유전자를 반복문으로 조회할 수 있습니다.
API란
NCBI 웹사이트에서 유전자를 검색해본 적 있을 것입니다. 검색창에 "EGFR"을 입력하면 유전자 정보 페이지가 나옵니다. 이때 브라우저는 NCBI 서버에 **요청(request)**을 보내고, 서버가 **응답(response)**을 보내주는 것입니다.
**API(Application Programming Interface)**는 이 과정을 코드로 하는 것입니다. 브라우저 대신 Python이 요청을 보내고, HTML 대신 구조화된 데이터(JSON)로 응답을 받습니다.
실험 장비에 비유하면 — 시료를 넣고 버튼을 누르면 결과가 나오듯, API에 유전자 이름을 넣으면 정보가 나옵니다. 다만 사람이 버튼을 누르는 대신 코드가 자동으로 누릅니다.
requests 라이브러리
pip install requestsimport requests
response = requests.get("https://api.github.com")print(f"상태 코드: {response.status_code}")print(f"응답 데이터: {response.json()}")requests.get(URL) — 해당 URL에 GET 요청을 보냅니다. 웹 브라우저에서 URL을 입력하는 것과 같습니다.
상태 코드:
- 200 — 성공
- 404 — 존재하지 않는 URL
- 429 — 요청이 너무 많음 (rate limit)
- 500 — 서버 내부 에러
JSON: API 응답 형식
API는 대부분 JSON 형식으로 응답합니다. Python의 딕셔너리와 거의 같은 구조입니다:
{
"gene": "EGFR",
"organism": "Homo sapiens",
"chromosome": "7",
"aliases": ["ERBB1", "HER1"]
}Python에서 JSON 응답을 다루는 법:
import requests
response = requests.get("https://rest.uniprot.org/uniprotkb/P04637.json")data = response.json()
print(f"Protein: {data['proteinDescription']['recommendedName']['fullName']['value']}")print(f"Organism: {data['organism']['scientificName']}")print(f"Sequence length: {data['sequence']['length']}")response.json() — JSON 응답을 Python 딕셔너리로 변환합니다. 이후 data["key"]로 원하는 값을 꺼냅니다.
실전: UniProt API로 단백질 정보 가져오기
import requests
def get_protein_info(uniprot_id: str) -> dict: url = f"https://rest.uniprot.org/uniprotkb/{uniprot_id}.json" response = requests.get(url)
if response.status_code != 200: print(f"에러: {uniprot_id} — 상태 코드 {response.status_code}") return {}
data = response.json() return { "id": uniprot_id, "name": data["proteinDescription"]["recommendedName"]["fullName"]["value"], "organism": data["organism"]["scientificName"], "length": data["sequence"]["length"], }
info = get_protein_info("P04637")print(info)함수로 만들면 여러 단백질을 반복문으로 조회할 수 있습니다:
ids = ["P04637", "P00533", "P38398"]results = []
for uid in ids: info = get_protein_info(uid) if info: results.append(info) print(f" ✓ {info['name']} ({info['length']} aa)")
print(f"\n총 {len(results)}개 조회 완료")실전: NCBI E-utilities
NCBI는 E-utilities라는 API를 제공합니다. 유전자 검색, 서열 다운로드, 논문 검색 등을 코드로 할 수 있습니다.
import requests
gene_name = "BRCA1"url = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi"params = { "db": "gene", "term": f"{gene_name}[Gene Name] AND Homo sapiens[Organism]", "retmode": "json",}
response = requests.get(url, params=params)data = response.json()
gene_ids = data["esearchresult"]["idlist"]print(f"{gene_name} 검색 결과: {gene_ids}")params — URL 파라미터를 딕셔너리로 전달합니다. requests가 자동으로 URL에 ?db=gene&term=...을 붙여줍니다.
API 호출 시 예의: Rate Limiting
API는 무한히 호출할 수 없습니다. 서버에 부하를 주지 않도록 요청 간 간격을 두어야 합니다:
import timeimport requests
ids = ["P04637", "P00533", "P38398", "Q13315", "P42336"]
for uid in ids: info = get_protein_info(uid) if info: print(f" {info['name']}") time.sleep(0.5)time.sleep(0.5) — 0.5초 대기. NCBI는 초당 3회, UniProt은 초당 10회 정도를 권장합니다. 이것은 실험실에서 공용 장비 사용 예절과 같습니다 — 혼자 독점하면 다른 사람이 쓸 수 없습니다.
API 키
일부 API는 API 키를 요구합니다. NCBI E-utilities는 API 키 없이도 사용 가능하지만, 키를 등록하면 초당 요청 한도가 3회에서 10회로 늘어납니다.
params = { "db": "gene", "term": "TP53[Gene Name]", "retmode": "json", "api_key": "YOUR_API_KEY_HERE",}API 키는 절대 코드에 직접 적지 마세요. 환경 변수나 별도 설정 파일에 저장하고, Git에 올리지 않습니다.
에러 처리
네트워크 문제나 잘못된 ID로 API 호출이 실패할 수 있습니다:
import requests
def safe_api_call(url: str, params: dict = None) -> dict: try: response = requests.get(url, params=params, timeout=10) response.raise_for_status() return response.json() except requests.exceptions.Timeout: print("요청 시간 초과 — 나중에 다시 시도하세요") return {} except requests.exceptions.HTTPError as e: print(f"HTTP 에러: {e}") return {}timeout=10 — 10초 안에 응답이 없으면 포기합니다. 서버가 느릴 때 프로그램이 영원히 멈추는 것을 방지합니다.
직접 해보기 (Faded Example)
아래 빈칸을 채워 UniProt API에서 단백질 서열 길이를 가져오는 코드를 완성하세요.
importurl = "https://rest.uniprot.org/uniprotkb/P04637.json"response = requests.(url)if response.status_code == :data = response.()length = data["sequence"]["length"]print(f"서열 길이: {length} aa")
흔한 에러 & 해결법
Q: ConnectionError 또는 Timeout 에러가 납니다
인터넷 연결을 확인하세요. 서버가 일시적으로 다운되었을 수도 있습니다. time.sleep(5) 후 재시도하거나, 나중에 다시 실행하세요.
Q: KeyError가 나면서 JSON에서 값을 못 가져옵니다
API 응답의 구조가 예상과 다를 수 있습니다. print(json.dumps(data, indent=2))로 전체 응답을 출력해서 실제 키 구조를 확인하세요. 또는 data.get("key", "없음")으로 키가 없을 때 기본값을 반환하도록 하세요.
Q: API 응답이 HTML로 옵니다
URL이 웹페이지 주소(브라우저용)이지 API 주소가 아닐 수 있습니다. API 문서에서 정확한 엔드포인트를 확인하세요. 보통 /api/ 또는 .json 이 포함된 URL이 API용입니다.
Q: 429 Too Many Requests 에러가 납니다
너무 빨리 많은 요청을 보냈습니다. time.sleep(1) 등으로 요청 간격을 늘리세요. NCBI는 API 키 등록을 권장합니다.