본문으로 건너뛰기

"Reference" 태그 — 38개 게시물

외부 아티클, 블로그 등 참고 자료 리뷰

모든 태그 보기

LangFlow OSS 분석

· 약 6분
최재훈
LEAD (AI Research Engineer), Brain Crew

TL;DR

Langflow는 MIT 라이선스 기반의 오픈소스 Python 프레임워크로, AI 워크플로우를 시각적으로 빠르게 구축할 수 있는 low-code 플랫폼입니다. n8n이나 Dify와 달리 컴포넌트의 완전한 커스터마이징이 가능하며, 드래그 앤 드롭 방식으로 Agent와 RAG 애플리케이션을 쉽게 프로토타이핑하고 API로 배포할 수 있습니다. 특정 LLM이나 벡터 스토어에 종속되지 않아 유연한 통합이 가능하며, Python 기반으로 무제한 확장이 가능합니다.

Key Takeaways

  • 완전한 오픈소스와 커스터마이징: MIT 라이선스로 셀프 호스팅이 가능하고, Python 코드로 모든 컴포넌트를 완전히 커스터마이징할 수 있어 프로덕션 환경에 유연하게 적용 가능
  • 빠른 프로토타이핑과 실시간 테스트: 시각적 에디터와 Playground로 전체 스택 구축 없이 워크플로우를 실시간으로 테스트하고 반복 개발 가능
  • API 기반 외부 통합: 구축한 Flow를 REST API로 즉시 서빙할 수 있어, SDK처럼 외부 애플리케이션에서 호출 가능한 공통 규격 제공
  • Agent 및 MCP 지원: 최신 AI 기능인 Agent와 Model Context Protocol(MCP)을 기본 지원하며, 수백 개의 데이터 소스 및 모델 통합 가능
  • 프로토타입에서 프로덕션까지: 컨테이너화 및 클라우드 배포를 지원하여, 프로토타입을 실제 서비스로 빠르게 전환 가능

상세 내용

Langflow 개요

[Figure 01] Langflow Flow 예시

Langflow는 컴포넌트를 드래그 앤 드롭하여 AI 워크플로우를 시각적으로 구축할 수 있는 오픈소스 플랫폼입니다. Python 기반으로 개발되었으며, Agent 및 RAG(Retrieval-Augmented Generation) 애플리케이션 개발에 특화되어 있습니다.

타 플랫폼과의 비교

  • 셀프호스팅 & 완전제어: n8n > Langflow > Dify
  • 비개발자 유저친화도: Dify > n8n > Langflow

Langflow의 핵심 차별점은 MIT 라이선스를 채택한 완전한 오픈소스이며, 컴포넌트의 완전한 커스터마이징(Fully-custom)이 가능하다는 점입니다. 이는 프로덕션 환경에서 비즈니스 요구사항에 맞춰 세밀한 조정이 필요한 Research Engineer에게 중요한 장점입니다.

프로젝트 목적과 활용 방향

1. 빠른 프로토타이핑 Langflow를 사용하면 복잡한 Agent 및 워크플로우를 시각적으로 빠르게 구성하고 테스트할 수 있습니다. 이를 통해 아이디어 검증 단계부터 프로덕션 배포까지의 시간을 대폭 단축할 수 있습니다.

2. 표준화된 외부 제공 인터페이스 구축한 Flow를 SDK처럼 외부에서 호출할 수 있는 공통 규격을 제공합니다. REST API를 통해 다른 시스템과 쉽게 통합할 수 있어, 마이크로서비스 아키텍처에 적합합니다.

핵심 구성 요소

Projects와 Flow

[Figure 02] Project와 flow

Langflow의 기본 구조는 ProjectsFlow로 구성됩니다:

  • Projects: 논리적 폴더 단위로, 관련된 여러 Flow를 그룹화하여 관리
  • Flow: 실제 워크플로우를 정의하는 단위로, 각 Flow는 여러 컴포넌트로 구성

Workflow Builder와 Canvas

[Figure 03] Canvas와 Components

시각적 에디터는 다음과 같이 구성됩니다:

  • Canvas: 컴포넌트를 드래그 앤 드롭하여 배치하고 연결하는 작업 영역
  • Components 패널: 사용 가능한 모든 컴포넌트의 목록

Flow를 구성할 때는 왼쪽 패널에서 필요한 컴포넌트를 Canvas로 드래그하고, 각 컴포넌트의 파라미터를 설정한 후 컴포넌트 간의 입출력을 연결하여 데이터 흐름을 정의합니다.

Component 시스템

[Figure 04] Components

Basic Components

Langflow는 다음과 같은 카테고리의 기본 컴포넌트를 제공합니다:

  • Language Models: OpenAI, Anthropic, Google, Meta, Mistral, Groq 등 다양한 LLM 지원
  • Vector Stores: Pinecone, Qdrant, Milvus, Weaviate, Couchbase 등 주요 벡터 DB 통합
  • Data Sources: Airbyte, Confluence, Gmail, Google Drive, Notion, Slack 등 다양한 데이터 소스
  • Tools: Serper, Tavily, Wolfram Alpha, Yahoo Finance 등 외부 API 통합
  • Agents: LangChain, CrewAI 등 에이전트 프레임워크 지원
  • Input/Output: 범용 입출력 컴포넌트

