[Python] REST API 개발둜 μ•Œμ•„λ³΄λŠ” WSGI, ASGI

λ°˜μ‘ν˜•

REST API μ„œλ²„λ₯Ό κ°œλ°œν•˜κΈ° μœ„ν•΄μ„œλŠ” 이제 νŠΉμ • μ–Έμ–΄λ₯Ό λ°°μ›Œμ•Ό ν•  ν•„μš” 없이 μ›ν•˜λŠ” μ–Έμ–΄λ‘œ 자유둭게 κ°œλ°œν•  수 μžˆλŠ” 세상이 였게 λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

 

Python μ–Έμ–΄ λ˜ν•œ λ‹€μ–‘ν•œ ν”„λ ˆμž„μ›Œν¬λ₯Ό μ œκ³΅ν•¨μœΌλ‘œμ¨ REST API μ„œλ²„λ₯Ό μ‰½κ²Œ κ°œλ°œν•  수 μžˆλŠ”λ°μš”. 이λ₯Ό μ œκ³΅ν•˜λŠ” λ‹€μ–‘ν•œ ν”„λ ˆμž„μ›Œν¬κ°€ 많이 μ‘΄μž¬ν•˜μ§€λ§Œ κ·Έ 쀑 κ°€μž₯ λ³΄νŽΈν™” λ˜μ–΄ μ•Œλ €μ§„ ν”„λ ˆμž„μ›Œν¬λŠ” μ•„λž˜μ˜ 두 가지 일 κ²ƒμž…λ‹ˆλ‹€.

 

  • Django
  • Flask

DjangoλŠ” MTV νŒ¨ν„΄μ„ μ œκ³΅ν•˜μ—¬ API 뿐만 μ•„λ‹ˆλΌ ν…œν”Œλ¦Ώμ„ μ΄μš©ν•˜μ—¬ 정적 HTML νŒŒμΌμ„ 생성해 λ·°λ₯Ό λ§Œλ“€ 수 μžˆλ„λ‘ μ œκ³΅ν•˜μ—¬ λΉ λ₯Έ κ°œλ°œμ„ 톡해 높은 생산성을 μžλž‘ν•˜λŠ” ν”„λ ˆμž„μ›Œν¬μž…λ‹ˆλ‹€. 반면 FlaskλŠ” 였직 APIλ§Œμ„ μ‰½κ²Œ μ œκ³΅ν•˜μ—¬ λΉ λ₯Έ API μ„œλ²„λ§Œμ„ λ§Œλ“€ 수 μžˆλ„λ‘ μ œκ³΅ν•˜λŠ” 것이 νŠΉμ§•μ΄μ£ .

 

Spring κ³„μ—΄μ—μ„œλŠ” μ΄λ ‡κ²Œ λ§Œλ“€μ–΄μ§„ μ›Ή μ„œλΉ„μŠ€λ₯Ό Tomcat λ“±μ˜ WAS둜 배포λ₯Ό ν•˜κ²Œ λ˜λŠ”λ°μš”. κ³΅κ΅λ‘­κ²Œλ„ Pythonμ—μ„œλŠ” μ΄λŸ¬ν•œ WASλ₯Ό μ œκ³΅ν•΄μ£Όμ§€ μ•ŠμŠ΅λ‹ˆλ‹€. κ·Έλ ‡λ‹€λ©΄ μ–΄λ–€ λ°©λ²•μœΌλ‘œ μ›Ή μ„œλ²„μ™€ Python μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ μ—°κ²°ν•  수 μžˆμ„κΉŒμš”?

 

 

 

 

CGI와 FastCGI

μ™ΈλΆ€ μ• ν”Œλ¦¬μΌ€μ΄μ…˜κ³Ό μ›Ή μ„œλ²„(nginx, Apache λ“±)와 μ—°κ²°ν•  λ–„ μ‚¬μš©ν•˜λŠ” μΈν„°νŽ˜μ΄μŠ€λ‘œ 보톡 CGIλ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€ CGIλŠ” Common Gateway Interface의 μ•½μžλ‘œ μ›Ή μ„œλ²„μ™€ μ™ΈλΆ€ ν”„λ‘œκ·Έλž¨μ„ μ—°κ²°ν•΄μ£ΌλŠ” ν‘œμ€€ν™”λœ ν”„λ‘œν† μ½œμž…λ‹ˆλ‹€.

 

