GROWTH LOG STORIES

함께 만든 성장을,
기록으로 연결합니다.

AI와 함께 배우고, 직접 만들고, 서로 나눈
그로스로그 멤버들의 생생한 성장 기록을 만나보세요.

성장 기록
5기+이어진 커뮤니티
HEALTHIO
PROJECT

사진 한 장으로 시작하는 건강 루틴, Health IO

대표 이야기 읽기

ALL STORIES

성장의 순간을
한곳에서 만나보세요.

프로젝트의 시작부터 모임에서 나눈 인사이트까지,
그로스로그가 함께 만든 기록을 모았습니다.
개의 성장 기록

성장일지

[GL 4기 7회차 ②] 전체를 한눈에 줄여보기 — Django 진입점 추적, Minikube 로컬 클러스터, MLOps 파이프라인 🌱

GROWTH LOG🌱 2026. 8. 11. 00:11
GL 4기 성장일지 7회차 큐레이션

안녕하세요! 그로스로그 입니다!😊 🌱

프로젝트의 첫 줄부터 따라 내려가 보기, 서버 여러 대짜리 클러스터를 노트북 한 대로 줄여보기, 그리고 머신러닝 운영 전체를 그림 한 장으로 그려보기. 4기 7회차 세 편입니다.

4기 7회차는 2025년 12월 말입니다. 세 편이 크기가 다른 세 가지를 각각 한눈에 들어오게 줄이는 이야기를 합니다.

 

01

🚪 DJANGO 프로젝트의 Entry Point 및 내부 소스 분석

노현주 님

이런 내용이에요
남이 짜둔 Django 프로젝트를 첫 줄부터 읽어 내려간 기록입니다.
manage.py의 맨 윗줄부터 시작해요. 셔뱅 한 줄이 무슨 뜻인지부터 적었습니다.
그리고 진입 부분의 데코레이터와 저장소 설정을 지나, 이미지 처리 로직까지 따라 들어갑니다.
정리 방식이 일정합니다. 코드 한 줄 · 그게 무슨 일을 하는지 한 줄로 계속 붙여갑니다.

4회차의 크롤러 수리, 6회차의 데이터베이스 이관에 이은 세 번째입니다. 매번 이미 있는 것을 다루고 있어요.

이번 글은 그중에서도 가장 앞 단계입니다. 고치기 전에 읽는 단계요.

조금 더 들어가 보면

🧭 왜 진입점부터 읽는가

처음 보는 프로젝트를 열면 파일이 수십 개입니다. 어디부터 봐야 할지 막막한 게 정상이에요.

이때 가장 확실한 방법이 진입점을 찾는 것입니다. 프로그램이 실제로 시작되는 지점이요. 거기서부터 호출을 따라가면 실제로 실행되는 경로만 보게 됩니다.

이 방법의 이점이 큽니다.

· 안 쓰는 코드를 안 읽습니다 — 프로젝트에는 예전에 쓰다 만 파일이 반드시 있습니다. 진입점에서 안 닿으면 지금은 안 도는 코드예요

· 순서가 생깁니다 — 파일 이름순으로 읽으면 앞뒤 맥락이 없는데, 실행 순서로 읽으면 이야기가 됩니다

· 어디까지 왔는지 알 수 있습니다 — 목표 지점까지 몇 단계 남았는지가 보입니다

저자가 manage.py에서 시작한 게 정확한 이유입니다. Django에서 이 파일이 명령을 받는 자리거든요.

🐚 셔뱅 한 줄을 그냥 넘기지 않았습니다

이 기록에서 눈에 띄는 게 첫 항목입니다. 파일 맨 위의 #!/usr/bin/env python 한 줄을 두고, 이 파일을 실행할 때 어떤 프로그램을 쓸지 알려주는 설정이라고 적어뒀어요.

대부분 그냥 넘기는 줄입니다. 주석처럼 생겼고, 실제로 파이썬 문법상으로는 주석이기도 하고요.

그런데 이 줄은 실행 방식을 정합니다. python manage.py 라고 치면 이 줄은 아무 역할도 안 합니다. 그런데 ./manage.py 라고 직접 실행하면, 운영체제가 이 줄을 읽어서 어떤 해석기로 돌릴지 정해요.

그리고 /usr/bin/env python 이라고 쓴 것에도 이유가 있습니다. 파이썬 경로를 고정으로 박지 않고 환경에서 찾아 쓰겠다는 뜻이거든요. 가상환경을 쓰는 프로젝트에서는 이게 중요합니다. 경로를 박아두면 어느 환경에서든 그 파이썬만 쓰게 되니까요.

2회차에서 다룬 모듈 검색 경로 이야기와 같은 자리입니다. "어디 있는 걸 쓰는가"요.

🛡️ @csrf_exempt를 짚어둔 것

읽어 내려가다 만난 데코레이터를 "보안 검사(CSRF)를 이 함수에서만 제외" 라고 적어뒀습니다. 짧은 설명인데, 남의 코드를 읽을 때 이런 표시를 만나면 멈춰 서는 게 맞습니다.

