[๊ฐœ๋…] API์— ๋Œ€ํ•ด์„œ ์ดํ•ดํ•ด๋ณด์ž!

Posted by Euisuk's Dev Log on April 27, 2025

[๊ฐœ๋…] API์— ๋Œ€ํ•ด์„œ ์ดํ•ดํ•ด๋ณด์ž!

์›๋ณธ ๊ฒŒ์‹œ๊ธ€: https://velog.io/@euisuk-chung/๊ฐœ๋…-API์—-๋Œ€ํ•ด์„œ-์ดํ•ดํ•ด๋ณด์ž

์ด๋ฏธ์ง€ ์ถœ์ฒ˜: https://appmaster.io/ko/blog/cobojareul-wihan-api-apireul-sayonghaneun-bangbeob-wanjeonhan-gaideu

  1. API๋Š” ๋ฌด์—‡์ธ๊ฐ€?

๐Ÿ’ก API๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์ธํ„ฐํŽ˜์ด์Šค(Application Programming Interface)์˜ ์ค„์ž„๋ง๋กœ,

  • ์†Œํ”„ํŠธ์›จ์–ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์„œ๋กœ ํ†ต์‹ ํ•˜๊ณ  ๋ฐ์ดํ„ฐ๋‚˜ ๊ธฐ๋Šฅ์„ ๊ตํ™˜ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ๊ทœ์น™์ด๋‚˜ ํ”„๋กœํ† ์ฝœ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
  • API๋ฅผ ํ†ตํ•ด ๊ฐœ๋ฐœ์ž๋Š” ๋‹ค๋ฅธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๊ธฐ๋Šฅ์„ ์ง์ ‘ ๊ตฌํ˜„ํ•˜์ง€ ์•Š๊ณ ๋„ ์‰ฝ๊ฒŒ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœ์„ ๊ฐ„์†Œํ™”ํ•˜๊ณ  ํšจ์œจ์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ณผ๊ฑฐ์—๋Š” ํ”„๋กœ๊ทธ๋žจ ๊ฐ„ ์ง์ ‘ ํ†ต์‹ ์ด ๋งค์šฐ ์–ด๋ ค์›Œ, ๊ฐœ๋ฐœ์ž๊ฐ€ ์ˆ˜์ž‘์—…์œผ๋กœ ์ผ์ผ์ด ๋Œ€์‘ํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค.

  • ํ•˜์ง€๋งŒ ํ˜„์žฌ๋Š” API๋ฅผ ํ†ตํ•ด ์ผ์ •ํ•œ ๊ตฌ์กฐ์™€ ๊ทœ์•ฝ์„ ์„ค์ •ํ•˜๊ณ  ํ†ต์‹ ํ•  ์ˆ˜ ์žˆ๊ธฐ์—,
  • ํ›จ์”ฌ ํšจ์œจ์ ์ด๊ณ  ์ฒด๊ณ„์ ์ธ ์‹œ์Šคํ…œ์„ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ” ๋น„์œ ํ•˜์ž๋ฉด, API๋Š” ์‹๋‹น์˜ ๋ฉ”๋‰ดํŒ ๊ฐ™์€ ๊ฒƒ์ž…๋‹ˆ๋‹ค:

  • ๊ณ ๊ฐ์ด ๋ฉ”๋‰ดํŒ์„ ๋ณด๊ณ  ์ฃผ๋ฌธํ•˜๋ฉด, ์ฃผ๋ฐฉ์€ ์ •ํ™•ํ•˜๊ฒŒ ์š”์ฒญ๋œ ๋ฉ”๋‰ด๋ฅผ ์ œ๊ณตํ•ด์ค๋‹ˆ๋‹ค.

๋˜ํ•œ, API๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด

  • ๋ฐ˜๋ณต์ ์ธ ์ฝ”๋“œ ์ž‘์„ฑ๋Ÿ‰์„ ์ค„์ด๊ณ ,
  • ์‚ฌ์šฉ์ž๋ณ„ ๋ฐ์ดํ„ฐ ์ ‘๊ทผ์„ ๋ณด๋‹ค ์•ˆ์ „ํ•˜๊ฒŒ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ,
  • ๋‚ด๋ถ€ ์‹œ์Šคํ…œ ๊ตฌ์ถ•์—๋„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฆ‰, API๋Š” ๊ฐœ๋ฐœ ์ƒ์‚ฐ์„ฑ๊ณผ ๋ณด์•ˆ์„ฑ์„ ๋ชจ๋‘ ํ–ฅ์ƒ์‹œํ‚ค๋Š” ํ•ต์‹ฌ ์ˆ˜๋‹จ์ด๋ผ๊ณ ๋„ ํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.


  1. 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())
    

  1. API ์‚ฌ์šฉ ์‹œ ๊ผญ ํ™•์ธํ•ด์•ผ ํ•  ์š”์†Œ/ํŒ

ํ™•์ธํ•ด์•ผ ํ•  ์š”์†Œ

API ์‚ฌ์šฉ ์‹œ์— ๊ผญ ํ™•์ธํ•ด์•ผ ํ•  ์š”์†Œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด 3๊ฐ€์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค:

  • Auth, HTTPS, CORS

Auth

  • ์„ค๋ช…: API ์š”์ฒญ์„ ์ธ์ฆํ•˜๋Š” ๋ฐฉ์‹ (apiKey, OAuth ๋“ฑ)
  • ๊ฒฐ๋ก : ์ธ์ฆ์ด ํ•„์š”ํ•œ API๋Š” ๋ฐ˜๋“œ์‹œ ํ‚ค๋‚˜ ํ† ํฐ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