μ΄λŸ¬ν•œ λͺ¨ν˜•μ€ μ›Ή μ„œλΉ„μŠ€μ˜ κ°€μž₯ 일반적인 λͺ¨μŠ΅μ΄μ§€λ§Œ κ³Όκ±°μ—λŠ” 정적 HTML 파일 ν•˜λ‚˜λ₯Ό 가지고 μ›Ή μ„œλΉ„μŠ€λ₯Ό ν•˜μ˜€κΈ° λ•Œλ¬Έμ— μ΄λŸ¬ν•œ μš”μ†Œ(CGI)κ°€ ν•„μš”ν•˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€. μ›Ή μ„œλ²„κ°€ 정적 파일 등을 μ‚¬μš©μžμ—κ²Œ λ‹€μš΄λ‘œλ“œ λ°©μ‹μœΌλ‘œ μ œκ³΅ν•˜λŠ” 것이 전뢀인데, 웹에 λŒ€ν•œ μˆ˜μš”κ°€ 증가함에 λ”°λΌμ„œ μ›Ή μ„œλ²„κ°€ μ²˜λ¦¬ν•  수 μ—†λŠ” 정보가 μš”μ²­λ˜μ—ˆμ„ 경우 κ·Έ 처리λ₯Ό μ™ΈλΆ€ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ΄ ν•  수 μžˆλ„λ‘ ν˜ΈμΆœν•¨μœΌλ‘œμ¨ 쀑계 역할을 ν•΄μ€λ‹ˆλ‹€.

 

κ·ΈλŸ¬λ‚˜ CGIλŠ” ν΄λΌμ΄μ–ΈνŠΈμ˜ μš”μ²­μ΄ λ°œμƒν•  λ•Œλ§ˆλ‹€ ν”„λ‘œμ„ΈμŠ€λ₯Ό μΆ”κ°€λ‘œ μƒμ„±ν•˜κ³  μ‚­μ œν•˜κ²Œ λ©λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄ μœ„ κ·Έλ¦Όκ³Ό 같이 λ‹€μˆ˜μ˜ μ‚¬μš©μžκ°€ λ™μ‹œμ— μš”μ²­ν•  경우 μƒˆλ‘œμš΄ ν”„λ‘œμ„ΈμŠ€λ₯Ό μƒμ„±ν•˜κ³ , μ‚­μ œν•˜λŠ” 것이 λΉˆλ²ˆν•΄μ§€λŠ”λ° μ΄λŠ” 컀널 λ¦¬μ†ŒμŠ€λ₯Ό 계속 생성/μ‚­μ œν•˜κΈ° λ•Œλ¬Έμ— μ˜€λ²„ν—€λ“œκ°€ 심해지고, μ„±λŠ₯ μ €ν•˜μ˜ 원인이 λ˜κΈ°λ„ ν•©λ‹ˆλ‹€.

 

ν˜„λŒ€μ˜ μ›Ή μ„œλΉ„μŠ€μ²˜λŸΌ λΉˆλ²ˆν•˜κ²Œ REST APIκ°€ 호좜 되고, μš”μ²­κ³Ό 응닡을 μˆ˜μ‹œλ‘œ λ°˜λ³΅ν•˜μ—¬ μ²˜λ¦¬ν•˜λŠ” κ³³μ—μ„œ μ΄λŸ¬ν•œ μ•„ν‚€ν…μ²˜λŠ” λ§žμ§€ μ•ŠμŠ΅λ‹ˆλ‹€. κ·Έλž˜μ„œ 생긴 것이 λ°”λ‘œ FastCGI μž…λ‹ˆλ‹€.

 

