MLOps, Docker๋กœ ์ฒซ๋ฐœ์„ ๋‚ด๋”›๋‹ค

๊ธฐ์ˆ  ์„ธ๋ฏธ๋‚˜ ์ฃผ์ œ๋Š” โ€œDocker๋กœ ๋ฐฐ์šฐ๋Š” MLOpsโ€. ์ด๋ก  ๊ณต๋ถ€๋ฅผ ๋„˜์–ด, ์‹ค์ œ ์šด์˜ ํ™˜๊ฒฝ์„ ๋‚ด ์†์œผ๋กœ ๊ตฌ์ถ•ํ•ด๋ณด๋Š” ์‹œ๊ฐ„์ด์—ˆ๋‹ค. ๋ชจ๋ธ๋งŒ ๋ƒ…๋‹ค ๋งŒ๋“œ๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ, ๋ฐ์ดํ„ฐ ์ˆ˜์ง‘๋ถ€ํ„ฐ ๋ฐฐํฌ, ๋ชจ๋‹ˆํ„ฐ๋ง๊นŒ์ง€ ์ „์ฒด ํŒŒ์ดํ”„๋ผ์ธ์„ ์„ค๊ณ„ํ•˜๋Š” ์•„์ฃผ ํŠน๋ณ„ํ•œ ๊ฒฝํ—˜์ด์—ˆ๋‹ค. ๊ณผ์—ฐ ์„ฑ๊ณตํ–ˆ์„๊นŒ? ๐Ÿค”

๐Ÿ”ฅ ์šฐ๋ฆฌ ํŒ€์˜ ๋ชฉํ‘œ

  • ์ฝ”๋“œ ๊ธฐ๋ฐ˜ ์ธํ”„๋ผ (IaC): docker-compose.yml ํ•˜๋‚˜๋กœ ๋ชจ๋“  ํ™˜๊ฒฝ์„ ํ†ต์ผํ•œ๋‹ค. โ€œ์ œ ์ปดํ“จํ„ฐ์—์„  ๋๋Š”๋ฐ์š”?โ€๋Š” ์ด์ œ ๊ทธ๋งŒ!
  • MLOps ํŒŒ์ดํ”„๋ผ์ธ ์ •๋ณต: ๋ฐ์ดํ„ฐ ์ˆ˜์ง‘-ํ•™์Šต-๋ฐฐํฌ-๋ชจ๋‹ˆํ„ฐ๋ง์˜ ํ๋ฆ„์„ ์ง์ ‘ ๋งŒ๋“ค๊ณ  ์ดํ•ดํ•œ๋‹ค.
  • MSA ์•„ํ‚คํ…์ฒ˜ ์ฒดํ—˜: ๊ฐ ๊ธฐ๋Šฅ์„ ๋…๋ฆฝ ์„œ๋น„์Šค๋กœ ์ชผ๊ฐœ ์œ ์—ฐํ•œ ์‹œ์Šคํ…œ์„ ์„ค๊ณ„ํ•ด๋ณธ๋‹ค.

๐Ÿง‘โ€๐Ÿ’ป ์‹œ์Šคํ…œ ์•„ํ‚คํ…์ฒ˜: ์šฐ๋ฆฌ๋Š” ์ด๋ ‡๊ฒŒ ๋งŒ๋“ค์—ˆ๋‹ค

ํ”„๋กœ์ ํŠธ์˜ ์‹ฌ์žฅ, MSA ๊ธฐ๋ฐ˜ ์•„ํ‚คํ…์ฒ˜๋‹ค. ๊ฐ์ž ๋งก์€ ์„œ๋น„์Šค๊ฐ€ docker-compose ์•ˆ์—์„œ ์œ ๊ธฐ์ ์œผ๋กœ ๋Œ์•„๊ฐ€๋„๋ก ์„ค๊ณ„ํ–ˆ๋‹ค.

MLOps Diagram

