DEV ℧ Developer Diary

[AI] LLM 애플리케이션을 이해하기 위한 핵심 용어 정리

ChatGPT가 세상에 나온 이후 LLM을 활용한 서비스가 빠르게 늘어나면서, 관련 개념도 많이 생겨났다. 처음에는 단순히 “프롬프트를 잘 쓰면 된다” 정도로 이해할 수 있었지만, 실제로 LLM을 애플리케이션에 적용하기 시작하면서 이야기가 달라졌다.

LLM은 단순히 사용자의 질문에 답하는 모델이 아니라, 외부 문서를 참고하고, 도구를 호출하고, 작업 절차를 따르고, 때로는 목표를 달성하기 위해 여러 단계를 반복하는 시스템의 일부가 되었다.

공부의 시작은 개념을 정리하는것이 먼저라 생각되기에, 몇몇 핵심용어들을 정리하여 보았다.


1. Prompt

Prompt는 사용자가 LLM에게 주는 지시문이다.

가장 단순하게는 사용자가 모델에게 입력하는 질문이나 명령을 의미한다.

예를 들어 다음과 같은 문장이 Prompt다.

이 Java 코드를 리뷰해줘.

하지만 사용자가 LLM에 어떻게 지시를 하냐에 따라 결과에 대한 품질이 달라질 수 있다.

Prompt에는 보통 다음과 같은 요소가 포함될 수 있다.

역할

  • 예시: 너는 시니어 백엔드 개발자다 작업
  • 예시: 이 코드를 리뷰해줘 제약
  • 예시: 보안 문제를 우선으로 봐줘 출력 형식
  • 예시: 표로 정리해줘 예시
  • 예시: 아래 예시와 같은 형식으로 답해줘 금지 조건
  • 예시: 추측하지 말고 모르면 모른다고 해줘

위의 요소를 추가해 조금 더 구체적으로 작성해보자.

너는 Java/Spring 백엔드 개발자다.

아래 코드를 리뷰해줘.
특히 트랜잭션 경계, 예외 처리, 동시성 문제를 중심으로 확인해줘.
수정이 필요한 부분은 이유와 함께 설명해줘.

두 프롬프트는 같은 작업을 요청하지만, 결과 품질은 꽤 달라질 수 있다.

LLM은 사용자의 지시를 바탕으로 답변을 생성하기 때문에, 어떤 역할을 부여하고, 어떤 기준으로 판단하게 하고, 어떤 형식으로 답변하게 할지가 중요하다.

초기 LLM를 사용할때에는 Prompt를 잘 작성하는 것이 가장 중요한 기술처럼 여겨졌다. 하지만 실제 애플리케이션에서는 Prompt만으로는 부족한 경우가 많다.

모델이 판단할 수 있는 정보, 즉 Context가 함께 필요하기 때문이다.


2. Context

Context는 LLM이 답변할 때 참고할 수 있도록 함께 제공되는 정보다.

Prompt가 “무엇을 하라”는 지시라면, Context는 “무엇을 보고 판단하라”는 자료에 가깝다.

예를 들어 장애 원인을 분석한다고 해보자.

Prompt:
아래 로그를 보고 장애 원인을 분석해줘.

Context:
- 에러 로그
- 최근 배포 내역
- DB 커넥션 풀 설정
- 트래픽 지표
- 관련 코드

LLM은 Prompt로 지시한 내용과 함께 Context에 포함된 정보를 바탕으로 답변을 생성한다. 따라서 같은 질문이라도 어떤 Context를 제공하느냐에 따라 답변은 크게 달라질 수 있다.

예를들어 회사 내부 환불 정책을 물어본다고 해보자.

질문:
우리 회사 디지털 상품 환불 정책 알려줘.

Context가 없다면 LLM은 일반적인 환불 정책을 바탕으로 답할 가능성이 높다.

일반적으로 디지털 상품은 다운로드 이후 환불이 제한될 수 있습니다.