FastCGIλŠ” λͺ‡ 번의 μš”μ²­μ΄ 듀어와도 ν•˜λ‚˜μ˜ ν”„λ‘œμ„ΈμŠ€λ§Œμ„ 가지고 μ²˜λ¦¬ν•˜κ²Œ λ©λ‹ˆλ‹€. 즉 λ©”λͺ¨λ¦¬μ— 단 ν•˜λ‚˜μ˜ ν”„λ‘œκ·Έλž¨λ§Œμ„ μ μž¬ν•˜μ—¬ 계속 μž¬ν™œμš©ν•˜κΈ° λ•Œλ¬Έμ— CGI에 λΉ„ν•˜μ—¬ μ˜€λ²„ν—€λ“œκ°€ μ›”λ“±ν•˜κ²Œ κ°μ†Œν•©λ‹ˆλ‹€.

 

Java의 Tomcat λ˜ν•œ Web Server + FastCGIλ₯Ό μ±„νƒν•œ ν˜•νƒœλ‘œ λ‹€μˆ˜μ˜ μ‚¬μš©μž 접속에 μœ λ¦¬ν•©λ‹ˆλ‹€. μš°λ¦¬λŠ” JVM κ³„μ—΄μ˜ μ–Έμ–΄λ‘œ μ„œλ²„ ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜λ©΄ JBoss, Tomcat λ“±μ˜ μ›Ή μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ„œλ²„λ₯Ό μ‚¬μš©ν•˜λŠ” 게 λ³΄νŽΈμ μ΄μ§€λ§Œ 이 외에도 μš°λ¦¬κ°€ CGIλ₯Ό μˆ˜λ™μœΌλ‘œ λΆ™μ—¬μ„œ μ‚¬μš©ν•  수 μžˆλŠ” 방법도 μžˆμ—ˆμŠ΅λ‹ˆλ‹€.

 

κ·ΈλŸ¬λ‚˜ Pythonμ—μ„œλŠ” μ΄λŸ¬ν•œ WASκ°€ λ³„λ„λ‘œ μ‘΄μž¬ν•˜μ§€ μ•ŠμœΌλ©° κ²°κ΅­ μš°λ¦¬κ°€ CGI, FastCGI 등을 μ΄μš©ν•΄μ„œ μ›ν•˜λŠ” WAS ν˜•νƒœλ₯Ό λ§Œλ“€μ–΄ μ‚¬μš©ν•΄μ•Ό ν•˜λŠ”λ°, μ‹€μ œλ‘œ Pythonμ—μ„œλŠ” Python만의 κ²Œμ΄νŠΈμ›¨μ΄ μΈν„°νŽ˜μ΄μŠ€κ°€ μ‘΄μž¬ν•©λ‹ˆλ‹€.

 

 

 

 

WSGI

Python μ• ν”Œλ¦¬μΌ€μ΄μ…˜, μŠ€ν¬λ¦½νŠΈκ°€ μ›Ή μ„œλ²„μ™€ ν†΅μ‹ ν•˜κΈ° μœ„ν•œ μΈν„°νŽ˜μ΄μŠ€λ‘œμ¨ CGI λ””μžμΈ νŒ¨ν„΄μ„ λͺ¨νƒœλ‘œ ν•˜μ—¬ λ§Œλ“€μ–΄μ§„ κ²ƒμ΄μ§€λ§Œ μ‹€μ œ CGIμ™€λŠ” λ‹€μ†Œ 차이가 μžˆμŠ΅λ‹ˆλ‹€.

 

