이 문서를 통해 아래 질문들에 답할 수 있게 됩니다.
- 개인 AI 프로젝트에서 어디까지 하면 “수준 있다”고 볼 수 있는가?
- 기업 수준 장치를 모두 붙이지 않고도 운영 감각을 보여주는 방법은 무엇인가?
- 포트폴리오 AI 기능에 꼭 넣으면 좋은 실패 처리와 관측성은 무엇인가?
- 작은 프로젝트에서도 피해야 할 위험 신호는 무엇인가?
개요
개인 프로젝트는 기업 운영 수준의 모든 장치를 넣을 필요는 없다. 그러나 AI 기능은 단순 데모와 실전 감각의 차이가 크다. timeout, schema validation, usage log, prompt version, 작은 eval set만 있어도 결과물의 수준이 달라진다.
목표는 거대한 플랫폼을 만드는 것이 아니라, 실패와 비용을 의식하고 설계했다는 것을 보여주는 것이다.
최소 기준
개인 프로젝트 AI 기능의 최소 기준은 다음이다.
- API key를 안전하게 관리한다.
- 모델 호출을 client wrapper로 감싼다.
- timeout을 둔다.
- retry는 제한적으로 적용한다.
- structured output은 schema validation을 한다.
- prompt version을 남긴다.
- token usage를 기록한다.
- 대표 질문 eval set을 둔다.
- RAG를 쓰면 source와 삭제 절차를 둔다.
추천 구조
app/
api/
services/
ai_summary_service.py
ai/
llm_client.py
prompts/
ticket_summary_v1.txt
schemas.py
eval_cases.json단순한 구조라도 AI 관련 책임을 모아두면 설명하기 좋다.
코드로 이해하기
작은 프로젝트에서도 client wrapper는 유용하다.
import os
import time
from dataclasses import dataclass
@dataclass(frozen=True)
class AiUsage:
model: str
elapsed_ms: int
prompt_version: str
class SimpleLlmClient:
def __init__(self, api_key: str | None = None):
self.api_key = api_key or os.environ["OPENAI_API_KEY"]
def generate(self, *, prompt: str, prompt_version: str, timeout_seconds: float) -> str:
started = time.monotonic()
try:
# 실제 SDK 호출 위치
return call_provider(prompt=prompt, timeout_seconds=timeout_seconds)
finally:
elapsed_ms = int((time.monotonic() - started) * 1000)
print({
"event": "ai.generate",
"prompt_version": prompt_version,
"elapsed_ms": elapsed_ms,
})핵심은 provider 호출을 흩뿌리지 않고 한곳에서 timeout과 logging을 적용하는 것이다.
포트폴리오에서 보여주면 좋은 것
- 왜 이 기능에 RAG가 필요한지 설명한다.
- source를 답변에 표시한다.
- 모델 응답이 깨졌을 때 사용자 메시지를 보여준다.
- 비용 제한이나 일일 호출 제한을 둔다.
- eval 결과를 README에 적는다.
- 개인정보를 로그에 남기지 않는다고 명시한다.
이런 요소는 화면보다 더 강하게 실전 감각을 보여준다.
개인 프로젝트 RAG 기준
RAG를 붙인다면 다음은 챙긴다.
- 문서마다 source id를 둔다.
- chunking 기준을 문서화한다.
- top-k와 token budget을 제한한다.
- 답변에 source id를 반환한다.
- 문서 삭제 시 index에서 제거하는 스크립트를 둔다.
삭제 절차가 없는 RAG는 개인 프로젝트에서도 위험하다. 잘못된 정보가 계속 검색될 수 있다.
장애 상황과 대응
개인 프로젝트에서도 다음 장애를 테스트한다.
- API key가 없을 때
- provider timeout
- JSON 파싱 실패
- 검색 결과가 없을 때
- 너무 긴 입력
- 일일 quota 초과
실패 화면과 로그를 준비해 두면 시연 중에도 안정적이다.
기업 수준과의 차이
기업 운영에서는 SLO, audit log, tenant quota, 보안 리뷰, 인프라 런북까지 필요하다. 개인 프로젝트는 그 전 단계로 충분하다.
중요한 것은 “나중에 확장할 수 있는 경계”를 보여주는 것이다. client wrapper, prompt version, eval set, usage log가 그 경계다.
실전 팁
- 공개 repo에는
.env.example만 올린다. - README에 “실패 처리” 섹션을 넣는다.
- eval case는 작아도 실제로 실행 가능한 형태로 둔다.
- 비용이 드는 기능은 기본적으로 호출 제한을 둔다.
위험 신호!
- API key가 코드에 있다.
- 모델 응답을 그대로 DB에 저장한다.
- 실패하면 무조건 500이다.
- prompt가 코드 여기저기에 복사되어 있다.
- RAG source와 삭제 절차가 없다.
확인 질문
확인 질문
- 개인 AI 프로젝트의 최소 실전 기준은 무엇인가?
- timeout, 제한적 retry, schema validation, prompt version, usage log, 작은 eval set이다.
- 포트폴리오에서 AI 기능의 수준을 보여주는 좋은 방법은 무엇인가?
- 실패 처리, source 표시, 비용 제한, eval 결과, 로그 설계를 함께 보여주는 것이다.
Spring AI 적용 연결
- 개인 프로젝트라도 Spring AI를 쓰면 gateway, eval, observability, 비용 제한을 작게라도 갖추는 편이 좋다. 최소 운영 기준은 12. Production Readiness와 인프라 협업에서 이어진다.
- 고객지원 RAG를 개인 프로젝트 수준에서 끝까지 설계해보려면 13. 고객지원 RAG Capstone을 함께 본다.