하지만 실제 회사 정책 문서를 Context로 제공하면 답변은 달라진다.

제공된 정책 문서에 따르면, 디지털 상품은 다운로드 이후 환불이 불가능합니다.
다만 파일 손상 등 회사 귀책 사유가 있는 경우에는 예외적으로 환불이 가능합니다.

LLM 애플리케이션에서 중요한 것은 단순히 “어떤 모델을 쓰는가”만이 아니다. 모델에게 어떤 Context를 제공하는지도 매우 중요하다.

Context에는 다음과 같은 것들이 들어갈 수 있다.

대화 기록

  • 예시: 이전 질문과 답변 문서
  • 예시: 정책 문서, API 문서, 사내 위키 코드
  • 예시: Java 클래스, SQL, 설정 파일 로그
  • 예시: 에러 로그, 서버 로그 도구 실행 결과
  • 예시: 테스트 결과, DB 조회 결과 사용자 정보
  • 예시: 선호 언어, 프로젝트 환경

LLM은 기본적으로 입력으로 받은 정보 안에서 답변을 생성한다. 따라서 좋은 답변을 얻기 위해서는 좋은 Context를 제공해야 한다.


3. Context Window

Context Window는 LLM이 한 번에 읽고 처리할 수 있는 최대 정보량을 의미한다.

LLM은 무한히 많은 텍스트를 한 번에 읽을 수 없다. 모델마다 한 번에 입력할 수 있는 토큰 수 제한이 있다.

모델에 따라 다음과 같은 Context Window를 가질 수 있다.

8K tokens
32K tokens
128K tokens
1M tokens

여기서 token은 모델이 텍스트를 처리하는 단위다. 정확히 “1글자 = 1토큰”은 아니고, 단어, 글자, 기호 등이 모델 내부 기준에 따라 쪼개진 단위라고 이해하면 된다.

Context Window가 중요한 이유는 단순하다. 모든 정보를 LLM에게 다 넣을 수 없기 때문이다.

예를 들어 사내 문서가 수천 개 있다고 해보자. 이 모든 문서를 매번 LLM에게 전달하는 것은 아래와 같은 이유로 어렵다.

비용 증가 : 입력 토큰이 많을수록 비용이 증가한다 응답 지연 : 처리해야 할 정보가 많아질수록 느려진다 노이즈 증가 : 중요한 정보가 불필요한 정보에 묻힐 수 있다 입력 제한 : Context Window를 넘으면 요청 자체가 실패할 수 있다

그러므로 모든 문서를 넣는 방식 보다는, 질문에 필요한 문서만 찾아 넣는 방식을 사용해야한다.

이때 등장하는 대표적인 구조가 RAG다.


4. RAG

RAG는 Retrieval-Augmented Generation의 약자다. 한국어로는 보통 검색 증강 생성이라고 부른다.

RAG는 LLM이 자기 내부 지식만으로 답하는 것이 아니라, 외부 문서를 먼저 검색한 뒤 그 검색 결과를 참고해서 답변하게 만드는 구조다.

RAG의 프로세스는 아래와 같다.

사용자 질문
  ↓
관련 문서 검색
  ↓
검색 결과를 Context로 구성
  ↓
LLM 답변 생성

예를 들어 사용자가 다음과 같이 질문했다고 해보자.

디지털 상품 다운로드 후 환불 가능한가요?

RAG 시스템은 먼저 관련 문서를 검색한다. 위의 경우엔 ‘환불’ 키워드에 맞춰 관련 문서를 검색 할 것이다.

[문서 1]
디지털 상품은 다운로드 이후 환불이 불가능하다.

[문서 2]
단, 파일 손상 등 회사 귀책 사유가 있는 경우 예외적으로 환불 가능하다.

그다음 검색된 문서를 LLM에게 Context로 제공한다.

아래 문서만 근거로 질문에 답하세요.

[문서 1]
디지털 상품은 다운로드 이후 환불이 불가능하다.