Python Web App을 MTV νŒ¨ν„΄κ³Ό 같이 λ·°κ°€ λ™μ‹œμ— μ μš©λ˜λŠ” ν”„λ ˆμž„μ›Œν¬λ₯Ό μ‚¬μš©ν•œλ‹€κ³  κ°€μ •ν–ˆμ„ λ–„ λͺ¨μŠ΅μ„ 같이 κ·Έλ €λ΄€μŠ΅λ‹ˆλ‹€. WSGIλŠ” CGI와 λ™μΌν•˜κ²Œ μ›Ή μ„œλ²„μ™€ μ• ν”Œλ¦¬μΌ€μ΄μ…˜ 쀑간에 μœ„μΉ˜ν•˜λŠ”λ°, CGI와 λ‹€λ₯Έ 점은 CGIλŠ” 맀 μš”μ²­λ§ˆλ‹€ ν”„λ‘œμ„ΈμŠ€λ₯Ό μƒμ„±ν•œλ‹€λŠ” 점이고, WSGIλŠ” ν•œ ν”„λ‘œμ„ΈμŠ€μ—μ„œ λͺ¨λ“  μš”μ²­μ„ λ°›λŠ”λ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€. μ’€ 더 λ””ν…ŒμΌν•˜κ²Œ μ„€λͺ…을 λ“œλ¦¬μžλ©΄ CGIλŠ” 맀 μš”μ²­λ§ˆλ‹€ Fork λ“±μ˜ ν•¨μˆ˜λ₯Ό 톡해 컀널 λ¦¬μ†ŒμŠ€λ₯Ό μΆ”κ°€/λ°˜λ‚©ν•˜κ³ , WSGIλŠ” λ§Žμ€ μš”μ²­μ„ 콜백(callback)으둜 λ°›μ•„ μ²˜λ¦¬ν•˜κ²Œ λ©λ‹ˆλ‹€.

 

μ΄λŸ¬ν•œ WSGI둜 λŒ€ν‘œμ μΈ 두 가지 방법이 μžˆμŠ΅λ‹ˆλ‹€.

 

  1. nginx, apacheμ—μ„œ λ‚΄μž₯ λͺ¨λ“ˆλ‘œ μ œκ³΅ν•˜λŠ” server-often high profile 방식 (ex: mod-wsgi, mod-python λ“±)
  2. Python μ½”λ“œλ‘œ μž‘μ„±λœ Web App Server (ex: gunicorn, cherrypy λ“±)

 

κ²°κ΅­ WSGIλŠ” μ›Ή μ„œλ²„μ™€ μ• ν”Œλ¦¬μΌ€μ΄μ…˜ 사이에 미듀웨어 역할을 ν•˜λ©° κΈ°μˆ μ μœΌλ‘œλŠ” μ›Ή μ„œλ²„λ„ WSGI에 λŒ€ν•œ μž‘λ™ μ½”λ“œκ°€ ν•„μš”ν•˜κ³ , μ• ν”Œλ¦¬μΌ€μ΄μ…˜ λ˜ν•œ WSGI에 λŒ€ν•œ μž‘λ™ μ½”λ“œκ°€ ν•„μš”ν•œ Client-Server Model을 μ‘μš©ν•œ 것이라고 보면 λ©λ‹ˆλ‹€. μ’€ 더 κ°„λ‹¨νžˆ μ„€λͺ…ν•΄λ³΄μžλ©΄, μ›Ή μ„œλ²„κ°€ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ μ½”λ“œλ₯Ό μ§μ ‘μ μœΌλ‘œ 읽을 수 μ—†μœΌλ―€λ‘œ μ€‘κ°„μ˜ 미듀웨어가 ν•΄λ‹Ή μ½”λ“œλ₯Ό μ½μ–΄μ„œ κ²°κ³Όλ₯Ό λŒ€μ‹  λ°˜ν™˜ν•΄μ£ΌλŠ” 녀석이라고 보면 λ©λ‹ˆλ‹€.

 

 

 

ASGI

