
LLM에 모든 것을 맡기지 않는, '미용 의료 AI 상담'의 설계와 구현 (백엔드 편)
요약
미용 의료 앱 '트리뷰'의 AI 상담 기능을 구현하기 위한 백엔드 설계 방식을 소개합니다. LLM에 모든 것을 맡기지 않고 RAG, API, 가드레일을 활용하여 안전성, 품질, 비용을 최적화하는 구조를 다룹니다.
핵심 포인트
- LLM의 역할을 정보 정리 및 제시로 한정하여 의학적 진단 위험 방지
- RAG와 실제 데이터를 결합하여 범용 LLM과 차별화된 맞춤형 정보 제공
- 의료법 및 약기법 등 도메인 특화 규제 준수를 위한 가드레일 설계
- 사용자의 고민 단계(언어화, 이해, 선택)에 맞춘 단계별 상담 흐름 구축
트리뷰(Trivue)에서 CTO를 맡고 있는 오비(@obiyuta)입니다.
저희 회사는 2026년 7월, 미용 의료 앱 「트리뷰」에 AI 상담 기능을 출시했습니다. 지난번 프론트엔드 편에서는, LLM의 업무를 어떤 화면 구성 요소에 무엇을 표시할지 지정하는 JSON (템플릿 JSON) 출력까지로 한정하고, 화면 구성과 실제 데이터 취득은 프론트엔드가 담당하는 설계를 소개해 드렸습니다.
이번에는 백엔드 편입니다. 백엔드도 생각하는 방식은 같습니다. LLM에 모든 것을 맡기는 것이 아니라, 맡길 범위와 역할을 명확하게 설계하고 있습니다. LLM · API · RAG의 역할 분담부터 가드레일 (Guardrail) 설계까지를 주제로, 안전 · 품질 · 비용을 어느 하나 희생하지 않는 구조에 도달하기까지의 실패 사례를 포함하여 소개해 드립니다.
AI 상담과 프로젝트의 전제
기능과 상담의 흐름
이번 주제인 「AI 상담」은 채팅 형식으로 미용 의료 상담을 할 수 있는 트리뷰의 기능입니다. 대화나 탭으로 선택할 수 있는 답변 후보를 통해 검토를 진행하면, 시술이나 클리닉, 메뉴 정보가 제시되며 그대로 예약 검토로 이어질 수도 있습니다.