CSRF 검사는 사용자가 의도하지 않은 요청이 다른 사이트에서 날아오는 것을 막는 장치입니다. 로그인된 상태에서 악성 페이지를 열면, 그 페이지가 몰래 우리 서비스로 요청을 보낼 수 있거든요.

그걸 끄는 데코레이터가 붙어 있다는 건 두 가지 중 하나입니다.

· 끌 이유가 있는 자리 — 외부 시스템이 부르는 API처럼 브라우저 세션과 무관한 경우

· 개발할 때 걸려서 그냥 끈 자리 — 이게 문제입니다. 켜야 하는데 꺼진 채로 남은 경우요

어느 쪽인지는 코드만 봐서는 모릅니다. 그래서 이런 표시를 발견하면 기록해두고 나중에 확인해야 해요. 저자가 소스 분석 노트에 이걸 남겨둔 게 그런 성격입니다.

🖼️ 이미지 처리 부분을 절차로 정리했습니다

뒷부분은 OCR을 위한 전처리 코드를 읽은 기록입니다. 각 함수가 무슨 일을 하는지 표로 붙였는데, 순서대로 보면 하나의 절차가 됩니다.

1. 회색으로 바꾼다 — 색 정보가 필요 없으니 버립니다. 계산할 양이 3분의 1로 줍니다

2. 흑백으로 딱 나눈다 — 밝으면 흰색, 어두우면 검은색으로 잘라 글자를 도드라지게 합니다

3. 테두리를 딴다 — 글자의 외곽선을 찾아 덩어리 위치를 잡습니다

4. 덩어리를 감싸는 사각형을 구한다 — 각 덩어리의 좌표를 얻습니다

5. 너무 작은 건 버린다 — 점이나 얼룩을 걸러냅니다

6. 키운다 — 글자가 작으면 인식이 안 되니 확대합니다

7. 잘라 저장한다 — 나중에 인식 엔진에 넘길 조각들입니다

전처리라는 게 결국 "필요 없는 걸 버리고, 필요한 걸 도드라지게 하는" 일이라는 게 이 순서에 그대로 나옵니다. 색을 버리고, 중간 밝기를 버리고, 작은 덩어리를 버립니다.

특히 5번의 조건이 흥미롭습니다. 이미지 너비의 몇 분의 일보다 작은 건 무시하는데, 이건 이 프로젝트의 문서 형태에 맞춘 값이에요. 다른 형태의 이미지에는 안 맞습니다. 남의 코드를 읽을 때 이런 숫자를 만나면 "이건 이 상황에 맞춘 값" 이라고 표시해두는 게 좋습니다. 나중에 다른 데 쓸 때 걸리는 자리거든요.

📝 원문에서는 이렇게 씁니다

코드와 설명을 한 줄씩 짝지어 나갑니다.

cv2.threshold(..., OTSU) — 이진화: 아주 밝은 회색은 흰색으로, 어두운 회색은 검은색으로 딱 나누어 글자를 도드라지게 합니다.

if w > img.shape[1] / 8... — 너무 작은 점이나 노이즈는 무시하고, 일정 크기 이상의 "글자 덩어리"만 골라냅니다.

"무엇을 하는 함수인가"가 아니라 "여기서 왜 이걸 하는가"로 적었습니다. 함수 설명은 문서에 있고, 이 프로젝트에서 그 함수가 맡은 역할은 여기에만 있어요.

🗺️ 읽은 것을 남겨두면 두 번 안 읽습니다

이런 기록의 실질적인 이득 하나를 짚어두겠습니다. 같은 프로젝트를 두 번 읽지 않아도 된다는 것이요.

처음 보는 코드를 읽는 데는 시간이 많이 듭니다. 그런데 읽고 나서 아무것도 안 남기면, 몇 달 뒤에 다시 열었을 때 처음과 비슷한 시간이 다시 듭니다. 기억은 생각보다 빨리 흐려지거든요.

그래서 읽으면서 남길 것이 셋입니다.

· 경로 — 어디서 시작해 어디를 거쳐 어디로 가는지

· 멈춘 자리 — "이건 왜 이렇게 돼 있지" 싶었던 곳과, 알아낸 답

· 이 프로젝트에만 맞춘 값 — 앞서 본 크기 기준 같은 것들요

세 번째가 특히 나중에 값을 합니다. 코드를 다른 데 옮겨 쓸 때 반드시 걸리는 자리이기 때문입니다.

그리고 이 기록은 팀에도 남습니다. 다음 사람이 같은 프로젝트를 열 때, 처음부터 읽는 대신 이 지도를 보고 필요한 지점으로 바로 갈 수 있어요. 남의 코드를 읽는 일은 어차피 누군가 한 번은 해야 하는 일이라, 한 번 하고 남겨두는 게 팀 전체로는 훨씬 쌉니다.

🔦 읽기만으로 안 될 때 쓰는 방법들

진입점을 따라가는 방식이 강력하긴 한데, 어느 지점에서는 막힙니다. 호출이 코드에 안 적혀 있는 경우요.

프레임워크를 쓰면 흔히 생깁니다. 내가 만든 함수를 내가 부르지 않고 프레임워크가 부르거든요. 코드를 아무리 따라가도 그 함수로 이어지는 화살표가 안 보입니다.