์„œ๋น„์Šค ์—ญํ•  ํ•ต์‹ฌ ๊ธฐ์ˆ 
MLflow Server ๋ชจ๋ธ ์‹คํ—˜/๋ฒ„์ „ ๊ด€๋ฆฌ, ์•„ํ‹ฐํŒฉํŠธ ์ €์žฅ MLflow, minio
PostgreSQL DB ๋ฐ์ดํ„ฐ ์ €์žฅ, MLflow ๋ฐฑ์—”๋“œ mySQL
DB Ingestion ์™ธ๋ถ€ ๋ฐ์ดํ„ฐ ์ˆ˜์ง‘ ๋ฐ DB ์ ์žฌ Python
Inference Server ์˜ˆ์ธก API ์ œ๊ณต FastAPI
Visualizer Server ์˜ˆ์ธก ๊ฒฐ๊ณผ ์‹œ๊ฐํ™” ๋Œ€์‹œ๋ณด๋“œ Streamlit

๋‚˜๋Š” ์ด ์ค‘์—์„œ Visualizer Server๋ฅผ ๋งก์•˜๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ๋ชจ๋ธ์˜ ์˜ˆ์ธก ๊ฒฐ๊ณผ๋ฅผ ๋ˆˆ์œผ๋กœ ๋ณด๊ณ , ์ง์ ‘ ํ”ผ๋“œ๋ฐฑ๊นŒ์ง€ ๋‚จ๊ธธ ์ˆ˜ ์žˆ๋Š” ์ฐฝ๊ตฌ๋ฅผ ๋งŒ๋“œ๋Š” ์ผ. ๋ฐ์ดํ„ฐ์™€ ์‚ฌ๋žŒ์ด ๋งŒ๋‚˜๋Š” ์ ‘์ ์„ ๋งŒ๋“ ๋‹ค๋Š” ๊ฒŒ ์ฐธ ๋งค๋ ฅ์ ์ด์—ˆ๋‹ค.


๐Ÿ› ๏ธ ํ”„๋กœ์ ํŠธ ์—ฐ์žฅ ๋ชจ์Œ

  • ์ปจํ…Œ์ด๋„ˆ: Docker, Docker-Compose
  • ML ํŒŒ์ดํ”„๋ผ์ธ: MLflow, minio
  • ๋ฐฑ์—”๋“œ: FastAPI
  • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค: mySQL
  • ํ”„๋ก ํŠธ์—”๋“œ: Streamlit

์ด ๋„๊ตฌ๋“ค์„ ์—ฎ์–ด ์ผ๊ด€์„ฑ ์žˆ๊ณ  ์žฌํ˜„ ๊ฐ€๋Šฅํ•œ MLOps ํ™˜๊ฒฝ์„ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ํ•ต์‹ฌ ๊ณผ์ œ์˜€๋‹ค.


โœจ ํŒŒ์ดํ”„๋ผ์ธ์€ ์ด๋ ‡๊ฒŒ ํ๋ฅธ๋‹ค: ๊ฐ ์„œ๋ฒ„์˜ ์—ญํ• 

