[๊ฐ๋ ] API์ ๋ํด์ ์ดํดํด๋ณด์!
์๋ณธ ๊ฒ์๊ธ: https://velog.io/@euisuk-chung/๊ฐ๋ -API์-๋ํด์-์ดํดํด๋ณด์
์ด๋ฏธ์ง ์ถ์ฒ: https://appmaster.io/ko/blog/cobojareul-wihan-api-apireul-sayonghaneun-bangbeob-wanjeonhan-gaideu
-
API๋ ๋ฌด์์ธ๊ฐ?
๐ก API๋ ์ ํ๋ฆฌ์ผ์ด์ ํ๋ก๊ทธ๋๋ฐ ์ธํฐํ์ด์ค(
Application Programming Interface
)์ ์ค์๋ง๋ก,
- ์ํํธ์จ์ด ์ ํ๋ฆฌ์ผ์ด์ ์ด ์๋ก ํต์ ํ๊ณ ๋ฐ์ดํฐ๋ ๊ธฐ๋ฅ์ ๊ตํํ ์ ์๋๋ก ํ๋ ๊ท์น์ด๋ ํ๋กํ ์ฝ์ ์๋ฏธํฉ๋๋ค.
- API๋ฅผ ํตํด ๊ฐ๋ฐ์๋ ๋ค๋ฅธ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ธฐ๋ฅ์ ์ง์ ๊ตฌํํ์ง ์๊ณ ๋ ์ฝ๊ฒ ํ์ฉํ ์ ์์ผ๋ฉฐ, ์ ํ๋ฆฌ์ผ์ด์ ๊ฐ๋ฐ์ ๊ฐ์ํํ๊ณ ํจ์จ์ฑ์ ๋์ผ ์ ์์ต๋๋ค.
๊ณผ๊ฑฐ์๋ ํ๋ก๊ทธ๋จ ๊ฐ ์ง์ ํต์ ์ด ๋งค์ฐ ์ด๋ ค์, ๊ฐ๋ฐ์๊ฐ ์์์ ์ผ๋ก ์ผ์ผ์ด ๋์ํด์ผ ํ์ต๋๋ค.
- ํ์ง๋ง ํ์ฌ๋ API๋ฅผ ํตํด ์ผ์ ํ ๊ตฌ์กฐ์ ๊ท์ฝ์ ์ค์ ํ๊ณ ํต์ ํ ์ ์๊ธฐ์,
- ํจ์ฌ ํจ์จ์ ์ด๊ณ ์ฒด๊ณ์ ์ธ ์์คํ ์ ๊ตฌ์ถํ ์ ์์ต๋๋ค.
๐ ๋น์ ํ์๋ฉด, API๋ ์๋น์ ๋ฉ๋ดํ ๊ฐ์ ๊ฒ์ ๋๋ค:
- ๊ณ ๊ฐ์ด ๋ฉ๋ดํ์ ๋ณด๊ณ ์ฃผ๋ฌธํ๋ฉด, ์ฃผ๋ฐฉ์ ์ ํํ๊ฒ ์์ฒญ๋ ๋ฉ๋ด๋ฅผ ์ ๊ณตํด์ค๋๋ค.
๋ํ, API๋ฅผ ์ฌ์ฉํ๋ฉด
- ๋ฐ๋ณต์ ์ธ ์ฝ๋ ์์ฑ๋์ ์ค์ด๊ณ ,
- ์ฌ์ฉ์๋ณ ๋ฐ์ดํฐ ์ ๊ทผ์ ๋ณด๋ค ์์ ํ๊ฒ ์ ์ดํ ์ ์์ผ๋ฉฐ,
- ๋ด๋ถ ์์คํ ๊ตฌ์ถ์๋ ํ์ฉํ ์ ์์ต๋๋ค.
์ฆ, API๋ ๊ฐ๋ฐ ์์ฐ์ฑ๊ณผ ๋ณด์์ฑ์ ๋ชจ๋ ํฅ์์ํค๋ ํต์ฌ ์๋จ์ด๋ผ๊ณ ๋ ํ ์ ์์ ๊ฒ ๊ฐ์ต๋๋ค.
-
API๋ ์ด๋ป๊ฒ ์๋ํ๋๊ฐ?
์ด๋ฏธ์ง ์ถ์ฒ: https://assaeunji.github.io/development/2020-08-29-api/
API๋ ํญ์ ์์ฒญ(Request) ๊ณผ ์๋ต(Response) ๊ตฌ์กฐ๋ฅผ ๋ฐ๋ฆ ๋๋ค.
- ์์ฒญ(Request): ํด๋ผ์ด์ธํธ(์ฌ์ฉ์)๊ฐ ์๋ฒ์ ํ์ํ ์ ๋ณด๋ฅผ ์๊ตฌํ๋ ๊ฒ.
- ์๋ต(Response): ์๋ฒ๊ฐ ์์ฒญ์ ์ฒ๋ฆฌํ ํ ํด๋ผ์ด์ธํธ์๊ฒ ๊ฒฐ๊ณผ๋ฅผ ๋๋ ค์ฃผ๋ ๊ฒ.
์ด ๊ณผ์ ์ ์ฃผ๋ก HTTP ํต์ ๋ฐฉ์์ ๋ฐ๋ฅด๋ฉฐ,
GET(์กฐํ)
,POST(์์ฑ)
,PUT(์์ )
,DELETE(์ญ์ )
๋ฑ์ ๋ฉ์๋๋ฅผ ์ฌ์ฉํฉ๋๋ค.
- ์๋ต ๋ฐ์ดํฐ๋ ๋๋ถ๋ถ JSON ํ์์ ํตํด ์ ๋ฌ๋ฉ๋๋ค.
JSON (JavaScript Object Notation):
Key
์Value
๋ก ๊ตฌ์ฑ๋ ๊ฐ๋ณ๊ณ ์ง๊ด์ ์ธ ๋ฐ์ดํฐ ํ์์ ๋๋ค.
API ํต์ ๋ฐฉ์์ ๋ค์๊ณผ ๊ฐ์ด ๋ค์ํ ์ ํ์ด ์กด์ฌํฉ๋๋ค:
SOAP API
: XML์ ์ฌ์ฉํ์ฌ ์๊ฒฉํ ๊ท์น ํ์ ํต์ ํ๋ ๋ฐฉ์RPC API
: ์๋ฒ์ ํจ์๋ฅผ ์๊ฒฉ์ผ๋ก ํธ์ถํ์ฌ ์๋ต๋ฐ๋ ๋ฐฉ์WebSocket API
: ์ค์๊ฐ ์๋ฐฉํฅ ํต์ ์ ์ง์ํ๋ ๋ฐฉ์REST API
: ๊ฐ์ฅ ๋๋ฆฌ ์ฐ์ด๋ฉฐ HTTP ๊ธฐ๋ฐ์ผ๋ก ์์(Resource)์ ์ฃผ๊ณ ๋ฐ๋ ๋ฐฉ์
๐ค ์ต๊ทผ FAST API๋ ๋ง์ด ๋ณด์ด๋๋ฐ, ์ด๊ฑด ํต์ ๋ฐฉ์์ด ์๋๊ฐ?
- FastAPI๋ Python์ผ๋ก API ์๋ฒ๋ฅผ ์ฝ๊ฒ ๊ตฌ์ถํ ์ ์๊ฒ ํด์ฃผ๋ ์น ํ๋ ์์ํฌ์ ๋๋ค.
- FastAPI๋ API๋ฅผ ๋ง๋๋ โ
๋๊ตฌ(tool)
โ์ด์ง, โํต์ ํ๋กํ ์ฝ
โ์ด๋ โํต์ ๋ฐฉ์
โ ์์ฒด๋ผ๊ณ ๋ณผ ์๋ ์์ต๋๋ค.
๐ผ FastAPI๋ฅผ ํตํด ๋ณดํต ์ฌ์ฉํ๋ ํต์ ๋ฐฉ์์?
- FastAPI๋ฅผ ์ด์ฉํด ๋ง๋ API ์๋ฒ๋ ์ฃผ๋ก RESTful API ํต์ ๋ฐฉ์์ ๋ฐ๋ฅด๊ฒ ๋ฉ๋๋ค.
- ์ฆ, HTTP ๋ฉ์๋(GET, POST ๋ฑ)์ URI(ํตํฉ์์์๋ณ์, Uniform Resource Identifier) ๊ฒฝ๋ก๋ฅผ ์ฌ์ฉํด์ ํต์ ํ๋ ๊ตฌ์กฐ)
- ๋ํ, FastAPI๋ Python ๊ธฐ๋ฐ์ด๊ธฐ ๋๋ฌธ์, ๋น๋๊ธฐ ํต์ (Async) ๋ ์์ฐ์ค๋ฝ๊ฒ ์ง์ํ๊ณ , WebSocket ํต์ ๋ ๋ณ๋ ์ค์ ์ผ๋ก ๊ตฌ์ถํ ์ ์์ต๋๋ค.
FastAPI ํจ์ ์์:
1
2
3
4
5
6
7
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def read_root():
return {"message": "Hello, World!"}
-> ์ฌ๊ธฐ์ async def
๋ฅผ ์ด ์ด์ ๊ฐ ๋ฐ๋ก ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ์ํด์ def
์์ async
๋ฅผ ์ฌ์ฉํจ
async
๋ Python 3.5 ๋ฒ์ ๋ถํฐ ๋์ ๋ ๊ณต์ ๋ฌธ๋ฒ์ผ๋ก,await
์ ์์ผ๋ก ์ฌ์ฉ๋จ.async def
:์ด ํจ์๋ โ๋น๋๊ธฐ์ ์ผ๋ก ์คํ๋ ์ ์๋ ํจ์โ. (Coroutine ์์ฑ)await
: ์ด ํจ์ ์์์, โ์ด๋ค ๋น๋๊ธฐ ์์ โ์ด ๋๋ ๋๊น์ง ๋๊ธฐ.
๐ฟ ์.. ๋น๋๊ธฐ/๋๊ธฐ ๊ทธ๊ฒ ๋ญ๋ฐ
์ด๋ฏธ์ง ์ถ์ฒ : https://geekpython.medium.com/asyncio-how-to-use-async-await-in-python-ef4372a8c2c5
โ๏ธ ๋๊ธฐ ํต์ (Synchronous Communication)์,
- ์์ฒญ(Request)์ ๋ณด๋ธ ๋ค์, ์๋ต(Response)์ด ์ฌ ๋๊น์ง โ๊ธฐ๋ค๋ ค์ผ๋งโ ๋ค์ ์์ ์ ํ ์ ์๋ ๋ฐฉ์์ ๋๋ค.
-
๋น์ :
- ์๋น์์ ์์์ ์ฃผ๋ฌธํ๊ณ , ์์์ด ๋์ฌ ๋๊น์ง ํ ์ด๋ธ์ ์์ ๊ธฐ๋ค๋ฆฌ๋ ๊ฒ. (๋์ฌ ๋๊น์ง ๋ค๋ฅธ ์ผ์ ๋ชป ํจ)
Python ์์ (requests ์ฌ์ฉ):
1 2 3 4 5
import requests response = requests.get('https://api.example.com/data') print(response.text) # ์์ฒญ ๋๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฐ ๋ค์ ์คํ
โ๏ธ ๋น๋๊ธฐ ํต์ (Asynchronous Communication)์
- ์์ฒญ(Request)์ ๋ณด๋ธ ๋ค, โ๊ธฐ๋ค๋ฆฌ์ง ์๊ณ โ ๋ฐ๋ก ๋ค์ ์์ ์ ์ฒ๋ฆฌํ๋ ๋ฐฉ์์ ๋๋ค.
-
๋น์ :
- ์๋น์์ ์์์ ์ฃผ๋ฌธํ๊ณ , ์ง๋๋ฒจ์ ๋ฐ์ ์์ ๋กญ๊ฒ ๋์๋ค๋๋ค๊ฐ ๋ฒจ์ด ์ธ๋ฆฌ๋ฉด ์์์ ๋ฐ์ผ๋ฌ ๊ฐ๋ ๊ฒ. (๊ธฐ๋ค๋ฆฌ๋ ๋์ ๋ค๋ฅธ ์ผ์ ํ ์ ์์)
Python ์์ (httpx ๋น๋๊ธฐ ๋ฒ์ ):
1 2 3 4 5 6 7 8 9 10
import httpx import asyncio async def fetch_data(): async with httpx.AsyncClient() as client: response = await client.get('https://api.example.com/data') print(response.text) # ์๋ต ์ค๋น๋๋ฉด ์คํ asyncio.run(fetch_data())
-
API ์ฌ์ฉ ์ ๊ผญ ํ์ธํด์ผ ํ ์์/ํ
ํ์ธํด์ผ ํ ์์
API ์ฌ์ฉ ์์ ๊ผญ ํ์ธํด์ผ ํ ์์๋ ๋ค์๊ณผ ๊ฐ์ด 3๊ฐ์ง๊ฐ ์์ต๋๋ค:
Auth
,HTTPS
,CORS
Auth
- ์ค๋ช : API ์์ฒญ์ ์ธ์ฆํ๋ ๋ฐฉ์ (apiKey, OAuth ๋ฑ)
- ๊ฒฐ๋ก : ์ธ์ฆ์ด ํ์ํ API๋ ๋ฐ๋์ ํค๋ ํ ํฐ์ด ํ์ํฉ๋๋ค.
HTTPS
- ์ค๋ช : ๋ฐ์ดํฐ๋ฅผ ์ํธํํ์ฌ ์์ ํ๊ฒ ์ ์กํ๋ ํ๋กํ ์ฝ
- ๊ฒฐ๋ก : ๋ฏผ๊ฐํ ์ ๋ณด๋ฅผ ๋ค๋ฃจ๋ ๊ฒฝ์ฐ HTTPS๋ ํ์์ ๋๋ค.
CORS
- ์ค๋ช : ๋ค๋ฅธ ์ถ์ฒ์ ์น์ฌ์ดํธ์์ API๋ฅผ ํธ์ถํ ์ ์๋๋ก ํ์ฉํ๋ ์ค์
- ๊ฒฐ๋ก : ์น ํ๋ก ํธ์๋์์ ์ง์ API๋ฅผ ํธ์ถํ ๊ฒฝ์ฐ CORS ์ ์ฑ ์ ๊ณ ๋ คํด์ผ ํฉ๋๋ค.
์ด ํญ๋ชฉ๋ค์ API๋ฅผ ์์ ํ๊ณ ์ ์์ ์ผ๋ก ์ฌ์ฉํ๊ธฐ ์ํด ๊ผญ ํ์ธํด์ผ ํฉ๋๋ค.
์ ์ฉํ ํ
public-api
๋ค์ ๋ฆฌ์คํธ์
ํด์ ์ ๋ฆฌยท์์นด์ด๋นํด๋๋ ์ข์ ๊นํ ๋งํฌ๋ค ๊ณต์ ๋๋ฆฝ๋๋ค.
- (์๋ฌธ) https://github.com/public-apis/public-apis
- (ํ๊ธ) https://github.com/dl0312/open-apis-korea
๋ค์ํ Index(ํ ๋ง) ๋ณ๋ก API๋ค์ ํ์ธํ ์ ์์ต๋๋ค.
-
์ฌ์ฉ๋๋ ๋ค์ํ API ํ์
๋ฐ์ดํฐ ๋ถ์๊ฐ๋ ๊ณผํ์์๊ฒ API๋ ๋จ์ํ ๊ธฐ์ ์ด ์๋๋ผ, ๋ฐ์ดํฐ๋ฅผ ์์งํ๊ณ ๋ถ์ ์์ ์ ์๋ํํ๋ ํต์ฌ ๋๊ตฌ์ ๋๋ค.
๋ค์ํ API ํ์์ด ์กด์ฌํ๋ ์ด์ ๋
- ๋ฐ์ดํฐ์ ์ฑ๊ฒฉ
- ํต์ ์ ์ค์๊ฐ์ฑ
- ๋ฐ์ดํฐ์๊ณผ ์๋ต์๋ ์ต์ ํ
๋ฑ์ ๊ณ ๋ คํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
๊ฐ๊ฐ์ ์กฐ๊ธ ๋ ๊น์ด ์ดํด๋ด ๋๋ค.
[1] API โํ์โ (๋ฐ์ดํฐ ์ฃผ๊ณ ๋ฐ๋ ๊ตฌ์กฐ)
REST API
์ถ์ฒ : https://stdio-han.tistory.com/88
- ๊ฐ๋ : ์น์์ ๋ฆฌ์์ค๋ฅผ URI๋ก ์๋ณํ๊ณ HTTP ๋ฉ์๋(GET, POST ๋ฑ)๋ฅผ ํตํด ์กฐ์ํ๋ ๊ฐ์ฅ ๋ณดํธ์ ์ธ ๋ฐฉ์.
- ํฌ๋งท: ์ฃผ๋ก JSON. (๊ฐํน XML)
- ํน์ง: ๋ฌด์ํ์ฑ, ๋จ์์ฑ, ๋ฒ์ฉ์ฑ.
- ํ์ฉ: ๊ณต๊ณต๋ฐ์ดํฐํฌํธ, ์ฃผ์, ๊ธฐ์์ฒญ ๋ฐ์ดํฐ ์์ง.
GraphQL
์ถ์ฒ : https://www.wallarm.com/what/what-is-graphql-definition-with-example
- ๊ฐ๋ : ํด๋ผ์ด์ธํธ๊ฐ ํ์ํ ๋ฐ์ดํฐ๋ง ๋ช ์์ ์ผ๋ก ์์ฒญํ ์ ์๋ ์ฟผ๋ฆฌ ๊ธฐ๋ฐ API.
- ํฌ๋งท: ์์ฒญ๊ณผ ์๋ต ๋ชจ๋ JSON.
- ํน์ง: ๋จ ํ๋์ Endpoint, ๊ณผ์์ฒญ/๊ณผ์์์ฒญ ๋ฌธ์ ํด๊ฒฐ.
- ํ์ฉ: GitHub, Shopify ๋ฑ ๋ณต์กํ ๊ด๊ณํ ๋ฐ์ดํฐ ์์ฒญ.
gRPC
์ถ์ฒ : https://www.oreilly.com/library/view/grpc-up-and/9781492058328/ch01.html
- ๊ฐ๋ : Google์ด ๊ฐ๋ฐํ ์ด๊ณ ์ ์ด์ง ํต์ ํ๋กํ ์ฝ.
- ํฌ๋งท: Protocol Buffers (๋ฐ์ด๋๋ฆฌ ์ง๋ ฌํ)
- ํน์ง: ๋งค์ฐ ๋น ๋ฆ. ์๋ฒ-์๋ฒ ๊ฐ ํต์ ์ต์ ํ.
- ํ์ฉ: ๋ง์ดํฌ๋ก์๋น์ค ์ํคํ ์ฒ, ์ด๋์ฉ๋ ๋ฐ์ดํฐ ์คํธ๋ฆฌ๋ฐ.
JSON-RPC
์ถ์ฒ: https://lab.wallarm.com/what/json-rpc%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80/?lang=ko
- ๊ฐ๋ : JSON ํฌ๋งท์ ๊ธฐ๋ฐ์ผ๋ก ์๊ฒฉ ํจ์ ํธ์ถ์ ํ์คํํ ํ๋กํ ์ฝ.
- ํฌ๋งท: JSON.
- ํน์ง: ๊ฐ๋ณ๊ณ ๋จ์ํจ.
- ํ์ฉ: ๋ด๋ถ ์๋น์ค ํธ์ถ, ๊ฐ๋ฒผ์ด ์๋ฒ ํต์ (์: MCP).
[2] API โํต์ ํ๋กํ ์ฝโ (๋ฐ์ดํฐ๋ฅผ ์ด๋ป๊ฒ ์ฃผ๊ณ ๋ฐ์๊น?)
HTTP/HTTPS
- ๊ฐ๋ : ์น ์๋ฒ์ ํด๋ผ์ด์ธํธ ๊ฐ ๊ธฐ๋ณธ ํต์ ๋ฐฉ์. HTTP๋ ๋น์ํธํ, HTTPS๋ ์ํธํ๋ ํต์ ์ ์ง์.
- ํน์ง: ์น API ๋๋ถ๋ถ์ด HTTP/HTTPS ๊ธฐ๋ฐ์ผ๋ก ๋์ํฉ๋๋ค.
์ถ์ฒ : https://han288.tistory.com/167
WebSocket
- ๊ฐ๋ : ์๋ฒ-ํด๋ผ์ด์ธํธ ๊ฐ ์๋ฐฉํฅ ํต์ ์ ์ง์์ ์ผ๋ก ์ ์งํ ์ ์๋ ํ๋กํ ์ฝ.
- ํน์ง: ์ฐ๊ฒฐ์ด ํ๋ฒ ์ฑ๋ฆฝ๋๋ฉด ๊ณ์ ์ด๋ฆฐ ์ฑ๋ก ๋ฉ์์ง๋ฅผ ์ฃผ๊ณ ๋ฐ์ ์ ์์ด, ์ฑํ , ๊ฒ์, ์ค์๊ฐ ๋ฐ์ดํฐ ์ ์ก ๋ฑ์ ์ต์ ํ.
SSE (Server-Sent Events)
- ๊ฐ๋ : ์๋ฒ๊ฐ ํด๋ผ์ด์ธํธ๋ก ๋จ๋ฐฉํฅ ์ค์๊ฐ ์คํธ๋ฆฌ๋ฐ์ ํ๋ ํต์ ๋ฐฉ์.
- ํน์ง: ์๋ฒ์์ ํด๋ผ์ด์ธํธ๋ก๋ง ์ด๋ฒคํธ๋ฅผ ์ง์์ ์ผ๋ก ํธ์. HTTP ๊ธฐ๋ฐ์ด๋ผ ๋ธ๋ผ์ฐ์ ์์ ์ฝ๊ฒ ์ฌ์ฉ ๊ฐ๋ฅ.
์ถ์ฒ : https://gong-check.github.io/dev-blog/BE/%EC%96%B4%EC%8D%B8%EC%98%A4/sse/sse/
SSE ํน์ง ์์ฝ
ํญ๋ชฉ | ์ค๋ช |
---|---|
ํต์ ๋ฐฉํฅ | ์๋ฒ โ ํด๋ผ์ด์ธํธ (๋จ๋ฐฉํฅ) |
์ฐ๊ฒฐ ๋ฐฉ์ | ์ฅ์๊ฐ ์ ์ง๋๋ HTTP ์ฐ๊ฒฐ |
์ธ์ฆ ์ง์ | JWT, API Key ์ธ์ฆ ๊ฐ๋ฅ |
์ฉ๋ | ์น์ฑ, ์๋ฆผ ์์คํ , ์คํธ๋ฆฌ๋ฐ ๋์๋ณด๋ ๋ฑ |
์์ | MCP Server C๊ฐ Remote Service์ ์ฐ๊ฒฐํ ๋ |
STDIO (Standard Input/Output)
- ๊ฐ๋ : ์ด์์ฒด์ ์์ค์ ํ์ค ์ ๋ ฅ(stdin)๊ณผ ํ์ค ์ถ๋ ฅ(stdout) ์คํธ๋ฆผ์ ์ด์ฉํ ํต์ ๋ฐฉ์.
- ํน์ง: ์๋ฒ์ ํด๋ผ์ด์ธํธ๊ฐ ๊ฐ์ ๋จธ์ ์์์ ๋์ํ๋ฉฐ, ํ์ผ์ฒ๋ผ ๋ฐ์ดํฐ ์คํธ๋ฆผ์ ์ฃผ๊ณ ๋ฐ์ต๋๋ค.
์ถ์ฒ ใ ฃ https://medium.com/@vkrishnan9074/mcp-clients-stdio-vs-sse-a53843d9aabb
STDIO ํน์ง ์์ฝ
ํญ๋ชฉ | ์ค๋ช |
---|---|
ํต์ ๋ฐฉํฅ | ํด๋ผ์ด์ธํธ โ ์๋ฒ (์๋ฐฉํฅ) |
์ฐ๊ฒฐ ๋ฐฉ์ | stdin/stdout ์คํธ๋ฆผ |
์ธ์ฆ ์ง์ | ์์ (๋ก์ปฌ ํ๋ก์ธ์ค๋ผ ๋ถํ์) |
์ฉ๋ | ์ปค๋งจ๋๋ผ์ธ ํด, ๋ก์ปฌ ํ ์คํธ, ๋ด๋ถ ํต์ |
์์ | MCP Server A, B์ Local Data ์ฐ๊ฒฐ ์ |
๐ฅ๐ฅ ์ฐธ๊ณ : ์ต๊ทผ ํซํ MCP ์๋ฒ๋
STDIO
,SSE
๋ ๋ค ์ง์ํฉ๋๋ค.
- ์ถ์ฒ : https://medium.com/@vkrishnan9074/mcp-clients-stdio-vs-sse-a53843d9aabb
STDIO ๋ชจ๋
๋ ๋น ๋ฅธ ๋ก์ปฌ ์ฐ๊ฒฐ์ฉ (ex: IDE, ๋ก์ปฌ ํด)SSE ๋ชจ๋
๋ ๋คํธ์ํฌ ๋์ด ๋ค์ ํด๋ผ์ด์ธํธ ์ฐ๊ฒฐ์ฉ (ex: ์น ๊ธฐ๋ฐ MCP ํด๋ผ์ด์ธํธ)
[3] API ์๋ฒ ๊ตฌ์ถ ํ๋ ์์ํฌ
Python ๊ธฐ๋ฐ
- FastAPI: ์ด๊ณ ์ ๋น๋๊ธฐ API ์๋ฒ. ํ์ ํํธ ํ์ฉ, OpenAPI ๋ฌธ์ ์๋ ์์ฑ.
- Flask: ๋งค์ฐ ๊ฐ๋ณ๊ณ ๋จ์ํ API ์๋ฒ ๊ตฌ์ถ. ์ปค์คํฐ๋ง์ด์ง ์ ์ฐํจ.
- Django REST Framework: Django ๊ธฐ๋ฐ API ๊ตฌ์ถ์ฉ ํ์ฅ ๋ผ์ด๋ธ๋ฌ๋ฆฌ.
Node.js ๊ธฐ๋ฐ
-
Express.js: Node.js์์ ๊ฐ์ฅ ๋์ค์ ์ธ ์น/REST API ์๋ฒ ํ๋ ์์ํฌ.
-
NestJS: ๋๊ท๋ชจ ๋ฐฑ์๋ ์์คํ ์ ์ํ ๊ตฌ์กฐํ๋ Node.js ๊ธฐ๋ฐ ํ๋ ์์ํฌ. TypeScript ์ง์.
Java ๊ธฐ๋ฐ
- Spring Boot: ์ํฐํ๋ผ์ด์ฆ ๊ธ ์น/REST API ์๋ฒ ๊ตฌ์ถ์ ๊ฐ์ฅ ๋๋ฆฌ ์ฌ์ฉ๋๋ ํ๋ ์์ํฌ.
-
API ์ฌ์ฉ ๋ฒ์์ ๋ฐ๋ฅธ ๋ถ๋ฅ
๊ตฌ๋ถ | ์ค๋ช |
---|---|
Private API | ๊ธฐ์ ๋ด๋ถ ์ ์ฉ, ์ธ๋ถ์ ๊ณต๊ฐํ์ง ์์ |
Public API | ๋๊ตฌ๋ ์ฌ์ฉํ ์ ์๋๋ก ๊ณต๊ฐ๋ API (ex. ๋ ์จ API) |
Partner API | ํน์ ํํธ๋ ๊ธฐ์ ์๋ง ์ ํ์ ์ผ๋ก ์ ๊ณต๋๋ API |
Composite API | ์ฌ๋ฌ API๋ฅผ ๊ฒฐํฉํ์ฌ ๋ณตํฉ์ ์ธ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ์ํ |
์ด์ฒ๋ผ API๋ ์ฉ๋์ ๋ฐ๋ผ ๋ค์ํ ํํ๋ก ์ ๊ณต๋๋ฉฐ, ๋ฐ์ดํฐ ๋ณด์๊ณผ ์ ๊ทผ ํต์ ๋ชฉ์ ์ ๋ง์ถฐ ์ค๊ณ๋ฉ๋๋ค.
-
Python์ผ๋ก ๊ฐ๋จํ๊ฒ API์ ํต์ ํด ๋ณด์
์์1: Kakao ์ฑ ๊ฒ์ API ์ฌ์ฉํ๊ธฐ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import requests
url = "https://dapi.kakao.com/v3/search/book"
params = {
"query": "ํ์ด์ฌ",
"sort": "accuracy",
"target": "title"
}
headers = {
"Authorization": "KakaoAK {REST_API_KEY}"
}
response = requests.get(url, params=params, headers=headers)
if response.status_code == 200:
result = response.json()
for book in result['documents']:
print(f"์ ๋ชฉ: {book['title']}")
print(f"์๊ฐ: {book['contents']}")
print(f"์ธ๋ค์ผ: {book['thumbnail']}\n")
else:
print("API ์์ฒญ ์คํจ", response.status_code)
์์1 ์ถ๋ ฅ ๊ฒฐ๊ณผ
์์2: Kakao ์น๋ฌธ์ ๊ฒ์ API ์ฌ์ฉํ๊ธฐ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import requests
# Kakao Web ๋ฌธ์ ๊ฒ์ API URL
url = "https://dapi.kakao.com/v2/search/web"
# ๊ฒ์ํ ํ๋ผ๋ฏธํฐ ์ค์
params = {
"query": "์ดํจ๋ฆฌ", # ๊ฒ์ํ ํค์๋
"sort": "accuracy", # ์ ํ๋์ ์ ๋ ฌ
"page": 1, # 1ํ์ด์ง
"size": 10 # ํ ๋ฒ์ 10๊ฐ ๋ฌธ์ ๊ฐ์ ธ์ค๊ธฐ
}
# ์ธ์ฆ ํค๋ ์ค์ (์ฌ๊ธฐ์ ๋ณธ์ธ REST API ํค ๋ฃ์ด์ผ ํจ)
headers = {
"Authorization": f"KakaoAK {REST_API_KEY}"
}
# GET ์์ฒญ ๋ณด๋ด๊ธฐ
response = requests.get(url, params=params, headers=headers)
# ๊ฒฐ๊ณผ ์ฒ๋ฆฌ
if response.status_code == 200:
result = response.json()
for doc in result['documents']:
print(f"์ ๋ชฉ: {doc['title']}")
print(f"๋ณธ๋ฌธ ์์ฝ: {doc['contents']}")
print(f"URL: {doc['url']}")
print(f"์์ฑ์ผ์: {doc['datetime']}\n")
else:
print("API ์์ฒญ ์คํจ", response.status_code)
์์2 ์ถ๋ ฅ ๊ฒฐ๊ณผ
Python์ ์ฌ์ฉํ๋ฉด ์ด๋ ๊ฒ ๊ฐ๋จํ ์ธ๋ถ API์ ํต์ ํ ์ ์์ผ๋ฉฐ, API ๊ตฌ์กฐ์ ํต์ ํ๋ฆ์ ์ง์ ์ฒดํํ ์ ์์ต๋๋ค.
๋ํ API ํตํฉ ์ ๊ณ ๋ คํด์ผ ํ ์ ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
- ๋ฐ์ดํฐ ๋ชจ๋ธ(์์ฒญ/์๋ต ํฌ๋งท)์ ์ดํดํ๊ณ ์ค๊ณํด์ผ ํจ
- ์ธ์ฆ ๋ฐฉ์๊ณผ ๊ถํ ์ ์ด ๋ก์ง์ ๋ช ํํ ์ค์ ํด์ผ ํจ
- API ์๋ํฌ์ธํธ๋ณ ํธ๋ํฝ๊ณผ ์ฑ๋ฅ ์ด์๋ฅผ ์ฌ์ ์ ์ ๊ฒํด์ผ ํจ
-
FastAPI ๊ฐ๋จ ์๊ฐ
โก
FastAPI
๋ Python 3.6+ ์ด์ ๋ฒ์ ์์ ์ฌ์ฉํ ์ ์๋ ํ๋์ ์ด๊ณ ๋น ๋ฅธ ์น ํ๋ ์์ํฌ์ ๋๋ค.
์ฃผ์ ํน์ง์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- ๋น ๋ฅธ ๊ฐ๋ฐ ์๋: ํ์ ํํธ๋ฅผ ์ฌ์ฉํด ์ฝ๋ ์๋ ์์ฑ๊ณผ ๋ฌธ์ ์๋ํ
- ๊ณ ์ฑ๋ฅ: ๋น๋๊ธฐ(Asyncio) ๊ธฐ๋ฐ์ผ๋ก ๋น ๋ฅธ ์๋ต ์ ๊ณต
- ์๋ ๋ฌธ์ํ: Swagger UI, Redoc ์ง์
- Pydantic ๊ธฐ๋ฐ ๋ฐ์ดํฐ ์ ํจ์ฑ ๊ฒ์ฌ
๊ฐ๋จํ FastAPI ์ฝ๋ ์์:
1
2
3
4
5
6
7
8
9
10
11
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.post("/items/")
def create_item(item: dict):
return {"item": item}
์๋ฒ ์คํ:
1
uvicorn main:app --reload
main
์ ํ์ผ๋ช ,app
์ FastAPI ๊ฐ์ฒด๋ช ์ ๋๋ค.
๋ง์น๋ฉฐ
์ด๋ฒ ๊ธ์์๋ API์ ๋ํด ์ ๋ฆฌํ๊ณ , ๋ค์ํ API ํต์ ํ์๊ณผ ๊ตฌ์ถ ํ๋ ์์ํฌ๊น์ง ์ดํด๋ณด์์ต๋๋ค.
๋ฐ์ดํฐ ๋ถ์๊ฐ๋ ๋ฐ์ดํฐ ๊ณผํ์์๊ฒ๋ API์ ๋ํ ์ดํด๋ ์ ์ ๋ ํ์ํ ์ญ๋์ด ๋๊ณ ์์ต๋๋ค.
ํนํ ์ต๊ทผ์๋ MCP์ ๊ฐ์ด JSON-RPC ๋ฐ SSE์ ๊ฐ์ ํต์ ๋ฐฉ์์ ์ฌ์ฉํ๋ ํ๋กํ ์ฝ์ด ์ฃผ๋ชฉ๋ฐ๊ณ ์์ด, ์๋ก์ด ํธ๋ ๋๋ฅผ ๋ฐ๋ผ๊ฐ๊ธฐ ์ํด์๋ผ๋ API ๊ธฐ๋ณธ๊ธฐ๋ฅผ ๋ค์ง๋ ๊ฒ์ด ์ค์ํ๋ค๊ณ ์๊ฐ๋ฉ๋๋ค.
์ฝ์ด์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค ๐