[문서 2]
단, 파일 손상 등 회사 귀책 사유가 있는 경우 예외적으로 환불 가능하다.

질문:
디지털 상품 다운로드 후 환불 가능한가요?

그러면 LLM은 검색된 문서를 참조하여 다음과 같은 결과를 답변해준다.

일반적으로 디지털 상품은 다운로드 이후 환불이 불가능합니다.
다만 파일 손상 등 회사 귀책 사유가 있는 경우에는 예외적으로 환불이 가능할 수 있습니다.

RAG가 중요한 이유는 LLM의 한계를 보완할 수 있기 때문이다.

LLM은 모델이 학습된 이후의 최신 정보를 알 수 없다. 그리고 작업하고자 하는 업무가 있을 경우 프롬프트로 지시한 요청 외 회사 내부 문서나 특정 프로젝트의 코드를 알지 못한다. 이런 상황에서는 모델이 모르는 내용을 추측해, 그럴듯하지만 사실이 아닌 답변을 생성하는 할루시네이션이 발생할 수 있다.

RAG는 이런 문제를 줄이기 위해 외부 문서를 근거로 답변하도록 만든다.

다만 RAG는 LLM이 문서를 Context로 읽어오기 위한 내부 알고리즘이 아니다. LLM 바깥에서 애플리케이션(ChatGPT, 사내 챗봇 등등..)이 관련 문서를 검색하고, 검색 결과를 LLM 입력으로 넣어주는 구조에 가깝다.

RAG의 핵심 구성은 다음과 같다.

문서 수집 : Markdown, PDF, Notion, DB 등 원본 문서 수집 Chunking : 문서를 작은 조각으로 나눔 Embedding : 문서를 벡터로 변환 Vector DB 저장 : 검색 가능한 형태로 저장 Retrieval : 질문과 관련 있는 문서 조각 검색 Generation : 검색 결과를 바탕으로 LLM이 답변 생성

이 중 Embedding과 Vector DB는 RAG를 이해할 때 자주 함께 등장하는 개념이다.


5. Embedding

Embedding은 사용자가 직접 설정하기보다는, RAG 내부에서 검색 품질을 결정하는 내부 로직에 가깝다.

Embedding은 텍스트를 의미를 가진 숫자 벡터로 바꾸는 것이다.

예를 들어 다음과 같은 문장이 있다고 해보자.

환불 정책

Embedding은 이 문장을 다음과 같은 숫자 배열로 변환한다.

[0.12, -0.03, 0.88, 0.41, ...]

실제로는 수백 개에서 수천 개의 숫자로 이루어진 벡터가 만들어진다. 텍스트를 숫자로 바꾸는 이유는, 컴퓨터가 요청한 문장의 유사도를 계산하기 위해서다.

추가적으로 예시를 들어보자.

환불은 언제 가능한가요?
결제 취소 조건을 알려주세요.

두 문장은 같지 않지만 비슷한 의미를 가지고있다.

만약 키워드만 사용해서 검색하면 “환불”이라는 단어가 없어 관련된 문서를 놓칠 수 있다. 반면 Embedding을 사용하면 단어가 정확히 일치하지 않아도 의미적으로 가까운 문서를 찾을 수 있다.

RAG에서는 문서와 질문을 모두 Embedding으로 변환한다.

문서 chunk:
구매 후 7일 이내에는 환불이 가능하다.
→ embedding A

질문:
환불 가능 기간이 어떻게 돼?
→ embedding B

그다음 두 벡터가 얼마나 가까운지 비교한다. 가까운 벡터를 가진 문서일수록 질문과 관련이 높다고 판단하여 결과를 도출한다.


6. Vector DB

Vector DB는 Embedding으로 만들어진 벡터를 저장하고, 유사한 벡터를 빠르게 검색하는 데이터베이스다.

RAG 내부에서 검색 품질을 결정하는 요소중 하나이다.

RAG에서는 문서를 작은 조각으로 나눈 뒤, 각 조각을 Embedding으로 변환한다. 그 결과를 Vector DB에 저장한다.