HTTPS

  • ์„ค๋ช…: ๋ฐ์ดํ„ฐ๋ฅผ ์•”ํ˜ธํ™”ํ•˜์—ฌ ์•ˆ์ „ํ•˜๊ฒŒ ์ „์†กํ•˜๋Š” ํ”„๋กœํ† ์ฝœ
  • ๊ฒฐ๋ก : ๋ฏผ๊ฐํ•œ ์ •๋ณด๋ฅผ ๋‹ค๋ฃจ๋Š” ๊ฒฝ์šฐ HTTPS๋Š” ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค.

CORS

  • ์„ค๋ช…: ๋‹ค๋ฅธ ์ถœ์ฒ˜์˜ ์›น์‚ฌ์ดํŠธ์—์„œ API๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋„๋ก ํ—ˆ์šฉํ•˜๋Š” ์„ค์ •
  • ๊ฒฐ๋ก : ์›น ํ”„๋ก ํŠธ์—”๋“œ์—์„œ ์ง์ ‘ API๋ฅผ ํ˜ธ์ถœํ•  ๊ฒฝ์šฐ CORS ์ •์ฑ…์„ ๊ณ ๋ คํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ด ํ•ญ๋ชฉ๋“ค์€ API๋ฅผ ์•ˆ์ „ํ•˜๊ณ  ์ •์ƒ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ๊ผญ ํ™•์ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์œ ์šฉํ•œ ํŒ

public-api๋“ค์„ ๋ฆฌ์ŠคํŠธ์—… ํ•ด์„œ ์ •๋ฆฌยท์•„์นด์ด๋น™ํ•ด๋‘๋Š” ์ข‹์€ ๊นƒํ—™ ๋งํฌ๋“ค ๊ณต์œ ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

๋‹ค์–‘ํ•œ Index(ํ…Œ๋งˆ) ๋ณ„๋กœ API๋“ค์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


  1. ์‚ฌ์šฉ๋˜๋Š” ๋‹ค์–‘ํ•œ 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

  • ๊ฐœ๋…: ์„œ๋ฒ„-ํด๋ผ์ด์–ธํŠธ ๊ฐ„ ์–‘๋ฐฉํ–ฅ ํ†ต์‹ ์„ ์ง€์†์ ์œผ๋กœ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋Š” ํ”„๋กœํ† ์ฝœ.
  • ํŠน์ง•: ์—ฐ๊ฒฐ์ด ํ•œ๋ฒˆ ์„ฑ๋ฆฝ๋˜๋ฉด ๊ณ„์† ์—ด๋ฆฐ ์ฑ„๋กœ ๋ฉ”์‹œ์ง€๋ฅผ ์ฃผ๊ณ ๋ฐ›์„ ์ˆ˜ ์žˆ์–ด, ์ฑ„ํŒ…, ๊ฒŒ์ž„, ์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ ์ „์†ก ๋“ฑ์— ์ตœ์ ํ™”.

์ถœ์ฒ˜ : https://blog.algomaster.io/p/websockets

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 ์„œ๋ฒ„ ๊ตฌ์ถ•์— ๊ฐ€์žฅ ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๋Š” ํ”„๋ ˆ์ž„์›Œํฌ.

  1. API ์‚ฌ์šฉ ๋ฒ”์œ„์— ๋”ฐ๋ฅธ ๋ถ„๋ฅ˜

๊ตฌ๋ถ„ ์„ค๋ช…
Private API ๊ธฐ์—… ๋‚ด๋ถ€ ์ „์šฉ, ์™ธ๋ถ€์— ๊ณต๊ฐœํ•˜์ง€ ์•Š์Œ
Public API ๋ˆ„๊ตฌ๋‚˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ณต๊ฐœ๋œ API (ex. ๋‚ ์”จ API)
Partner API ํŠน์ • ํŒŒํŠธ๋„ˆ ๊ธฐ์—…์—๋งŒ ์ œํ•œ์ ์œผ๋กœ ์ œ๊ณต๋˜๋Š” API
Composite API ์—ฌ๋Ÿฌ API๋ฅผ ๊ฒฐํ•ฉํ•˜์—ฌ ๋ณตํ•ฉ์ ์ธ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ์ˆ˜ํ–‰

์ด์ฒ˜๋Ÿผ API๋Š” ์šฉ๋„์— ๋”ฐ๋ผ ๋‹ค์–‘ํ•œ ํ˜•ํƒœ๋กœ ์ œ๊ณต๋˜๋ฉฐ, ๋ฐ์ดํ„ฐ ๋ณด์•ˆ๊ณผ ์ ‘๊ทผ ํ†ต์ œ ๋ชฉ์ ์— ๋งž์ถฐ ์„ค๊ณ„๋ฉ๋‹ˆ๋‹ค.


  1. 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 ์—”๋“œํฌ์ธํŠธ๋ณ„ ํŠธ๋ž˜ํ”ฝ๊ณผ ์„ฑ๋Šฅ ์ด์Šˆ๋ฅผ ์‚ฌ์ „์— ์ ๊ฒ€ํ•ด์•ผ ํ•จ

  1. 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 ๊ธฐ๋ณธ๊ธฐ๋ฅผ ๋‹ค์ง€๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•˜๋‹ค๊ณ  ์ƒ๊ฐ๋ฉ๋‹ˆ๋‹ค.

์ฝ์–ด์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค ๐Ÿ˜Ž



-->