13장. REST API 와 FastAPI
API 와 REST
식당에서 손님은 메뉴판을 보고 주문서를 냅니다. 주방이 어떻게 요리하는지 몰라도 되고, 주방은 손님이 누구든 주문서만 맞으면 요리를 내보냅니다. 프로그램끼리도 이렇게 "무엇을 보내면 무엇이 돌아오는지"만 정해 두고 주고받습니다. 이 약속이 API 입니다.
왼쪽 클라이언트는 요청을 보내는 쪽입니다. 웹 화면, 모바일 앱, 다른 서버가 될 수 있습니다. 가운데 API 는 주소, 메서드, 보낼 JSON 의 꼴, 돌아올 JSON 의 꼴을 정한 약속입니다. 오른쪽 서버는 요청을 받아 모델로 예측하고 응답을 돌려줍니다. 여기서 손님이 클라이언트, 메뉴판과 주문서가 API, 주방이 서버입니다. 식당과 달리 API 는 같은 요청에 늘 같은 꼴의 답을 돌려줘야 합니다.
함수 부르기와 API 부르기
| 견줄 것 | 함수 부르기 | API 부르기 |
|---|---|---|
| 어디서 | 같은 파이썬 프로그램 안 | 네트워크 너머의 다른 프로그램 |
| 주고받는 것 | 파이썬 객체 | 글(JSON). 객체를 글로 바꿔 보낸다 |
| 언어 | 파이썬끼리 | 언어가 달라도 된다(자바스크립트, 자바 등) |
| 실패 | 예외 | 상태 코드(4xx, 5xx)와 오류 본문 |
| 시간 | 마이크로초 | 밀리초 이상(네트워크 왕복) |
요청과 응답은 JSON
import json
# 클라이언트가 보낼 주문 하나(파이썬 사전) → 네트워크로 보낼 글(JSON)
order = {"주문시각": 22, "지역": "지방", "거리km": 197.6, "무게kg": 4.6, "상품분류": "도서", "날씨": "눈", "택배사": "빠른별택배"}
body = json.dumps(order, ensure_ascii=False)
print(body)
# 서버가 돌려줄 응답의 꼴(설명용 숫자)
print(json.loads('{"지연확률": 0.83, "지연예상": true}'))코드에 나오는 함수
| 코드 | 쉬운 뜻 |
|---|---|
json.dumps(order, ensure_ascii=False) | dumps 는 dump string(글로 쏟아 내기)의 뜻이다. 파이썬 사전을 JSON 글로 바꾼다. ensure_ascii=False 는 한글을 부호로 바꾸지 않고 그대로 둔다 |
json.loads('...') | loads 는 load string(글에서 읽어 들이기)의 뜻이다. JSON 글을 파이썬 사전으로 되돌린다 |
true (JSON) | JSON 의 참이다. json.loads 를 거치면 파이썬의 True 가 된다 |
이 코드가 뜻하는 것
식당에서 손님은 머릿속으로 정한 주문을 정해진 칸이 있는 주문서에 적어 냅니다. 주방은 그 주문서를 읽고, 답을 쪽지에 적어 돌려줍니다. 손님은 쪽지를 읽어 다시 머릿속 내용으로 받아들입니다. 여기서 머릿속 주문이 파이썬 사전, 주문서에 적는 일이 json.dumps, 쪽지를 읽는 일이 json.loads 입니다.
| 줄 | 하는 일 | 쉽게 말하면 |
|---|---|---|
order = {...} | 주문 하나를 파이썬 사전으로 적는다 | 머릿속 주문 |
body = json.dumps(...) | 사전을 네트워크로 보낼 JSON 글로 바꾼다 | 주문서에 옮겨 적기 |
print(body) | 보낼 글을 보인다 | 주문서를 읽어 본다 |
json.loads('{...}') | 서버가 돌려줄 법한 JSON 글을 사전으로 읽는다 | 주방의 답 쪽지 읽기 |
실행하면 첫 줄에 {"주문시각": 22, "지역": "지방", ...} 꼴의 JSON 글이, 둘째 줄에 {'지연확률': 0.83, '지연예상': True} 가 나옵니다. JSON 글의 true 가 파이썬의 True 로 바뀌어 돌아온 것을 볼 수 있습니다.
작게 줄여서 눈으로 보기
True, None, 한글이 든 작은 사전을 JSON 으로 바꿔 봅니다.
import json
d = {"지연예상": True, "메모": None, "지역": "서울"}
print(json.dumps(d))
print(json.dumps(d, ensure_ascii=False))
back = json.loads(json.dumps(d))
print(back, type(back)){"\uc9c0\uc5f0\uc608\uc0c1": true, "\uba54\ubaa8": null, "\uc9c0\uc5ed": "\uc11c\uc6b8"}
{"지연예상": true, "메모": null, "지역": "서울"}
{'지연예상': True, '메모': None, '지역': '서울'} <class 'dict'>| 결과 | 읽는 법 |
|---|---|
| 첫 줄 | ensure_ascii 를 주지 않으면 한글을 \u 로 시작하는 부호로 바꿔 적는다. 받는 쪽이 되돌리면 같은 글이지만 사람이 읽기 어렵다 |
| 둘째 줄 | 한글이 그대로 남고, True 는 true, None 은 null 로 바뀌었다 |
| 셋째 줄 | JSON 글을 다시 읽으면 처음과 같은 파이썬 사전(dict)이 된다 |
주의할 점
- API 는 한번 공개하면 바꾸기 어렵습니다. 쓰는 쪽 프로그램이 그 꼴에 맞춰 만들어져 있기 때문입니다. 응답의 칸을 빼거나 이름을 바꿀 때는 판(버전)을 올립니다.
- JSON 에는 파이썬의
True,None대신true,null을 씁니다.json.dumps가 바꿔 줍니다.