์šฐ๋ฆฌ ํŒŒ์ดํ”„๋ผ์ธ์€ ๊ฐ์ž ๋ช…ํ™•ํ•œ ์—ญํ• ์„ ๊ฐ€์ง„ ์„œ๋น„์Šค๋“ค์˜ ํ˜‘๋ ฅ์œผ๋กœ ์ด๋ฃจ์–ด์ง„๋‹ค.

  1. ๋ฐ์ดํ„ฐ ์ˆ˜์ง‘ (db-ingestion-server): ๋ชจ๋“  ๊ฒƒ์˜ ์‹œ์ž‘. Kaggle API๋กœ ์›๋ณธ ๋ฐ์ดํ„ฐ๋ฅผ ๋‚ด๋ ค๋ฐ›์•„ ๊ฐ„๋‹จํ•œ ์ „์ฒ˜๋ฆฌ๋ฅผ ๊ฑฐ์นœ ํ›„, PostgreSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์•ˆ์ •์ ์œผ๋กœ ์ €์žฅํ•˜๋Š” ์ž„๋ฌด๋ฅผ ์ˆ˜ํ–‰ํ•œ๋‹ค. ํŒŒ์ดํ”„๋ผ์ธ์— ์‹ ์„ ํ•œ ํ”ผ๋ฅผ ๊ณต๊ธ‰ํ•˜๋Š” ์—ญํ• !

  2. ๋ชจ๋ธ ํ•™์Šต ๋ฐ ์‹คํ—˜ ๊ด€๋ฆฌ (mlflow-client & mlflow-server): mlflow-client๊ฐ€ PostgreSQL์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊บผ๋‚ด ๋ชจ๋ธ์„ ํ•™์Šต์‹œํ‚จ๋‹ค. ์ด ๊ณผ์ •์—์„œ ์‚ฌ์šฉ๋œ ๋ชจ๋“  ํŒŒ๋ผ๋ฏธํ„ฐ, ์„ฑ๋Šฅ ๋ฉ”ํŠธ๋ฆญ, ๊ทธ๋ฆฌ๊ณ  ํ•™์Šต๋œ ๋ชจ๋ธ ํŒŒ์ผ(์•„ํ‹ฐํŒฉํŠธ)๊นŒ์ง€ mlflow-server์— ๊ผผ๊ผผํ•˜๊ฒŒ ๊ธฐ๋กํ•œ๋‹ค. ์—ฌ๊ธฐ์„œ ๊ฐ€์žฅ ์„ฑ๋Šฅ ์ข‹์€ ๋ชจ๋ธ์„ ์„ ๋ณ„ํ•ด MLflow Model Registry์— โ€˜Productionโ€™ ๋ฒ„์ „์œผ๋กœ ๋”ฑ์ง€๋ฅผ ๋ถ™์—ฌ ๋“ฑ๋กํ•œ๋‹ค. ๐Ÿ‘‘

  3. ์‹ค์‹œ๊ฐ„ ์ถ”๋ก  API (inference-server): FastAPI๋กœ ๋งŒ๋“ค์–ด์ง„ ์ด ์„œ๋ฒ„๋Š” Model Registry๋ฅผ ๊ณ„์† ์ฃผ์‹œํ•˜๋‹ค๊ฐ€, โ€˜Productionโ€™ ๋”ฑ์ง€๊ฐ€ ๋ถ™์€ ์ตœ์‹  ๋ชจ๋ธ์„ ์ž๋™์œผ๋กœ ๊ฐ€์ ธ์˜จ๋‹ค. ๊ทธ๋ฆฌ๊ณ  /predict๋ผ๋Š” API ์—”๋“œํฌ์ธํŠธ๋ฅผ ํ†ตํ•ด ๋ชจ๋ธ์˜ ์˜ˆ์ธก ๊ธฐ๋Šฅ์„ ์™ธ๋ถ€ ์„ธ๊ณ„์— ์ œ๊ณตํ•œ๋‹ค.

  4. ์‚ฌ์šฉ์ž ๋Œ€์‹œ๋ณด๋“œ (visualizer-server): Streamlit์œผ๋กœ ๊ตฌํ˜„๋œ ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค. ์‚ฌ์šฉ์ž๊ฐ€ ๋Œ€์‹œ๋ณด๋“œ์—์„œ โ€œ์˜ˆ์ธกโ€ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด, visualizer-server๋Š” inference-server์˜ /predict API๋กœ ์š”์ฒญ์„ ๋ณด๋‚ธ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์‘๋‹ต์œผ๋กœ ๋ฐ›์€ ์˜ˆ์ธก ๊ฒฐ๊ณผ๋ฅผ ์‚ฌ์šฉ์ž์—๊ฒŒ ์นœ์ ˆํ•œ ๊ทธ๋ž˜ํ”„์™€ ํ•จ๊ป˜ ๋ณด์—ฌ์ฃผ๋Š” ์ž„๋ฌด๋ฅผ ๋งก์•˜๋‹ค. ๋ชจ๋ธ๊ณผ ์‚ฌ์šฉ์ž๊ฐ€ ๋งŒ๋‚˜๋Š” ์ตœ์ „์„ !

๐ŸŽ‰ ์„ฑ๊ณต์˜ ์ˆœ๊ฐ„!