이때 쓰는 방법이 셋 있습니다.

· 거꾸로 찾습니다 — 궁금한 함수 이름으로 전체를 검색해 누가 부르는지 봅니다. 위에서 아래 대신 아래에서 위로요

· 실제로 돌려봅니다 — 중단점을 걸고 그 지점에서 멈춰 세우면, 호출 스택에 거기까지 온 경로가 통째로 찍힙니다. 읽어서 못 찾는 경로를 실행이 알려줍니다

· 로그를 뿌려봅니다 — 도구를 붙이기 어려운 환경이면 출력문을 몇 군데 넣어 순서를 확인합니다. 10회차에서 노현주 님이 필터와 인터셉터에 번호를 찍은 게 이 방법이에요

두 번째가 가장 확실합니다. 코드를 읽는 것과 실행을 보는 것은 다른 정보를 주거든요. 특히 조건에 따라 갈라지는 곳에서는 "실제로 어느 쪽으로 갔는가"가 읽기만으로는 안 나옵니다.

읽기로 지도를 그리고, 실행으로 그 지도를 확인하는 순서가 대체로 빠릅니다.

🧾 그리고 고치기 전에 한 번 더 확인할 것

읽기가 끝나면 고치는 단계로 갑니다. 그 사이에 하나만 더 하면 좋은 게 있어요. 지금 동작을 기록해두는 것입니다.

고치기 전에 몇 가지 입력을 넣어보고 결과를 적어둡니다. 그러면 고친 뒤에 같은 입력을 넣어 결과가 그대로인지 확인할 수 있어요. 의도한 것만 바뀌었는지 아는 유일한 방법입니다.

테스트 코드가 있으면 가장 좋고, 없어도 됩니다. 화면 캡처든 출력 파일이든 남겨두면 비교할 수 있으니까요.

이게 특히 중요한 게 남의 코드입니다. 내가 짠 코드는 어디가 영향받는지 감이 있는데, 남의 코드는 없거든요. 그래서 "이건 안 건드렸으니 괜찮겠지"가 자주 틀립니다.

4회차의 크롤러 수리 기록에 수집 건수를 세는 코드가 있었던 게 같은 맥락입니다. 고친 뒤에 숫자가 그대로인지 보는 장치요.

큐레이터 노트

남의 코드를 읽는 과정 자체를 남긴 기록이라 뽑았습니다. 결과물 소개가 아니라 읽어 내려간 순서가 그대로 남아 있어요. 진입점에서 시작해 아래로 따라간 경로가 다음 사람의 지도가 됩니다.

셔뱅 한 줄, CSRF 예외 표시처럼 그냥 넘기기 쉬운 자리에서 멈춘 것도 좋았습니다. 코드를 읽는 일의 대부분이 "이건 왜 여기 있지"를 붙잡는 것이니까요.

4회차·6회차에 이어 세 번째로 만나는 분입니다. 고치기 · 옮기기 · 읽기 순서로 실무의 서로 다른 국면이 남았어요.

원문 읽으러 가기  ↗anyway03.tistory.com/8
 

02

☸️ [Kubernetes] Minikube

박현구 님

이런 내용이에요
쿠버네티스를 노트북 한 대에 축소해 띄우고 직접 만져본 기록입니다. 읽는 데 20분이 넘는 분량이에요.
실습 전에 개념 열한 개를 먼저 정리합니다. 컴포넌트, 노드, 클러스터, 파드, 디플로이먼트, 서비스, 네임스페이스, 컨피그맵, 시크릿, 인그레스, PVC요.
각 개념마다 공식 문서 링크를 달았습니다.
그리고 실행 로그를 그대로 붙였어요. 무엇이 뜨는지 눈으로 볼 수 있습니다.

6회차의 MySQL 프로시저에 이어 만나는 분입니다. 이번에는 규모가 확 커졌어요.

이 글의 성격은 첫 부분의 인용에 있습니다. "minikube에서 사용하는 개념은 실제 Kubernetes와 100% 동일하다." 축소판인데 개념은 그대로라는 것이죠.

조금 더 들어가 보면

🧪 왜 축소판이 필요한가

쿠버네티스를 배우기 어려운 이유가 있습니다. 제대로 된 걸 띄우려면 서버가 여러 대 필요하기 때문입니다.

원래 구조가 그렇습니다. 전체를 관리하는 쪽과 실제로 컨테이너를 돌리는 쪽이 나뉘어 있고, 나뉘어 있는 게 이 도구의 존재 이유거든요. 한 대가 죽어도 다른 대가 받아주는 것이요.

그런데 배우려는 사람 입장에서는 서버 여러 대를 마련하는 것 자체가 첫 장벽입니다. 클라우드에 띄우면 돈이 들고, 집에 컴퓨터가 여러 대 있는 것도 아니고요.

축소판 도구는 이 장벽을 없앱니다. 컨테이너 하나를 노드처럼 취급해서 노트북 안에 클러스터를 만들어요. 그래서 명령 하나로 시작할 수 있습니다.