AI 상담이 동행하는 사용자의 검토 단계는 대략 다음과 같습니다.
고민의 언어화: "왠지 모르게 눈가가 신경 쓰인다"와 같은 추상적인 고민을 언어화함 -
시술의 이해 · 비교: 고민에 대한 시술 선택지를 알고 차이점을 이해함 -
개별 선택: 클리닉 · 메뉴 · 의사를 예산이나 선호도 등의 조건에 따라 구체적인 후보로 좁힘
이 흐름은 그대로 AI 상담 설계의 베이스가 되어 있으며, 질문받은 것에 무턱대고 답하는 것이 아니라, 해당 사용자가 어느 단계에 해당하는 질문을 하고 있는지에 따라 필요하다고 판단되는 정보를 제시하도록 되어 있습니다.
프로젝트의 요건과 규제
실제로 기능으로서 제공함에 있어, 이 프로젝트에는 5가지 요건이 있었습니다.
| 요건 | 내용 |
|---|---|
| 독자 데이터로의 차별화 | ChatGPT로는 할 수 없는 납득 가능한 제안 |
| ... |
첫 번째인 「독자 데이터로의 차별화」는 애초에 기능의 의의이기도 하며, ChatGPT와 같은 범용 LLM과의 차이점을 어떻게 만들 것인가에 대한 이야기입니다. 일반적인 LLM도 시술에 관한 일반론까지는 답할 수 있습니다. 하지만 단계가 「어느 클리닉의, 어느 메뉴인가」라는 개별 선택으로 넘어가면, 데이터를 가지고 있지 않아 답변의 품질이 급격히 떨어집니다. 그렇게 하는 것이 아니라, 각 레이어의 후보를 실제 데이터로 구성할 수 있다는 것, 그리고 예약까지 동일한 장소에서 연결된다는 것이 AI 상담의 독자성입니다.
그중에서도 백엔드 설계에 큰 영향을 미친 것은 의사법 · 약기법 (Pharmaceutical and Medical Device Act) · 의료 광고 가이드라인 · 플랫폼의 중립성 등, 의료 도메인의 법령 및 가이드라인 준수입니다.
특히 상세한 「리뷰 (체험담)」에는 「특정 클리닉의 우수성이나 시술 효과를 나타내기 위해 제시할 수 없다」, 「애초에 가공해서는 안 된다」라는 가이드라인이 있습니다. 따라서 AI 상담에서도 개별 리뷰를 요약하여 "이 클리닉은 붓기가 적은 것 같습니다"와 같은 제시를 할 수 없습니다 [1].
중립성 관점에서는 특정 클리닉으로의 부당한 유인을 하지 않는 객관성 · 망라성, 그리고 게재된 클리닉들 사이에서 근거 없이 우열을 가리지 않도록 하는 배려가 필요했습니다. 미승인 의료기기나 의약품에는 약기법에 대한 고려도 필요합니다.
그리고 무엇보다도, 답변은 의사 등 전문가를 거치지 않고 그대로 엔드 유저(End-user)에게 전달됩니다. 의료업에 해당하지 않도록, 답변은 시술 선택지 등의 「정보 정리 · 제시」에 머물게 하고 의학적 판단 (진단)은 수행하지 않는 설계로 하여, 운영으로 커버하는 것이 아니라 구조적으로 안전하다고 말할 수 있는 상태를 담보할 필요가 있었습니다.
전체 처리 플로우와 기술 구성
최종적으로는 1회의 상담 요청에 대해 다음과 같은 흐름으로 답변을 제시하도록 되어 있습니다.
LLM의 지식만으로 응답이 완결되는 질문도 있고, 백엔드가 기존 API로부터 실제 데이터를 취득하는 경우, 답변을 받은 프론트엔드가 실제 데이터를 취득하는 경우도 있어, 질문 내용에 따라 데이터 취득 방식을 바꾸고 있습니다.
또한, AI 관련 기반은 Bedrock을 중심으로 AWS의 매니지드 서비스(Managed Service)로 갖추고 있습니다. 기술 스택은 다음과 같습니다.
| 용도 | 채택 기술 |
|---|---|
| LLM | Claude Sonnet 4.5 (Bedrock converse API) |
| ... |
프로토타입의 3가지 과제
처음부터 이 설계였던 것은 아닙니다. 수십만 건의 리뷰라는 자산이 있다면, 리뷰 등의 자사 데이터를 학습시킨 RAG (Retrieval-Augmented Generation) 채팅을 만들면 되지 않을까 하는 발상으로 프로토타입을 구현해 본 결과, 지난번에 작성한 프론트엔드 측의 문제(깨진 HTML이 출력되는 등) 외에도 백엔드 유래의 과제들이 있었습니다.
답변의 편향성: 클리닉 상담에 대해 LLM (Large Language Model)의 일반 지식에 기반한 답변이 섞이면서, 특정 클리닉이 근거 없이 과도하게 추천되었습니다. 추천된 곳은 광고 노출이 많은 클리닉이나 「자칭 No.1」을 내세우는 클리닉(No.1 표기 자체가 광고 가이드라인 위반 표현입니다) 등으로, 웹상의 노출에 강하게 영향을 받은 결과로 보였습니다. 이는 중립성을 현저히 결여한 것으로서 허용할 수 없었습니다. -
비용: 툴 실행 루프(Tool execution loop)에서는 과거의 툴 결과까지 포함하여 질의를 반복하기 때문에, 리뷰 본문이나 이미지 URL 등의 데이터를 응답에 포함하면 토큰이 눈덩이처럼 불어났습니다. -
법무: 프로토타입은 검색한 리뷰를 LLM이 요약·인용하여 답변하고 있었습니다. 서두에 기술한 바와 같이, 개별 체험담을 AI가 요약하거나 이를 바탕으로 평가나 효과를 언급할 가능성이 있어, 규제 관점에서 제공할 수 없습니다.
"RAG를 하고 싶지만, RAG를 할 수 없는" 상태였습니다. 수십만 건의 체험담이라는, 그야말로 RAG에 적합한 자산을 가지고 있지만, 그대로 학습시키면 편향되거나, 비용이 불어나거나, 위험한 것이 되어버렸기에 이러한 과제들을 해결할 수 있는 설계와 구현을 진행해 나갔습니다.
LLM · API · RAG의 역할 분담
첫 번째 과제인 답변의 편향성에 대해서는 "화면에 노출하는 구체적인 후보는 트리뷰(triview)의 실제 데이터 이외의 것에서 나오지 않게 한다"라는 대책을 세웠습니다. 이는 요구사항인 「독자적인 데이터로의 차별화」와도 연결되는 이야기입니다. 구현으로 옮기기 위해 먼저 데이터를 정리합니다. AI 상담이 다루는 데이터는 성격이 다른 두 종류가 있습니다.
| 데이터 | 성격 | 취득 방법 |
|---|---|---|
| 클리닉 · 시술 · 메뉴 · 요금 · 예약 슬롯 | 구조화된 「실제 데이터」 | 기존 API · 검색 기반 |
| 리뷰 (수십만 건) | 비구조화되고 주관적인 「실제 체험」 | 전체 텍스트 검색만 가능 (프로젝트 시작 시점) |
구조화된 실제 데이터와 비구조화된 체험담이 있으며, 성격과 제약이 크게 다르기 때문에 취득 방법과 분담은 다음과 같이, 일반 지식과 대화는 LLM, 실제 데이터는 구조화 API, 체험담은 RAG로 정리했습니다.
| 구성 요소 | 담당 | 구체적 방침 |
|---|---|---|
| LLM | 일반 지식과 대화 | 시술 등의 일반론은 LLM의 지식으로 답변. 상담을 검색 조건으로 변환하여 대화를 진행하고, 템플릿 JSON을 출력한다 |
| ... |
시나리오에 따른 프롬프트 설계 (Prompt Design)
「기능과 상담의 흐름」에서 검토한 단계는 베이스 시스템 프롬프트(System Prompt)에 시나리오로서 정의되어 있습니다.
| 상담 단계 | 시나리오에서의 동작 | 근거 |
|---|---|---|
| 고민의 언어화 | 고민 · 예산 · 다운타임 허용도 등을 통해 시술 선택지를 제시한다 | LLM의 일반 지식 |
| ... |
사용자가 어느 단계에 있더라도 상담을 접수하고, 그 시점의 검토에 맞춰 가이드할 수 있도록 하고 있습니다. 받고 싶은 시술을 지정하여 시작하면 해당 단계부터 진입하고, 망설임이 생기면 이전 단계로 돌아가는 등 기본 시나리오는 정의되어 있지만 유연하게 대응합니다.
표의 오른쪽 열이 나타내는 바와 같이, LLM의 지식만으로 충분한 단계에서는 이를 적극적으로 사용합니다. 어떤 고민에 어떤 시술이 있는지, 다운타임이나 시세는 어떠한지 등 시술의 일반론은 LLM이 원래 잘하는 영역입니다. 단, 후보로 올릴 시술은 트리뷰에 존재하는 시술과 대응시킵니다. 프롬프트에 시술 마스터(Master)를 포함하고 있으며, 프론트에 반환할 템플릿 JSON에 전달할 시술 ID는 거기서 선택하도록 되어 있습니다. 일반론은 LLM의 지식으로 답하고, 개별 데이터의 제시가 필요한 단계에서 툴(Tool)을 이용하도록 시나리오를 설계했습니다.
툴로 LLM의 행동 범위를 규정
LLM에 공개한 툴은 5개입니다. 구조화 검색 4개와 리뷰의 의미 검색(Semantic Search) 1개입니다. 검토 단계마다 어떤 데이터를 언제 취득할지가 달라지기 때문에, 클리닉 · 시술 · 메뉴 · 닥터 각각을 실제 데이터로 검색할 수 있도록 하고 있습니다.
| 툴 | 역할 |
|---|---||
| 클리닉 검색 | 구조화 검색 (기존 API의 래퍼 (Wrapper)) |
| ... | |
실행 루프는 자체적으로 구현하였으며, 툴 실행의 왕복은 최대 2회로 제한하고 있습니다.
또한, 툴 레이어(Tool Layer)는 MCP 서버로서 본체와 분리되어 있으며, LLM이 호출할 수 있는 조작과 인수를 여기서 제한하고 있습니다. 툴의 설명문(description)에는 사용 예시를 포함해 두었으며, LLM은 이를 충분히 잘 따르고 있습니다.
description 발췌 (일부 수정)
{
"tool_spec": {
"name": "clinics_search",
...
5개 중 RAG를 사용하는 것은 리뷰 검색뿐이며, 여기에 체험담을 안전하게 다루기 위한 장치를 마련했습니다.
지연 확장적(Lazy Expansion) RAG의 구축
기본적으로는 서비스 본체와 동일한 로직으로 검색 데이터를 사용하여 정보를 제시하고 있지만, 리뷰만은 예외적으로 AI 상담용으로 독자적인 구현을 했습니다.
툴에서는 리뷰의 내용(content)을 반환하지 않고 ID로만 제한하고 있는데, 이 배경을 일반적인 RAG의 동작과 비교하여 설명하겠습니다.
통상적인 RAG는 검색한 문서를 LLM의 생성에 주입하여, 요약이나 인용을 통해 답변을 만듭니다 (Bedrock에서는 RetrieveAndGenerate라는 API가 이에 해당합니다). AI 상담에서도 리뷰 검색은 수행하며 검색 결과로 답변을 보강하기도 하지만, LLM이 생성하는 답변 그 자체에는 이용하지 않도록 하고 있습니다.
| 일반적인 RAG | 리뷰 RAG | |
|---|---|---|
| 검색 결과의 활용처 | LLM의 프롬프트 (Prompt) | 화면 (표시 시점에 합류) |
| ... |
구조화 검색(Structured Search)의 4개는 이름, 가격, 평점과 같은 속성 정보가 텍스트로 반환되며, 후보를 구성하는 데 사용하는 실제 데이터로서 LLM에 전달됩니다. 체험담이라는 본문 콘텐츠를 가진 리뷰만은 LLM에 ID만을 반환합니다. Bedrock Knowledge Base에는 검색부터 생성까지 수행하는 RetrieveAndGenerate와 검색만 수행하는 Retrieve라는 두 가지 API가 있으며, AI 상담의 리뷰 검색 툴이 호출하는 것은 Retrieve뿐입니다.
represent 구현 발췌 (검색 결과를 LLM용으로 정형화하는 부분. 필드명은 일부 변경)
def represent(response)
response.retrieval_results.filter_map do |r|
next if r.content&.text.blank?
...
청크 본문(r.content.text)은 존재 여부 확인용으로만 사용하고 버립니다.
LLM이 리뷰 본문에 물리적으로 접촉하지 못하게 하고, ID의 실체는 프론트엔드(Front-end)가 API로부터 가져와 표시 통제 규칙(효과 표현을 포함한 발췌문 치환 등)을 통해 렌더링함으로써, 리뷰가 변조되거나 클리닉 및 효과에 대한 평가로 사용되는 것을 구조적으로 방지하고 있습니다.
검색으로 답변을 확장하되, 그 합류 시점을 생성 시점이 아닌 표시 시점으로 늦추는, 말하자면 '지연 확장 RAG(Lazy Expansion RAG)'적인 아키텍처가 되어 있습니다.
이를 통해 리뷰 변조와 같은 법무·통제 과제뿐만 아니라, 리뷰 본문을 LLM의 왕복 과정에 싣지 않음으로써 토큰이 팽창하지 않아 비용 문제도 완화할 수 있었습니다.
또한, Knowledge Base에 투입하는 리뷰도 만족도 등에 따른 선별은 하지 않습니다. 여기서 서열을 매기게 되면 체험담의 집합이 '평가'로 변해버리기 때문입니다.
품질 향상과 안정화
최종적인 품질을 높이려면 모델 선정이, 안정화하려면 각 레이어에서의 통제와 가드레일(Guardrail)이 중요합니다.
모델 선정
LLM 모델 자체도 검증을 거듭하여 선정했습니다. 최종적으로는 다양한 관점에서 Sonnet 4.5를 채택했으나, 비용 최적화를 위해 GPT-OSS 120B, Kimi K2.5 등의 오픈 웨이트(Open-weight) 모델을 포함하여 폭넓게 검증했습니다. 비용 측면에서는 단가보다 프롬프트 캐시(Prompt Cache)의 영향이 더 컸으며, 특히 이번 에이전트 구성에서는 툴 정의와 시스템 프롬프트를 매 요청마다 보내기 때문에, 캐시가 적용되지 않는 모델은 단가가 낮더라도 총액이 내려가기 어려운 결과가 나왔습니다.
품질 측면에서도 복잡한 시스템 프롬프트에 대한 충실도(Faithfulness)라는 점에서, Kimi는 큰 틀의 시나리오는 따를 수 있었으나 "후보를 내기 전에 이것과 이것을 질문해줘"와 같은 세밀한 지시의 재현성이 낮아 제외했습니다.
다만, 모델·프롬프트·툴 그룹의 버전은 요청 단위로 전환할 수 있는 구조로 설계하였으며, 프론트엔드에서 구성 정보를 이벤트 로그에도 부여하고 있으므로, A/B 테스트 등을 진행할 때 어떤 구성의 응답인지 분석 과정에서 비교할 수 있도록 되어 있습니다.
다층적인 품질 향상 메커니즘
지금까지 언급한 것 외에도, 각 레이어에서의 통제 및 가드레일 (Guardrail)은 다음과 같습니다. 필터링이나 표시 통제는 한 곳에 집중시키지 않고, 레이어별로 역할을 나누고 있습니다.
| 레이어 | 통제 내용 |
|---|---|
| WAF | 레이트 리미트 (Rate Limit). 악용 및 그에 따른 비용 증가 억제 |
| ... |
LLM의 출력이 확률적으로 흔들리는 것 자체를 제로(0)로 만들 수는 없습니다. 그래서 실데이터를 직접 참조하거나, 스크립트로 규칙을 통제하는 등 결정론적 (Deterministic)으로 동작하는 부분을 늘려, 확률적인 흔들림이 품질에 최대한 영향을 주지 않도록 설계하고 있습니다. 어느 레이어도 단독으로는 완벽하지 않지만, 이를 조합하여 품질을 담보하고, 문제가 발생했을 때 어느 레이어의 과제인지 분리할 수 있도록 구성했습니다.
요약
백엔드 측 설계에서는 답변의 근거를 LLM · 구조화 API · RAG로 분리하고, 리뷰(口コミ)는 검색 결과의 합류를 표시 시점까지 늦추는 등의 방식을 통해 프로토타입의 세 가지 과제에 대응했습니다.
편향성: 화면에 노출하는 구체적 후보의 근거를 트리뷰(トリビュー)의 실데이터로 한정 (툴 구성에서의 제한. 후보 구성은 기존 검색 API를 그대로 활용) -
비용: 리뷰 본문을 LLM의 왕복 과정에 포함하지 않고, 프롬프트 캐시 (Prompt Cache)와 함께 적용하여 초기 버전 대비 실측 약 1/10 -
법무: 리뷰는 ID로만 지칭하고 AI가 다루지 않게 함으로써 가이드라인 등을 준수
"LLM인 이상, 가끔 이상한 답변이 나오는 것은 어쩔 수 없다"라고 넘겨버린다면, 사용자에게 안정적인 품질의 서비스를 제공할 수 없습니다. 규제가 있으니 RAG를 포기한다는 식의 단순한 선택이 아니라, 과제 해결을 위해 다양한 기술을 어떻게 활용할지 고민하고, 결정론적으로 동작하는 부분을 늘려 흔들림의 폭을 줄이는 등, 사용자에게 전달되는 품질을 확률에 맡기지 않는 것이 중요합니다. 이를 위한 고안을 쌓아가는 것이 LLM을 다루는 엔지니어의 업무라고 생각합니다. 제약이 심한 도메인에 국한되지 않고, LLM을 활용한 기능을 만들 때 참고가 된다면 기쁘겠습니다.
참고 기사
또한, AI 상담에 대해서는 PdM 관점에서 목적과 경험 구축을 소개한 인터뷰 기사도 공개되어 있습니다.
전편입니다. 함께 확인해 보세요.
※ 본 기사는 2026/7/29 이벤트 「RAG × 실서비스 운용의 최전선」에서 발표한 내용을 가감 및 상세화한 버전입니다. 당일 슬라이드는 이쪽입니다.
리뷰 전체의 집계에서 알 수 있는 점은 개별 체험담의 가공과는 별개의 정리 사항입니다. 그 경우에도 효과에 대해 언급하는 표현은 사용할 수 없습니다. ↩︎
Discussion

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기