Vector DB가 저장되는 데이터는 대략 다음과 같이 저장된다.

{
  "id": "refund-policy-001",
  "text": "구매 후 7일 이내 환불 가능...",
  "embedding": [0.12, -0.03, 0.88],
  "metadata": {
    "source": "refund-policy.md",
    "section": "환불 가능 조건"
  }
}

사용자가 질문하면, 질문도 Embedding으로 변환한다.

환불 가능 기간 알려줘
→ [0.11, -0.04, 0.87]

그다음 Vector DB에서 이 질문 벡터와 가까운 문서 벡터를 찾는다.

Top 1: 구매 후 7일 이내 환불 가능
Top 2: 디지털 상품은 다운로드 후 환불 불가
Top 3: 환불 신청은 마이페이지에서 가능

7. Tool Use

Tool Use는 LLM이 외부 도구를 사용할 수 있게 하는 방식이다.

LLM은 텍스트를 이해하고 생성하는 데 강점이 있지만, 그 자체로 모든 일을 직접 처리할 수 있는 것은 아니다. 예를 들어 LLM은 현재 날씨를 직접 확인하거나, 데이터베이스를 조회하거나, 로컬 파일을 읽거나, 코드를 실행할 수 없다.

이런 작업을 하려면 LLM의 외부 도구의 힘들 빌려야 하는데 각 작업에 따라 아래와 같은 도구를 필요로 할것이다.

현재 날씨 확인 : 실시간 API 필요 DB 조회 : 데이터베이스 접근 필요 파일 읽기 : 파일 시스템 접근 필요 계산 : 정확한 계산기 필요 이메일 보내기 : 외부 서비스 API 필요 코드 실행 : 런타임 필요

이외에도 어떤 외부 도구를 사용하냐에 따라 무궁부진한 LLM활용이 가능해진다.

예를 들어 사용자가 다음과 같이 물었다고 해보자.

오늘 서울 날씨 알려줘.

LLM이 학습된 지식만으로 답하면 최신 날씨를 알 수 없다. 하지만 날씨 API라는 도구를 사용할 수 있다면 결과는 달라진다.

모델 판단:
날씨 API를 호출해야겠다.

도구 호출:
getWeather(city="Seoul")

도구 결과:
현재 서울 27도, 흐림, 강수확률 40%

최종 답변:
현재 서울은 27도이고 흐립니다.
강수확률은 40%입니다.

Tool Use가 생기면 LLM은 단순한 질문답변기를 넘어 작업 실행자에 가까워진다.

예를 들어 다음과 같은 요청도 가능해진다.

캘린더 확인해줘.
파일 정리해줘.
DB에서 주문 내역 찾아줘.
테스트 실행해줘.
배포 상태 확인해줘.

이런 요청은 LLM이 학습된 지식만을 이용한 텍스트로는 답변이 불가능 하다. 캘린더 API, 파일 시스템, 데이터베이스, 터미널, 배포 시스템 같은 도구와 연결되어야 한다.

다만 중요한 점은, LLM이 도구를 직접 실행한다기보다는 어떤 도구를 사용할지 판단하고, 애플리케이션이 실제 도구 실행을 담당한다는 것이다.

사용자 요청
  ↓
LLM이 필요한 도구 판단
  ↓
애플리케이션이 도구 실행
  ↓
도구 실행 결과를 LLM에게 전달
  ↓
LLM이 최종 답변 생성

예를 들어 “DB에서 주문 내역을 찾아줘”라는 요청이 들어오면 LLM은 데이터베이스 조회가 필요하다고 판단할 수 있다. 하지만 실제 DB에 접속하고 SQL을 실행하는 것은 LLM 자체가 아니라 애플리케이션의 역할이다.

Tool Use는 LLM을 “말만 하는 모델”에서 “외부 시스템을 활용해 작업을 수행하는 모델”로 확장하는 핵심 개념이다.