중요한 건 "개념이 동일하다"는 부분입니다. 축소했다고 다른 도구가 되면 배운 게 안 옮겨가는데, 여기서는 같은 명령과 같은 개념을 씁니다. 연습장에서 익힌 게 실전에서 그대로 쓰이는 구조예요.

🗂️ 개념 열한 개를 먼저 정리한 순서

이 글이 실습보다 개념 정리에 더 많은 분량을 쓴 게 눈에 띕니다. 그리고 그 순서가 좋아요.

바깥에서 안으로 들어갑니다. 클러스터라는 큰 덩어리에서 시작해 노드로, 파드로 내려가고, 그다음에 그것들을 다루는 것들이 나옵니다.

정리하면 이렇게 층이 나뉩니다.

무엇 하는 일
담는 그릇 클러스터 · 노드 · 네임스페이스 어디에서 돌 것인가
도는 것 파드 실제로 실행되는 최소 단위
관리하는 것 디플로이먼트 파드를 몇 개 유지할지, 어떻게 갈아 끼울지
이어주는 것 서비스 · 인그레스 어떻게 접근할 것인가
넣어주는 것 컨피그맵 · 시크릿 · PVC 설정과 비밀값과 저장 공간

이 다섯 층이 사실상 쿠버네티스 전부입니다. 처음 배울 때 헷갈리는 이유가 개념 이름이 한꺼번에 쏟아지기 때문인데, 층으로 묶어두면 새 개념이 나와도 어디에 넣을지 알게 됩니다.

🔁 선언형이라는 것의 의미

디플로이먼트 설명에 "애플리케이션의 상태를 선언적으로 업데이트" 라는 표현이 나옵니다. 이 단어가 쿠버네티스를 이해하는 열쇠입니다.

명령형은 "이걸 해라"입니다. 서버를 세 대 띄워라, 하나 꺼라 같은 것이죠. 선언형은 "이 상태가 유지되게 해라" 입니다. 세 개가 돌고 있어야 한다고 적어두면, 하나가 죽었을 때 알아서 하나를 더 띄웁니다.

차이가 큰 이유는 실패했을 때입니다. 명령형은 명령이 실패하면 거기서 끝나고 사람이 다시 시켜야 합니다. 선언형은 원하는 상태와 지금 상태를 계속 비교하니까, 차이가 생기면 알아서 좁힙니다.

저자가 정리한 컴포넌트 목록에서 컨트롤러가 하는 일이 정확히 이겁니다. 원하는 상태를 계속 확인하고 맞춰가는 것이요.

5회차에서 본 무상태 웹 계층 이야기가 여기서 이어집니다. 서버를 아무 때나 죽이고 새로 띄울 수 있어야 이런 자동 복구가 성립하거든요. 상태를 밖으로 뺐기 때문에 가능한 구조입니다.

🚦 인그레스에 붙인 실무 이야기

개념 설명 중에 한 줄이 특히 좋았습니다.

"현업에서는 Service(Load Balancer)를 여러 개 쓰면 비용이 많이 들기 때문에, Ingress 하나만 외부에 노출하고 내부 Load Balancing 방식을 주로 사용한다."

문서에는 안 나오는 이야기입니다. 문서는 각 리소스가 무엇을 하는지 알려주지, 실제로 어느 쪽을 고르는지는 안 알려주거든요.

이유가 현실적입니다. 클라우드에서 외부 접근용 서비스를 하나 만들면 로드밸런서가 하나 붙고, 그건 돈이 나갑니다. 서비스마다 하나씩 만들면 개수만큼 요금이 붙어요. 그래서 바깥으로 나가는 문은 하나만 두고, 그 안에서 주소별로 나눠 보내는 방식을 씁니다.

개념 목록 사이에 이런 판단이 한 줄 끼어 있는 게 이 글의 값어치입니다.

🔐 시크릿에 대해 덧붙일 것

컨피그맵과 시크릿을 나눠 설명한 것도 정확한데, 한 가지만 보태겠습니다. 시크릿은 기본 설정에서 암호화되지 않습니다.

이름 때문에 비밀번호가 안전하게 보관되는 것처럼 느껴지는데, 기본적으로는 저장소에 그냥 인코딩된 형태로 들어갑니다. 인코딩은 암호화가 아니라 형식 변환이라 되돌리기가 쉽고요.

그래서 실무에서는 별도 조치를 합니다. 저장소 자체를 암호화하도록 설정하거나, 외부 비밀 관리 서비스와 연동하거나요. 저자가 적은 "권한이 있는 사용자만 접근할 수 있습니다" 가 실제 방어선인 셈입니다. 암호화가 아니라 권한 통제요.

이름이 주는 인상과 실제 동작이 다른 자리라 짚어둘 만합니다.

📝 원문에서는 이렇게 씁니다

실행 로그를 그대로 붙였습니다.

😄 minikube v1.37.0 on Ubuntu 24.04
✨ Using the docker driver based on user configuration
👍 Starting "minikube" primary control-plane node in "minikube" cluster
🚜 Pulling base image v0.0.48 ...
🔥 Creating docker container (CPUs=2, Memory=5900MB) ...
🐳 Preparing Kubernetes v1.34.0 on Docker 28.4.0 ...
🔗 Configuring bridge CNI (Container Networking Interface) ...
🔎 Verifying Kubernetes components...

