당신의 앱은 CRUD를 위해 구축되었습니다. AI를 위해 무엇이 바뀌어야 하는가
요약
기존 CRUD 중심의 결정론적 아키텍처와 확률론적 유용성을 지향하는 AI 아키텍처의 근본적인 차이를 분석합니다. AI 시대에 맞춰 데이터 모델링이 스키마 중심에서 컨텍스트 중심으로 변화해야 함을 강조합니다.
핵심 포인트
- CRUD는 결정론적 일관성에, AI는 확률적 유용성에 최적화되어 있음
- AI는 단순 데이터 검색을 넘어 데이터에 대한 추론과 판단을 수행함
- 데이터 모델링 패러다임이 스키마 우선에서 컨텍스트 우선으로 전환되어야 함
- 기존 아키텍처 위에 확률적 연산을 처리하는 새로운 계층 구축 필요
애플리케이션이 기록 보관소(record keepers)였을 때는 CRUD가 합리적이었습니다.
사용자를 생성(Create)합니다. 주문을 읽고(Read), 상태를 업데이트(Update)하며, 레코드를 삭제(Delete)합니다. 데이터베이스 스키마(database schema), API 설계, 서비스 경계(service boundaries)를 포함한 전체 아키텍처는 데이터가 유입되어 저장된 후, 들어왔던 것과 동일한 형태로 다시 흘러나간다는 가정하에 구축되었습니다.
AI는 그 가정을 완전히 깨뜨립니다.
AI는 데이터를 단순히 검색(retrieve)하지 않습니다. 데이터에 대해 추론(reason)합니다. AI는 레코드를 반환하는 것이 아니라, 판단(judgment)을 반환합니다. 따라서 한쪽에서는 완벽하게 작동하는 아키텍처가 다른 쪽에서는 소리 없이 실패하게 됩니다.
이 글은 기존 앱에 AI 기능을 추가하는 것에 관한 글이 아닙니다. 지능(intelligence)이 부가 기능이 아닌 핵심 요구사항이 될 때, 애플리케이션 아키텍처를 생각하는 방식에서 구조적으로 무엇이 바뀌어야 하는지를 이해하기 위한 글입니다.
CRUD 아키텍처가 실제로 최적화되어 있는 것
무엇을 바꿔야 하는지 이해하려면, 전통적인 CRUD 아키텍처가 무엇을 위해 설계되었는지에 대해 솔직해져야 합니다.
CRUD 시스템은 **결정론(determinism)과 일관성(consistency)**에 최적화되어 있습니다.
모든 작업은 예측 가능한 입력, 예측 가능한 출력, 그리고 명확한 성공/실패 상태를 가집니다. 사용자는 존재하거나 존재하지 않거나 둘 중 하나입니다. 주문은 업데이트되었거나 되지 않았거나 둘 중 하나입니다. 데이터베이스는 진실의 원천(source of truth)이며 애플리케이션은 전달자(messenger)입니다.
이러한 예측 가능성은 한계가 아니라 특징입니다. 이것이 CRUD 시스템이 테스트하기 쉽고, 디버깅하기 쉬우며, 논리적으로 파악하기 쉬운 이유입니다.
문제는 지능적인 동작(intelligent behavior)은 이 중 그 어느 것도 아니라는 점입니다.
AI 아키텍처가 실제로 최적화되어 있는 것
AI 시스템은 **확률적 유용성(probabilistic usefulness)**에 최적화되어 있습니다.
단 하나의 정답인 출력은 존재하지 않습니다. 더 나은 출력과 더 나쁜 출력이 있을 뿐입니다. 응답은 맞거나 틀린 것이 아니라, 맥락(context)에 따라 더 유용하거나 덜 유용하고, 더 정확하거나 덜 정확하며, 더 적절하거나 덜 적절합니다.
이 근본적인 차이는 아키텍처의 모든 계층으로 파급됩니다:
| 차원 (Dimension) | CRUD | AI |
|---|---|---|
| 출력 유형 (Output type) | 결정론적 (Deterministic) | 확률론적 (Probabilistic) |
| ... |
이 중 어느 것도 기존의 CRUD 기반을 버려야 한다는 뜻은 아닙니다. 이는 그 위에 완전히 다른 클래스의 연산을 처리하는 두 번째 계층을 구축해야 함을 의미합니다.
네 가지 구조적 변화
변화 1: 스키마 우선 (Schema-First)에서 컨텍스트 우선 (Context-First) 데이터 모델링으로
CRUD는 테이블과 컬럼으로 생각합니다. AI는 컨텍스트 윈도우 (Context Window)로 생각합니다.
전통적인 사용자 레코드는 다음과 같습니다:
users
id UUID
email VARCHAR
...
이 스키마는 사용자를 저장하고 검색하는 데는 완벽합니다. 하지만 사용자에 대해 추론 (Reasoning)하는 데는 무용지물입니다.
이 사용자를 AI 시스템에 의미 있게 만들기 위해서는 컨텍스트 (Context)를 조립해야 합니다. 즉, 이 사용자가 누구인지, 무엇을 했는지, 무엇이 필요한지를 나타내는 풍부하고 산문(Prose)과 호환 가능한 표현이 필요합니다:
def build_user_context(user_id: str) -> str:
user = db.get_user(user_id)
events = db.get_recent_events(user_id, limit=30)
...
데이터베이스 스키마는 변하지 않습니다. 변하는 것은 데이터베이스와 AI 호출 사이에 위치하여, 구조화된 데이터를 가져와 LLM이 추론할 수 있는 무언가로 렌더링하는 컨텍스트 조립 계층 (Context Assembly Layer)이 생긴다는 점입니다.
이 계층은 CRUD 아키텍처에는 존재하지 않습니다. 직접 구축해야 합니다.
변화 2: 요청/응답 (Request/Response)에서 관찰/추론/행동 (Observe/Reason/Act)으로
CRUD는 단순한 실행 모델을 가집니다: 요청을 받고, 연산을 실행하고, 응답을 반환합니다. 세 단계로 이루어진 동기적(Synchronous)이고 예측 가능한 방식입니다.
AI 통합 시스템은 완전히 다른 모델이 필요합니다:
이것은 CRUD의 사소한 확장이 아닙니다. 애플리케이션이 기존 모델과 병행하여 지원해야 하는 병렬 실행 모델입니다.
아키텍처 측면에서의 의미:
기존의 엔드포인트(Endpoints)는 CRUD 연산을 동기적으로 처리합니다. AI 연산은 다른 경로를 따릅니다:
# CRUD 경로 — 동기적, 결정론적
@app.route('/orders/<order_id>', methods=['GET'])
def get_order(order_id):
...
두 개의 엔드포인트. 완전히 다른 두 가지 실행 모델. 이 모두가 동일한 애플리케이션 내에 존재합니다.
변화 3: 이진 테스트(Binary Testing)에서 평가 파이프라인(Evaluation Pipelines)으로
이것은 대부분의 엔지니어링 팀이 가장 준비가 안 되어 있는 변화입니다.
CRUD 테스트는 간단합니다:
def test_create_order():
response = client.post('/orders', json={...})
assert response.status_code == 201
...
통과(Pass) 아니면 실패(Fail). 결정론적(Deterministic)이며 자동화하기 쉽습니다.
AI 출력은 이런 방식으로 테스트할 수 없습니다. 단 하나의 정답을 단언(assert)할 수 없기 때문입니다. "이것이 좋은 요약인가?"라는 질문에는 assert summary == expected_summary와 같은 방식으로 답할 수 없습니다.
테스트(Tests)가 아니라 평가(Evaluations)가 필요합니다.
# AI 출력을 위한 평가 파이프라인 (Evaluation pipeline)
def evaluate_summary_quality(
input_ticket: dict,
...
여러분의 CI/CD 파이프라인에는 평가 단계(evaluation stage)가 필요합니다. 프롬프트(Prompt) 변경은 스키마(schema) 변경이 마이그레이션 테스트를 트리거하는 것과 동일한 방식으로, 이미 알려진 입력값과 허용 가능한 출력값으로 구성된 골든 데이터셋(golden dataset)에 대한 재평가를 트리거해야 합니다.
평가 파이프라인 없이 프롬프트 변경 사항을 배포한다면, 여러분은 상황이 더 좋아졌는지 아니면 나빠졌는지 알 방법이 없습니다.
변화 4: 로그(Logs)에서 행동 관측성(Behavioral Observability)으로
CRUD 관측성(Observability)은 비교적 단순합니다. 요청률(request rates), 에러율(error rates), 지연 시간(latency), 그리고 데이터베이스 쿼리 성능을 추적합니다. 에러는 예외(exception)이며, 실패는 5xx 에러입니다. 신호(signals)가 명확합니다.
AI 시스템은 조용히 실패합니다.
자신감 있게 틀린 답을 내놓는 200 응답은 기존의 모니터링 시스템에서는 보이지 않습니다. 에러율은 0%로 유지되고, 지연 시간은 정상적으로 보입니다. 사용자들은 잘못된 출력을 받고 있지만 여러분은 이를 알지 못합니다.
AI 행동에 특화된 새로운 관측성 계층(observability layer)이 필요합니다:
class AIObservability:
def log_inference(
self,
...
추적해야 할 항목:
- 출력 품질 신호 (수락률 (acceptance rate), 편집률 (edit rate), 거부율 (rejection rate))
- 테넌트(tenant)별 기능당 비용
- 모델 및 기능별 지연 시간 분포 (Latency distribution)
- 시간에 따른 프롬프트 버전별 성능
- 환각 (Hallucination) 또는 거부 (refusal) 비율
이러한 데이터는 CRUD 관측성 (observability)에는 존재하지 않습니다. 이를 위한 계측 (instrumentation)을 직접 구축해야 하며, AI 기능을 전체 사용자 기반으로 확장하기 전에 반드시 준비되어 있어야 합니다.
두 가지를 모두 지원하는 아키텍처
기존의 CRUD 아키텍처를 교체하는 것이 아닙니다. 그 옆에서 함께 실행되는 AI 레이어 (layer)를 통해 확장하는 것입니다.
CRUD 레이어는 구조화된 데이터, 결정론적 작업 (deterministic operations), 사용자 관리, 결제, 권한 부여와 같이 기존에 잘 수행해 온 작업들을 처리합니다.
AI 레이어는 다른 범주의 작업들을 처리합니다 — 컨텍스트 조립 (context assembly), 추론 (inference), 출력 평가 (output evaluation), 피드백 캡처 (feedback capture).
두 레이어는 동일한 인증 (authentication), 동일한 API 게이트웨이 (API gateway), 그리고 동일한 기반 데이터베이스를 공유하지만, 서로 다른 관심사 (concerns), 별도의 테스트 전략, 그리고 별도의 관측성 (observability) 요구 사항을 가집니다.
시작하는 방법
기존 CRUD 애플리케이션을 보유하고 있으며 처음으로 AI를 본격적으로 통합하려 한다면, 다음과 같은 순서를 따르십시오.
1단계: 가치가 높고 리스크가 낮은 유스케이스 (use case)를 하나 식별합니다. 백그라운드 강화 (background enrichment, 점수 매기기, 분류, 태깅)는 가장 안전한 시작점입니다. 이는 비동기 (async)로 실행되며 사용자를 절대 차단하지 않습니다.
2단계: 해당 유스케이스를 위한 컨텍스트 조립 (context assembly) 함수를 구축합니다. 이를 통해 실제로 보유하고 있는 데이터와 필요한 데이터가 무엇인지 식별하게 됩니다.
3단계: 첫날부터 전체 로깅 (logging)을 포함하여 AI 호출을 배포합니다. 모든 호출에 대해 입력, 출력, 모델, 지연 시간 (latency), 비용, 그리고 프롬프트 버전을 기록하십시오.
4단계: 피드백 신호를 추가합니다. 설령 그것이 암시적인 형태(사용자가 이 출력을 활용했는가, 아니면 무시했는가?)일지라도 말입니다.
5단계: 평가 기준점 (evaluation baseline)을 구축합니다. 50개의 실제 출력을 가져와 수동으로 채점하고, 이를 향후 프롬프트 변경에 대한 벤치마크 (benchmark)로 사용하십시오.
이 다섯 단계를 모두 완료한 후에야 두 번째 유스케이스로 확장하거나 제품 UI에 임베디드 (embedded)된 AI 기능을 고려해야 합니다.
솔직한 요약
CRUD 아키텍처는 고장 난 것이 아닙니다. 단지 소프트웨어에 점점 더 요구되는 역할들을 수행하기에는 불완전할 뿐입니다.
CRUD에서 AI 통합 시스템으로의 전환은 기존에 잘 작동하던 것을 대체하는 것이 아닙니다. 이는 지능적인 동작(intelligent behavior)을 위해서는 기존의 결정론적(deterministic) 토대와 병행하여 작동하는 다른 실행 모델(execution model), 다른 데이터 표현(data representation), 다른 테스트 전략(testing strategy), 그리고 다른 관측성 스택(observability stack)이 필요하다는 점을 인식하는 것입니다.
이를 제대로 해내는 팀들은 단순히 AI 애플리케이션을 만드는 것이 아닙니다. 그들은 결정론적 연산(deterministic operations)과 확률적 추론(probabilistic reasoning) 모두에 능숙한 애플리케이션을 구축하고 있으며, 제품이 요구하기 전까지는 이 두 가지 관심사를 깔끔하게 분리하여 유지합니다.
_이 포스트는 OutworkTech의 백엔드 엔지니어링 시리즈의 일부입니다. 관련 읽을거리: How to Add AI to Your Existing SaaS Product 및 How to Handle 1M+ Users Without Breaking Your System.
OutworkTech는 과도한 비용 부담 없이 엔지니어링의 깊이가 필요한 기업들을 위해 백엔드 시스템을 구축하고 제품에 AI를 통합합니다. 만약 당신의 애플리케이션이 CRUD를 넘어설 준비가 되었다면 — 함께 이야기해 봅시다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기