하지만 Tool Use에는 주의할 점도 있다. 도구를 사용할 수 있다는 것은 파일을 읽거나, 데이터를 수정하거나, 외부로 메시지를 보낼 수 있다는 뜻이기도 하다.

따라서 실제 서비스에서는 다음과 같은 통제가 필요하다.

권한 제한 : 어떤 도구를 사용할 수 있는지 제한한다 입력 검증 : 도구에 전달되는 인자가 안전한지 확인한다 실행 승인 : 이메일 발송, 결제, 삭제 같은 작업은 사람의 승인을 받는다 로그 기록 : 어떤 도구를 왜 호출했는지 남긴다 실패 처리 : 도구 호출 실패 시 재시도하거나 대체 경로를 사용한다

Tool Use는 LLM 애플리케이션을 실용적으로 만드는 중요한 기술이다. 하지만 동시에 실제 시스템에 영향을 줄 수 있기 때문에, 편의성과 안전성을 함께 고려해야 한다.


8. Function Calling

Function Calling은 모델이 어떤 함수를 어떤 인자로 호출해야 하는지 구조화해서 반환하는 기능이다.

Tool Use를 구현하는 대표적인 방식이라고 볼 수 있다. Tool Use가 “LLM이 외부 도구를 사용할 수 있게 하는 개념”이라면, Function Calling은 그 도구 호출을 프로그램이 이해할 수 있는 형태로 표현하는 방식이다.

예를 들어 개발자가 모델에게 다음과 같은 함수를 알려준다고 해보자.

{
  "name": "get_weather",
  "description": "특정 도시의 현재 날씨를 조회한다",
  "parameters": {
    "city": "string"
  }
}

사용자가 이렇게 묻는다.

서울 날씨 알려줘.

이때 모델은 자연어 답변 대신 다음과 같은 구조화된 출력을 반환할 수 있다.

{
  "function": "get_weather",
  "arguments": {
    "city": "Seoul"
  }
}

애플리케이션은 이 결과를 보고 실제 함수를 실행한다. 그리고 함수 실행 결과를 다시 모델에게 전달해 최종 답변을 생성하게 할 수 있다.

사용자 질문
  ↓
모델이 필요한 함수 판단
  ↓
함수명과 인자를 구조화해서 반환
  ↓
애플리케이션이 실제 함수 실행
  ↓
함수 실행 결과를 다시 모델에 전달
  ↓
최종 답변 생성

위의 흐름을 날씨 조회라는 예시로 들어보자.

사용자:
서울 날씨 알려줘.

모델:
get_weather 함수를 호출해야 한다고 판단

Function Calling 결과:
get_weather(city="Seoul")

애플리케이션:
실제 날씨 API 호출

도구 결과:
서울 27도, 흐림, 강수확률 40%

최종 답변:
현재 서울은 27도이고 흐립니다. 강수확률은 40%입니다.

Tool Use와 Function Calling의 관계는 다음과 같이 이해할 수 있다.

Tool Use • 설명: LLM이 외부 도구를 사용하는 전체 개념

Function Calling • 설명: 도구 호출을 함수명과 인자 형태로 구조화하는 방식

LLM이 단순히 “날씨 API를 호출하면 됩니다”라고 말하는 것은 프로그램이 처리하기 어렵다. 반면 Function Calling을 사용하면 모델의 출력을 애플리케이션이 바로 해석할 수 있다.

Function Calling은 LLM과 실제 애플리케이션 로직을 연결하는 중요한 방식이다. LLM이 “무엇을 해야 하는지”를 판단하고, 애플리케이션은 “실제로 실행하는 일”을 맡는 구조라고 볼 수 있다.


09. MCP

MCP는 Model Context Protocol의 약자다. LLM 애플리케이션이 외부 도구나 데이터와 연결되는 방식을 표준화하려는 프로토콜이라고 볼 수 있다.

LLM 애플리케이션이 사용할 수 있는 외부 도구는 많다.

GitHub
Slack
Notion
Google Drive
브라우저
사내 API

