LLM 애플리케이션 개발
요약
본 가이드는 LLM 기반 애플리케이션을 설계하는 방법을 심층적으로 다룹니다. LLM의 작동 원리부터 프롬프트 엔지니어링, 구조화된 입력 처리, 컨텍스트 관리, 환각 현상 감소 전략까지 포괄합니다. 특히 전통적인 결정론적 소프트웨어와 달리 확률론적 특성을 가진 LLM을 활용하는 애플리케이션 설계에 초점을 맞춥니다.
핵심 포인트
- LLM은 다음 토큰을 예측하는 확률론적 모델입니다.
- 애플리케이션 설계는 프롬프트 엔지니어링과 구조화된 입력 처리가 핵심입니다.
- 환각 현상(Hallucinations)의 원인 이해와 감소 전략이 필수적입니다.
- 대화 메모리 및 AI 에이전트 구현을 통해 상태 비저장성을 극복해야 합니다.
LLM 애플리케이션 개발
대규모 언어 모델(LLM)을 기반으로 애플리케이션을 구축하는 심층적인 가이드입니다. 이 글에서는 LLM이 실제로 어떻게 작동하는지, 그리고 그것이 애플리케이션 설계, 프롬프트 엔지니어링, 시스템/사용자/어시스턴트 메시지 역할, Few-shot 및 구조화된 프롬프팅, 컨텍스트 윈도우와 토큰, 환각(hallucinations) 발생 원인과 감소 방법, 모델 선택 방법, 대화 메모리 전략, 그리고 AI 에이전트에 이르기까지 다룹니다. 이들 주제에는 무엇인지, 루프가 어떻게 작동하는지, 그리고 안전하고 제한적으로 유지하는 방법을 포함합니다.
목차
- 서론
- LLM 기본 원리
- 프롬프트 엔지니어링
- 시스템, 사용자 및 어시스턴트 메시지
- Few-Shot 프롬프팅
- 구조화된 프롬프팅
- 컨텍스트 윈도우
- 토큰
- 환각(Hallucinations)
- 모델 선택
- 대화 메모리
- AI 에이전트
- LLM 애플리케이션 평가
- 종합: LLM 애플리케이션의 해부학적 구조
- 일반적인 함정(Pitfalls)
- 빠른 참고표
- 결론
서론
LLM을 활용하여 구축하는 것은 전통적인 소프트웨어와는 다른 종류의 엔지니어링입니다. 기존 함수는 결정적(deterministic)입니다. 즉, 동일한 입력에는 항상 동일한 출력이 나오고, 버그는 찾아서 고칠 수 있는 결함입니다. 반면 LLM은 **확률론적(probabilistic)**입니다. 그 결과로 그럴듯한 텍스트를 생성하며, 보통은 정확하지만 때로는 자신감 있게 틀릴 수도 있습니다. 그리고 작성하는
이 가이드는 이 시리즈의 'AI APIs with .NET' 가이드에 대한 개념적 보조 자료입니다. 해당 가이드는 API 호출 메커니즘(클라이언트, 스트리밍, 툴 호출 코드, 재시도, 속도 제한, 비용)을 다루는 반면, 본 가이드는 모델을 중심으로 애플리케이션을 설계하는 방법을 다룹니다. 메커니즘에 대한 내용은 반복하기보다는 해당 가이드로 되돌아가 안내합니다.
1. LLM 기본 원리
LLM은 다음 토큰을 예측하며, 나머지는 그로부터 파생된다
대규모 언어 모델(LLM)은 방대한 양의 텍스트를 학습한 신경망으로, 단 하나의 작업을 수행하도록 설계되었습니다: 주어진 토큰 시퀀스를 바탕으로 다음 토큰에 대한 확률 분포를 예측하는 것입니다. 이 모델은 토큰을 반복적으로 예측하고, 이를 추가하며, 다시 예측하는 방식으로 응답을 생성합니다.
Input: "The capital of France is"
Model: P(" Paris") = 높음, P(" Lyon") = 낮음, ...
Output: " Paris" -> 추가됨 -> 다음 토큰 예측 -> "." ...
이 간단한 메커니즘만으로도 요약, 번역, 코드 작성, 문제 추론 등 놀라울 정도로 유능한 행동을 만들어냅니다. 왜냐하면 인간 글쓰기의 광범위한 영역에 걸쳐 텍스트를 잘 예측하려면 세상에 대한 방대한 지식을 모델링해야 하기 때문입니다. 하지만 이는 또한 여러분이 설계 단계에서 반드시 고려해야 할 특징적인 한계점들을 설명해줍니다:
- 그것은 검증된 텍스트가 아닌, 그럴듯한(PLAUSIBLE) 텍스트를 생성합니다. 유창함이 정확성을 의미하지는 않습니다.
(섹션 8: 환각 현상)
- 그것은 상태 비저장적(STATELESS)입니다. 여러분이 보내주는 것을 제외하고는 호출 간에 기억을 가지고 있지 않습니다.
...
모델들이 행동을 얻는 방법
1. 사전 학습 (PRE-TRAINING): 방대한 텍스트 코퍼스에서 다음 토큰을 예측함으로써 언어와 광범위한 지식을 학습합니다. 이는 '기반(base)' 모델을 생성하며, 유능하지만 대화형이거나 신뢰할 수 있게 도움이 되지는 못합니다.
...
이것이 애플리케이션 개발자에게 의미하는 바
LLM은 다음과 같은 언어 작업에 강점을 보입니다: 요약, 재작성, 추출, 분류, 번역, 초안 작성, 설명, 코드 생성 등 — 그리고 지저분하고 비정형적인 입력을 처리하는 데 강합니다.
...
임베딩(Embeddings): 도구 상자의 나머지 절반
생성(generation) 외에도 모델은 임베딩을 생성할 수 있습니다. 이는 유사한 의미를 가까이 배치하는 벡터입니다 (본 시리즈의 AI/ML Fundamentals 가이드에서 다루었습니다). 임베딩은 시맨틱 검색(semantic search)과 검색 증강 생성(retrieval-augmented generation, RAG)에 동력을 제공하여, _의미_로 관련 텍스트를 찾아 모델에게 컨텍스트로 전달할 수 있게 합니다.
2. 프롬프트 엔지니어링 (Prompt Engineering)
프롬프트는 프로그램입니다 — 코드처럼 신중하게 다루세요
프롬프트는 모델에 제공하는 입력이며, 단어의 작은 변화가 출력에 큰 변화를 가져올 수 있습니다. 프롬프트 엔지니어링은 안정적으로 좋은 결과를 산출하도록 프롬프트를 설계하는 실습입니다.
잘 구성된 프롬프트는 명확한 부분이 있습니다
1. 역할/컨텍스트 (ROLE / CONTEXT) 모델이 수행하는 역할과 상황.
2. 작업 (TASK) 무엇을 해야 하는지 정확하고 모호하지 않게 지정합니다.
3. 입력 데이터 (INPUT DATA) 작업할 자료 (지침과 명확히 구분되어야 합니다).
...
일관되게 도움이 되는 원칙들
구체적으로 작성하세요 (BE SPECIFIC). 모호하게 입력하면, 모호하게 출력됩니다. '이것을 요약해줘'는 일반적인 요약을 가져오지만, '재현 단계를 중점적으로 하여 엔지니어를 위한 두 문장으로 이 지원 티켓을 요약해줘'는 활용 가능한 결과를 얻게 합니다.
...
약한 프롬프트 대 강력한 프롬프트
나쁜 예:
이 티켓을 요약하세요.
...
프롬프트는 코드입니다: 버전을 관리하고, 테스트하며, 검토하세요
- 프롬프트를 인라인 문자열로 여기저기 흩어 놓지 말고 소스 컨트롤(파일 또는 리소스)에 보관하세요.
- 임시적인 문자열 연결 대신 이름이 지정된 플레이스홀더를 사용하는 TEMPLATE를 사용하세요.
- 한 번에 하나의 것만 변경하고, 테스트 세트(Section 12)에서 그 영향을 측정하세요 —
...
3. 시스템 메시지, 사용자 메시지 및 어시스턴트 메시지
채팅 모델은 단일 문자열이 아닌 구조화된 대화를 처리합니다
system -> 개발자의 기본 지침: 역할(role), 규칙(rules), 어조(tone), 형식(format), 안전 경계(safety boundaries). 전체 대화의 틀을 설정합니다.
user -> 최종 사용자가 (또는 귀하의 애플리케이션이 그를 대신하여) 요청하는 내용
...
[.NET에서 이러한 메시지 목록을 구축하는 메커니즘은 이 시리즈의 'AI APIs with .NET' 가이드, 섹션 4에 있습니다.]
시스템 메시지에 포함되어야 할 것
System message -> 모든 턴(turn)에 적용되는 안정적인 규칙:
신원("당신은 ACME 지원 어시스턴트입니다"),
범위("ACME 제품에 대한 질문만 답변합니다"),
...
안정적인 지침을 시스템 메시지에, 가변 데이터를 사용자 메시지에 유지하는 것은 비용 절감에도 도움이 됩니다. 제공업체들은 종종 반복적이고 변하지 않는 접두사(prefix)를 캐시할 수 있기 때문입니다 (AI APIs with .NET, 섹션 12 참조).
시스템 프롬프트는 보안 경계가 아닌 가이드라인이다
Models는 일반적으로 시스템 지침에 우선순위를 부여하지만 — 이는 강한 경향성(TENDENCY)일 뿐, 강제된 규칙은 아닙니다. 노출되는 것을 감당할 수 없는 내용은 시스템 프롬프트에 넣지 말고, 보안을 시행하기 위해 여기에만 의존해서도 안 됩니다.
...
코드에서의 역할 규율 (Role discipline)
- 사용자 제공 텍스트를 SYSTEM 역할에 절대 배치하지 마십시오. 이는 사용자에게 가장 높은 우선순위의 채널을 넘겨주는 행위입니다.
- 어시스턴트의 이전 턴(turn)들을 충실하게 재현하십시오. 이를 다시 작성하면 모델이 혼란스러워질 수 있습니다.
...
4. Few-Shot Prompting (퓨샷 프롬프팅)
예시를 통한 학습, 프롬프트 내부에서
Zero-shot : 지침만 제공하고 예시는 없음. "이 티켓을 분류하세요."
One-shot : 지침과 하나의 예시(ONE example).
Few-shot : 지침과 여러 개의 예시(SEVERAL examples)를 보여줌 (일반적으로 2~10개).
...
예시는 **형식(format), 어조(tone), 그리고 엣지 케이스 행동(edge-case behavior)**을 전달하는 데 있어 설명보다 더 효과적일 때가 많습니다. 모델에게 좋은 답변이 어떻게 보이는지를 보여주는 것이 그것을 설명하는 것보다 쉽기 때문입니다.
예시: 메시지 쌍으로 구축된 Few-shot 분류기
예시를 번갈아 가며 사용자/어시스턴트 메시지로 제시하는 것은 채팅 모델에 자연스럽게 적합합니다. 모델은 자신이 요청받을 형식과 동일한 형식에서 '올바른 답변'이 어떻게 보이는지 보기 때문입니다.
좋은 예시 선택하기
- 다양성(DIVERSE): 다섯 개의 거의 중복되는 예시보다는 다양한 카테고리와 까다로운 엣지 케이스를 다루어야 합니다.
- 대표성(REPRESENTATIVE): 모델이 실제로 보게 될 것과 일치하도록 실제 입력에서 가져와야 합니다.
- 정확성(CORRECT): 잘못된 예시는 잘못된 것을 가르칩니다. 모델은 자신의 예시를 충실히 모방하기 때문입니다.
...
트레이드오프 및 변형
비용: 모든 예시는 요청마다 INPUT TOKENS를 소모합니다. 긴 예시 10개는 실제적이고 반복적인 비용이 됩니다 (섹션 7). 필요한 품질을 달성하는 최소한의 예시만 사용하세요.
...
5. 구조화된 프롬프팅(Structured Prompting)
프롬프트 자체에 명확한 구조 부여하기
길고 비정형적인 프롬프트는 인간과 모델 모두에게 파싱하기 어렵습니다. **구조화된 프롬프팅(Structured prompting)**이란 프롬프트를 명확하게 레이블링된 섹션으로 구성하고, 일관된 구분자(delimiter)를 사용하여 모델이 지침(instructions), 컨텍스트(context), 입력(input)을 구별할 수 있도록 조직하는 것을 의미합니다.
You are a contract-review assistant.
<instructions>
...
구조가 도움이 되는 이유
- 분리(SEPARATION): 구분자(XML 스타일 태그, 마크다운 헤더, 삼중 따옴표)는 지침이 어디서 끝나고 신뢰할 수 없는 데이터가 시작되는지를 명확하게 표시하여 혼란을 줄이고 프롬프트 주입 공격(prompt injection)에 대한 (부분적인) 방어책을 제공합니다.
...
출력물도 구조화하기
프롬프트로 JSON 요청(
하나의 거대한 프롬프트 대신, 작업을 여러 단계로 나누고 각 단계마다 집중된 프롬프트를 사용하며 출력을 다음 단계로 전달하고 일반 코드를 통해 중간 검사를 수행하세요:
...
### 템플릿 및 안전한 조립 (Templates and safe assembly)
// 분산된 문자열 연결이 아닌, 템플릿에서 프롬프트를 구축합니다
const string Template = """
<instructions>{0}</instructions>
...
주의할 점: 신뢰할 수 없는 텍스트가 자체 구분자 태그(예를 들어 리터럴 `</document>`)를 포함할 수 있다면, 이로 인해 섹션을 일찍 '닫으려고' 시도하여 지침을 몰래 삽입할 수 있습니다. 신뢰할 수 없는 입력에서 구분자 시퀀스를 제거하거나 이스케이프 처리하고, 구분자를 그 자체만으로는 보안 보장으로 취급하지 마십시오.
## 6. 컨텍스트 창 (Context Windows)
### 컨텍스트 창은 모델의 작업 메모리이며 유한합니다
**컨텍스트 창(context window)**이란 모델이 단일 요청에서 고려할 수 있는 최대 토큰 수를 의미하며, 여기에는 시스템 프롬프트, 대화 기록, 검색된 문서, 도구 정의 및 결과, 사용자의 새로운 질문, **그리고** 모델이 생성하는 답변까지 모든 것이 포함됩니다.
컨텍스트 창 >= 시스템 프롬프트
+ 대화 기록
+ 검색된 문서/도구 결과
...
창 크기는 모델마다 다르며 극적으로 증가했지만, 결코 무한하지 않으며, 더 크다고 해서 무료이거나 자동으로 더 좋지는 않습니다.
### 더 큰 창이 모든 것을 채워 넣을 수 있는 면허가 아닙니다
비용(COST): 요청당 모든 입력 토큰에 대해 비용을 지불합니다. 질문마다 100페이지짜리 문서를 재전송하면 비용이 빠르게 증가합니다.
...
### 창 내에서 작동하기 위한 전략들
검색 증강 생성 (RETRIEVAL, RAG): 임베딩을 사용하여 문서를 청크로 저장하고; 질문당 가장 관련성이 높은 상위 몇 개의 청크만 검색하여 포함합니다. '문서와 채팅하기'의 표준 접근 방식입니다.
축소/슬라이딩 (TRIMMING / SLIDING): 가장 최근 대화 턴만 유지합니다(섹션 10).
컨텍스트 창(WINDOW)
요약 (SUMMARIZATION): 오래된 컨텍스트를 짧은 내용으로 압축합니다
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기