![[Figure 05] Detail Component](https://prod-files-secure.s3.us-west-2.amazonaws.com/bb84b169-cb88-81fc-90c3-00032f05f905/bfee0afa-1c2a-42f7-9ab8-38b328c4a5e8/image.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=ASIAZI2LB466QACOPKHI%2F20260325%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20260325T071048Z&X-Amz-Expires=3600&X-Amz-Security-Token=IQoJb3JpZ2luX2VjEN%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwEaCXVzLXdlc3QtMiJGMEQCIBQmL%2BFAp0PMwK46HeFb0uQwC%2FAQgR7%2BazQSnCp3bfvkAiA8Bd0SNNnrgAwe7HNhWSXZChjcoYlPUQoau%2BEBrffC7SqIBAin%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F8BEAAaDDYzNzQyMzE4MzgwNSIMaPildgUq4u2ZFuD2KtwDnZbCzmrO2TZ3NIf1v0B%2BTFSbRQCVxYAmAyU%2BKIzM8mNDLC%2B10Xbq7FlYlkcfBkMPXqWwzC2gtXv1QzLjS5SEQG1T4m3OUtSWE16%2B7DNWXx1%2FQsSBnqxpYj3CKapVmogwJmkKhNFOIwssA799oW41JiBUtrNymd2QVTXkmj%2FoS4oad%2B3yWnMxUfUV8BWEDgMbmgTZysxUCuueiX1KYytRK3xmoPy0lPzSdP1caOhHzSeeYolGYIN3rD%2FgylFCGA0AAkJGxPPhnHZlzNBld6lXNvr7Qgi1GRErpQqLC1AO1RMwsCp3zy8dPiV4xXG6xhHgPD%2FCVfiMKucwFhqON73NjhmAhvlKqm5nJwcpPCVBVG0HJ9ZAUlSz6dm48r9iBehFtJR%2BLTaFMJSm%2FnlCCTsSoB7Vdt8yoXp5dXpKV6lQ72fsC9wMuyVyVwiSrKdFp%2FQnW%2BgVTpGwyLqhyRDg6os0%2FG78bMUrh5TlKXnDTuiI1DXnStWw8sZCWnFYYuLEhJIKzQV2FaHAwFEQgaWVitr9MW%2FihTfFQ5XZ6x3aPKlr82j9osjO4NWfp%2Bmz7fZn1hkXXMnzkxOr5tFTbYhSMQRvyyp8oFKwanOTpOJXGSLp2yYgHXkXozutmDMepBYwvf2NzgY6pgGTwKFvokVxrPveLPYmiIRwkH5s9QA%2

Salesforce, Agent 정확도 높이기 위해 LLM 의존도 축소

· 약 5분
최재훈
LEAD (AI Research Engineer), Brain Crew

TL;DR

Salesforce가 AI 에이전트의 정확도와 신뢰성 확보를 위해 LLM 의존도를 줄이고 결정론적(deterministic) 접근 방식을 도입했다. LLM의 확률적 특성은 같은 입력에도 다른 결과를 내놓아 기업 운영에 부적합하며, 환각 문제와 높은 토큰 비용도 발생시켰다. 이에 Salesforce는 'Agentforce Script'와 하이브리드 추론 아키텍처를 통해 LLM의 지능을 활용하되 미리 정의된 워크플로우로 제어하는 전략을 채택했다. 이는 AI 에이전트 도입의 새로운 패러다임을 제시하며, 특히 정확성이 필수적인 비즈니스 워크플로우에서 LLM과 전통적 프로그래밍의 균형이 중요함을 시사한다.

Key Takeaways

  • 결정론적 제어의 필요성: 기업 환경에서는 같은 입력에 항상 동일한 출력이 보장되어야 하므로, LLM의 확률적 특성을 결정론적 워크플로우로 제어하는 것이 필수적
  • 하이브리드 추론 아키텍처: LLM의 지능을 활용하되, Agent Graph와 같은 구조적 제약을 통해 출력 범위를 미리 지정하는 방식이 실무적 해법
  • 비용 최적화: 정형화된 작업에 LLM 사용을 줄이면 불필요한 토큰 소비를 방지하고(상담 건당 $2+ 절감 가능), 정확성도 향상시킬 수 있음
  • AI Drift 방지: 에이전트가 목표를 잃고 방황하는 현상을 막기 위해 'deterministic trigger' 같은 명확한 제어 지점 설정이 중요
  • 적재적소 활용: 모든 문제를 LLM으로 해결하려 하지 말고, 규칙 기반 접근과 LLM 추론을 작업 특성에 따라 선택적으로 조합하는 전략이 효과적

상세 내용

LLM의 확률적 특성과 기업 운영의 괴리

AI 에이전트 도입에 가장 적극적이었던 Salesforce가 전략 전환을 선언했다. 산즈나 파룰레카르(Sanzana Parulkar) 마케팅 담당 수석 부사장은 The Information과의 인터뷰에서 "AI 에이전트의 신뢰성을 향상하기 위해 결정론적(deterministic) 자동화 방식을 사용하고 있다"고 밝혔다.

이러한 전략 전환의 핵심은 LLM의 본질적 특성에 있다. LLM으로 작동하는 에이전트는 확률적(stochastic)으로 작동하여, 같은 질문에도 매번 조금씩 다른 답변을 생성한다. 하지만 기업 환경에서는 입력값이 같으면 결과도 항상 동일해야 한다. 재고 관리, 환불 처리, 고객 응대와 같은 핵심 비즈니스 프로세스에서 예측 가능성은 선택이 아닌 필수다.

Google Cloud의 마이클 클라크(Michael Clark) 책임자도 이 문제를 지적한 바 있다. 그는 기업이 에이전트를 도입하려면 LLM 출력을 검증하고 오류를 수정하거나, 여러 모델의 교차 검증, 그리고 인간의 모니터링과 개입이 가능한 구조가 필요하다고 강조했다.

실제 사례: Vivint의 AI Drift 문제

이론적 우려는 실제 운영에서 구체적 문제로 드러났다. 보안 카메라 전문 기업 Vivint는 Agentforce를 도입해 250만 고객 지원을 처리했지만, 예상치 못한 문제에 직면했다. 모든 고객에게 상담 후 만족도 설문조사를 보내도록 지시했으나, 알 수 없는 이유로 설문조사가 전송되지 않는 경우가 발생한 것이다.

이는 'AI Drift' 현상으로, AI가 주제와 관계없는 질문을 받으면 원래 목표를 잃고 방황하는 것을 의미한다. Vivint는 Salesforce와 협력하여 '확정적 트리거(deterministic trigger)'를 설정해 이 문제를 해결했다. 이는 LLM의 판단과 무관하게 특정 조건이 충족되면 반드시 실행되는 규칙 기반 로직이다.

비용 문제: 토큰 낭비와 운영 효율성

정확성 문제 외에도 비용이 중요한 고려사항으로 떠올랐다. Salesforce 챗봇이 불필요하게 긴 추론으로 토큰을 낭비해 상담 건당 2달러 이상이 소요된다는 불만이 접수됐다.

무라리다 크리시나파사드(Muralida Krishnaprasad) Salesforce CTO는 "반드시 정확한 답을 얻어야 하는 부분에서 LLM이 쓸데없이 긴 추론으로 토큰을 낭비하는 것은 문제"라며, "LLM에 'if this, then that'과 같은 전통적 조건문을 결합하면 비용을 절감하면서도 정확한 답을 보장할 수 있다"고 설명했다.

Salesforce의 해법: 하이브리드 추론 아키텍처

Salesforce AI 연구소의 필 무이(Phil Mui) 수석 부사장은 블로그를 통해 '하이브리드 추론을 통한 유도형 결정론(Guided Determinism through Hybrid Reasoning)'이라는 접근법을 소개했다.

이 아키텍처의 핵심은 다음과 같다:

1. Agent Graph를 통한 구조적 제어 디자인 타임에 미리 정의된 워크플로우 구조를 통해 LLM이 허용된 범위 내에서만 작동하도록 제약한다. 에이전트가 실행될 때마다 동일한 조치를 취할 수 있도록 출력 범위를 미리 지정한다.

2. Agentforce Script 시스템 현재 테스트 단계인 이 시스템은 LLM의 판단 없이도 작업을 처리할 수 있는 시점을 파악한다. Salesforce 웹사이트는 이를 "LLM의 본질적인 무작위성을 제거해 핵심 비즈니스 워크플로우가 매번 정확히 동일한 단계를 따르도록 보장"한다고 설명한다.

3. 선택적 LLM 활용 정형화된 작업에는 규칙 기반 로직을, 복잡한 맥락 이해가 필요한 작업에만 LLM을 활용하는 선택적 접근을 취한다.

논쟁: 과거로의 회귀인가, 진화인가?

이러한 접근에 대해 "LLM 도입 이전 기본 챗봇 시절로 되돌아가는 것 아니냐"는 비판이 제기됐다. 실제로 LLM 의존도를 낮추면 챗봇이 고객 질문의 맥락과 미묘한 뉘앙스를 이해하지 못하거나, 포괄적인 답변을 제공하지 못할 수 있다.

그러나 Salesforce는 이를 "기능 축소"가 아닌 "정교화"로 반박했다. 대변인은 "주제 구조를 개선하고, 가이드라인을 강화하고, 정보 검색 품질을 향상하고, 더 구체적이고 맥락에 맞으며 실제 고객 요구에 맞는 답변을 제공하도록 조정했다"고 설명했다.

파룰레카르 부사장의 "1년 전만 해도 우리는 모두 LLM을 더 많이 신뢰했었다"는 발언은 업계의 학습 곡선을 단적으로 보여준다. 이는 LLM의 가능성에 대한 초기의 과도한 기대에서, 실무적 한계를 인정하고 보완책을 마련하는 성숙한 단계로의 전환을 의미한다.

산업에 미치는 영향

세계 최대 소프트웨어 기업 중 하나인 Salesforce의 전략 전환은 AI 에이전트를 도입하는 다른 기업들에게 중요한 시사점을 제공한다. 특히 법률, 재무, 의료, 마케팅, 영업, 고객 서비스 등 정확성이 중요한 영역에서는 LLM의 환각(hallucination)과 비결정론적 특성이 치명적인 결과로 이어질 수 있다.

이는 "모든 것을 LLM으로"라는 단순한 접근에서 벗어나, 작업 특성에 따라 규칙 기반 시스템과 LLM을 전략적으로 조합하는 하이브리드 접근이 실무적 해법임을 보여준다. AI 에이전트의 성공적인 도입은 기술의 한계를 인정하고, 기업 운영의 현실적 요구사항과 균형을 맞추는 것에서 시작된다.

References

You don’t need Elasticsearch : BM25 is now in Postgres

· 약 8분
최재훈
LEAD (AI Research Engineer), Brain Crew

TL;DR

Postgres의 기본 전문 검색(Full-Text Search)은 키워드 반복 남용, 문서 길이 편향, 희귀 단어 처리 실패 등의 문제로 실무에서 한계가 있었습니다. 이를 해결하기 위해 Elasticsearch를 추가하는 것이 일반적이었지만, 이제 pg_textsearch 확장을 통해 BM25 알고리즘을 Postgres에서 직접 사용할 수 있습니다. BM25는 TF 포화(Term Frequency Saturation), IDF(Inverse Document Frequency), 문서 길이 정규화를 통해 검색 품질을 대폭 개선하며, pgvector와 결합한 하이브리드 검색으로 RAG 파이프라인과 AI 에이전트의 검색 성능을 향상시킬 수 있습니다.

Key Takeaways

  • 인프라 단순화: BM25를 Postgres에서 직접 사용하면 Elasticsearch 같은 별도 검색 클러스터, 데이터 동기화 파이프라인, 추가 운영 부담 없이 검색 품질을 크게 개선할 수 있습니다.
  • BM25의 핵심 개선사항: TF Saturation(키워드 반복 스팸 방지), IDF(희귀 단어 가중치 증가), Length Normalization(짧고 집중된 문서 우대)으로 Postgres 기본 검색의 4가지 주요 문제를 해결합니다.
  • 하이브리드 검색의 필요성: RAG와 AI 에이전트는 정확한 키워드 매칭(BM25)과 의미적 유사성(Vector Search)을 모두 필요로 하며, Reciprocal Rank Fusion으로 두 방식을 결합할 수 있습니다.
  • 실무 적용 간편성: CREATE EXTENSION pg_textsearchCREATE INDEX USING bm25 만으로 즉시 적용 가능하며, 기존 pgvector와 함께 사용하면 한 쿼리로 하이브리드 검색을 구현할 수 있습니다.
  • 99%의 사용 사례에 충분: 페타바이트급 로그 수집이 아닌 일반적인 애플리케이션 검색(문서, 제품 카탈로그, 지원 티켓 등)에는 Postgres + BM25 + Vector 조합이 충분하며 운영 복잡도를 크게 낮춥니다.

상세 내용

Postgres 검색의 현실과 복잡성의 덫

Postgres는 Stripe, Instagram, Spotify를 비롯한 수백만 개발자의 표준 데이터베이스입니다. 검색 기능 역시 모든 앱에 필수적입니다—제품 카탈로그, 문서, 사용자 콘텐츠, 지원 티켓, 그리고 최근에는 답변 생성 전에 관련 문서를 찾아야 하는 AI 에이전트와 RAG 파이프라인까지.

개발자들은 자연스럽게 Postgres로 검색을 구현하려 하지만 곧 한계에 부딪힙니다. 그러면 다음 단계는? Elasticsearch, Algolia, Typesense 같은 전문 검색 시스템 도입입니다.

그 순간부터:

  • 별도 클러스터를 운영하고 24/7 가동 상태를 유지해야 합니다
  • Postgres와 검색 시스템 간 데이터 동기화 파이프라인을 구축해야 합니다
  • 검색 결과가 오래되거나 누락된 이유를 디버깅해야 합니다
  • On-call 대응 시스템 목록에 또 하나가 추가됩니다
  • 매달 수천 달러를 매니지드 서비스에 지불하거나, 운영 전문가를 고용해야 합니다

물론 1%는 이런 복잡성이 필요합니다. 페타바이트급 로그 수집을 위한 Elasticsearch, 실시간 분석을 위한 Clickhouse, Google과 OpenAI의 맞춤형 인프라. 하지만 나머지 99%는 이런 복잡성이 필요 없습니다. 이미 사용 중인 데이터베이스에서 더 나은 검색만 있으면 됩니다.

데모 앱에서 Native Search, BM25, Vector Search, Hybrid Search를 직접 비교해볼 수 있습니다.

Postgres Native Search의 4가지 핵심 문제

검색의 주요 목표는 주어진 쿼리에 대해 가장 관련성 높고 유용한 결과를 반환하는 것입니다. 간단해 보이지만, 실제로는 전혀 그렇지 않습니다.

구체적인 예시를 위해 다음과 같은 문서들이 있다고 가정해봅시다:

📄 Database Connection Pooling Guide
"Database connection pooling improves application performance.
A pool maintains reusable connections. Configure pool size based on workload."

📄 PostgreSQL Authentication Setup
"Set up PostgreSQL database authentication methods.
Configure pg_hba.conf for password, certificate, and LDAP authentication."

📄 Generic Blog Post (스팸)
"Database database database. Learn about database. Database is important.
Database database database. More database info."

📄 EXPLAIN ANALYZE Quick Tip (15 단어)
"Use EXPLAIN ANALYZE to find slow PostgreSQL queries.
Shows execution plan and actual timing."

📄 Complete PostgreSQL Query Tuning Guide (80 단어)
"This comprehensive PostgreSQL guide covers query tuning. PostgreSQL query
performance depends on proper use of EXPLAIN and EXPLAIN ANALYZE..."

Problem 1: 키워드 스터핑이 승리한다

"database"를 검색하면, Native Postgres는 키워드 개수로 순위를 매깁니다. "database"를 12번 반복한 스팸 문서가 1위를 차지하고, 실제 유용한 가이드는 하위에 랭크됩니다.

Problem 1

Problem 2: 흔한 단어가 지배한다

"database authentication"을 검색하면, "database"는 10개 이상의 문서에 등장하고, "authentication"은 단 1개에만 등장합니다. 어떤 단어가 실제로 찾고자 하는 내용을 식별할까요?

Native Postgres는 두 단어를 동등하게 취급합니다. BM25는 "authentication"이 진짜 시그널임을 압니다.

Problem 2

Problem 3: 긴 문서가 승리한다

"EXPLAIN ANALYZE"를 검색하면, 80단어 가이드는 8번 언급하고, 15단어 팁은 2번 언급합니다. Native는 긴 문서를 더 높게 랭크합니다.

하지만 짧은 팁은 전체가 EXPLAIN ANALYZE에 관한 것입니다. 이것이 최고의 결과입니다.

Problem 3

Problem 4: All-or-Nothing 매칭

"database connection pooling"을 검색하면, Native는 Boolean AND를 사용합니다. 세 단어가 모두 있는 문서만 매치됩니다. 15개 중 2개만 결과로 나옵니다.

OR로 바꾸면? 13개 결과가 나오지만, 많은 문서가 동일한 점수를 갖습니다. 어떤 것이 실제로 관련 있는지 알 방법이 없습니다.

Problem 4

해결책: BM25 알고리즘

좋은 소식은 검색 업계가 이미 1990년대에 이 문제를 해결했다는 것입니다. 단지 Postgres에 추가되지 않았을 뿐입니다. 그것이 바로 BM25(Best Matching 25)입니다.

BM25는 Elasticsearch, Solr, Lucene 등 거의 모든 프로덕션 검색 시스템을 구동하며, 위의 문제들을 정확히 해결합니다:

Term Frequency Saturation (TF 포화) - 단어를 12번 언급한다고 해서 문서가 12배 더 관련성 있는 것은 아닙니다. 몇 번 언급 후에는 추가 반복이 거의 도움이 되지 않습니다. 스팸이 패배합니다.

Inverse Document Frequency (IDF) - 희귀한 단어가 더 중요합니다. "Database"는 어디에나 있으므로 노이즈입니다. "Authentication"은 한 번만 등장하므로 시그널입니다. BM25는 이에 따라 가중치를 부여합니다.

Length Normalization (길이 정규화) - 쿼리에 집중된 15단어 팁이 지나가듯 언급한 80단어 문서를 이깁니다. BM25는 문서 길이를 조정합니다.

Ranked Retrieval (순위 기반 검색) - 모든 문서가 의미 있는 관련성 점수를 받으며, 단순히 "매치" 또는 "매치 안 됨"이 아닙니다. 부분 매치도 나타나지만 낮은 순위로 표시됩니다.

BM25 Venn Diagram

이것이 Google이 처음부터 작동한 방식입니다. 검색의 기본 요건입니다.

Postgres에서 BM25 사용하기

pg_textsearch는 BM25를 Postgres에 도입합니다:

CREATE EXTENSION pg_textsearch;
CREATE INDEX ON articles USING bm25(content);

SELECT * FROM articles
ORDER BY content <@> to_bm25query('database performance')
LIMIT 10;

BM25 수식의 이해

BM25 점수는 다음과 같이 계산됩니다:

score(D,Q) = Σ IDF(qi) · [f(qi,D) · (k1+1)] / [f(qi,D) + k1·(1-b + b·|D|/avgdl)]

여기서:

  • f(qi,D): 문서 D에서 키워드 qi가 등장하는 횟수
  • |D|: 문서 D의 길이(단어 수)
  • avgdl: 컬렉션의 평균 문서 길이
  • k1: TF 포화를 제어하는 파라미터 (일반적으로 1.2~2.0)
  • b: 길이 정규화를 제어하는 파라미터 (0~1, 일반적으로 0.75)

AI 에이전트와 RAG를 위한 하이브리드 검색

AI 에이전트와 RAG 파이프라인도 검색이 필요합니다. 그리고 BM25만으로는 해결할 수 없는 문제가 있습니다.

사용자가 "why is my database slow?"라고 물으면, "query optimization"이나 "index tuning"과 직접적인 키워드 매치가 없습니다. BM25는 아무것도 찾지 못합니다. 에이전트가 실패합니다.

Vector Search는 의미를 이해합니다. "slow database"가 "performance optimization"과 관련되어 있다는 것을 압니다. 하지만 벡터는 반대 문제가 있습니다: 너무 퍼지(fuzzy)합니다. 에러 코드 PG-1234를 검색하면 벡터는 일반적인 에러 문서를 반환하지, 정확한 에러 코드가 있는 문서를 반환하지 않습니다.

해결책: 둘 다 사용하는 것입니다.

Query: error PG-1234

  • BM25 finds: 정확한 코드가 있는 문서
  • Vectors find: 일반적인 에러 문서
  • Hybrid finds: 정확한 코드 문서 ✓

Query: why is my database slow

  • BM25 finds: 없음 (키워드 매치 없음)
  • Vectors find: 성능 최적화 문서
  • Hybrid finds: 성능 문서 ✓

Query: fix connection timeout

  • BM25 finds: 타임아웃 설정 문서
  • Vectors find: 트러블슈팅 가이드
  • Hybrid finds: 둘 다, 관련성 순으로 정렬 ✓

이것이 모든 주요 AI 검색 시스템이 하이브리드 검색을 사용하는 이유입니다.

  • LangChain의 EnsembleRetriever는 Reciprocal Rank Fusion을 사용하여 BM25와 벡터를 결합합니다
  • Cohere Rerank는 BM25를 첫 번째 단계 리트리버로 권장합니다
  • Pinecone은 sparse와 dense 벡터를 결합하는 하이브리드 검색을 추가했습니다

Postgres에서 하이브리드 검색 구현하기

pgvector와 함께 Postgres에서도 가능합니다:

-- Reciprocal Rank Fusion을 사용한 하이브리드 검색
WITH bm25 AS (
SELECT id, ROW_NUMBER() OVER (ORDER BY content <@> to_bm25query($1)) as rank
FROM docs LIMIT 20
),
vector AS (
SELECT id, ROW_NUMBER() OVER (ORDER BY embedding <=> $2) as rank
FROM docs LIMIT 20
)
SELECT id, 1.0/(60+bm25.rank) + 1.0/(60+vector.rank) as score
FROM bm25 FULL JOIN vector USING (id)
ORDER BY score DESC LIMIT 10;

키워드 + 의미. 하나의 데이터베이스에서.

Hybrid Search

핵심 요점

대부분의 애플리케이션은 별도의 검색 인프라가 필요하지 않습니다. BM25와 벡터 검색을 Postgres에서 직접 사용하면:

  • 운영 복잡도 감소: 별도 클러스터, 동기화 파이프라인, 추가 모니터링 없음
  • 일관성 보장: 단일 트랜잭션 내에서 데이터와 검색 인덱스 업데이트
  • 비용 절감: 수천 달러의 매니지드 검색 서비스 비용 제거
  • 개발 속도 향상: 이미 익숙한 Postgres SQL로 검색 구현
  • RAG 최적화: BM25의 정확성과 벡터의 의미 이해를 결합

물론 페타바이트급 로그 검색이나 밀리초 단위 레이턴시가 필요한 대규모 검색 서비스는 전문 솔루션이 필요합니다. 하지만 99%의 사용 사례—일반적인 앱의 문서 검색, 제품 카탈로그, 지원 티켓, RAG 파이프라인—에는 Postgres + pg_textsearch + pgvector가 충분하며, 훨씬 단순합니다.

References

What Actually Makes you Senior

· 약 5분
최재훈
LEAD (AI Research Engineer), Brain Crew

TL;DR

시니어 엔지니어를 정의하는 핵심은 코딩 실력이나 기술 스택이 아니라 **'모호함을 줄이는 능력(Reducing Ambiguity)'**입니다. 중간급 엔지니어가 명확한 명세를 받아 뛰어난 결과물을 만든다면, 시니어는 불분명한 요구사항을 분석하고 실행 가능한 구체적 계획으로 전환하여 프로젝트 리스크를 사전에 제거합니다. 이는 타고난 재능이 아닌 연습 가능한 기술이며, 코딩 전에 올바른 질문을 던지는 것부터 시작됩니다.

Key Takeaways

  • 모호함 제거가 시니어의 핵심 역량: 아키텍처, 리더십 등 모든 기술은 '무엇을 만들지'가 명확해진 후에야 가치를 발휘하며, 불확실성 해소가 선행되어야 함
  • De-risking이 진짜 가치: 시니어의 급여는 코딩 품질보다 "무엇인지 모르는 상태"를 "실행 가능한 작은 프로젝트"로 변환하여 프로젝트 실패 확률을 낮추는 능력에서 나옴
  • 현재 채용 시스템의 맹점: LeetCode와 기술 스택 체크리스트는 모호한 요구사항을 다루는 실전 능력을 평가하지 못해 '무늬만 시니어'를 양산
  • 본질적 질문이 출발점: "해결하려는 근본 문제는?", "우리의 가정 중 틀린 것은?", "실패 시 최악의 시나리오는?" 등의 질문으로 문제를 구체화
  • 보이지 않는 작업의 가치: 시니어가 잘 일하면 프로젝트가 '너무 쉬워 보이지만', 실제로는 사전에 막대한 명확화 작업이 수행된 결과

상세 내용

시니어 엔지니어의 진짜 정의

일반적으로 시니어 엔지니어를 정의할 때 우리는 긴 체크리스트를 나열합니다. 아키텍처 설계, 커뮤니케이션, 오너십, 리더십, 멘토링... 하지만 직함과 연봉, 경력 연차를 모두 제거하고 나면, 시니어 이상의 엔지니어를 실질적으로 구분 짓는 핵심 기술은 단 하나입니다.

모호함을 줄이는 능력(Reducing Ambiguity)

다른 모든 역량은 이 기본 능력을 토대로 파생됩니다. 아무리 뛰어난 아키텍처 설계 능력이 있어도, 무엇을 만들어야 하는지 명확하지 않다면 그 기술은 방향을 잃습니다.

중간급 vs 시니어: 문제 해결 방식의 본질적 차이

중간급(Mid-level) 엔지니어의 강점은 명확한 문제 해결입니다. 잘 정의된 명세(Spec)와 합리적인 제약 조건이 주어지면 탁월한 결과물을 만들어냅니다. 이것 자체로도 충분히 가치 있는 능력입니다.

하지만 문제의 성격이 바뀌면 상황이 달라집니다:

  • "성능을 개선해야 합니다"
  • "사용자들이 온보딩 플로우에 대해 불만을 제기하고 있습니다"
  • "확장성을 고려해야 할 것 같습니다"

이처럼 모호하고 추상적인 요구사항 앞에서 시니어 엔지니어와의 차이가 드러납니다. 이는 중간급 엔지니어가 능력이 부족해서가 아니라, 불확실한 문제는 근본적으로 다른 접근법을 요구하기 때문입니다.

시니어 엔지니어는 크고 복잡하고 추상적인 문제를 받으면 즉시 분석을 시작합니다:

  • 다른 사람들이 생각하지 못한 질문을 던짐
  • 중요한 신호와 노이즈를 분리
  • 지금 해야 할 것과 미뤄도 될 것을 구분

프로젝트 De-risking: 시니어의 핵심 가치

시니어 엔지니어가 높은 급여를 받는 이유는 단순히 좋은 코드를 작성하기 때문만은 아닙니다(물론 그것도 중요하지만). 진짜 가치는 프로젝트의 리스크를 제거(De-risk)하는 데 있습니다.

그들은 "이게 뭔지도 모르겠는" 상태를 "2개의 작은 프로젝트와 1개의 제거해야 할 요소"로 구체화합니다. 이 과정에서:

  • 불필요한 서프라이즈 감소
  • 프로덕션 장애 최소화
  • 긴급 회의 빈도 축소

흥미로운 점은 시니어가 이 일을 잘 수행하면 '아무것도 한 것 같지 않아' 보인다는 것입니다. 프로젝트가 그냥 순조롭게 진행됩니다. 하지만 실제로는 사전에 엄청난 양의 '보이지 않는 작업(Invisible Work)'이 수행되었습니다.

모호함을 해소하는 구체적 질문들

시니어 엔지니어는 코딩에 앞서 문제를 명확히 하기 위해 다음과 같은 질문을 던집니다:

1. 실제로 해결하려는 문제는 무엇인가?

  • 우리가 원하는 솔루션이 아니라, 근본적인(Underlying) 문제를 찾음
  • 예: "사용자가 원하는 기능"이 아닌 "사용자가 겪는 고통"

2. 사용자는 구체적으로 누구이며, 무엇이 그들에게 고통스러운가?

  • "사용자들"이라는 포괄적 답변을 거부
  • 특정 페르소나와 구체적 맥락을 정의

3. 우리가 전제하고 있는 것 중 틀린 것은 무엇인가?

  • 모든 계획에는 숨겨진 가정들이 있음
  • 이를 명시적으로 끄집어내어 검증

4. 잘못 판단했을 때 최악의 시나리오는?

  • 실패의 다운사이드를 미리 평가
  • 되돌릴 수 없는 결정과 실험 가능한 변경을 구분

이러한 질문들은 먼저 문제를 명확하게 만들고, 그 다음에야 해결에 착수하는 순서를 강제합니다.

채용 시스템이 놓치고 있는 것

안타깝게도 많은 기업들은 여전히 이 핵심 역량을 평가하는 데 실패하고 있습니다:

현재 채용 프로세스의 문제점:

  • 직무 기술서는 기술 스택과 경력 연차만 나열
  • 면접은 LeetCode 스타일 알고리즘 문제에 집중
  • 모호한 제품 요구사항을 실행 가능한 계획으로 변환하는 능력은 측정하지 않음

결과적으로: 화이트보드에서 이진 트리를 뒤집는 데는 능숙하지만, 명세가 불완전하면 얼어붙는 시니어 엔지니어들이 양산됩니다. 코딩 실력은 뛰어나지만 불확실성 앞에서는 무력한 '무늬만 시니어'입니다.

AI Research Engineer 관점에서의 적용

이 원칙은 AI/ML 분야에서 특히 중요합니다:

AI 프로젝트의 전형적인 모호한 요구사항들:

  • "모델 성능을 개선해야 합니다"
  • "추천 시스템이 더 개인화되어야 합니다"
  • "LLM 응답 품질을 높여야 합니다"

시니어 AI Research Engineer의 접근:

  • 어떤 메트릭으로 무엇을 측정할 것인가?
  • 성능 저하의 근본 원인은 데이터인가, 모델인가, 인프라인가?
  • A/B 테스트 설계 시 최소 유의미한 효과 크기는?
  • 모델 개선이 비즈니스 목표와 어떻게 연결되는가?

성장을 위한 실천 방법

모호함 해소 능력은 타고난 재능이 아닌 연습 가능한 기술입니다. 다음과 같이 시작할 수 있습니다:

  1. 코딩 전 일시정지 습관: 티켓을 받았을 때 즉시 코드를 작성하는 대신, 10분간 문제를 구체화하는 시간을 가지세요

  2. "왜?"를 5번 묻기: 요구사항 뒤에 숨은 진짜 문제를 찾을 때까지 질문을 반복하세요

  3. 가정 명시하기: 프로젝트 시작 전 "우리가 맞다고 가정하는 것들" 리스트를 작성하고 팀과 공유하세요

  4. Post-mortem에서 배우기: 프로젝트가 끝난 후 "초기에 어떤 질문을 했다면 문제를 예방할 수 있었을까?" 돌아보세요

마무리: 우아하게 틀린 문제를 푸는 함정

아키텍처와 커뮤니케이션 능력도 중요합니다. 하지만 이런 기술들은 '무엇을 만들지'가 명확해진 이후에야 진가를 발휘합니다.

모호함을 줄이지 못한 채 발휘되는 기술적 우수성은 '잘못된 문제를 우아하게 해결하는 것'에 불과합니다. 완벽한 아키텍처로 설계되었지만 아무도 원하지 않는 기능, 깔끔한 코드로 구현되었지만 본질적 문제는 해결하지 못하는 솔루션.

자신이 시니어 레벨에서 일하고 있는지 판단하는 기준:

  • 추상적인 과제를 받았을 때, 누군가 명확히 해주기를 기다리는가?
  • 아니면 스스로 팀이 실행할 수 있도록 구체화하는가?

그 차이가 바로 시니어를 정의합니다.

References

GUG 6th : 온톨로지 구축 및 평가

· 약 4분
최재훈
LEAD (AI Research Engineer), Brain Crew

TL;DR

GUG(Graph User Group) 6차 모임에서 다룬 온톨로지 구축 및 평가 방법론에 대한 내용입니다. 온톨로지는 도메인 지식을 형식화하여 표현하는 구조로, AI 시스템의 지식 표현과 추론에 핵심적인 역할을 합니다. 구축 프로세스는 도메인 정의, 개념 추출, 관계 정의, 검증 단계를 거치며, 품질 평가를 통해 실무 활용 가능성을 검증합니다.

Key Takeaways

  • 온톨로지는 Knowledge Graph의 스키마 레이어: 엔티티 간 관계를 정형화하여 AI 모델의 추론 능력을 향상시키고, RAG(Retrieval-Augmented Generation) 시스템의 검색 정확도를 높일 수 있음
  • 체계적인 구축 방법론 필요: 도메인 전문가와의 협업을 통한 개념 추출, 계층 구조 설계, 관계 정의가 온톨로지 품질을 결정하는 핵심 요소
  • 평가 지표의 다차원성: 구문적 완전성, 의미적 일관성, 실용적 유용성 등 다층적 평가 기준을 통해 온톨로지의 실무 적용 가능성 판단
  • 반복적 개선 프로세스: 초기 구축 후 지속적인 검증과 피드백을 통해 온톨로지를 진화시키는 것이 중요
  • 도구와 표준의 활용: Protégé, OWL, RDF 등 표준화된 도구와 언어를 사용하면 구축 효율성과 상호운용성을 확보 가능

상세 내용

온톨로지란 무엇인가

온톨로지(Ontology)는 특정 도메인의 개념과 그 개념들 간의 관계를 명시적으로 정의한 형식적 명세입니다. AI Research Engineer 관점에서 온톨로지는 단순한 데이터 스키마를 넘어, 기계가 이해하고 추론할 수 있는 지식 구조를 제공합니다.

Knowledge Graph와의 관계에서 온톨로지는 스키마 레이어 역할을 하며, 실제 데이터 인스턴스들이 어떻게 구조화되고 연결되어야 하는지에 대한 규칙을 정의합니다. 이는 LLM 기반 시스템에서 Semantic Search, 지식 기반 추론, 질의응답 시스템의 정확도 향상에 직접적으로 기여합니다.

온톨로지 구축 프로세스

1. 도메인 및 범위 정의 구축하고자 하는 온톨로지의 목적과 범위를 명확히 하는 단계입니다. 어떤 질문에 답할 수 있어야 하는지, 누가 사용할 것인지, 어떤 유스케이스를 지원해야 하는지 정의합니다.

2. 기존 온톨로지 재사용 검토 처음부터 새로 만들기보다는 Schema.org, FOAF(Friend of a Friend), Dublin Core 등 표준 온톨로지를 참조하거나 확장하는 것이 효율적입니다.

3. 핵심 개념(Classes) 추출 도메인 전문가와의 협업을 통해 중요한 개념들을 식별합니다. 이 단계에서는 명사형 용어들을 추출하고, 이들의 계층 구조를 설계합니다.

4. 클래스 계층 구조 정의 is-a 관계를 기반으로 상위-하위 개념을 구조화합니다. 적절한 추상화 수준을 유지하는 것이 중요하며, 너무 깊거나 얕은 계층은 유지보수와 활용에 어려움을 초래할 수 있습니다.

5. 속성(Properties) 및 관계 정의 개념들 간의 관계(Object Properties)와 개념의 특성(Data Properties)을 정의합니다. 관계의 방향성, 제약조건(domain, range), 카디널리티 등을 명시합니다.

6. 인스턴스 생성 및 검증 실제 데이터 인스턴스를 생성하고, 정의한 제약조건들이 올바르게 작동하는지 검증합니다.

온톨로지 평가 방법

온톨로지의 품질을 평가하는 것은 실무 적용 전 필수적인 단계입니다. 다음과 같은 차원에서 평가가 이루어집니다:

구문적(Syntactic) 평가

  • OWL, RDF 문법 준수 여부
  • 논리적 일관성 (Consistency) 검증
  • Reasoner를 통한 자동 추론 가능성

의미적(Semantic) 평가

  • 개념 정의의 명확성과 완전성
  • 계층 구조의 적절성
  • 관계 정의의 정확성
  • 도메인 지식의 충실한 반영 여부

실용적(Pragmatic) 평가

  • 목표 유스케이스 지원 여부
  • 쿼리 성능 및 확장성
  • 유지보수 용이성
  • 다른 시스템과의 통합 가능성

커뮤니티 기반 평가

  • 도메인 전문가의 검토
  • 사용자 피드백
  • 실제 적용 사례를 통한 검증

실무 적용 시 고려사항

AI Research Engineer가 온톨로지를 구축하고 활용할 때 다음 사항들을 고려해야 합니다:

  • 버전 관리: 온톨로지는 도메인 지식의 변화에 따라 진화합니다. Git 등을 활용한 버전 관리가 필수적입니다.
  • 문서화: 각 클래스와 속성에 대한 명확한 설명(rdfs:comment, rdfs:label)을 포함하여 협업과 유지보수를 용이하게 합니다.
  • 모듈화: 큰 온톨로지는 도메인별로 모듈화하여 관리하면 재사용성과 유지보수성이 향상됩니다.
  • 성능 최적화: 복잡한 추론 규칙은 쿼리 성능에 영향을 미칠 수 있으므로, 실제 사용 패턴을 고려한 설계가 필요합니다.

AI 시스템에서의 활용

최근 LLM과 Knowledge Graph의 결합이 주목받으면서, 온톨로지의 중요성이 더욱 부각되고 있습니다:

  • RAG 시스템 강화: 온톨로지 기반 관계 정보를 활용하여 더 정확한 컨텍스트 검색 가능
  • Hallucination 감소: 구조화된 지식을 통해 LLM의 환각 현상 완화
  • 설명 가능한 AI: 추론 과정을 온톨로지 경로로 시각화하여 투명성 제공
  • 도메인 특화 AI: 전문 영역의 지식을 체계적으로 인코딩하여 특화된 AI 시스템 구축

References

  • GUG 6th 발표 자료: 온톨로지 구축 및 평가

AI시대 기획서(PRD)는 죽었다. 실리콘밸리가 지금

· 약 6분
최재훈
LEAD (AI Research Engineer), Brain Crew

TL;DR

실리콘밸리 AI 프로덕트 개발의 핵심이 "어떤 모델을 쓸까"에서 "성능을 어떻게 측정할까"로 전환되고 있습니다. 평가 시스템(Evals)은 단순한 QA가 아니라 AI 애플리케이션의 데이터 분석이자 새로운 기획서(PRD)입니다. 로그를 직접 분석하는 '노가다'부터 시작해 LLM-as-a-Judge로 자동화하면, 회귀 방지, 비용 절감, 신뢰성 확보라는 세 마리 토끼를 잡을 수 있습니다. 완벽한 평가 지표보다 중요한 것은 "어제보다 나아졌는지" 확인하는 반복 가능한 시스템을 구축하는 것입니다.

Key Takeaways

  • "Vibe Check"의 시대는 끝났다: 프롬프트 수정 시 발생하는 회귀(Regression) 현상을 방지하려면 체계적인 평가 시스템이 필수적이며, 이는 AI 제품의 핵심 경쟁력(Moat)이 됩니다.
  • 로그 분석이 혁신의 출발점: 거창한 MLOps 툴보다 50~100개의 실제 대화 로그를 직접 읽고 패턴을 찾는 '오픈 코딩' 방식이 가장 빠르고 효과적인 인사이트를 제공합니다.
  • LLM-as-a-Judge는 이진 분류로 설계하라: "품질을 1~5점으로 평가"하는 모호한 지시 대신, "경쟁사 언급 포함 여부(True/False)" 같은 명확한 이진 질문이 신뢰할 수 있는 자동 평가를 가능하게 합니다.
  • Evals는 새로운 PRD다: 에이전트 기반 복잡한 워크플로우에서는 각 단계의 의도 검증이 필수이며, 테스트 케이스 자체가 제품 요구사항 정의서 역할을 대신합니다.
  • 평가 기준이 있으면 비용을 절감할 수 있다: 고성능 모델(GPT-4o) 대신 저비용 모델(GPT-4o-mini, Llama 3)로 동일한 품질을 달성할 수 있는지 객관적으로 테스트하여 운영 비용을 획기적으로 낮출 수 있습니다.

상세 내용

AI 프로덕트 품질 보장의 패러다임 전환

최근 실리콘밸리에서 AI 프로덕트를 만드는 팀들 사이에서 기류가 바뀌고 있습니다. 작년까지만 해도 "어떤 파운데이션 모델(GPT-4o, Claude 3.5 Sonnet)을 쓸까?"가 논의의 핵심이었다면, 지금은 **"내 AI가 헛소리를 안 한다는 걸 어떻게 보장할 것인가?"**로 주제가 옮겨갔습니다.

Lenny's Podcast에 출연한 머신러닝 엔지니어 하멜 후세인(Hamel Husain)과 슈레야 샨카(Shreya Shankar)의 대담은 이 지점에서 매우 중요한 시사점을 던집니다. 그들은 AI 제품 개발의 성패가 모델의 성능 그 자체가 아니라, 그 성능을 측정하는 **'평가 시스템(Evaluations, Evals)'**의 유무에 달려 있다고 강조합니다.

단순히 몇 번 써보고 "느낌 좋은데?(Vibe Check)"라며 배포하던 낭만의 시대는 끝났습니다. 이제는 집요한 평가(Evaluation)가 곧 제품의 해자(Moat)가 되는 시대입니다.

"감(Vibe)"에 의존하는 개발의 치명적 함정

생성형 AI 서비스를 기획하고 개발하다 보면 치명적인 착각에 빠지기 쉽습니다. 프롬프트를 몇 번 수정하고, 테스트 케이스 10개 정도를 돌려본 뒤 답변이 그럴듯하면 "개발 완료"를 외치는 것이죠.

하지만 라이브 환경은 다릅니다. 사용자는 우리가 상상하지 못한 엣지 케이스(Edge Case)를 끊임없이 던집니다. 이때 개발팀이 직면하는 가장 큰 문제는 **'수정의 딜레마'**입니다. 사용자 불만을 해결하기 위해 프롬프트를 수정했더니, 기존에 잘 동작하던 기능이 망가지는 '회귀(Regression)' 현상이 발생합니다.

시스템적인 평가 기준이 없다면, 우리는 AI가 더 똑똑해진 건지 멍청해진 건지 알 방법이 없습니다. Evals는 단순한 QA 테스트가 아닙니다. AI 애플리케이션에 대한 '데이터 분석' 그 자체입니다.

로그를 직접 읽는 '노가다'가 혁신의 시작

많은 팀이 자동화된 MLOps 툴이나 거창한 대시보드부터 도입하려 합니다. 하지만 가장 빠르고 확실한 방법은 원시 데이터(Raw Data)를 직접 눈으로 확인하는 것입니다.

Step 1: 오픈 코딩 (Open Coding)

우선 AI와 사용자가 나눈 대화 로그(Trace)를 무작위로 50~100개 정도 읽어보세요. 그리고 이상한 부분이 보일 때마다 직관적인 메모를 남깁니다.

  • "답변이 너무 장황함"
  • "경쟁사 제품을 추천함 (Hallucination)"
  • "JSON 포맷이 깨짐"

거창한 분류 체계는 필요 없습니다. 일단 눈에 띄는 문제들을 날것 그대로 적는 것이 중요합니다.

Step 2: 패턴의 범주화 (Categorization)

100개 정도의 로그만 봐도 문제의 패턴이 보이기 시작합니다. 이제 LLM을 활용해 앞서 남긴 메모들을 그룹화합니다. '부정확한 정보', '톤앤매너 위반', '포맷 오류' 등으로 유형을 묶고, 피벗 테이블(Pivot Table)을 돌려보세요.

여기서 중요한 건 **'우선순위'**입니다. 모든 문제를 다 고칠 순 없습니다. 빈도수가 가장 높고, 비즈니스에 치명적인 문제(예: 고객에게 욕설을 하거나, 잘못된 법률 정보를 제공하는 것)를 찾아내야 합니다.

Step 3: 자비로운 독재자 (Benevolent Dictator)

이 과정에서 흔히 저지르는 실수가 '민주적인 합의'를 하려는 것입니다. "이 답변이 좋은가?"에 대한 기준은 사람마다 다릅니다. 여러 명이 모여 토론하느라 시간을 낭비하지 마세요.

도메인 지식이 가장 풍부한 한 명(주로 PM이나 리드 엔지니어)이 기준을 잡고 빠르게 데이터를 라벨링하는 것이 훨씬 효율적입니다. 초기 단계에서는 속도와 일관성이 완벽함보다 중요합니다.

LLM을 판사로 세우기: 자동화 전략

패턴이 파악되었다면 이제 자동화할 차례입니다. 매번 사람이 로그를 볼 수는 없으니까요. 이때 LLM을 평가자(Judge)로 활용합니다.

여기서 핵심 팁은 평가 기준을 단순화하는 것입니다. "이 답변의 품질을 1~5점으로 평가해줘"라는 모호한 지시는 실패할 확률이 높습니다. 대신 이진 분류(Binary) 질문을 던지세요.

"이 답변에 경쟁사 제품에 대한 언급이 포함되었는가? (True/False)"

명확한 기준은 LLM도 잘 판단합니다. 그리고 LLM이 내린 평가가 사람(Human)의 판단과 일치하는지 검증하는 과정을 거치면, 신뢰할 수 있는 자동 평가 파이프라인이 완성됩니다.

Evals는 '새로운 기획서(New PRD)'다

이러한 평가 체계 구축은 단순히 버그를 잡는 것을 넘어 제품 기획의 패러다임을 바꿉니다.

최근 주목받는 에이전트(Agentic Workflow) 기반 서비스나 LangGraph 같은 복잡한 구조에서는 각 단계가 의도대로 작동하는지 확인하는 단위 테스트(Unit Test)가 필수적입니다. 과거 제품 요구사항 정의서(PRD)에 "사용자에게 친절해야 한다"라고 적었다면, 이제는 "사용자가 모욕적인 언사를 해도 정중하게 거절하는지 판단하는 테스트 케이스" 자체가 기획서의 역할을 대신합니다.

비용 절감의 핵심 무기로서의 Evals

잘 짜인 Evals는 비용 절감의 핵심 무기가 됩니다. 우리는 불안하기 때문에 무조건 성능 좋은 고비용 모델(GPT-4o 등)을 씁니다. 하지만 우리만의 평가 기준(Eval)이 있다면, 특정 태스크에서 더 저렴한 모델(GPT-4o-mini, Llama 3 등)이 동일한 점수를 내는지 테스트해 볼 수 있습니다.

평가를 통과한다면 과감하게 모델을 교체하여 운영 비용을 획기적으로 낮출 수 있습니다. 이는 막연한 불안감이 아닌 데이터 기반의 의사결정을 가능하게 합니다.

완벽함을 버리고 데이터와 직면하라

많은 팀이 Evals를 "어렵고 복잡한 엔지니어링 과제"로 생각하여 시작조차 하지 못합니다. 하지만 목표는 완벽한 학술적 평가 지표를 만드는 것이 아닙니다. 오늘 우리 제품이 어제보다 나아졌는지 확인하는 것입니다.

지금 당장 여러분의 AI 제품 로그를 열어 30분만 투자해서 유저들이 어떤 대화를 나누고 있는지, AI가 어디서 헤매고 있는지 눈으로 확인해 보세요. 그 '30분의 노가다'가 수천만 원짜리 툴보다 훨씬 강력한 인사이트를 줄 것입니다.

평가 시스템은 한 번에 완벽하게 구축하는 것이 아니라, 작은 규모로 시작해 점진적으로 확장하는 것입니다. 첫 50개의 로그 분석에서 시작해, 패턴을 발견하고, 이진 분류 기준을 만들고, LLM으로 자동화하고, 사람의 평가와 비교하며 신뢰도를 높여가는 이 반복 가능한 프로세스가 바로 AI 시대의 진정한 제품 개발 방법론입니다.

References

Fastapi 모범사례 15선

· 약 5분
최재훈
LEAD (AI Research Engineer), Brain Crew

TL;DR

FastAPI를 프로덕션 환경에서 안정적으로 운영하기 위한 15가지 핵심 모범 사례를 다룹니다. 블로킹 작업 시 동기 함수 사용, 비동기 라이브러리 활용, 무거운 작업의 분리, 보안을 위한 문서 노출 제한, 구조화된 로깅, 그리고 Gunicorn+Uvicorn 조합의 배포 전략까지 실무에서 즉시 적용 가능한 패턴을 제시합니다. 특히 async/await의 올바른 사용과 의존성 주입을 통한 코드 재사용성 향상이 핵심입니다.

Key Takeaways

  • async/def 선택 기준: 블로킹 작업(파일 I/O, 동기 DB 쿼리)은 def로, 논블로킹 작업은 async def로 정의하여 FastAPI가 적절한 스레드 풀에서 처리하도록 설계
  • ML 추론 작업 분리: CPU/GPU 집약적인 작업은 Triton, TensorFlow Serving 등 전용 엔진으로 오프로드하고, FastAPI는 요청 검증과 라우팅만 담당
  • 의존성 주입 활용: DB 연결, 인증, 검증 로직을 의존성으로 분리하여 코드 재사용성을 높이고 테스트 용이성 확보
  • 보안 강화: 프로덕션에서 Swagger/ReDoc 비활성화, env 파일로 민감 정보 관리, Pydantic Settings로 설정 검증
  • 구조화된 로깅: structlog/loguru로 request_id 기반 컨텍스트 로깅을 구현하여 분산 환경에서 추적 가능성 확보

상세 내용

비동기 처리의 올바른 이해

FastAPI에서 async defdef의 선택은 성능에 직접적인 영향을 미칩니다. async 엔드포인트는 메인 스레드에서 실행되므로, 블로킹 작업(time.sleep(), requests.get(), 동기 DB 클라이언트)을 포함하면 전체 서버가 멈추게 됩니다.

블로킹 작업 처리 방법:

# ❌ 잘못된 방법 - 서버가 10초간 멈춤
@app.get("/")
async def endpoint():
time.sleep(10)

# ✅ 올바른 방법 - Thread Pool에서 처리
@app.get("/")
def endpoint():
time.sleep(10)

반대로 비동기 지원 라이브러리를 활용하면 더 높은 동시성을 달성할 수 있습니다:

# ✅ 비동기 라이브러리 활용
async def endpoint():
await asyncio.sleep(1)
async with httpx.AsyncClient() as client:
await client.get(url)
client = AsyncIOMotorClient()
await client.db.collection.find_one()

무거운 작업의 아키텍처 분리

머신러닝 추론: NVIDIA Triton, TensorFlow Serving, TorchServe 같은 전용 추론 엔진을 사용하면 FastAPI는 경량화된 API 게이트웨이 역할만 수행합니다. 이는 GPU 자원을 효율적으로 사용하고, 추론 서버의 독립적인 스케일링을 가능하게 합니다.

오래 걸리는 작업: Queue + Worker 패턴으로 비동기 처리를 구현합니다:

  1. FastAPI → 메시지 큐(Redis, RabbitMQ)로 작업 전달
  2. 별도 워커가 큐에서 작업 처리
  3. 결과를 DB에 저장
  4. 클라이언트는 polling 또는 webhook으로 결과 조회

간단한 백그라운드 작업:

@app.post("/register")
async def register_user(user_data: UserCreate, bg_tasks: BackgroundTasks):
bg_tasks.add_task(send_email, user_data.email)
bg_tasks.add_task(event_user_registered, user_data.email)
return {"message": "OK"}

⚠️ BackgroundTasks는 서버 재시작 시 작업이 손실되므로, 중요한 작업은 메시지 큐를 사용하세요.

의존성 주입 패턴

의존성 주입은 1-3번 규칙이 동일하게 적용되며, 코드 재사용성을 크게 향상시킵니다.

DB 연결 관리:

@asynccontextmanager
async def lifespan(app: FastAPI):
app.state.pool = await create_pool()
yield
await app.state.pool.close()

async def get_conn(request: Request):
async with request.app.state.pool.acquire() as conn:
yield conn

@app.get("/data")
async def endpoint(db_conn = Depends(get_conn)):
# 커넥션 풀 재사용

검증 로직 분리:

async def validate_owner(
post_id: int,
user = Depends(get_user)
):
post = await db.get(post_id)
if post.user_id != user.id:
raise HTTPException(403)
return post

@app.put("/posts/{post_id}")
async def update_post(post = Depends(validate_owner)):
# 검증 로직 재사용

Pydantic 기반 검증 및 설정 관리

커스텀 Base 모델:

class CustomBaseModel(BaseModel):
class Config:
alias_generator = to_camel
populate_by_name = True
json_encoders = {
datetime: datetime.isoformat,
Decimal: str,
ObjectId: str
}

Validator 활용:

class UserIn(BaseModel):
email: EmailStr
age: int = Field(gte=18)

@validator("email")
def must_be_corporate(cls, v):
if not v.endswith("@company.com"):
raise ValueError("Must be a company email")
return v

응답 자동 검증:

# ✅ FastAPI가 자동으로 검증 및 직렬화
@app.get("/user", response_model=UserOut)
async def get_user():
return {"id": 1, "name": "Alice"} # dict 반환만으로 충분

설정 관리:

from pydantic_settings import BaseSettings

class Settings(BaseSettings):
db_url: str
api_key: str
debug: bool

settings = Settings() # .env 자동 로드

보안 강화

문서 노출 제한:

app = FastAPI(
docs_url=None if PRODUCTION else "/docs",
redoc_url=None if PRODUCTION else "/redoc",
openapi_url=None if PRODUCTION else "/openapi.json",
)

프로덕션에서 API 문서를 노출하면 공격자에게 엔드포인트 구조, 파라미터 형식, 인증 방식을 알려주는 것과 같습니다.

환경 변수 관리:

# .env
API_KEY="secret_key"
DATABASE_URL="postgresql://..."

# .gitignore
.env

# .env.example (템플릿)
API_KEY="your_api_key_here"
DATABASE_URL="your_database_url"

구조화된 로깅

structlog 미들웨어:

class LoggingMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next):
structlog.contextvars.clear_contextvars()
structlog.contextvars.bind_contextvars(
request_id=str(uuid.uuid4())
)
logger.info("request_received",
method=request.method,
path=request.url.path
)
response = await call_next(request)
logger.info("request_completed",
status_code=response.status_code)
return response