로그를 그대로 남긴 게 실용적입니다. 따라 하는 사람이 자기 화면과 비교할 수 있거든요. 어디까지 같고 어디서 달라졌는지 보이면 문제를 훨씬 빨리 찾습니다.

그리고 환경에 대한 안내도 있습니다. 우분투라 별도 가상 머신 없이 돌렸고, 다른 운영체제에서는 다른 방식이 편할 거라고요. 자기 환경을 밝히고 다른 환경의 대안을 적어두는 것이 실습 기록의 기본인데 잘 지켜졌습니다.

⚖️ 축소판이 실제와 다른 지점

"개념은 100% 동일하다"가 이 도구의 강점인데, 그래도 다른 부분은 있습니다. 알고 쓰는 게 좋아서 짚어둡니다.

· 노드가 하나입니다 — 파드를 여러 개 띄워도 결국 한 대에 다 뜹니다. 그래서 "노드가 죽으면 다른 노드로 옮겨간다"는 동작은 연습이 안 됩니다

· 네트워크가 단순합니다 — 실제 클러스터에서 골치 아픈 게 노드 간 통신인데, 한 대 안에서는 그 문제가 거의 안 생깁니다

· 외부 접근 방식이 다릅니다 — 클라우드에서는 로드밸런서가 자동으로 붙는데, 로컬에서는 별도 명령으로 통로를 열어줘야 합니다

· 저장소가 다릅니다 — 클라우드의 영구 볼륨과 로컬 디스크는 동작이 다릅니다

그래서 연습되는 것과 안 되는 것이 갈립니다. 리소스를 정의하고 배포하고 갈아 끼우는 흐름은 그대로 옮겨가는데, 여러 대에 걸친 문제는 여기서 못 배웁니다.

이건 축소판의 한계가 아니라 성격입니다. 저자가 "학습과 개발"을 목적으로 소개한 도구니까요. 그리고 개념을 익히는 단계에서는 이 한계가 문제가 안 됩니다. 다만 "로컬에서 됐으니 클러스터에서도 되겠지"는 위험해요.

🎛️ 첫 실습에서 보면 좋은 것 하나

이 도구로 시작할 때 가장 얻는 게 큰 실습이 하나 있습니다. 파드를 일부러 죽여보는 것이요.

디플로이먼트로 파드를 세 개 띄워두고, 그중 하나를 강제로 지웁니다. 그리고 목록을 다시 보면 새 파드가 하나 떠 있습니다. 아무도 시키지 않았는데요.

이 장면을 한 번 보면 앞에서 이야기한 선언형이 몸으로 이해됩니다. "세 개가 돌고 있어야 한다"고 적어둔 것이 실제로 지켜지는 것을 보는 거니까요.

그리고 그다음에 자연스럽게 질문이 따라옵니다. "그럼 파드가 죽는 동안 요청은 어떻게 되나", "새로 뜬 파드는 언제부터 요청을 받나" 같은 것들이요. 서비스와 준비 상태 점검이 왜 필요한지가 그 질문에서 나옵니다.

저자가 개념을 열한 개나 먼저 정리해둔 게 여기서 값을 합니다. 실습에서 질문이 생겼을 때 돌아가서 볼 자리가 이미 만들어져 있거든요.

큐레이터 노트

실습 전에 개념 지도를 먼저 그린 기록이라 뽑았습니다. 명령을 따라 치는 글은 많은데, 열한 개 개념을 정리하고 각각에 공식 문서 링크까지 붙인 다음 실습으로 들어가는 구성은 드물어요.

개념 설명 사이에 끼어 있는 실무 판단도 값어치가 컸습니다. 인그레스를 하나만 두는 이유 같은 것이요. 그리고 실행 로그를 그대로 붙여 따라 하는 사람이 비교할 수 있게 한 것도요.

3회차 김경보 님의 컨테이너 빌드 글과 이어 읽으면 좋습니다. 만드는 쪽과 굴리는 쪽이 각각 정리돼 있어요.

원문 읽으러 가기  ↗medium.com/@hyungu1215/kubernetes-minikube-858749386e34
 

03

🔄 MLOps란 무엇일까?

박나은 님

이런 내용이에요
스터디에서 들은 발표를 정리한 글입니다. 시작 이유가 정직해요. "정리하지 않으면 영영 까먹을 것 같아 정리해본다."
왜 필요한지부터 짚습니다. 모델은 시간이 지나면 성능이 떨어진다는 것이요.
구성 요소를 셋으로 나눕니다. 버전 관리 · CI/CD · 모니터링이요.
그리고 파이프라인을 여섯 단계로 정리하고 그림으로 그렸습니다.

2회차와 5회차에 이어 세 번째입니다. 앞선 두 편이 쓰던 것 정리하기필요해서 공부하기였다면, 이번은 들은 것 정리하기예요.

조금 더 들어가 보면

📉 모델이 시간이 지나면 나빠지는 이유

이 글이 제일 먼저 짚은 게 필요성입니다. 그리고 그 이유가 소프트웨어 일반과 다릅니다.

