부록 E18: API와 데이터 수집
이 장에서 배울 것
이번 장에서는 API와 데이터 수집을 배웁니다. API는 프로그램이 다른 프로그램이나 서버에 정해진 방식으로 요청을 보내고 데이터를 받는 통로입니다. 생물정보학에서는 공개 데이터베이스에서 유전자, 단백질, 논문, 변이 정보를 가져올 때 API를 자주 씁니다.
핵심 용어를 먼저 정리하겠습니다.
- API(application programming interface): 프로그램끼리 정해진 규칙으로 데이터를 주고받게 해 주는 통로입니다. 앞으로는 API라고 부르겠습니다.
- 요청(request): 데이터를 달라고 서버에 보내는 메시지입니다.
- 응답(response): 서버가 돌려주는 결과입니다.
- REST API: 인터넷 주소와 HTTP 방식으로 데이터를 요청하는 API 형태입니다.
- JSON: key-value 구조로 데이터를 표현하는 텍스트 형식입니다.
- XML: 태그를 이용해 데이터를 표현하는 텍스트 형식입니다.
- 파싱(parsing): 받은 데이터에서 필요한 정보를 꺼내는 작업입니다.
- rate limit: 서버가 너무 많은 요청을 막기 위해 정한 요청 제한입니다.
- 페이지네이션(pagination): 결과가 많을 때 여러 페이지로 나누어 받는 방식입니다.
- 캐시(cache): 한 번 받은 데이터를 저장해 두고 다시 쓰는 방식입니다.
가장 쉬운 비유: 식당 주문 창구
API는 식당 주문 창구와 비슷합니다. 손님은 아무 말이나 하는 것이 아니라 메뉴판의 규칙에 맞춰 주문합니다. “김치찌개 하나 주세요”라고 요청하면 식당은 김치찌개를 줍니다.
데이터 서버도 비슷합니다. 정해진 주소와 규칙에 맞춰 요청하면, 서버는 JSON이나 XML 같은 형식으로 데이터를 돌려줍니다.
URL은 데이터 요청 주소입니다
웹사이트 주소처럼 보이는 URL은 데이터 요청 주소가 될 수 있습니다.
https://example.org/api/gene/TP53
이 주소는 “TP53 유전자 정보를 주세요”라는 요청처럼 설계될 수 있습니다. 실제 API마다 주소 규칙은 다릅니다. 그래서 API 문서를 읽는 습관이 중요합니다.
JSON 이해하기
JSON은 파이썬 딕셔너리와 비슷하게 생겼습니다.
{
"gene": "TP53",
"organism": "human",
"chromosome": "17"
}
여기서 gene, organism, chromosome은 key이고, 오른쪽 값은 value입니다. 파이썬에서는 JSON을 딕셔너리처럼 다룰 수 있습니다.
data = {
"gene": "TP53",
"organism": "human",
"chromosome": "17"
}
print(data["gene"])
결과는 다음과 같습니다.
TP53
파이썬으로 API 요청하기
파이썬에서는 requests 라이브러리를 자주 씁니다.
import requests
url = "https://example.org/api/gene/TP53"
response = requests.get(url)
data = response.json()
print(data)
여기서 requests.get(url)은 해당 주소로 요청을 보내는 코드입니다. response.json()은 응답을 JSON으로 해석해 파이썬 객체로 바꾸는 코드입니다.
실제 생물정보학에서는 NCBI, Ensembl, UniProt 같은 데이터베이스 API를 사용할 수 있습니다. 다만 각 사이트마다 주소와 요청 규칙이 다르므로 공식 문서를 확인해야 합니다.
XML도 만날 수 있습니다
XML은 태그로 데이터를 감싸는 형식입니다.
<gene>
<name>TP53</name>
<organism>human</organism>
</gene>
JSON보다 길어 보이지만, 생물학 데이터베이스에서는 XML 형식도 자주 등장합니다. 입문 단계에서는 “JSON은 딕셔너리처럼, XML은 태그 구조처럼 생겼다” 정도를 알면 됩니다.
rate limit: 너무 빨리 많이 요청하면 안 됩니다
공개 데이터베이스 서버는 많은 사람이 함께 씁니다. 짧은 시간에 너무 많은 요청을 보내면 서버에 부담을 줄 수 있습니다. 그래서 API는 보통 rate limit를 둡니다.
좋은 데이터 수집 코드는 다음 태도를 가져야 합니다.
필요한 데이터만 요청하기
요청 사이에 짧은 쉬는 시간 두기
이미 받은 데이터는 캐시하기
오류가 나면 무한 반복하지 않기
API 사용 규칙 확인하기
페이지네이션
검색 결과가 너무 많으면 한 번에 전부 주지 않고 여러 페이지로 나누어 줄 수 있습니다. 이것을 페이지네이션이라고 합니다.
예를 들어 1000개 결과가 있는데 한 번에 100개씩 준다면, 10번 요청해야 모든 결과를 받을 수 있습니다. 이때 다음 페이지 주소나 토큰을 잘 따라가야 합니다.
캐시와 재현성
API에서 받은 데이터는 시간이 지나면 바뀔 수 있습니다. 유전자 주석이나 단백질 정보가 업데이트될 수 있기 때문입니다. 그래서 중요한 분석에서는 언제, 어떤 API에서, 어떤 조건으로 데이터를 받았는지 기록해야 합니다.
캐시는 같은 요청을 반복하지 않기 위해 받은 결과를 저장하는 방식입니다. 서버 부담도 줄이고, 분석 재현성도 높일 수 있습니다.
실전 보강: API는 항상 정상 응답을 주지 않는다
API 요청은 인터넷을 통해 외부 서버에 질문하는 일입니다. 따라서 실패할 수 있습니다. 상태 코드(status code)는 요청 결과를 알려주는 숫자입니다.
200: 정상 응답
404: 요청한 주소나 자료를 찾을 수 없음
429: 너무 많이 요청해서 제한됨
500: 서버 쪽 오류
초보자는 requests.get(url).json()만 쓰고 끝내기 쉽지만, 실제 연구 코드에서는 상태 코드와 timeout을 확인해야 합니다.
response = requests.get(url, timeout=10)
if response.status_code == 200:
data = response.json()
else:
print(response.status_code)
실전 보강: 페이지네이션과 재현성 기록
API가 결과 10,000개를 한 번에 주지 않고 100개씩 나눠 줄 수 있습니다. 이것을 페이지네이션이라고 합니다. 첫 페이지만 저장하면 데이터가 일부만 수집됩니다.
또 API 데이터는 시간이 지나면 바뀔 수 있습니다. 그래서 다음 정보를 기록해야 합니다.
요청 URL
쿼리 조건
수집 날짜
API 버전
페이지 수
응답 파일 checksum 또는 저장 경로
숫자 감각: 페이지네이션 요청 수 계산하기
API 수집에서도 간단한 계산이 필요합니다. 검색 결과가 10,000개이고 API가 한 번에 100개씩만 돌려준다면 전체를 받으려면 최소 100번 요청해야 합니다.
전체 결과 수 = 10,000개
한 페이지 크기 = 100개
필요 페이지 수 = 10,000 / 100 = 100페이지
첫 페이지만 저장하면 전체의 1%만 수집한 셈입니다. 그래서 다음 페이지 토큰, 총 결과 수, 실제 저장한 개수를 함께 확인해야 합니다.
초보자가 자주 하는 오해
- 오해 1: API에서 받은 데이터는 항상 완전하다. 페이지네이션, rate limit, 오류 응답 때문에 일부만 받을 수 있습니다.
- 오해 2: JSON 구조는 영원히 같다. API 버전이 바뀌면 key 이름이나 구조가 바뀔 수 있습니다.
- 오해 3: 429가 뜨면 더 빠르게 재시도하면 된다. rate limit에 걸렸다는 뜻이므로 기다리거나 요청 속도를 줄여야 합니다.
- 오해 4: 캐시는 게으른 방식이다. 같은 요청을 반복하지 않고 재현성을 높이는 좋은 습관입니다.
이전 개념과 다음 개념의 연결
API로 받은 유전자 주석, 변이 정보, 문헌 정보는 E17 데이터베이스 구조로 정리할 수 있습니다. 수집 코드의 버전은 E19 Git으로 관리하고, 실행 환경은 E20으로 기록해야 합니다.
생물정보학에서 왜 중요한가
생물정보학 연구자는 모든 데이터를 직접 만들지 않습니다. 공개 데이터베이스에서 필요한 정보를 가져와 자신의 데이터와 합칩니다. 예를 들어 유전자 ID를 유전자 이름으로 바꾸거나, 변이에 질병 정보를 붙이거나, 단백질 기능 정보를 가져올 수 있습니다. API는 이런 작업을 자동화하게 해 줍니다.
미니 실습 블록: API로 받은 데이터를 파일과 로그로 남기기
이 실습은 API로 받은 데이터를 파일과 로그로 남기기를 직접 손으로 확인하는 연습입니다. 왜 필요한가 하면, API 데이터는 시간이 지나며 바뀔 수 있으므로 언제 어떤 주소에서 받았는지 기록해야 재현성이 생기기 때문입니다.
import requests
import json
from datetime import datetime
url = "https://example.org/api/gene/TP53"
response = requests.get(url)
data = response.json()
with open("results/tp53.json", "w") as f:
json.dump(data, f, indent=2)
with open("results/api_log.txt", "a") as log:
log.write(f"{datetime.now()}\t{url}\t{response.status_code}\n")
각 코드 요소의 의미를 풀어보면 다음과 같습니다. requests.get은 URL에 요청을 보내고, response.json()은 JSON 응답을 Python 객체로 바꿉니다. 로그에는 시간, URL, 상태코드를 남깁니다.
생물정보학/계산생물학에서 쓰이는 장면은 분명합니다. Ensembl, NCBI, UniProt 같은 데이터베이스에서 유전자·단백질 정보를 가져올 때 필요합니다.
흔한 오해 또는 주의점도 있습니다. API 결과를 매번 새로 받으면 데이터베이스 업데이트 때문에 과거 결과와 달라질 수 있습니다. 받은 원본 응답도 보관하는 것이 좋습니다.
핵심 정리
API는 프로그램이 데이터 서버에 정해진 방식으로 요청하고 응답을 받는 통로입니다. JSON과 XML은 API 응답에서 자주 보는 형식이며, 파이썬에서는 requests로 데이터를 가져올 수 있습니다. 좋은 데이터 수집은 rate limit, 페이지네이션, 캐시, 재현성 기록을 함께 고려해야 합니다.
문제 풀이
API와 데이터 수집
주관식 답안은 Gemini API로 채점합니다. API 키는 이 브라우저에만 저장됩니다.
-
1. [객관식] 객관식
API의 설명으로 적절한 것은?
-
2. [객관식] 객관식
요청(request)의 의미로 적절한 것은?
-
3. [객관식] 객관식
응답(response)의 의미로 적절한 것은?
-
4. [객관식] 객관식
JSON의 설명으로 적절한 것은?
-
5. [객관식] 객관식
XML의 설명으로 적절한 것은?
-
6. [객관식] 객관식
파싱(parsing)의 뜻으로 적절한 것은?
-
7. [객관식] 객관식
rate limit의 목적은?
-
8. [객관식] 객관식
페이지네이션(pagination)의 설명으로 적절한 것은?
-
9. [객관식] 객관식
캐시(cache)의 설명으로 적절한 것은?
-
10. [객관식] 객관식
requests.get(url)의 역할에 가까운 것은? -
11. [객관식] 객관식
response.json()의 역할로 적절한 것은? -
12. [객관식] 객관식
JSON 예시
{ "gene": "TP53" }에서gene은 무엇인가? -
13. [객관식] 객관식
JSON 예시
{ "gene": "TP53" }에서TP53은 무엇인가? -
14. [객관식] 객관식
공개 데이터베이스 API를 사용할 때 좋은 태도는?
-
15. [객관식] 객관식
API에서 받은 데이터가 시간이 지나면 바뀔 수 있는 이유는?
-
16. [객관식] 객관식
재현성을 위해 API 데이터 수집 시 기록할 것으로 적절한 것은?
-
17. [객관식] 객관식
API로 가져올 수 있는 생물정보 예시로 적절한 것은?
-
18. [객관식] 객관식
XML 예시
<name>TP53</name>에서 태그 안 값은? -
19. [객관식] 객관식
페이지네이션에서 다음 페이지 토큰을 놓치면 생길 수 있는 문제는?
-
20. [객관식] 객관식
API와 SQL의 차이에 대한 설명으로 적절한 것은?
-
21. [객관식] 객관식
API 응답 코드 429를 받았을 때 적절한 대응은?
-
22. [객관식] 객관식
API 응답 코드 404의 의미로 가장 적절한 것은?
-
23. [객관식] 객관식
페이지네이션을 무시하고 첫 페이지만 저장하면 생기는 문제는?
-
24. [객관식] 객관식
다음 JSON에서 gene 값은?
-
25. [객관식] 객관식
API 수집 코드에서
timeout=10을 주는 이유로 적절한 것은? -
26. [객관식] 객관식
API 데이터 재현성을 위해 기록해야 할 정보로 부적절한 것은?
-
27. [객관식] 객관식
같은 API 요청을 반복하지 않기 위해 응답을 파일로 저장해 두는 전략은?
-
28. [객관식] 객관식
API 응답 JSON 구조가 바뀌었을 때 깨지기 쉬운 코드는?
-
29. [객관식] 객관식
다음 코드에서 문제될 수 있는 점은?
-
30. [객관식] 객관식
공개 데이터베이스 API에서 오늘 받은 결과와 1년 뒤 받은 결과가 달라질 수 있는 이유는?
-
31. [실전] 객관식
API 요청 로그에 URL과 날짜를 남기는 이유는?
-
32. [실전] 객관식
HTTP status code가 200이 아니라면 우선 해야 할 일은?
-
주관식 33. [응용] 주관식 · Gemini 채점
API를 식당 주문 창구 비유로 설명하라.
-
주관식 34. [응용] 주관식 · Gemini 채점
JSON과 XML의 차이를 간단히 설명하라.
-
주관식 35. [응용] 주관식 · Gemini 채점
rate limit를 지켜야 하는 이유를 설명하라.
-
주관식 36. [응용] 주관식 · Gemini 채점
캐시가 API 데이터 수집에서 유용한 이유를 설명하라.
-
주관식 37. [응용] 주관식 · Gemini 채점
페이지네이션이 있는 API에서 주의할 점을 설명하라.
-
주관식 38. [응용] 주관식 · Gemini 채점
API에서 받은 생물정보를 분석에 사용할 때 기록해야 할 것을 설명하라.
-
주관식 39. [응용] 주관식 · Gemini 채점
API 수집 코드에서 상태 코드, timeout, 페이지네이션을 확인해야 하는 이유를 설명하라.
-
주관식 40. [응용] 주관식 · Gemini 채점
API로 받은 데이터를 재현 가능하게 저장하기 위한 기록 항목을 쓰라.
-
주관식 41. [실습] 주관식 · Gemini 채점
API 응답 JSON을
results/tp53.json에 저장하는 Python 코드의 핵심 부분을 작성하라. -
주관식 42. [실습] 주관식 · Gemini 채점
API 데이터 수집에서 provenance가 중요한 이유를 설명하라.