문제는 각 도구마다 연동 방식이 다르다는 점이다. 각 애플리케이션이 GitHub, Notion, Slack, DB 연동을 모두 직접 구현하면 복잡도가 빠르게 증가한다.

MCP는 이런 연결 방식을 공통된 형태로 표준화 한것이다.

구조를 단순화하면 다음과 같다.

LLM Client
  ↕️ MCP
MCP Server
  ↕️
외부 도구 / 데이터

예를 들어 GitHub MCP Server가 있다면, LLM 애플리케이션은 GitHub API를 직접 다루지 않고 MCP Server를 통해 LLM끼리 정해진 방식으로 GitHub 기능을 사용할 수 있다.

MCP는 LLM 세계의 USB-C 같은 연결 규격이라고 비유할 수 있다.

각 서비스마다 제각각 연결 방식을 만드는 대신, 공통된 프로토콜로 연결하자는 것이다.

API와 MCP의 차이는 다음과 같다.

API • 설명: 특정 서비스가 제공하는 기능 호출 인터페이스

MCP • 설명: LLM 앱이 여러 API와 도구를 일관된 방식으로 사용할 수 있게 하는 프로토콜

MCP는 API를 대체한다기보다는, LLM 애플리케이션이 다양한 API와 도구를 더 일관되게 사용할 수 있도록 돕는 계층에 가깝다.


10. Skills

Skills는 특정 작업을 잘 수행하기 위한 재사용 가능한 절차, 지식, 규칙의 묶음이다. 쉽게 말하면, LLM이 어떤 기술을 사용하기 위해 참고하는 메뉴얼로 정리된 문서라고 볼 수 있다.

예를 들어 GitHub PR 리뷰 Skill은 다음과 같은 내용을 포함할 수 있다.

GitHub PR 리뷰 Skill
- 변경 의도를 파악한다.
- diff를 확인한다.
- 테스트 결과를 확인한다.
- 보안, 성능, 호환성 이슈를 점검한다.
- 리뷰 코멘트는 근거와 함께 작성한다.

기술블로그 작성 Skill이라면 다음과 같은 절차가 들어갈 수 있다.

기술블로그 작성 Skill
- 문제 배경을 설명한다.
- 재현 가능한 예시를 제시한다.
- 원인을 분석한다.
- 해결 과정을 설명한다.
- 검증 방법을 포함한다.
- 마지막에 재사용 가능한 교훈을 정리한다.

Prompt와 Skill은 비슷해 보이지만 역할이 다르다.

Prompt • 설명: 한 번의 요청 지시문

Skill • 설명: 반복 작업에 재사용하는 절차와 지식 묶음

Prompt가 다음과 같은 요청이라면:

이 PR 리뷰해줘.

Skill은 그 요청을 어떤 기준과 절차로 수행해야 하는지를 정의한다.

Skills가 필요한 이유는 LLM의 작업 방식을 일관되게 만들기 위해서다. 반복된 작업을 매번 다르게 처리하는 것이 아니라, 정해진 기준과 절차에 따라 수행하게 할 수 있다. 질문에 따라 달라지는 답변이 아닌 어느정도 일관된 작업으로 인해 정해진 결과를 받아 볼 수 있다.


11. Agent

Agent는 목표를 달성하기 위해 계획하고, 도구를 사용하고, 결과를 관찰한 뒤 다음 행동을 결정하는 LLM 기반 실행 주체다.

단순 LLM 호출은 보통 한 번의 질문과 답변으로 끝난다.

질문 → 답변

반면 Agent는 완료할때까지 반복적으로 움직인다.

목표 이해
  ↓
계획 세우기
  ↓
도구 사용
  ↓
결과 관찰
  ↓
다음 행동 결정
  ↓
완료할 때까지 반복

예를 들어 사용자가 다음과 같이 요청했다고 해보자.

이 프로젝트 테스트 실패 원인 찾아서 고쳐줘.