보통의 프로그램은 가만 두면 그대로 돌아갑니다. 어제 정답을 내던 코드가 오늘 갑자기 틀리지 않아요.

그런데 학습된 모델은 다릅니다. 세상이 바뀌면 성능이 떨어집니다. 코드는 한 글자도 안 바뀌었는데요.

저자가 적은 "새로운 패턴의 등장 혹은 데이터 분포의 변화" 가 그 이야기입니다. 조금 더 나눠보면 이렇습니다.

· 입력이 달라집니다 — 사용자층이 바뀌거나 유행이 바뀌면 들어오는 데이터의 성격이 달라집니다

· 정답이 달라집니다 — 같은 입력에 대한 옳은 답 자체가 시간에 따라 변하는 경우가 있습니다

· 모델이 세상을 바꿉니다 — 추천 모델이 추천한 결과가 다음 학습 데이터가 되면서, 자기가 만든 편향을 자기가 학습합니다

세 번째가 특히 까다롭습니다. 밖에서 보면 잘 돌고 있는 것처럼 보이거든요.

그래서 "배포하면 끝"이 성립하지 않습니다. 계속 지켜보고 다시 학습시켜야 하고, 그 반복을 사람이 손으로 하면 감당이 안 됩니다. 자동화가 필요한 이유가 여기서 나와요.

📦 무엇을 버전 관리할 것인가

구성 요소 중 첫 번째인 버전 관리에서 저자가 나눈 네 가지가 정확합니다. 코드 · 데이터 · 모델 · 개발환경이요.

일반 소프트웨어에서는 코드만 관리하면 대체로 재현이 됩니다. 같은 코드를 같은 입력에 돌리면 같은 결과가 나오니까요.

머신러닝은 다릅니다. 같은 코드라도 학습에 쓴 데이터가 다르면 다른 모델이 나옵니다. 그래서 "이 모델이 어떻게 만들어졌는가"를 답하려면 넷이 다 있어야 해요.

· 코드 — 어떤 절차로 학습했는가

· 데이터 — 무엇으로 학습했는가

· 모델 — 그래서 나온 결과물이 무엇인가

· 환경 — 어떤 라이브러리 버전에서 돌렸는가

넷 중 하나만 빠져도 "왜 이 모델이 이런 판단을 했는지" 추적이 끊깁니다. 그리고 이건 성능 문제만이 아니라 책임 문제이기도 합니다. 모델이 잘못된 판정을 했을 때 근거를 못 대면 곤란해지니까요.

데이터 버전 관리가 특히 어렵습니다. 코드는 텍스트라 변경분만 저장하면 되는데, 데이터는 크기가 커서 그 방식이 안 통하거든요. 그래서 이 분야에 별도 도구가 따로 있습니다.

🔬 평가에 온라인 테스트를 넣은 것

파이프라인 6단계 중 모델 평가 부분에 저자가 붙인 한 줄이 눈에 띕니다.

"일반적인 오프라인 지표 테스트 뿐만 아닌, A/B테스트와 같은 온라인 테스트도 수행 가능"

이 구분이 실무에서 계속 문제가 되는 자리입니다.

오프라인 평가는 모아둔 데이터로 정확도를 재는 것입니다. 빠르고 싸요. 그런데 모아둔 데이터에서 잘한다고 실제 사용자에게도 잘한다는 보장이 없습니다.

이유가 여럿입니다. 평가용 데이터가 과거의 것이라 지금과 다를 수 있고, 정확도가 올랐는데 사용자가 원하는 것과는 무관할 수 있어요. 추천 정확도를 올렸더니 다양성이 사라져서 사용자가 금방 질리는 경우 같은 것이죠.

그래서 진짜 판정은 실제 트래픽 일부를 새 모델에 흘려보고 비교하는 것입니다. 저자가 두 가지를 나란히 적어둔 게 그 지점을 짚은 것이고요.

🚨 모니터링에서 무엇을 보는가

세 번째 구성 요소인 모니터링에 "모델 드리프트 감지" 가 들어 있습니다. 앞에서 말한 "시간이 지나면 나빠지는 것"을 실제로 어떻게 알아채느냐는 문제죠.

여기에 함정이 하나 있습니다. 정답을 바로 알 수 없는 경우가 많다는 것이요.

예를 들어 대출 심사 모델이라면, 이 사람이 실제로 갚을지 안 갚을지는 몇 달 뒤에나 알 수 있습니다. 정확도를 재려면 몇 달을 기다려야 해요. 그때는 이미 늦었고요.

그래서 실무에서는 정답 없이도 볼 수 있는 것들을 함께 봅니다.

· 입력이 예전과 비슷한가 — 들어오는 데이터의 분포가 학습 때와 달라졌는지

· 출력이 예전과 비슷한가 — 모델이 내놓는 판정의 비율이 갑자기 바뀌었는지

· 확신도가 떨어지지 않았는가 — 애매하다고 판정하는 비율이 늘었는지

정답을 기다리지 않고도 이상 신호를 잡는 것이 목적입니다. 저자가 적은 "데이터 품질 모니터링"과 "실시간 경고 시스템"이 이 자리예요.