로그 출력 예시:

{
"method": "GET",
"path": "/hello",
"event": "request_received",
"request_id": "d22f859d-443d-9a19-5b8073dd27b6",
"level": "info",
"timestamp": "2025-06-28T17:13:08.501954Z"
}

분산 환경에서는 FileBeat → Elasticsearch → Kibana 같은 중앙 로깅 시스템을 구축하여 여러 인스턴스의 로그를 추적할 수 있습니다.

프로덕션 배포 전략

Gunicorn + Uvicorn 조합:

# 개발 환경
uvicorn main:app --reload

# 프로덕션 환경
gunicorn main:app \
--workers 4 \
--worker-class uvicorn.workers.UvicornWorker \
--bind 0.0.0.0:8000

uvloop 성능 향상: Node.js의 libuv 기반 고성능 이벤트 루프를 제공합니다. 설치만 하면 FastAPI가 자동으로 감지하여 사용합니다.

Worker 수 결정: 일반 공식은 (CPU 코어 * 2) + 1이지만, 부하 테스트를 통해 최적값을 찾는 것이 중요합니다. I/O 바운드 애플리케이션은 더 많은 워커가, CPU 바운드는 적은 워커가 유리할 수 있습니다.

Docker 컨테이너화: Docker를 사용하면 일관된 환경 보장, 쉬운 스케일링, Kubernetes 같은 오케스트레이션 도구와의 통합이 가능합니다.

