| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 |
- 룩백
- anxiety
- 이터널리턴
- 스케치퀴즈
- 카카오톡공유하기
- 개인앱
- 페이스북광고
- 영원회귀
- Redis
- git pull
- 코딩공부
- 메모장앱
- 카카오톡
- 플러터
- funnel
- 토이프로젝트
- 라인광고플랫폼
- 사이드프로젝트
- 펀널
- 캐치마인드
- 블랙서바이벌
- git
- 구글검색광고
- Kotlin
- nodejs
- submodules
- 개발자를_위한 #PPT팁
- nestjs
- 광고플랫폼
- 스케치데브
- Today
- Total
가을기 Workspace
백엔드 개발자를 위한 AI Agent 입문 - LLM, 트랜스포머, Agent 기초 본문
목차
- LLM이란 무엇인가?
- Token이란 무엇인가?
- Transformer란 무엇인가?
- 챗봇이란 무엇인가?
- AI Agent는 챗봇과 어떻게 다른가?
- Agent가 Tool을 호출한다니, 그게 어떻게 가능할까?
- Multi-Agent가 왜 필요할까? Agent 하나면 되는 거 아닌가?
- Langchain, 꼭 필요할까? 그냥 API 호출하면 안 되나?
- 정리
1. LLM이란 무엇인가?
LLM(Large Language Model) 은 "엄청 큰 언어 모델"이라는 뜻입니다. 쉽게 말하면 "다음에 올 단어를 정말 잘 맞히는 기계" 예요.
핵심 원리: 다음 단어 맞히기
입력: "오늘 점심으로 김치"
출력: "찌개" (확률 35%)
"볶음밥" (확률 25%)
"전" (확률 15%)
...
LLM은 인터넷에 있는 엄청난 양의 글(책, 위키백과, 블로그 등)을 읽고 "이런 단어 뒤에는 보통 이런 단어가 나오더라"를 학습한 거대한 통계 기계입니다.
백엔드 개발자식 비유
LLM = function next_token(context: string): string
- 입력: 지금까지의 문장
- 출력: 다음에 올 가장 그럴듯한 단어 하나
- 이걸 반복해서 문장을 완성합니다.
flowchart LR
A["입력: '안녕'"] --> B[LLM]
B --> C["출력: '하세요'"]
C --> D["다시 입력: '안녕하세요'"]
D --> B
B --> E["출력: ','"]
E --> F["다시 입력: '안녕하세요,'"]
F --> B
B --> G["출력: '반갑'..."]
이렇게 한 단어씩 만들어내는 걸 자기회귀(autoregressive) 생성 이라고 부릅니다.
2. Token이란 무엇인가?
LLM은 사실 "단어"가 아니라 Token(토큰) 단위로 생각합니다.
Token = 글자 조각
토큰은 단어보다 작을 수도, 클 수도 있어요. 영어 단어 하나가 토큰 하나일 수도 있고, 긴 단어는 여러 토큰으로 쪼개지기도 합니다.
"Hello" → ["Hello"] (1 token)
"unbelievable" → ["un", "believ", "able"] (3 tokens)
"안녕하세요" → ["안", "녕", "하세요"] (3 tokens 정도)
왜 토큰을 알아야 할까?
- 돈 💰: API 호출 비용은 토큰 수로 계산됩니다.
- 속도 ⚡: 토큰이 많을수록 응답이 느려져요.
- 한계 📏: 모델마다 한 번에 처리할 수 있는 토큰 수가 정해져 있습니다(Context Window).
flowchart TD
A["사용자 입력: '오늘 날씨 어때?'"] --> B[Tokenizer]
B --> C["['오늘', ' 날씨', ' 어때', '?']"]
C --> D[LLM이 숫자로 변환]
D --> E["[2941, 8821, 5532, 33]"]
E --> F[LLM 처리]
F --> G["출력 토큰들"]
G --> H[Detokenizer]
H --> I["사람이 읽는 글자로 변환"]
3. Transformer란 무엇인가?
Transformer는 2017년 구글에서 발표한 신경망 구조예요. 지금 우리가 쓰는 거의 모든 LLM(GPT, Claude, Gemini 등)이 이 구조를 기반으로 합니다.
핵심 아이디어: Attention(주의 집중)
문장에서 어떤 단어가 다른 단어와 얼마나 관련이 있는지 계산하는 방식입니다.
"그 학생은 시험을 봤는데, 그는 결과를 기다렸다."
여기서 "그"가 누구를 가리킬까요? 사람은 자연스럽게 "학생"이라고 알지만, 기계는 모든 단어를 비교해서 "그 ↔︎ 학생"의 관련도가 높다는 걸 계산합니다. 이게 Attention이에요.
flowchart TD
A["그는"] -.->|0.05| B[학생은]
A -.->|0.85| C[학생]
A -.->|0.02| D[시험을]
A -.->|0.03| E[봤는데]
A -.->|0.05| F[결과를]
Transformer가 강력한 이유
- 병렬 처리: 기존 모델(RNN)은 단어를 하나씩 순서대로 읽었지만, Transformer는 한 번에 다 봅니다.
- 장거리 관계: 문장 앞쪽 단어와 뒤쪽 단어의 관계도 잘 파악합니다.
- 확장성: 데이터와 컴퓨터 자원을 더 쏟아부으면 더 똑똑해집니다.
flowchart LR
subgraph 기존방식[RNN: 순차 처리]
A1[나는] --> A2[학교에] --> A3[갔다]
end
subgraph 트랜스포머[Transformer: 병렬 처리]
B1[나는] -.-> B2[학교에]
B1 -.-> B3[갔다]
B2 -.-> B3
B2 -.-> B1
B3 -.-> B1
B3 -.-> B2
end
백엔드 비유: RNN은 for문, Transformer는 멀티스레딩이라고 생각해도 됩니다.
4. 챗봇이란 무엇인가?
챗봇 = LLM + 대화 인터페이스 + 대화 기록
LLM은 그 자체로는 그냥 "다음 단어 맞히기 기계"입니다. 챗봇은 여기에 다음을 더한 거예요.
- 사용자/AI 역할 구분 (system, user, assistant)
- 이전 대화를 기억 (Context로 계속 전달)
- 사람이 쓰기 좋은 UI
챗봇이 동작하는 방식
sequenceDiagram
participant U as 사용자
participant S as 서버
participant L as LLM API
U->>S: "안녕"
S->>L: messages=[{user: "안녕"}]
L->>S: "반가워요!"
S->>U: "반가워요!"
U->>S: "내 이름은 철수야"
S->>L: messages=[{user: "안녕"}, {assistant: "반가워요!"}, {user: "내 이름은 철수야"}]
L->>S: "철수님 반가워요"
S->>U: "철수님 반가워요"
U->>S: "내 이름이 뭐였지?"
S->>L: messages=[전체 대화 기록]
L->>S: "철수님이라고 하셨어요"
S->>U: "철수님이라고 하셨어요"
중요한 사실
LLM은 사실 기억이 없습니다.
매 요청마다 이전 대화를 전부 다시 보내야 기억하는 것처럼 보이는 거예요. 백엔드 개발자라면 "stateless API에 매번 전체 컨텍스트를 전달하는 구조"라고 이해하면 됩니다.
5. AI Agent는 챗봇과 어떻게 다른가?
가장 큰 차이는 한 단어로 요약할 수 있습니다.
챗봇은 "말"을 한다. Agent는 "행동"을 한다.
비교표
| 구분 | 챗봇 | AI Agent |
|---|---|---|
| 입력 | 사용자 메시지 | 사용자 목표(goal) |
| 출력 | 텍스트 응답 | 행동(action) + 결과 |
| 외부 시스템 | 못 건드림 | API/DB/파일 조작 가능 |
| 반복 | 한 번 답하고 끝 | 목표 달성까지 스스로 반복 |
| 비유 | 똑똑한 친구 | 똑똑한 인턴 |
예시로 보기
챗봇에게: "내일 날씨 어때?" → "죄송해요, 저는 실시간 정보를 모릅니다."
Agent에게: "내일 날씨 어때?"
→ (속으로) "날씨 API를 호출해야겠다"
→ getWeather(date="2026-05-27", location="서울") 호출
→ API 응답: { temp: 22, condition: "맑음" }
→ "내일 서울은 맑고 22도 정도예요!"
Agent의 동작 흐름
flowchart TD
A[사용자 목표 입력] --> B[LLM이 상황 판단]
B --> C{도구가 필요한가?}
C -->|예| D[도구 호출]
D --> E[결과 받기]
E --> B
C -->|아니오| F[최종 답변 생성]
F --> G[사용자에게 응답]
이 "생각 → 행동 → 관찰 → 다시 생각" 의 반복(Loop)이 Agent의 핵심입니다. 이걸 ReAct 패턴(Reasoning + Acting) 이라고 부릅니다.
6. Agent가 Tool을 호출한다니, 그게 어떻게 가능할까?
"잠깐만요, LLM은 그냥 텍스트만 뱉는 거 아니에요? 어떻게 함수를 호출해요?"
이게 처음 보면 정말 신기한 부분입니다. 핵심을 먼저 말하면:
LLM이 직접 함수를 호출하는 게 아닙니다. LLM은 "이 함수를 이런 인자로 호출하고 싶어요"라고 JSON으로 말하고, 우리가 대신 호출해줍니다.
단계별로 보기
1단계: 도구 설명서를 LLM에게 알려줌
{
"tools": [
{
"name": "getWeather",
"description": "특정 도시의 현재 날씨를 가져옵니다",
"parameters": {
"city": { "type": "string", "description": "도시 이름" }
}
},
{
"name": "sendEmail",
"description": "이메일을 보냅니다",
"parameters": {
"to": { "type": "string" },
"subject": { "type": "string" },
"body": { "type": "string" }
}
}
]
}2단계: 사용자가 질문
"서울 날씨 알려줘"
3단계: LLM이 텍스트 대신 JSON을 뱉음
{
"tool_call": {
"name": "getWeather",
"arguments": { "city": "서울" }
}
}4단계: 우리(백엔드 코드)가 실제로 함수 실행
result = getWeather(city="서울")
# → { "temp": 22, "condition": "맑음" }5단계: 결과를 다시 LLM에게 전달
"getWeather 결과: 온도 22도, 맑음"
6단계: LLM이 사람 말로 답변
"서울은 지금 22도이고 맑아요!"
전체 흐름도
sequenceDiagram
participant U as 사용자
participant A as Agent 서버
participant L as LLM
participant T as Tool/API
U->>A: "서울 날씨 알려줘"
A->>L: 메시지 + tool 정의 목록
L->>A: tool_call: getWeather(city="서울")
Note over A: LLM은 직접 호출 못함<br/>JSON으로만 요청
A->>T: getWeather("서울")
T->>A: {temp: 22, condition: "맑음"}
A->>L: tool 결과 = {temp:22, ...}
L->>A: "서울은 22도이고 맑아요"
A->>U: "서울은 22도이고 맑아요"
더 깊이: 어떻게 LLM이 정확한 JSON을 뱉을까?
- 학습 데이터: LLM은 학습 단계에서 "이런 상황에선 이런 JSON을 만들어라"를 엄청나게 많이 본 상태입니다.
- System Prompt: "도구를 쓰려면 반드시 이 형식의 JSON으로 응답하라"고 시스템 메시지로 강제합니다.
- Structured Output: 최신 API는 아예 "이 schema에 맞는 JSON만 뱉어라"고 강제하는 기능이 있어요(잘못된 JSON이 절대 안 나오게 막아줌).
핵심 깨달음: Tool calling은 마법이 아니라 "잘 정의된 프로토콜 + LLM의 패턴 매칭 능력" 입니다. 백엔드식으로 보면 RPC와 비슷해요.
7. Multi-Agent가 왜 필요할까? Agent 하나면 되는 거 아닌가?
좋은 질문입니다. 처음엔 다 한 Agent로 해보는 게 맞아요. 하지만 일이 복잡해지면 한계가 옵니다.
한 Agent가 모든 걸 다 할 때의 문제점
flowchart TD
A[슈퍼 Agent] --> B[도구 1: 검색]
A --> C[도구 2: 코드 실행]
A --> D[도구 3: 이메일]
A --> E[도구 4: DB 조회]
A --> F[도구 5: 결제]
A --> G[도구 6: 번역]
A --> H[도구 7: ...]
A --> I[도구 50: ...]
- System prompt가 너무 길어짐: 도구 50개 설명을 다 넣으면 매번 수만 토큰을 보내야 함 → 비쌈, 느림.
- 헷갈림: 도구가 많으면 LLM이 잘못된 도구를 고를 확률이 올라감.
- 유지보수 지옥: "이 Agent는 도대체 뭘 하는 애야?" 한 명이 모든 걸 하면 디버깅이 어려움.
Multi-Agent: 회사 조직도처럼 나누기
flowchart TD
U[사용자] --> O[Orchestrator Agent<br/>조율자]
O --> R[Research Agent<br/>리서치 담당]
O --> C[Coder Agent<br/>코딩 담당]
O --> W[Writer Agent<br/>문서 작성 담당]
R --> R1[웹 검색]
R --> R2[논문 검색]
C --> C1[코드 실행]
C --> C2[테스트 실행]
W --> W1[Markdown 생성]
W --> W2[번역]
백엔드 개발자식 비유
- 단일 Agent = God Object (모든 책임을 가진 거대한 클래스)
- Multi-Agent = 마이크로서비스 아키텍처 (각 서비스가 하나의 일만 잘함)
실전 예시: "AI에 대한 블로그 글 써줘"
sequenceDiagram
participant U as 사용자
participant O as Orchestrator
participant R as Research Agent
participant W as Writer Agent
participant E as Editor Agent
U->>O: "AI 에이전트 블로그 글 써줘"
O->>R: "AI Agent 최신 트렌드 조사해줘"
R->>R: 웹 검색, 논문 검색
R->>O: 자료 정리본
O->>W: "이 자료로 초안 써줘"
W->>O: 초안
O->>E: "문법/논리 검토해줘"
E->>O: 수정본
O->>U: 최종 글
언제 Multi-Agent로 가야 하나?
- ✅ 단일 Agent의 system prompt가 너무 길어졌을 때
- ✅ 도구가 명확히 다른 도메인으로 나뉠 때
- ✅ 각 단계를 다른 모델로 쓰고 싶을 때 (예: 리서치는 큰 모델, 단순 변환은 작은 모델)
- ❌ 단순한 task에 굳이 나누지 말 것. 오버엔지니어링 주의.
8. Langchain, 꼭 필요할까? 그냥 API 호출하면 안 되나?
답부터 말하면: 꼭 필요하진 않습니다. 그냥 API 호출로도 충분히 만들 수 있어요.
하지만 "왜 사람들이 Langchain 같은 프레임워크를 쓰는가"를 이해하면 좋습니다.
그냥 API 호출로 Agent 만들기 (Pseudo code)
import anthropic
client = anthropic.Anthropic()
messages = []
tools = [...] # 도구 정의
def run_agent(user_input):
messages.append({"role": "user", "content": user_input})
while True:
response = client.messages.create(
model="claude-opus-4-7",
messages=messages,
tools=tools
)
if response.stop_reason == "tool_use":
tool_call = response.content[-1]
result = execute_tool(tool_call.name, tool_call.input)
messages.append({"role": "assistant", "content": response.content})
messages.append({"role": "user", "content": [
{"type": "tool_result", "tool_use_id": tool_call.id, "content": result}
]})
else:
return response.content[0].text이게 사실상 Agent의 전부예요. 약 30줄 이면 됩니다.
그럼 Langchain은 뭘 해주는데?
- 추상화: OpenAI/Anthropic/Gemini 등을 같은 인터페이스로 쓸 수 있게.
- 유틸리티 모음: 문서 로딩, 청킹, 벡터 DB 연결, 메모리 관리 등 자주 쓰는 걸 미리 만들어 놓음.
- 체인 구성: 여러 단계의 LLM 호출을 파이프라인처럼 엮을 수 있음.
- 콜백/로깅: 어떤 단계에서 무슨 일이 일어났는지 추적.
flowchart LR
subgraph 직접구현[직접 구현]
A1[내가 다 짜야 함]
A2[모델 바꿀 때마다 코드 수정]
A3[메모리/로깅 직접]
end
subgraph 프레임워크[Langchain 등 사용]
B1[추상화 제공]
B2[모델 교체 쉬움]
B3[유틸 풍부]
B4[추상화의 무게 ⚠️]
end
Langchain을 쓰지 않으면 무슨 일이 벌어지나?
좋은 점 ✅
- 코드가 짧고 명확함. "이 줄에서 정확히 뭐가 일어나는지" 안다.
- 디버깅이 쉬움. 모든 게 내 코드.
- 외부 라이브러리 업데이트로 망가질 일 없음.
- 의존성이 적어서 보안/유지보수에 좋음.
불편한 점 ❌
- 자주 쓰는 패턴(메모리, 벡터 검색, 도구 실행 루프)을 직접 짜야 함.
- 여러 모델 지원하려면 어댑터를 만들어야 함.
- 복잡한 워크플로(분기, 병렬)는 직접 설계해야 함.
실전 권장 사항
- 프로토타입/학습 단계: 그냥 SDK(Anthropic SDK 등)로 직접 호출하세요. Agent의 작동 원리를 체감할 수 있습니다.
- 간단한 프로덕션: 직접 호출이 더 명확하고 안정적입니다.
- 복잡한 워크플로/여러 모델 동시 지원: LangGraph, CrewAI, LlamaIndex 같은 프레임워크 검토.
핵심: 프레임워크는 도구일 뿐, 본질을 가리지 마세요. Agent의 원리(LLM + Tool Loop)를 이해하면 어떤 프레임워크를 써도 됩니다.
9. 정리
지금까지 살펴본 내용을 한 장으로 요약하면 다음과 같습니다.
flowchart TD
A[Token<br/>글자 조각] --> B[LLM<br/>다음 토큰 예측기]
C[Transformer<br/>병렬 신경망 구조] --> B
B --> D[Chatbot<br/>LLM + 대화 기록]
D --> E[Agent<br/>Chatbot + Tool 사용 루프]
E --> F[Multi-Agent<br/>여러 Agent의 협력]
F --> I[고도화된 AI 시스템]
핵심 요약 5줄
- LLM은 다음 토큰을 예측하는 통계 기계 입니다.
- 챗봇은 LLM에 대화 기록을 계속 던지는 stateless API 구조 입니다.
- Agent는 챗봇에 "Tool 호출 루프"를 더한 것 입니다.
- Tool calling은 마법이 아니라 LLM이 JSON으로 의도를 전달하면 우리가 대신 실행 해주는 프로토콜입니다.
- Langchain은 편의일 뿐 본질은 아닙니다. 직접 만들 수 있어야 진짜 이해한 거예요.
'개발' 카테고리의 다른 글
| [git] submodule 최신으로 업데이트하기 (0) | 2021.12.07 |
|---|---|
| [git] master 브랜치 빼고 모두 삭제하기 (0) | 2021.09.28 |
| DTO말고 다른 이름은 없을까? (0) | 2021.09.07 |
| [개발] git submodule update (0) | 2021.06.02 |