WSGIλ§ŒμœΌλ‘œλ„ μš°λ¦¬λŠ” μΆ©λΆ„νžˆ ν΄λΌμ΄μ–ΈνŠΈμ˜ μš”μ²­μ„ μ›Ή μ„œλ²„κ°€ λ°›μ•„ λ‚΄ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μœΌλ‘œ 올 수 μžˆλ„λ‘ ꡬ성할 수 μžˆμ—ˆμŠ΅λ‹ˆλ‹€. ν•˜μ§€λ§Œ κ³΅κ΅λ‘­κ²Œλ„ μ΄κ²ƒλ§ŒμœΌλ‘œλŠ” ν˜„λŒ€ μ›Ή μ„œλΉ„μŠ€μ˜ λŒ€μš©λŸ‰ νŠΈλž˜ν”½ 처리λ₯Ό μœ μ—°ν•˜κ²Œ ν•˜κΈ° μœ„ν•œ 만쑱된 쑰건을 μΆ©μ‘±ν•˜κΈ° μ–΄λ €μš΄ 점이 μžˆμŠ΅λ‹ˆλ‹€.

 

Pythonμ—μ„œλŠ” asyncio, coroutineκ³Ό 같은 비동기 처리λ₯Ό μ§€μ›ν•©λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ WSGIλŠ” 동기 ν•¨μˆ˜ μ²˜λ¦¬λ§Œμ„ μ§€μ›ν•˜μ—¬ μ—¬λŸ¬ μž‘μ—…μ„ λ™μ‹œμ— μ²˜λ¦¬ν•˜λŠ” 것에 ν•œκ³„κ°€ μžˆμŠ΅λ‹ˆλ‹€. κ°€λ Ή ν˜„λŒ€ μ›Ή μ„œλΉ„μŠ€μ—μ„œλŠ” μ›Ή μ†ŒμΌ“ 등을 μ‚¬μš©ν•œ μ‹€μ‹œκ°„ μ±„νŒ… μ„œλΉ„μŠ€ 등을 ν•  μˆ˜λ„ μžˆλŠ”λ°, WSGIλ‘œλŠ” μ΄λŸ¬ν•œ μ„œλΉ„μŠ€λ₯Ό κ΅¬ν˜„ν•˜λŠ” 데 어렀움이 μžˆλŠ” 것이죠.

 

λ¬Όλ‘  μ•ˆλ˜λŠ” 것은 μ•„λ‹™λ‹ˆλ‹€. 비동기 큐와 같은 Celeryλ₯Ό 잘만 ν™œμš©ν•œλ‹€λ©΄ λŒ€μš©λŸ‰ νŠΈλž˜ν”½ 처리λ₯Ό μš”κ΅¬ν•˜λŠ” μ„œλΉ„μŠ€ κ΅¬ν˜„μ΄ λΆˆκ°€λŠ₯ν•œ 것은 μ•„λ‹ˆμ§€λ§Œ νŠΈλ ˆμ΄μ‹± λ“±κ³Ό 같은 μœ μ§€ 보수, 기본적인 κ΅¬ν˜„μ΄ 쉽지 μ•Šλ‹€λŠ” 점이 μžˆμŠ΅λ‹ˆλ‹€.

 

λ”°λΌμ„œ μ΅œκ·Όμ—λŠ” Django 3.0 뿐만 μ•„λ‹ˆλΌ FastAPI λ“±μ˜ ν”„λ ˆμž„μ›Œν¬μ—μ„œλ„ ASGI μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ μš©ν•˜μ˜€μœΌλ©° 뒀따라 Falcon ν”„λ ˆμž„μ›Œν¬λ„ 3.0λΆ€ν„° ASGI κ°œλ°œμ— λ“€μ–΄κ°”μŠ΅λ‹ˆλ‹€.

 

운영 μ•„ν‚€ν…μ²˜λ‘œ 봀을 λ•ŒλŠ” 크게 λ‹€λ₯΄μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ WSGI와 λ‹€λ₯΄κ²Œ ASGIλŠ” 기본적으둜 μš”μ²­μ„ λΉ„λ™κΈ°λ‘œ μ²˜λ¦¬ν•œλ‹€λŠ” 점이 ν½λ‹ˆλ‹€. λ”°λΌμ„œ WSGIμ—μ„œλŠ” μ§€μ›λ˜μ§€ μ•ŠλŠ” Websocket ν”„λ‘œν† μ½œκ³Ό HTTP 2.0을 μ§€μ›ν•©λ‹ˆλ‹€. 

 

 

Uvicorn