References

Is TOON really saving you tokens?

· 약 4분
최재훈
LEAD (AI Research Engineer), Brain Crew

TL;DR

TOON(Token-Oriented Object Notation)은 LLM 프롬프트의 토큰 효율성을 높이는 포맷이지만, 만능 솔루션은 아닙니다. 평면적(flat)이고 균일한 데이터에서는 JSON 대비 30-60% 토큰을 절약하지만, 깊게 중첩된(deeply nested) 데이터에서는 오히려 비효율적일 수 있습니다. 실제 벤치마크에서 flat 데이터는 35% 절약, nested 데이터는 오히려 9% 더 많은 토큰을 소비했습니다. 프로덕션 환경에서는 데이터 구조에 따라 포맷을 전략적으로 선택해야 합니다.

Key Takeaways

  • 데이터 구조가 효율성을 결정: Flat/tabular 데이터에서는 TOON이 JSON 대비 35% 이상 토큰을 절약하지만, 깊게 중첩된 구조에서는 indentation overhead로 인해 오히려 더 많은 토큰을 소비할 수 있음
  • 전처리 전략의 중요성: JSON을 TOON으로 단순 변환하는 것보다 "flatten → TOON 변환" 파이프라인이 더 효과적이며, 이를 통해 토큰 절약과 LLM 이해도를 동시에 개선 가능
  • 프로덕션 비용 최적화: 포맷 선택은 API 비용, 레이턴시, 모델 컨텍스트 용량에 직접적인 영향을 미치므로, 데이터 스키마 분석을 통한 포맷 결정이 필수
  • 스키마 일관성이 핵심: TOON은 일관된 스키마를 가진 반복적인 구조에서 가장 효과적이며, 이는 정확도(accuracy) 향상에도 기여
  • 하이브리드 접근: JSON과 TOON을 경쟁 관계가 아닌 상호 보완적 도구로 활용하여, 데이터 형태에 따라 최적의 포맷을 선택하는 것이 실용적 전략