단순 LLM은 코드를 직접 실행하거나 파일을 확인할 수 없다면 일반적인 조언만 할 수 있다.

하지만 Agent는 다음과 같이 행동할 수 있다.

1. 테스트 실행
2. 실패 로그 확인
3. 관련 파일 검색
4. 코드 수정
5. 테스트 재실행
6. 결과 보고

Agent는 Tool Use와 결합될 때 강력해진다. 파일을 읽고, 터미널 명령을 실행하고, API를 호출하고, 검색 결과를 바탕으로 다음 행동을 선택할 수 있기 때문이다.

Agent와 Workflow는 자주 비교된다.

- 흐름
  - Workflow: 미리 정해진 순서대로 실행
  - Agent: 상황에 따라 다음 행동을 선택
- 예시
  - Workflow: A → B → C 순서대로 실행
  - Agent: 결과를 보고 다음 행동 선택
- 장점
  - Workflow: 예측 가능하고 안정적
  - Agent: 유연함
- 단점
  - Workflow: 예외 상황 대응이 약함
  - Agent: 통제가 어려울 수 있음

Agent는 강력하지만 그만큼 통제가 중요하다. 무제한으로 도구를 사용하거나 반복 실행하게 두면 비용, 보안, 안정성 문제가 생길 수 있다.

따라서 Agent에는 보통 다음과 같은 제한이 필요하다.

도구 권한 : 어떤 도구를 사용할 수 있는지 제한 반복 횟수 제한 : 무한 루프 방지 비용 제한 : API 비용 폭주 방지 승인 단계 : 이메일 발송, 파일 삭제 등은 사람 승인 필요 성공 기준 : 언제 작업을 완료로 볼지 정의 로그 : 어떤 판단으로 어떤 도구를 사용했는지 기록

이처럼 Agent가 안전한 범위 안에서 동작하도록 도구 권한, 반복 횟수, 비용, 승인 절차 등을 감싸는 실행 구조를 Harness라고 볼 수 있다.

Agent는 “스스로 모든 것을 알아서 하는 AI”라기보다는, 정해진 도구와 제약 안에서 목표를 향해 반복적으로 작업하는 실행 구조로 이해하는 것이 좋다.


12. Evaluation

Evaluation, 줄여서 Eval은 LLM 애플리케이션의 품질을 평가하는 체계다.

일반적인 소프트웨어는 테스트 코드를 통해 동작을 검증할 수 있다. 하지만 LLM 애플리케이션은 자연어 답변을 생성하기 때문에 품질 판단이 더 어렵다.

예를 들어 프롬프트를 수정했다고 해보자.

기존 프롬프트:
답변이 짧지만 정확했다.

새 프롬프트:
답변은 더 친절해졌지만, 문서에 없는 내용을 섞기 시작했다.

겉으로 보기에는 새 프롬프트가 더 좋아 보일 수 있다. 하지만 실제로는 품질이 나빠졌을 수도 있다.

그래서 LLM 애플리케이션에는 별도의 평가 체계가 필요하다. 프롬프트, 모델, 문서, 검색 방식이 바뀌었을 때 결과가 좋아졌는지 나빠졌는지 확인해야 하기 때문이다.

Evaluation에서는 다음과 같은 항목을 볼 수 있다.

정확성 : 답이 맞는가 근거성 : 제공된 문서나 데이터에 기반하는가 완전성 : 필요한 내용을 빠뜨리지 않았는가 형식 준수 : JSON, schema, 표 형식을 지켰는가 안전성 : 위험하거나 부적절한 답을 하지 않았는가 일관성 : 비슷한 질문에 비슷하게 답하는가 비용 : 너무 비싼 모델이나 긴 Context를 쓰지 않는가 지연 시간 : 응답 속도가 적절한가

많은 프로세스에서 Evaluation를 진행하지만 RAG단계에서는 평가를 두 단계로 나누어 볼 필요가 있다.

1. 검색이 잘 되었는가?
2. 검색 결과를 바탕으로 답변을 잘 생성했는가?

