실전 프로젝트 완전 정복 A-Z
HuggingFace · FastAPI · Docker · CI/CD · 포트폴리오 · 취업 전략
AI 개발자 취업의 모든 것 — 포트폴리오 완성부터 이직까지 한 번에 끝내기!
AI Dev Guide 시리즈 완주 현황
| 단계 | 가이드 | 핵심 주제 | 상태 |
|---|---|---|---|
| 01 | AiDevGuide0001 | AI 개념 완전 정복 | 완료 |
| 02 | AiDevGuide0002 | Python 기초 완전 정복 | 완료 |
| 03 | AiDevGuide0003 | 데이터 다루기 (NumPy·Pandas·Matplotlib) | 완료 |
| 04 | AiDevGuide0004 | 머신러닝 완전 정복 (Scikit-learn) | 완료 |
| 05 | AiDevGuide0005 | 딥러닝 완전 정복 (TensorFlow·PyTorch) | 완료 |
| 06 | AiDevGuide0006 | 생성형 AI (OpenAI API·LangChain·RAG) | 완료 |
| 07 | AiDevGuide0007 (현재 · 최종) | 실전 프로젝트 (HuggingFace·FastAPI·Docker) | 학습중 |
전체 학습 목차 (10 Chapters)
| Ch. | 챕터명 | 핵심 내용 | 난이도 |
|---|---|---|---|
| 01 | HuggingFace 완전 정복 | Hub, Transformers, Datasets, Spaces | ★★★☆☆ |
| 02 | FastAPI로 AI 서비스 개발 | REST API, 비동기, WebSocket, 미들웨어 | ★★★☆☆ |
| 03 | Docker & 컨테이너화 | Dockerfile, Docker Compose, 멀티스테이지 | ★★★★☆ |
| 04 | 클라우드 배포 (AWS · GCP · Azure) | EC2, ECS, Lambda, Cloud Run, 로드밸런서 | ★★★★☆ |
| 05 | CI/CD 파이프라인 구축 | GitHub Actions, 자동 테스트, 자동 배포 | ★★★★☆ |
| 06 | MLOps & 모델 관리 | MLflow, DVC, 모델 레지스트리, 드리프트 감지 | ★★★★★ |
| 07 | 포트폴리오 프로젝트 — AI 챗봇 서비스 | 풀스택 AI 서비스 E2E 구현 | ★★★★★ |
| 08 | 포트폴리오 구성 전략 | GitHub, 블로그, README, 데모 사이트 | ★★★★☆ |
| 09 | AI 개발자 취업 전략 | 이력서, 코딩 테스트, 기술 면접 완전 정복 | ★★★★★ |
| 10 | 현업 면접 Q&A TOP 10 | 시스템 설계, MLOps, 배포 관련 핵심 질문 | ★★★★★ |
Ch 01. HuggingFace 완전 정복
AI 개발의 GitHub — 수십만 개 모델과 데이터셋을 손끝에서 활용하기
1-1. HuggingFace 생태계
| 서비스 | 설명 | 주요 활용 |
|---|---|---|
| Hub | 모델/데이터셋/Space 저장소 | 모델 다운로드, 공유 |
| Transformers | BERT, GPT, Llama 등 통합 라이브러리 | 파인튜닝, 추론 |
| Datasets | 수만 개 공개 데이터셋 | 학습 데이터 로드 |
| Spaces | Gradio/Streamlit 앱 무료 호스팅 | 데모 배포 |
| Inference API | 모델 API 즉시 사용 | 빠른 프로토타이핑 |
1-2. Pipeline — 5줄로 AI 완성
pip install transformers torch accelerate
from transformers import pipeline
# 텍스트 분류
classifier = pipeline("text-classification", model="snunlp/KR-FinBert-SC")
result = classifier("이 영화 정말 재미있어요!")
print(result) # [{"label": "positive", "score": 0.998}]
# 번역
translator = pipeline("translation_ko_to_en", model="Helsinki-NLP/opus-mt-ko-en")
result = translator("안녕하세요! 반갑습니다.")
print(result[0]["translation_text"])
# 요약
summarizer = pipeline("summarization", model="facebook/bart-large-cnn")
result = summarizer("Long text to summarize...", max_length=130, min_length=30)
print(result[0]["summary_text"])
# 이미지 분류
img_classifier = pipeline("image-classification", model="google/vit-base-patch16-224")
result = img_classifier("cat.jpg")
print(result[0]) # {"label": "tabby cat", "score": 0.956}
# 텍스트 생성 (LLM)
generator = pipeline("text-generation", model="meta-llama/Llama-3.2-1B-Instruct",
device_map="auto", torch_dtype="auto")
result = generator("파이썬 학습 방법:", max_new_tokens=200)
print(result[0]["generated_text"])
1-3. HuggingFace Hub — 모델 업로드 & 관리
from huggingface_hub import HfApi, login
# 로그인
login(token="hf_...") # HuggingFace 토큰
api = HfApi()
# 모델 업로드
api.upload_folder(
folder_path="./my_model",
repo_id="username/my-awesome-model",
repo_type="model"
)
# 모델 카드 작성
model_card = """
---
language: ko
license: mit
tags:
- text-classification
- korean
datasets:
- nsmc
metrics:
- accuracy
---
# 한국어 감성 분석 모델
NSMC 데이터셋으로 파인튜닝된 BERT 기반 한국어 감성 분석 모델입니다.
## 사용 방법
```python
from transformers import pipeline
clf = pipeline("text-classification", model="username/my-awesome-model")
```
"""
api.upload_file(
path_or_fileobj=model_card.encode(),
path_in_repo="README.md",
repo_id="username/my-awesome-model"
)
1-4. Gradio로 데모 앱 & Spaces 배포
pip install gradio
import gradio as gr
from transformers import pipeline
sentiment_pipeline = pipeline("text-classification", model="snunlp/KR-FinBert-SC")
def analyze_sentiment(text):
result = sentiment_pipeline(text)[0]
label = "긍정" if result["label"] == "positive" else "부정"
return f"{label} (신뢰도: {result['score']:.1%})"
# Gradio 인터페이스
demo = gr.Interface(
fn=analyze_sentiment,
inputs=gr.Textbox(label="텍스트 입력", placeholder="감성 분석할 텍스트를 입력하세요..."),
outputs=gr.Textbox(label="분석 결과"),
title="한국어 감성 분석 데모",
description="BERT 기반 한국어 감성 분석 모델입니다.",
examples=[
["이 제품 정말 최고예요! 강추합니다!"],
["배송이 너무 느려서 실망했어요."]
],
theme=gr.themes.Soft()
)
# HuggingFace Spaces에 배포
# 1. huggingface.co에서 새 Space 생성
# 2. app.py로 저장 후 push
demo.launch(share=True) # 로컬 + 공개 링크 생성
Ch 02. FastAPI로 AI 서비스 개발
현업 표준 Python 웹 프레임워크 — 고성능 AI API 서버 완전 구축
2-1. FastAPI 기본 설정 & 프로젝트 구조
pip install fastapi uvicorn[standard] pydantic python-multipart
# 프로젝트 구조
ai-service/
├── app/
│ ├── __init__.py
│ ├── main.py # FastAPI 앱 진입점
│ ├── api/
│ │ ├── routes/
│ │ │ ├── predict.py # AI 예측 엔드포인트
│ │ │ ├── chat.py # 챗봇 엔드포인트
│ │ │ └── health.py # 헬스체크
│ ├── core/
│ │ ├── config.py # 환경 설정
│ │ └── security.py # 인증/인가
│ ├── models/
│ │ └── schemas.py # Pydantic 스키마
│ └── services/
│ └── ai_service.py # AI 비즈니스 로직
├── Dockerfile
├── docker-compose.yml
├── requirements.txt
└── .env
2-2. 완전한 AI API 서버 구현
# app/main.py
from fastapi import FastAPI, HTTPException, Depends, Security
from fastapi.middleware.cors import CORSMiddleware
from fastapi.middleware.trustedhost import TrustedHostMiddleware
from contextlib import asynccontextmanager
from app.core.config import settings
import logging
logger = logging.getLogger(__name__)
# 앱 시작 시 모델 로드
@asynccontextmanager
async def lifespan(app: FastAPI):
logger.info("AI 모델 로딩 중...")
app.state.model = load_ai_model() # 무거운 모델 1회만 로드
logger.info("모델 로드 완료!")
yield
logger.info("서버 종료")
app = FastAPI(
title="AI Service API",
version="1.0.0",
description="AI 기반 텍스트 분석 서비스",
lifespan=lifespan
)
# CORS 설정
app.add_middleware(
CORSMiddleware,
allow_origins=["https://yourdomain.com"],
allow_credentials=True,
allow_methods=["GET", "POST"],
allow_headers=["*"],
)
# 라우터 등록
from app.api.routes import predict, chat, health
app.include_router(predict.router, prefix="/api/v1/predict", tags=["Predict"])
app.include_router(chat.router, prefix="/api/v1/chat", tags=["Chat"])
app.include_router(health.router, prefix="/health", tags=["Health"])
2-3. 엔드포인트 구현 — 감성 분석 API
# app/models/schemas.py
from pydantic import BaseModel, Field
from typing import List, Optional
class SentimentRequest(BaseModel):
text: str = Field(..., min_length=1, max_length=1000, description="분석할 텍스트")
language: str = Field(default="ko", description="언어 코드")
class SentimentResponse(BaseModel):
text: str
sentiment: str # positive/negative/neutral
confidence: float # 0.0 ~ 1.0
processing_time_ms: float
class BatchSentimentRequest(BaseModel):
texts: List[str] = Field(..., max_items=100)
# app/api/routes/predict.py
from fastapi import APIRouter, Request, HTTPException, Depends
from app.models.schemas import SentimentRequest, SentimentResponse
from app.core.security import verify_api_key
import time
router = APIRouter()
@router.post("/sentiment", response_model=SentimentResponse)
async def analyze_sentiment(
request_body: SentimentRequest,
http_request: Request,
api_key: str = Depends(verify_api_key) # API 키 인증
):
start = time.time()
model = http_request.app.state.model
try:
result = model(request_body.text)[0]
elapsed = (time.time() - start) * 1000
return SentimentResponse(
text=request_body.text,
sentiment=result["label"],
confidence=round(result["score"], 4),
processing_time_ms=round(elapsed, 2)
)
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.post("/sentiment/batch")
async def batch_sentiment(
request_body: BatchSentimentRequest,
http_request: Request
):
model = http_request.app.state.model
results = model(request_body.texts)
return {"results": results, "count": len(results)}
2-4. 스트리밍 WebSocket 챗봇 API
# app/api/routes/chat.py
from fastapi import APIRouter, WebSocket, WebSocketDisconnect
from fastapi.responses import StreamingResponse
from openai import AsyncOpenAI
import json, asyncio
router = APIRouter()
async_client = AsyncOpenAI()
# HTTP 스트리밍 (SSE)
@router.post("/stream")
async def stream_chat(message: dict):
async def generate():
stream = await async_client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": message["content"]}],
stream=True
)
async for chunk in stream:
if chunk.choices[0].delta.content:
data = json.dumps({"token": chunk.choices[0].delta.content})
yield f"data: {data}
"
yield "data: [DONE]
"
return StreamingResponse(generate(), media_type="text/event-stream")
# WebSocket (양방향 실시간)
@router.websocket("/ws/{session_id}")
async def websocket_chat(websocket: WebSocket, session_id: str):
await websocket.accept()
conversation = [] # 세션별 대화 이력
try:
while True:
msg = await websocket.receive_text()
conversation.append({"role": "user", "content": msg})
full_response = ""
stream = await async_client.chat.completions.create(
model="gpt-4o-mini",
messages=conversation,
stream=True
)
async for chunk in stream:
token = chunk.choices[0].delta.content or ""
if token:
await websocket.send_json({"token": token})
full_response += token
conversation.append({"role": "assistant", "content": full_response})
await websocket.send_json({"done": True})
except WebSocketDisconnect:
print(f"Session {session_id} disconnected")
Ch 03. Docker & 컨테이너화
"내 컴퓨터에서는 됐는데" 문제 완전 해결 — AI 서비스 이식성 100%
3-1. AI 서비스용 Dockerfile
# Dockerfile (멀티스테이지 빌드)
# Stage 1: 의존성 설치
FROM python:3.11-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir --user -r requirements.txt
# Stage 2: 실행 이미지 (최소화)
FROM python:3.11-slim AS runtime
WORKDIR /app
# 비루트 사용자 생성 (보안)
RUN useradd -m -u 1000 appuser
# 의존성 복사
COPY --from=builder /root/.local /home/appuser/.local
COPY --chown=appuser:appuser . .
USER appuser
ENV PATH=/home/appuser/.local/bin:$PATH
# 환경 변수
ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
PORT=8000
EXPOSE 8000
# 헬스체크
HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
CMD curl -f http://localhost:8000/health || exit 1
# GPU 지원 (필요시)
# FROM nvidia/cuda:12.1-cudnn8-runtime-ubuntu22.04
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", \
"--workers", "4", "--access-log", "--log-level", "info"]
3-2. Docker Compose — 전체 스택 구성
# docker-compose.yml
version: "3.9"
services:
# FastAPI 앱
api:
build:
context: .
dockerfile: Dockerfile
target: runtime
ports:
- "8000:8000"
environment:
- DATABASE_URL=postgresql://user:pass@db:5432/aidb
- REDIS_URL=redis://redis:6379
- OPENAI_API_KEY=${OPENAI_API_KEY}
env_file:
- .env
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
volumes:
- ./models:/app/models # 모델 파일 마운트
restart: unless-stopped
networks:
- ai-network
# Nginx 리버스 프록시
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./ssl:/etc/nginx/ssl
depends_on: [api]
networks:
- ai-network
# PostgreSQL DB
db:
image: postgres:16-alpine
environment:
POSTGRES_DB: aidb
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user"]
interval: 10s
networks:
- ai-network
# Redis 캐시
redis:
image: redis:7-alpine
command: redis-server --maxmemory 256mb
networks:
- ai-network
volumes:
postgres_data:
networks:
ai-network:
driver: bridge
3-3. 핵심 Docker 명령어 정리
# 빌드
docker build -t ai-service:v1.0 .
docker build --no-cache -t ai-service:latest .
# 실행
docker run -d -p 8000:8000 --name ai-api ai-service:latest
docker run -e OPENAI_API_KEY=sk-... ai-service:latest
# Docker Compose
docker compose up -d # 백그라운드 실행
docker compose down # 중단
docker compose logs -f api # 로그 확인
docker compose ps # 상태 확인
docker compose exec api bash # 컨테이너 접속
# 이미지 관리
docker images # 이미지 목록
docker rmi ai-service:v1.0 # 이미지 삭제
docker system prune -a # 미사용 전체 정리
# ECR 배포 (AWS)
aws ecr get-login-password --region ap-northeast-2 | docker login --username AWS --password-stdin 123456789.dkr.ecr.ap-northeast-2.amazonaws.com
docker tag ai-service:latest 123456789.dkr.ecr.ap-northeast-2.amazonaws.com/ai-service:latest
docker push 123456789.dkr.ecr.ap-northeast-2.amazonaws.com/ai-service:latest
Ch 04. 클라우드 배포 (AWS · GCP · Azure)
실제 서비스 운영 — 글로벌 접근 가능한 AI 서비스 배포
4-1. 클라우드 서비스 비교
| 서비스 | AWS | GCP | Azure |
|---|---|---|---|
| 컨테이너 | ECS / EKS | Cloud Run / GKE | ACI / AKS |
| 서버리스 | Lambda | Cloud Functions | Azure Functions |
| ML 플랫폼 | SageMaker | Vertex AI | Azure ML |
| 무료 티어 | 12개월 프리티어 | $300 크레딧 | $200 크레딧 |
| 한국 리전 | ap-northeast-2 (서울) | asia-northeast3 (서울) | Korea Central |
4-2. AWS EC2 + ECS 배포 실전
# AWS CLI 설치 및 설정
pip install awscli
aws configure # Access Key, Secret Key, Region 입력
# ECR 레포지토리 생성
aws ecr create-repository --repository-name ai-service --region ap-northeast-2
# ECS 태스크 정의 (task-definition.json)
{
"family": "ai-service",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"cpu": "1024",
"memory": "2048",
"containerDefinitions": [{
"name": "ai-api",
"image": "123456789.dkr.ecr.ap-northeast-2.amazonaws.com/ai-service:latest",
"portMappings": [{"containerPort": 8000, "protocol": "tcp"}],
"environment": [
{"name": "ENV", "value": "production"}
],
"secrets": [
{"name": "OPENAI_API_KEY", "valueFrom": "arn:aws:ssm:ap-northeast-2:123456789:parameter/openai-key"}
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {"awslogs-group": "/ecs/ai-service", "awslogs-region": "ap-northeast-2"}
},
"healthCheck": {
"command": ["CMD-SHELL", "curl -f http://localhost:8000/health || exit 1"],
"interval": 30, "timeout": 5, "retries": 3
}
}]
}
# ECS 서비스 배포
aws ecs register-task-definition --cli-input-json file://task-definition.json
aws ecs create-service \
--cluster ai-cluster \
--service-name ai-service \
--task-definition ai-service:1 \
--desired-count 2 \
--launch-type FARGATE \
--load-balancers targetGroupArn=arn:aws:...
4-3. GCP Cloud Run — 가장 간편한 배포
# Google Cloud SDK 설치
gcloud auth login
gcloud config set project my-ai-project
# Cloud Build로 이미지 빌드 + 배포 (한 번에!)
gcloud run deploy ai-service \
--source . \
--region asia-northeast3 \
--platform managed \
--allow-unauthenticated \
--memory 2Gi \
--cpu 2 \
--concurrency 80 \
--max-instances 10 \
--set-env-vars OPENAI_API_KEY=sk-... \
--set-secrets OPENAI_API_KEY=openai-key:latest
# Cloud Run 특징
# - 요청이 없으면 0으로 스케일 다운 (비용 절약)
# - 요청 급증 시 자동 스케일 업
# - HTTPS 자동 제공
# - 첫 2백만 요청/월 무료
Ch 05. CI/CD 파이프라인 구축
코드 Push → 자동 테스트 → 자동 배포 — 개발 생산성 10배 향상
5-1. GitHub Actions 완전한 CI/CD 파이프라인
# .github/workflows/deploy.yml
name: AI Service CI/CD
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
# 1. 테스트
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
cache: "pip"
- run: pip install -r requirements.txt -r requirements-dev.txt
- name: 린트 (코드 스타일 검사)
run: |
ruff check .
black --check .
- name: 타입 체크
run: mypy app/
- name: 단위 테스트
run: pytest tests/ -v --cov=app --cov-report=xml
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY_TEST }}
- name: 커버리지 업로드
uses: codecov/codecov-action@v4
# 2. Docker 빌드 & 푸시
build:
needs: test
runs-on: ubuntu-latest
if: github.ref == "refs/heads/main"
outputs:
image-tag: ${{ steps.meta.outputs.tags }}
steps:
- uses: actions/checkout@v4
- name: Docker 메타데이터
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=sha,prefix=sha-
type=raw,value=latest
- name: GitHub Container Registry 로그인
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Docker Buildx 설정
uses: docker/setup-buildx-action@v3
- name: 빌드 & 푸시
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
cache-from: type=gha
cache-to: type=gha,mode=max
# 3. 프로덕션 배포
deploy:
needs: build
runs-on: ubuntu-latest
environment: production # 수동 승인 필요
steps:
- name: GCP 인증
uses: google-github-actions/auth@v2
with:
credentials_json: ${{ secrets.GCP_SA_KEY }}
- name: Cloud Run 배포
uses: google-github-actions/deploy-cloudrun@v2
with:
service: ai-service
region: asia-northeast3
image: ${{ needs.build.outputs.image-tag }}
- name: 배포 알림 (Slack)
uses: slackapi/slack-github-action@v1
with:
payload: '{"text": "배포 완료! ${{ github.sha }}"}'
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}
5-2. pytest로 AI 서비스 테스트
# tests/test_api.py
import pytest
from fastapi.testclient import TestClient
from unittest.mock import patch, MagicMock
from app.main import app
client = TestClient(app)
class TestSentimentAPI:
def test_sentiment_positive(self):
"""긍정 텍스트 분류 테스트"""
with patch("app.api.routes.predict.model") as mock_model:
mock_model.return_value = [{"label": "positive", "score": 0.99}]
response = client.post("/api/v1/predict/sentiment",
json={"text": "이 제품 정말 좋아요!"},
headers={"X-API-Key": "test-key"})
assert response.status_code == 200
data = response.json()
assert data["sentiment"] == "positive"
assert data["confidence"] > 0.9
def test_empty_text_returns_422(self):
"""빈 텍스트 검증 테스트"""
response = client.post("/api/v1/predict/sentiment",
json={"text": ""},
headers={"X-API-Key": "test-key"})
assert response.status_code == 422
def test_health_check(self):
"""헬스체크 테스트"""
response = client.get("/health")
assert response.status_code == 200
assert response.json()["status"] == "ok"
Ch 06. MLOps & 모델 관리
프로덕션에서 AI 모델을 안정적으로 운영하기 — 실험 추적부터 드리프트 감지까지
6-1. MLflow — 실험 추적 & 모델 레지스트리
pip install mlflow
import mlflow
import mlflow.sklearn
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
# MLflow 서버 실행 (로컬)
# mlflow server --host 0.0.0.0 --port 5000
mlflow.set_tracking_uri("http://localhost:5000")
mlflow.set_experiment("sentiment-classifier-v2")
with mlflow.start_run(run_name="rf-baseline"):
# 하이퍼파라미터 기록
params = {"n_estimators": 100, "max_depth": 10, "random_state": 42}
mlflow.log_params(params)
# 모델 학습
model = RandomForestClassifier(**params)
model.fit(X_train, y_train)
# 지표 기록
accuracy = accuracy_score(y_test, model.predict(X_test))
mlflow.log_metric("accuracy", accuracy)
mlflow.log_metric("f1_score", f1_score(y_test, model.predict(X_test)))
# 모델 저장
mlflow.sklearn.log_model(model, "model",
registered_model_name="sentiment-classifier")
# 아티팩트 저장
mlflow.log_artifact("confusion_matrix.png")
mlflow.log_artifact("feature_importance.csv")
# 최고 모델 로드
best_model = mlflow.sklearn.load_model("models:/sentiment-classifier/Production")
predictions = best_model.predict(X_new)
6-2. 모델 모니터링 & 드리프트 감지
pip install evidently
from evidently import ColumnMapping
from evidently.report import Report
from evidently.metric_preset import DataDriftPreset, ModelPerformancePreset
# 데이터 드리프트 감지
report = Report(metrics=[DataDriftPreset(), ModelPerformancePreset()])
report.run(
reference_data=train_df, # 학습 때 데이터
current_data=production_df, # 현재 프로덕션 데이터
column_mapping=ColumnMapping(target="label", prediction="prediction")
)
report.save_html("drift_report.html")
# 드리프트 감지 시 알림
result = report.as_dict()
drift_detected = result["metrics"][0]["result"]["dataset_drift"]
if drift_detected:
send_slack_alert("경고: 데이터 드리프트 감지! 모델 재학습 필요")
trigger_retraining_pipeline()
6-3. MLOps 성숙도 모델
| 레벨 | 특징 | 도구 |
|---|---|---|
| Level 0 | 수동 프로세스, 스크립트 실행 | Jupyter Notebook |
| Level 1 | ML 파이프라인 자동화 | MLflow + DVC |
| Level 2 | CI/CD + 자동 재학습 | GitHub Actions + MLflow |
| Level 3 | 완전 자동화 + 모니터링 | Kubeflow + Evidently |
Ch 07. 포트폴리오 프로젝트 — 풀스택 AI 챗봇 서비스
취업에 필요한 모든 기술을 담은 완성형 AI 프로젝트 — 기획부터 배포까지
7-1. 프로젝트 개요 — AI 문서 분석 서비스
| 항목 | 내용 |
|---|---|
| 서비스명 | DocAI — 기업 문서 AI 분석 플랫폼 |
| 핵심 기능 | PDF 업로드 → RAG 기반 Q&A → 요약 → 번역 |
| 기술 스택 | FastAPI + LangChain + Chroma + OpenAI + PostgreSQL + Redis + Docker |
| 프론트엔드 | Next.js + Tailwind CSS + WebSocket |
| 배포 | GCP Cloud Run + GitHub Actions CI/CD |
7-2. 백엔드 전체 구현
# app/services/doc_ai_service.py
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_chroma import Chroma
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.document_loaders import PyPDFLoader
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser
import hashlib, os, redis, json
redis_client = redis.from_url(os.getenv("REDIS_URL"))
class DocAIService:
def __init__(self):
self.embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
self.llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
self.splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
async def process_document(self, file_path: str, doc_id: str) -> dict:
"""문서 처리 및 벡터 DB 저장"""
loader = PyPDFLoader(file_path)
docs = loader.load()
chunks = self.splitter.split_documents(docs)
for c in chunks:
c.metadata["doc_id"] = doc_id
vectordb = Chroma.from_documents(
chunks, self.embeddings,
persist_directory=f"./chroma/{doc_id}"
)
return {"doc_id": doc_id, "chunks": len(chunks), "pages": len(docs)}
async def ask_question(self, doc_id: str, question: str) -> str:
"""RAG 기반 질문 답변 (캐싱 포함)"""
cache_key = f"qa:{doc_id}:{hashlib.md5(question.encode()).hexdigest()}"
cached = redis_client.get(cache_key)
if cached:
return json.loads(cached)["answer"]
vectordb = Chroma(
persist_directory=f"./chroma/{doc_id}",
embedding_function=self.embeddings
)
retriever = vectordb.as_retriever(
search_type="mmr", search_kwargs={"k": 5, "fetch_k": 20}
)
prompt = ChatPromptTemplate.from_template("""
주어진 문서 내용만을 기반으로 질문에 답변하세요.
문서에 없는 내용은 "해당 문서에서 찾을 수 없습니다"라고 답하세요.
문서 내용:
{context}
질문: {question}
답변:""")
chain = (
{"context": retriever | (lambda d: "
".join(x.page_content for x in d)),
"question": RunnablePassthrough()}
| prompt | self.llm | StrOutputParser()
)
answer = await chain.ainvoke(question)
# 캐시 저장 (24시간)
redis_client.setex(cache_key, 86400, json.dumps({"answer": answer}))
return answer
async def summarize(self, doc_id: str) -> str:
"""문서 요약"""
vectordb = Chroma(persist_directory=f"./chroma/{doc_id}",
embedding_function=self.embeddings)
all_docs = vectordb.get()
full_text = " ".join(all_docs["documents"][:20]) # 상위 20청크
response = await self.llm.ainvoke(
f"다음 문서를 3~5줄로 요약하세요:
{full_text[:3000]}"
)
return response.content
7-3. REST API 엔드포인트
# app/api/routes/documents.py
from fastapi import APIRouter, UploadFile, File, HTTPException, BackgroundTasks
import uuid, aiofiles, os
router = APIRouter()
service = DocAIService()
@router.post("/upload")
async def upload_document(
file: UploadFile = File(...),
background_tasks: BackgroundTasks = None
):
if not file.filename.endswith(".pdf"):
raise HTTPException(status_code=400, detail="PDF만 지원합니다")
if file.size > 50 * 1024 * 1024: # 50MB 제한
raise HTTPException(status_code=400, detail="파일 크기 초과")
doc_id = str(uuid.uuid4())
file_path = f"/tmp/{doc_id}.pdf"
async with aiofiles.open(file_path, "wb") as f:
await f.write(await file.read())
background_tasks.add_task(service.process_document, file_path, doc_id)
return {"doc_id": doc_id, "status": "processing", "filename": file.filename}
@router.post("/{doc_id}/ask")
async def ask_question(doc_id: str, body: dict):
answer = await service.ask_question(doc_id, body["question"])
return {"doc_id": doc_id, "question": body["question"], "answer": answer}
@router.get("/{doc_id}/summary")
async def get_summary(doc_id: str):
summary = await service.summarize(doc_id)
return {"doc_id": doc_id, "summary": summary}
Ch 08. 포트폴리오 구성 전략
합격하는 AI 개발자 포트폴리오 만들기 — GitHub부터 데모까지
8-1. 포트폴리오 체크리스트
| 항목 | 중요도 | 구체적 내용 |
|---|---|---|
| GitHub 프로필 | 필수 | 잔디 일관성, 핀된 레포 6개, 프로필 README |
| 프로젝트 README | 필수 | 데모 GIF, 기술스택 배지, 아키텍처 다이어그램 |
| 라이브 데모 | 권장 | HuggingFace Spaces, Streamlit Cloud, Vercel |
| 기술 블로그 | 권장 | 프로젝트 회고, 기술 선택 이유, 트러블슈팅 |
| 논문/대회 | 가산점 | Kaggle 입상, arXiv 논문, AI 해커톤 |
8-2. 완벽한 GitHub README 템플릿
# 🤖 DocAI — AI 문서 분석 플랫폼
[]()
[]()
[]()
[]()
[](https://docai-demo.com)
> PDF 문서를 업로드하면 AI가 즉시 분석하고 질문에 답변합니다.
## 데모

## 주요 기능
- 📄 PDF 업로드 및 자동 텍스트 추출
- 🔍 RAG 기반 정확한 Q&A (환각 방지)
- 📝 3~5줄 자동 요약
- 🌐 한/영 번역 지원
- ⚡ 실시간 스트리밍 응답
## 아키텍처
```
Client → Nginx → FastAPI → OpenAI API
→ LangChain → Chroma VectorDB
→ PostgreSQL (메타데이터)
→ Redis (캐싱)
```
## 기술 스택
| 분류 | 기술 | 선택 이유 |
|------|------|----------|
| Backend | FastAPI | 비동기, 자동 문서화 |
| AI | LangChain + OpenAI | RAG 파이프라인 |
| VectorDB | Chroma | 개발 편의성 |
| Cache | Redis | API 비용 50% 절감 |
| Deploy | GCP Cloud Run | 서버리스, 비용 최적화 |
## 성능 지표
- 평균 응답 시간: 1.2초
- 답변 정확도: 94.3% (100개 Q&A 수동 평가)
- 캐시 히트율: 43% (API 비용 절감)
## 로컬 실행
```bash
git clone https://github.com/username/docai
cd docai
cp .env.example .env # API 키 설정
docker compose up -d
# http://localhost:8000/docs 접속
```
8-3. GitHub 프로필 README
# 안녕하세요! AI 개발자 홍길동입니다 👋
> 생성형 AI와 백엔드 개발로 가치 있는 서비스를 만드는 것을 즐깁니다.
## 기술 스택
**AI/ML**: Python · PyTorch · TensorFlow · HuggingFace · LangChain · OpenAI API
**Backend**: FastAPI · PostgreSQL · Redis · Docker
**Cloud**: GCP · AWS · GitHub Actions
## 주요 프로젝트
| 프로젝트 | 설명 | 기술 | 링크 |
|---------|------|------|------|
| DocAI | AI 문서 분석 플랫폼 | FastAPI, RAG, LangChain | [Demo](https://docai.com) |
| SentimentBot | 한국어 감성 분석 API | BERT, HuggingFace | [GitHub](https://github.com/...) |
## 최근 활동


Ch 09. AI 개발자 취업 전략
면접 합격을 위한 모든 것 — 이력서, 코딩테스트, 기술면접 완전 정복
9-1. AI 개발자 취업 로드맵
| 직군 | 필수 기술 | 연봉 (2025) | 주요 기업 |
|---|---|---|---|
| ML Engineer | Python, PyTorch, Docker, CI/CD | 5천~1억5천 | 카카오, 네이버, 쿠팡 |
| AI 백엔드 | FastAPI, LangChain, RAG, AWS | 4천~1억2천 | 스타트업, 핀테크 |
| MLOps Engineer | Kubernetes, MLflow, Airflow | 6천~1억8천 | 빅테크, AI 스타트업 |
| AI 연구원 | 논문 독해/구현, PyTorch, 수학 | 6천~억+ | 삼성리서치, LG AI |
9-2. 합격하는 AI 이력서 작성법
# 이력서 프로젝트 작성 공식: STAR 방법
# S(Situation): 상황/문제
# T(Task): 맡은 역할
# A(Action): 실제 한 일
# R(Result): 수치화된 결과
# 나쁜 예:
"RAG 기반 챗봇 개발"
# 좋은 예:
"사내 문서 검색 효율 개선 필요로 RAG 기반 챗봇을 설계·구현하여
평균 문서 검색 시간을 15분 → 30초로 97% 단축.
(FastAPI + LangChain + Chroma + GPT-4o-mini, Redis 캐싱으로 API 비용 43% 절감)"
# 기술 스택 분류 예시
기술 스택:
AI/ML: Python, PyTorch, TensorFlow, HuggingFace, LangChain, OpenAI API
Backend: FastAPI, PostgreSQL, Redis, SQLAlchemy
DevOps: Docker, GitHub Actions, GCP Cloud Run, AWS EC2
Tools: Git, MLflow, Jupyter, VS Code
9-3. 기술 면접 필수 준비 항목
| 분야 | 준비 항목 | 참고 자료 |
|---|---|---|
| 코딩 테스트 | 자료구조, 알고리즘, DP, 그래프 | 프로그래머스, 백준 200+ |
| ML 이론 | 손실함수, 역전파, 정규화, 평가지표 | cs229, 면접 질문집 |
| 시스템 설계 | AI 서비스 아키텍처, 스케일링, 캐싱 | System Design Interview |
| 프로젝트 회고 | 기술 선택 이유, 트러블슈팅, 성과 | 본인 프로젝트 철저히 준비 |
9-4. 추천 학습 커뮤니티 & 자료
| 분야 | 추천 자료 |
|---|---|
| 논문 읽기 | Papers With Code, arXiv, Semantic Scholar |
| 실습 | Kaggle, DrivenData, HuggingFace 대회 |
| 커뮤니티 | 모두의연구소, 가짜연구소, AI 코리아 |
| 영상 | Andrej Karpathy, Yannic Kilcher, 이수안 컴퓨터 연구소 |
| 채용 정보 | 원티드, 링크드인, 로켓펀치, 잡플래닛 |
Ch 10. 현업 면접 Q&A TOP 10
AI 개발자 최종 면접 — 시스템 설계, MLOps, 배포 핵심 질문 완벽 답변
Q1. AI 서비스의 시스템 아키텍처를 설계해보세요.
① Load Balancer → ② FastAPI 서버 (다중 인스턴스) → ③ Redis 캐시 → ④ AI 모델 서버 (GPU) → ⑤ Vector DB → ⑥ PostgreSQL. 스케일링 전략: 수평 확장(ECS) + 오토스케일링 + CDN. 모델은 별도 서버 분리로 확장성 확보.
Q2. API 응답 속도를 개선하는 방법은?
① Redis 캐싱 (동일 쿼리 재처리 방지) ② 비동기 처리 (FastAPI async/await) ③ 배치 처리 (여러 요청 묶어서 처리) ④ 모델 경량화 (Quantization, ONNX) ⑤ CDN 활용 ⑥ DB 인덱싱 최적화 ⑦ Connection Pool 관리
Q3. Docker와 가상머신(VM)의 차이는?
VM: 하이퍼바이저 위에 전체 OS를 가상화(GB 단위). Docker: 호스트 OS 커널을 공유하는 컨테이너 (MB 단위, 5-10배 빠른 시작). AI 서비스에서 Docker 선호 이유: 재현성, 배포 일관성, 마이크로서비스 구성 용이.
Q4. CI/CD에서 Blue-Green 배포란?
현재 서비스(Blue)를 유지하면서 새 버전(Green)을 별도 환경에 배포. 테스트 완료 후 트래픽을 Green으로 전환. 문제 발생 시 즉시 Blue로 롤백 가능. 다운타임 제로 배포의 핵심 전략. Canary 배포는 일부 트래픽만 새 버전으로 보내는 점진적 방식.
Q5. RAG 시스템의 품질을 어떻게 평가하나요?
RAGAS 프레임워크 사용: ① Faithfulness (컨텍스트 충실도) ② Answer Relevance (답변 관련성) ③ Context Precision (검색 정밀도) ④ Context Recall (검색 재현율). 실제로는 100~300개 Q&A 골든셋 구성 후 정기 평가. 인간 평가와 자동 평가 병행.
Q6. 모델 배포 시 A/B 테스트 설계는?
① 트래픽 분할 (80/20으로 시작) ② 측정 지표 사전 정의 (CTR, 전환율, 응답만족도) ③ 통계적 유의성 검증 (p-value < 0.05) ④ 충분한 샘플 수 확보 후 결론. 온라인 평가와 오프라인 평가를 함께 사용.
Q7. LLM 서비스의 Rate Limiting 설계는?
Redis + Sliding Window 방식: 사용자별 분당/시간당 요청 수 제한. 토큰 버킷 알고리즘으로 burst 허용. 429 Too Many Requests 반환 시 Retry-After 헤더 포함. 플랜별 차등 제한 (Free: 10req/min, Pro: 100req/min).
Q8. MLflow와 DVC의 차이는?
MLflow: 실험 추적 (파라미터, 지표, 모델 아티팩트), 모델 레지스트리, 서빙. DVC: 데이터 버전 관리 (Git과 유사), 대용량 파일 Git 외부 저장, 재현 가능한 ML 파이프라인. 둘은 상호보완적으로 함께 사용하면 완전한 MLOps 구성 가능.
Q9. 대규모 데이터 처리 시 성능 최적화는?
① 배치 임베딩 (단건보다 10배 빠름) ② 비동기 I/O (aiofiles, httpx) ③ 멀티프로세싱 (CPU 병렬화) ④ 스트리밍 처리 (메모리 절약) ⑤ 데이터 파이프라인 (Apache Kafka, Airflow) ⑥ GPU 병렬 추론 (DataParallel)
Q10. 프로덕션 AI 서비스 장애 대응 방법은?
① Fallback 전략: OpenAI 오류 시 로컬 LLM으로 전환 ② Circuit Breaker 패턴 ③ 알림: Slack + PagerDuty ④ 로깅: 구조화 로그 (JSON) + ELK Stack ⑤ 사후 분석 (Post-mortem): 원인 분석 → 재발 방지 → 문서화 ⑥ SLO/SLA 정의 (가용성 99.9%)
학습 완료 체크리스트 — AI 개발자 취업 준비
Ch01~Ch03 인프라 기초
☐
HuggingFace Hub 모델 업로드
☐ Gradio Space 데모 배포
☐ FastAPI AI 서버 구현
☐ Docker로 컨테이너화
Ch04~Ch06 배포&운영
☐ GCP
Cloud Run 배포 완료
☐ GitHub Actions CI/CD 파이프라인
☐ MLflow 실험 추적 설정
☐ 모델 모니터링 시스템 구축
Ch07~Ch08 포트폴리오
☐ 풀스택 AI
서비스 E2E 구현
☐ GitHub README 완성
☐ 라이브 데모 배포
☐ 기술 블로그 포스팅 3개+
Ch09~Ch10 취업 준비
☐ STAR 방식 이력서
작성
☐ 코딩 테스트 프로그래머스 Lv.3
☐ 면접 Q&A 10개 완벽 답변
☐ 5개 회사 이상 지원!
AI Dev Guide 시리즈 완주!
Guide 01 → 07 — 7개 가이드 완전 정복
AI 개념부터 실전 배포까지 — 당신은 이제 AI 개발자입니다!
✅ Guide 01 — AI 개념 완전 정복
✅ Guide
02 — Python 기초 완전 정복
✅ Guide 03 — 데이터 다루기
(NumPy·Pandas·Matplotlib)
✅ Guide 04 — 머신러닝 완전
정복 (Scikit-learn)
✅ Guide 05 — 딥러닝 완전 정복
(TensorFlow·PyTorch)
✅ Guide 06 — 생성형 AI (OpenAI
API·LangChain·RAG)
🏆 Guide 07 — 실전 프로젝트
(HuggingFace·FastAPI·Docker·취업)
다음 목표
AI 개발자 취업 성공!
계속 성장하기
Kaggle · 논문 구현 · 오픈소스