상세 내용

TOON이란 무엇인가?

TOON(Token-Oriented Object Notation)은 LLM 프롬프트를 위해 설계된 컴팩트하고 스키마 인식형 데이터 포맷입니다. JSON의 가독성은 유지하면서도 토큰 효율성을 극대화하려는 시도로, 특히 LLM API 비용 절감과 컨텍스트 윈도우 최적화를 목표로 합니다.

최근 TOON에 대한 관심이 급증하고 있으며, 실제로 특정 상황에서는 상당한 효율성 개선을 보여줍니다. 하지만 모든 데이터 구조에 적용 가능한 만능 솔루션은 아닙니다.

실제 벤치마크 결과

다음은 실제 테스트를 통해 측정된 토큰 사용량 비교입니다:

평면적 데이터 (Flat Data)

  • JSON: 797 tokens
  • TOON: 517 tokens
  • 결과: 35% 절약

중첩 데이터 (Nested Data)

  • JSON: 802 tokens
  • TOON: 877 tokens
  • 결과: TOON이 9% 더 많은 토큰 소비

TOON vs JSON 벤치마크 비교

왜 중첩 데이터에서 비효율적인가?

TOON의 구조적 특성상, 깊게 중첩된 데이터에서는 다음과 같은 오버헤드가 발생합니다:

  1. 인덴테이션 오버헤드: TOON은 구조를 명확하게 표현하기 위해 들여쓰기를 사용하는데, nested 구조가 깊어질수록 이로 인한 토큰 비용이 증가합니다.

  2. 구조 정보의 반복: 중첩된 객체마다 스키마 정보를 유지하려면 추가적인 메타데이터가 필요합니다.

  3. 압축 효과 감소: 평면적 데이터에서는 반복되는 키 이름을 효율적으로 압축할 수 있지만, 중첩 구조에서는 이러한 이점이 감소합니다.