예를 들어 다음과 같은 질문이 있다고 해보자.

디지털 상품 다운로드 후 환불 가능한가요?

정답을 만들기 위해서는 다음 문서가 검색되어야 한다고 가정해보자.

refund-policy.md > 디지털 상품 환불 조건

그런데 실제 검색 결과로 다음 문서가 나왔다면 잘못된 RAG단계를 거친것이다.

payment-error.md

이 경우 답변이 틀렸다면 LLM 자체의 문제가 아니라 검색 단계의 문제일 가능성이 높다. RAG 품질을 평가할 때는 “답변이 맞았는가”뿐만 아니라 “정답에 필요한 문서를 제대로 찾았는가”도 함께 봐야 한다.

간단한 평가를 위한 예시는 다음과 같이 만들 수 있다.

[
  {
    "question": "디지털 상품 다운로드 후 환불 가능한가요?",
    "expected_answer": "일반적으로 불가능하지만, 회사 귀책 사유가 있으면 예외적으로 가능하다.",
    "expected_source": "refund-policy.md"
  },
  {
    "question": "환불 신청은 어디서 하나요?",
    "expected_answer": "마이페이지의 결제 내역에서 신청할 수 있다.",
    "expected_source": "refund-guide.md"
  }
]

이런 예시을 만들어두면 프롬프트나 모델을 바꿨을 때 결과를 비교할 수 있다. 예를 들어 다음과 같은 변경이 있을 때마다 평가를 다시 돌려볼 수 있다.

프롬프트 변경
모델 변경
문서 추가 또는 수정
Chunk 크기 변경
검색 방식 변경
Top-K 개수 변경
Reranking 추가

Evaluation은 LLM 애플리케이션에서 테스트 코드와 비슷한 역할을 한다. 한 번 잘 답했다고 해서 계속 잘 답한다고 보장할 수 없기 때문이다.

따라서 LLM 애플리케이션을 안정적으로 운영하려면, 감으로 “좋아진 것 같다”고 판단하기보다 평가 기준과 평가셋을 만들어두고 반복적으로 확인하는 과정이 필요하다.


마무리

LLM 애플리케이션은 단순히 모델에게 질문을 보내고 답변을 받는 구조에서 시작할 수 있다. 하지만 실제 서비스로 확장하려면 더 많은 개념이 필요해진다.

처음에는 Prompt를 잘 작성하는 것이 중요해 보인다. 하지만 곧 모델에게 어떤 Context를 제공할지, Context Window 안에 무엇을 넣을지 고민하게 된다.

외부 문서를 참고해야 한다면 RAG가 필요하고, RAG를 구현하려면 Embedding과 Vector DB 같은 개념을 이해해야 한다. LLM이 단순히 답변만 하는 것이 아니라 실제 작업을 수행해야 한다면 Tool Use와 Function Calling이 필요해진다. 여러 도구와 데이터를 일관된 방식으로 연결하려면 MCP 같은 표준도 중요해진다.

반복적으로 수행해야 하는 작업은 Skills로 정리할 수 있고, 목표를 위해 계획하고 도구를 사용하며 반복 실행하는 구조는 Agent로 발전한다. 마지막으로, 이런 LLM 애플리케이션이 실제로 좋아지고 있는지 확인하기 위해서는 Evaluation이 필요하다.

정리하면 다음과 같다.

LLM_word

LLM을 제대로 활용한다는 것은 단순히 좋은 모델을 고르는 일이 아니다. 모델이 참고할 정보를 설계하고, 필요한 도구를 연결하고, 반복 가능한 작업 절차를 만들고, 결과를 평가하는 전체 시스템을 설계하는 일에 가깝다.

이 관점으로 보면 LLM 애플리케이션은 “프롬프트 하나로 동작하는 기능”이 아니라, Prompt, Context, Retrieval, Tool, Agent, Evaluation이 함께 맞물려 돌아가는 하나의 소프트웨어 시스템이라고 볼 수 있다.