The lightning-fast ASGI server. Introduction Uvicorn is a lightning-fast ASGI server implementation, using uvloop and httptools. Until recently Python has lacked a minimal low-level server/application interface for asyncio frameworks. The ASGI specificatio

www.uvicorn.org

μ΄λŸ¬ν•œ λŒ€ν‘œμ μΈ ASGI Web Appμ—λŠ” uvicorn이 μžˆμŠ΅λ‹ˆλ‹€. uvicorn은 ASGI 기반의 μ›Ή μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ„œλ²„λ‘œμ¨ κ·Έ λ‚΄μž₯ λͺ¨λ“ˆλ‘œ uvloop을 μ‚¬μš©ν•©λ‹ˆλ‹€. μ•„λ§ˆ 듀어보신 뢄듀은 μ•„μ‹€ μˆ˜λ„ μžˆκ² μ§€λ§Œ uvloopμ—μ„œ uvλŠ” libuv 즉, Javascript V8μ—μ„œ μ‚¬μš©λ˜λŠ” 비동기 λͺ¨λ“ˆμ„ μ‚¬μš©ν•œ κ²ƒμž…λ‹ˆλ‹€. ASGIλŠ” Cython 기반으둜 C++ μ–Έμ–΄λ‘œ μž‘μ„±λ˜μ–΄ 맀우 λΉ λ₯Έ 속도λ₯Ό μ œκ³΅ν•œλ‹€λŠ” 것이 νŠΉμ§•μΈλ°λ‹€κ°€ libuvλ₯Ό μ‚¬μš©ν•˜μ—¬ 비동기 처리λ₯Ό ν•˜λ‹ˆ Node.js와 같은 비동기 처리 속도λ₯Ό μ–΄λŠ 정도 λˆ„λ¦΄ 수 μžˆλ‹€λŠ” μž₯점이 μžˆμŠ΅λ‹ˆλ‹€.

 

 

 

 

마치며...

Python을 μ΄μš©ν•˜μ—¬ μ›Ή μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ 배포할 수 μžˆλŠ” λ‹€μ–‘ν•œ 방법에 λŒ€ν•΄ μ•Œμ•„λ΄€μŠ΅λ‹ˆλ‹€. 

 

Pythonμ—μ„œλ„ Java와 λ§ˆμ°¬κ°€μ§€λ‘œ 비동기 μ²˜λ¦¬μ— λŒ€ν•΄ 관심을 보이고 있으며 그에 λŒ€μ•ˆμœΌλ‘œ WSGI의 μƒμœ„μΈ ASGIλ₯Ό κ°œλ°œν•˜μ˜€κ³ , 이미 λͺ‡λͺ‡ ν”„λ ˆμž„μ›Œν¬μ—μ„œ 지원을 ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.

 

μ–΄μ©Œλ‹€λ³΄λ‹ˆ Python μ§„μ˜μ— μ™€μ„œ λ°±μ—”λ“œ μ„œλ²„ κ°œλ°œμ„ 맑게 λ˜μ—ˆμ§€λ§Œ Python도 Java와 λ§ˆμ°¬κ°€μ§€λ‘œ μ—¬λŸ¬κ°€μ§€ μ‹ κ²½μ¨μ€˜μ•Ό ν•  뢀뢄듀이 λ§Žμ•˜μŠ΅λ‹ˆλ‹€. κ·Έλ ‡λ‹€λ³΄λ‹ˆ 이것저것 곡뢀λ₯Ό ν•˜κ²Œ λ˜μ—ˆκ³ , μ΄λ ‡κ²Œ 글을 μ“°κ²Œ λ˜μ—ˆλŠ”λ°μš”. μ°¨ν›„ Python 포슀트둜 REST API μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ κ°œλ°œν•œ μ‚½μ§ˆκΈ°μ— λŒ€ν•΄ μ—¬λŸ¬ 글을 써보고자 ν•©λ‹ˆλ‹€. 

 

 

 

 

 

 

λ°˜μ‘ν˜•
TAGS.

Tistory Comments