🧪 전처리가 학습과 서비스에서 어긋나는 문제

파이프라인 6단계 중 두 번째인 전처리에 실무에서 유명한 함정이 하나 있습니다. 학습할 때와 서비스할 때 전처리가 달라지는 것이요.

학습은 대개 모아둔 데이터로 배치 처리합니다. 노트북에서 스크립트를 돌려 정규화하고 결측치를 채우죠. 그런데 서비스에서는 요청 하나가 실시간으로 들어옵니다. 그때 같은 전처리를 다시 구현하게 되고, 미묘하게 달라집니다.

예를 들어 학습할 때는 전체 데이터의 평균으로 값을 채웠는데, 서비스에서는 그 평균이 없어서 다른 값을 쓰는 식이요. 모델은 그대로인데 들어가는 값이 달라지니 성능이 떨어집니다.

그리고 이 문제는 정확도 지표로는 잘 안 잡힙니다. 오프라인 평가에서는 같은 전처리를 쓰니 문제가 없거든요. 실제 서비스에서만 나빠집니다.

그래서 이 분야에 전처리 로직을 한 벌만 두고 학습과 서비스가 같이 쓰게 하는 방식이 자리를 잡았습니다. 저자가 버전 관리 대상에 코드개발환경을 함께 넣어둔 게 이 문제와 닿아 있어요. 같은 코드가 같은 환경에서 도는 걸 보장해야 하니까요.

1회차에서 이야기한 "대신 해주는 것의 안쪽"이 여기서도 반복됩니다. 전처리를 라이브러리가 알아서 해주는데, 그게 어디서 어떤 값으로 하는지 모르면 이 어긋남을 못 찾습니다.

🚀 배포 전략 두 가지가 실제로 다른 점

저자가 배포 단계에서 "실시간 배포와 배치성 배포"를 나눈 대목도 조금 풀어보겠습니다. 이 선택이 시스템 구조를 통째로 바꾸거든요.

실시간 — 요청이 올 때마다 모델이 답을 냅니다. 추천이나 이상 거래 탐지처럼 그 순간의 답이 필요한 경우요. 그래서 응답 시간이 중요해지고, 모델을 서버에 띄워 계속 대기시켜야 합니다. 트래픽이 몰리면 모델 서버도 같이 늘려야 하고요.

배치 — 정해진 시간에 한꺼번에 계산해 저장해둡니다. 다음날 보낼 메일 대상을 밤에 골라두는 식이요. 응답 시간이 상관없으니 큰 모델을 써도 되고, 자원도 그 시간에만 쓰면 됩니다.

비용 차이가 큽니다. 배치는 하루에 한 번만 자원을 쓰는데, 실시간은 하루 종일 켜둬야 하니까요. 그래서 실무에서는 실시간이 꼭 필요한지를 먼저 묻습니다.

그리고 중간 형태도 흔합니다. 미리 계산해두고 조회만 실시간으로 하는 방식이요. 사용자별 추천 목록을 밤에 만들어두고 낮에는 꺼내 보여주기만 하는 것이죠. 5회차에서 이야기한 캐싱과 같은 발상입니다.

저자가 "서비스의 목적과 특성에 따라 달라질 수 있다"고 쓴 게 이 선택입니다. 정답이 하나가 아니라고 적어둔 것이 정확했어요.

📝 원문에서는 이렇게 씁니다

여섯 단계를 순서대로 적고 각각에 무엇을 하는지 붙였습니다.

데이터 수집데이터 전처리모델 학습모델 평가모델 배포성능 모니터링 및 반복

마지막 단계 이름에 "및 반복" 이 붙어 있는 게 이 파이프라인의 핵심입니다. 여섯 번째가 끝이 아니라 첫 번째로 돌아가는 고리거든요.

그리고 배포에 대해 이렇게 적었습니다.

"서비스의 목적과 특성 그리고 달성하고자 하는 비즈니스 목표 등에 따라서 배포 전략이 달라질 수 있다. 대표적으로는 실시간 배포와 배치성 배포를 살펴볼 수 있다."

정답이 하나가 아니라고 적어둔 것이 좋습니다. 실시간으로 예측해야 하는 서비스와 밤에 한 번 돌려두면 되는 서비스는 필요한 구조가 완전히 다르니까요.

큐레이터 노트

들은 것을 그냥 두지 않고 구조로 옮긴 기록이라 뽑았습니다. "정리하지 않으면 영영 까먹을 것 같아"라는 이유가 정직하고, 결과물은 개인 메모를 넘어섰어요.

특히 필요성부터 짚고 들어간 구성이 좋았습니다. 도구 이름을 나열하는 대신 "모델은 시간이 지나면 나빠진다"에서 시작하니, 뒤에 나오는 버전 관리와 모니터링이 왜 필요한지가 자연스럽게 이어집니다.

2회차 · 5회차 · 7회차를 나란히 놓으면 궤적이 보입니다. 쓰던 것 정리 → 필요해서 공부 → 들은 것 구조화. 기록의 성격이 회차마다 다른데 방식은 일정해요. 늘 전체 지도를 먼저 그립니다.