반면 compact JSON은 중괄호와 쉼표만으로 구조를 표현하므로, 깊은 중첩에서도 상대적으로 일관된 오버헤드를 유지합니다.

실무 적용 전략

1. 데이터 구조 분석이 우선

TOON 도입 전에 반드시 데이터의 특성을 분석해야 합니다:

  • TOON이 유리한 경우: 테이블 형태의 데이터, 반복적인 레코드, 일관된 스키마를 가진 배열
  • JSON이 유리한 경우: 복잡한 계층 구조, 불규칙한 스키마, 깊은 중첩(3단계 이상)

2. Flatten → TOON 파이프라인

최적의 접근 방식은 다음과 같습니다:

원본 JSON → 구조 평면화(flatten) → TOON 변환 → LLM 입력

이 방법을 사용하면:

  • ✔ 토큰 사용량 최소화
  • ✔ 더 명확한 데이터 구조
  • ✔ LLM의 데이터 이해도 향상
  • ✔ API 비용 절감

3. 스키마 일관성 확보

TOON은 일관된 스키마에서 최고의 성능을 발휘합니다. 데이터 전처리 단계에서 스키마를 정규화하면 TOON의 효율성이 극대화됩니다.

프로덕션 환경에서의 임팩트

올바른 포맷 선택이 프로덕션 LLM 파이프라인에 미치는 영향:

비용 절감

  • 30-60% 토큰 절약 시 API 비용이 직접적으로 감소
  • 대규모 배치 처리에서는 월간 수천 달러의 절약 가능

레이턴시 개선

  • 더 적은 토큰 = 더 빠른 처리 속도
  • 특히 긴 컨텍스트를 다룰 때 체감 가능

모델 용량 최적화

  • 컨텍스트 윈도우 절약으로 더 많은 정보 포함 가능
  • 프롬프트 엔지니어링의 여유 공간 확보

정확도 향상

  • 평면적 구조와 명확한 스키마는 LLM의 데이터 파싱 오류를 줄임
  • 특히 structured output generation에서 효과적

하이브리드 접근의 필요성

TOON vs JSON은 경쟁이 아니라 선택의 문제입니다. 실무에서는 다음과 같은 하이브리드 전략이 효과적입니다:

  • 라우팅 로직 구현: 데이터 구조를 분석하여 자동으로 적절한 포맷 선택
  • A/B 테스트: 실제 워크로드에서 두 포맷의 성능 비교
  • 모니터링: 토큰 사용량, 응답 품질, 비용을 지속적으로 추적

TOON은 특정 상황에서 강력한 최적화 도구이지만, 맹목적 적용보다는 데이터 특성에 기반한 전략적 선택이 중요합니다.

References