docker-compose upโ€ฆ ์ˆ˜๋งŽ์€ ์„œ๋น„์Šค๊ฐ€ ํ„ฐ๋ฏธ๋„ ์œ„๋กœ ์˜ฌ๋ผ์˜ค๋ฉฐ ๊ฐ์ž์˜ ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋งˆ์นจ๋‚ด, ๋‚ด๊ฐ€ ๋งŒ๋“  Streamlit ๋Œ€์‹œ๋ณด๋“œ์— FastAPI ์„œ๋ฒ„๊ฐ€ ์˜ˆ์ธกํ•œ ๊ฒฐ๊ณผ๊ฐ€ ๋”ฑ! ํ•˜๊ณ  ๋–ด์„ ๋•Œ. ๊ทธ ์งœ๋ฆฟํ•จ์€ ์ •๋ง ์žŠ์„ ์ˆ˜๊ฐ€ ์—†๋‹ค. ์ด๊ฒŒ ๋ฐ”๋กœ MLOps๊ตฌ๋‚˜! ์˜จ๋ชธ์œผ๋กœ ๋А๋‚€ ์ˆœ๊ฐ„์ด์—ˆ๋‹ค.


ํšŒ๊ณ : ๋ฌด์—‡์„ ์–ป์—ˆ๋‚˜

์ด๋ฒˆ ํ”„๋กœ์ ํŠธ๋Š” ๋‹จ์ˆœํ•œ ์ฝ”๋”ฉ ๊ทธ ์ด์ƒ์ด์—ˆ๋‹ค. ์‹œ์Šคํ…œ ์ „์ฒด๋ฅผ ๋ณด๋Š” ์—”์ง€๋‹ˆ์–ด์˜ ์‹œ์•ผ๋ฅผ ์–ป์—ˆ๋‹ค๊ณ  ํ• ๊นŒ.

  • ํฐ ๊ทธ๋ฆผ: ๊ฐ ์„œ๋น„์Šค๊ฐ€ API๋กœ ํ†ต์‹ ํ•˜๋ฉฐ ํ•˜๋‚˜์˜ ํŒŒ์ดํ”„๋ผ์ธ์„ ์ด๋ฃจ๋Š” ์ „์ฒด ๊ตฌ์กฐ๋ฅผ ์ดํ•ดํ•˜๊ฒŒ ๋๋‹ค.
  • ์ž๋™ํ™”์˜ ํž˜: MLOps๊ฐ€ ์™œ ํ•„์š”ํ•œ์ง€, ๋ฐ˜๋ณต ์ž‘์—…์„ ์ค„์ด๋Š” ๊ฒƒ์ด ์–ผ๋งˆ๋‚˜ ์ค‘์š”ํ•œ์ง€ ๋ผˆ์ €๋ฆฌ๊ฒŒ ๋А๊ผˆ๋‹ค.
  • ์ง„์งœ ํ˜‘์—…: MSA ํ™˜๊ฒฝ์—์„œ ๊ฐ์ž ์„œ๋น„์Šค์— ์ฑ…์ž„์„ ๋‹คํ•˜๊ณ , API ๋ช…์„ธ๋ฅผ ๋งž์ถ”๋ฉฐ ํ•จ๊ป˜ ๊ฒฐ๊ณผ๋ฌผ์„ ๋งŒ๋“œ๋Š” ์ฆ๊ฑฐ์›€์„ ์•Œ๊ฒŒ ๋๋‹ค.

๋ฌผ๋ก  ์•„์ง ๊ฐˆ ๊ธธ์€ ๋ฉ€๋‹ค. CI/CD๋„ ๋„์ž…ํ•ด์•ผ ํ•˜๊ณ , ๋ชจ๋ธ ์žฌํ•™์Šต ํŒŒ์ดํ”„๋ผ์ธ๋„ ์ž๋™ํ™”ํ•ด์•ผ ํ•œ๋‹ค. ํ•˜์ง€๋งŒ ์ด๋ฒˆ ๊ฒฝํ—˜์€ ์•ž์œผ๋กœ ๋” ๋ณต์žกํ•œ ์‹œ์Šคํ…œ์— ๋„์ „ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฐ•๋ ฅํ•œ ์ž์‹ ๊ฐ์„ ์‹ฌ์–ด์ฃผ์—ˆ๋‹ค. ๐Ÿ”ฅ

ํ”„๋กœ์ ํŠธ์˜ ๋” ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์šฐ๋ฆฌ ํŒ€ GitHub์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ๋!