원문 읽으러 가기  ↗world970511.github.io/blog/posts/2025-12-23-mlops.html

💡 세 편을 겹쳐 읽으며

크기가 다른 셋을 각각 한눈에 넣습니다

세 편의 대상이 규모 순으로 늘어섭니다. 프로젝트 하나 · 서버 여러 대 · 시스템의 한살이요.

그런데 하는 일이 같습니다. 너무 커서 한 번에 안 보이는 것을 볼 수 있는 크기로 줄이는 것이죠.

노현주 님은 파일 수십 개를 실행 경로 한 줄기로 줄였습니다. 박현구 님은 서버 여러 대짜리 클러스터를 노트북 한 대로 줄였고요. 박나은 님은 몇 달에 걸친 운영 과정을 여섯 단계 그림 한 장으로 줄였습니다.

줄이는 방식이 각각 다릅니다. 하나는 안 쓰는 것을 빼서, 하나는 규모만 축소해서, 하나는 단계로 추상화해서요. 그런데 목적은 같습니다. 전체를 한 번에 잡을 수 있게 만드는 것.

줄인 것이 실물과 같아야 합니다

여기에 조건이 하나 붙습니다. 줄인 게 실제와 다르면 배운 게 안 옮겨갑니다.

박현구 님이 인용한 문장이 그 이야기예요. "축소판에서 쓰는 개념은 실제와 100% 동일하다"고요. 개념이 같아야 연습장에서 익힌 게 실전에서 쓰입니다.

노현주 님의 진입점 추적도 같습니다. 실제로 실행되는 경로를 따라갔기 때문에 그 지도가 유효한 것이지, 파일 목록을 정리했다면 안 쓰는 코드까지 섞였을 거예요.

요약이 쓸모 있으려면 원본과 대응이 유지되어야 합니다.

그냥 지나칠 자리에서 멈췄습니다

세 편 모두 작은 데서 한 번씩 멈춥니다.

노현주 님은 셔뱅 한 줄과 CSRF 예외 표시에서요. 박현구 님은 인그레스를 하나만 두는 이유에서요. 박나은 님은 평가에 온라인 테스트를 나란히 적어둔 데서요.

이 한 줄씩이 정리 글과 경험 글을 가릅니다. 목록은 검색하면 나오는데, "여기서 멈춰야 한다"는 표시는 겪어본 사람만 붙일 수 있거든요.

이번 회차에서 가져갈 것

1. 처음 보는 프로젝트는 진입점부터 따라가기.

파일 이름순으로 읽으면 맥락이 없습니다. 실행 경로를 따라가면 안 쓰는 코드를 자동으로 걸러내고 순서가 생깁니다.

2. 보안 검사를 끄는 표시를 발견하면 기록해두기.

끌 이유가 있는 자리와 개발 중에 그냥 끈 자리는 코드만 봐서는 구분이 안 됩니다. 표시해두고 확인하세요.

3. 새 시스템은 개념을 층으로 묶어 정리하기.

이름이 한꺼번에 쏟아지면 안 외워집니다. "담는 것 / 도는 것 / 관리하는 것 / 이어주는 것 / 넣어주는 것"처럼 묶어두면 새 개념이 나와도 자리를 찾습니다.

4. 실습 기록에는 자기 환경과 실행 로그를 남기기.

따라 하는 사람이 어디까지 같은지 비교할 수 있어야 합니다. 로그 몇 줄이 설명 한 문단보다 낫습니다.

5. 모델은 배포가 끝이 아니라 시작.

코드는 가만 두면 그대로인데 모델은 세상이 바뀌면 나빠집니다. 정답을 기다릴 수 없는 경우가 많으니 입력과 출력의 분포부터 지켜보세요.


4기 7회차는 2025년 12월 말이었습니다.

남의 코드 읽기와 클러스터 실습과 스터디 정리라는 서로 다른 자리에서, 세 분이 나란히 너무 커서 안 보이는 것을 볼 수 있게 줄이는 이야기를 남겼습니다. 줄이는 방법은 각자 달랐어요.

성장일지는 멤버들이 2주에 한 번씩 자신의 성장을 기록하는 활동이에요. 지난 기수의 성장일지를 다시 읽으면서, 그때 소개해드리지 못한 글을 하나씩 꺼내고 있습니다.

좋은 글 남겨주신 노현주 님, 박현구 님, 박나은 님께 감사드립니다. 그리고 4기를 함께 채워주신 모든 멤버분들께도요! 😊

다음 큐레이션으로 다시 찾아오겠습니다! 🌱

- 에디터 · 성장일지 큐레이터 -


※ 본 큐레이션은 각 저자가 공개한 글을 소개하는 것이며, 모든 원문의 저작권은 저자에게 있습니다. 저자 본인의 요청이 있을 경우 즉시 수정 또는 삭제합니다.

WRITE YOUR GROWTH

오늘의 배움을
내일의 성장으로.

기록은 나를 돌아보게 하고, 공유는 우리를 연결합니다.
당신의 다음 성장 이야기도 그로스로그에서 시작해보세요.

커뮤니티 둘러보기