Key Takeaways
- Ollama๋ OpenAI API์ ๋์ผํ ํ์์ REST API๋ฅผ `http://localhost:11434/v1`์์ ์ ๊ณตํฉ๋๋ค.
- OpenAI Python ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฌ์ฉ ์: `api_key="openai"`๋ฅผ `api_key="ollama"`๋ก, `base_url="http://localhost:11434/v1"`๋ก ๋ณ๊ฒฝํ๋ฉด ๋ฉ๋๋ค.
- Node.js๋ ๋์ผํ ๋ฐฉ์์ผ๋ก ์ฌ์ฉ ๊ฐ๋ฅํฉ๋๋ค. OpenAI SDK๋ฅผ ์ฌ์ฉํ์ฌ localhost:11434๋ก ์ฐ๊ฒฐํ๋ฉด ๋ฉ๋๋ค.
- OpenAI ํธํ API๋ Ollama, vLLM, LM Studio ๋ชจ๋ ๋์ผํฉ๋๋ค. ์ฝ๋ ๋ณ๊ฒฝ ์์ด ์ ๊ณต์๋ฅผ ์ ํํ ์ ์์ต๋๋ค.
- 2026๋ 5์ ๊ธฐ์ค, ์คํธ๋ฆฌ๋ฐ(ํ ํฐ๋ณ ์๋ต)๊ณผ ํจ์ ํธ์ถ ๋ชจ๋ ์ด API๋ฅผ ํตํด ๋ก์ปฌ ๋ชจ๋ธ์์ ์๋ํฉ๋๋ค.
โก ๋น ๋ฅธ ์ ๋ณด
Ollama API: `http://localhost:11434/v1` โ OpenAI์ `/chat/completions`์ ์์ ํ ๋์ผ
LM Studio API: `http://localhost:1234/v1` โ ๋์ผํ ํ์, ๋ค๋ฅธ ํฌํธ
vLLM API: `http://localhost:8000/v1` โ ํ๋ก๋์ ์์ค ์๋น
์ฝ๋ ๋ณ๊ฒฝ: 2์ค โ `base_url`๊ณผ `api_key`. ๋๋จธ์ง ์ฝ๋๋ ๊ทธ๋๋ก ์ ์ง๋ฉ๋๋ค.
์ง์ ๊ธฐ๋ฅ: ์ฑํ ์์ฑ, ํ ์คํธ ์์ฑ, ์๋ฒ ๋ฉ, ์คํธ๋ฆฌ๋ฐ, ํจ์ ํธ์ถ
์ธ์ฆ: ๊ธฐ๋ณธ์ ์ผ๋ก ์์ โ localhost ์ ๊ทผ๋ง ๊ฐ๋ฅ. ๋คํธ์ํฌ ์ ๊ทผ์ ์ํด์๋ ๋ฆฌ๋ฒ์ค ํ๋ก์๋ฅผ ์ถ๊ฐํ์ธ์.
์ฝ๋ ์์ ๋ชจ๋ธ: Llama 4 Scout (12 GB์์ ์ต๊ณ ํ์ง, MoE) ๋๋ Llama 3.2 3B (๊ฒฝ๋ํ)
OpenAI ํธํ์ด๋ ๋ฌด์์ ์๋ฏธํฉ๋๊น?
OpenAI ํธํ์ด๋ API ์๋ํฌ์ธํธ๊ฐ OpenAI API์ ๋์ผํ ํ์์ผ๋ก ์๋ต์ ๋ฐํํ๋ค๋ ์๋ฏธ์ ๋๋ค. ์ด๋ฅผ ํตํด OpenAI์ฉ์ผ๋ก ๋ง๋ค์ด์ง ๋ชจ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ๋๊ตฌ๊ฐ ๋ค๋ฅธ URL์ ๊ฐ๋ฆฌํค๋ ๊ฒ๋ง์ผ๋ก ๋ก์ปฌ ๋ชจ๋ธ๊ณผ ํจ๊ป ์๋ํ ์ ์์ต๋๋ค. ์ด ํ์ค์ ๊ตฌํ ๋ฐฉ์์์ Ollama vs LM Studio๊ฐ ์ด๋ป๊ฒ ๋ค๋ฅธ์ง ์์๋ณด์ธ์.
์์: OpenAI Python ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ๋ค์๊ณผ ๊ฐ์ด ์์ฒญ์ ๋ณด๋ ๋๋ค:
``` POST /chat/completions { "model": "gpt-4o", "messages": [...], "temperature": 0.7 } ```
Ollama์ API๋ `localhost:11434/v1/chat/completions`์์ ์์ ํ ๋์ผํ ์์ฒญ์ ์์ ํ๋ฉฐ OpenAI ํ์์ผ๋ก ์๋ต์ ๋ฐํํฉ๋๋ค:
``` { "choices": [{"message": {"content": "..."}}], "usage": {"prompt_tokens": 10, "completion_tokens": 20} } ```
ํ์์ด ๋์ผํ๊ธฐ ๋๋ฌธ์ ์๋ก์ด API๋ฅผ ๋ฐฐ์ธ ํ์๋, ์ฝ๋๋ฅผ ๋ค์ ์์ฑํ ํ์๋ ์์ต๋๋ค.
---
๐ ์๊ณ ๊ณ์ จ์ต๋๊น? OpenAI API ํ์์ ๋ชจ๋ LLM API์ ๋น๊ณต์ ํ์ค์ด ๋์์ต๋๋ค. Anthropic(Claude), Google(Gemini), ๊ทธ๋ฆฌ๊ณ ๋ชจ๋ ์ฃผ์ ๋ก์ปฌ ์ถ๋ก ๋๊ตฌ(Ollama, vLLM, LM Studio, llama.cpp)๊ฐ ์ด ํ์์ ์ง์ํฉ๋๋ค. ์ด ํ์์ผ๋ก ์์ฑ๋ ์ฝ๋๋ ์ง์ ํ ์๋ฏธ์์ ์ ๊ณต์์ ๋ ๋ฆฝ์ ์ ๋๋ค. AI ์ ๊ณ๊ฐ ๋ณด์ ํ ๋ฒ์ฉ API์ ๊ฐ์ฅ ๊ฐ๊น์ด ํํ์ ๋๋ค.
Ollama์ API ์๋ํฌ์ธํธ๋ ๋ฌด์์ ๋๊น?
**`ollama serve`๋ฅผ ์คํํ๋ฉด Ollama๊ฐ `http://localhost:11434`์์ REST API๋ฅผ ์์ํฉ๋๋ค.** OpenAI ํธํ ์๋ํฌ์ธํธ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
| Endpoint | URL | Description |
|---|---|---|
| ์ฑํ ์์ฑ | POST http://localhost:11434/v1/chat/completions | OpenAI์ `/chat/completions`์ ์ผ์น |
| ํ ์คํธ ์์ฑ | POST http://localhost:11434/v1/completions | OpenAI์ `/completions`์ ์ผ์น |
| ์๋ฒ ๋ฉ | POST http://localhost:11434/v1/embeddings | ํ ์คํธ๋ฅผ ๋ฒกํฐ๋ก ๋ณํ |
| ๋ชจ๋ธ ๋ชฉ๋ก | GET http://localhost:11434/v1/models | ์ฌ์ฉ ๊ฐ๋ฅํ ๋ชจ๋ธ ๋ชฉ๋ก ์กฐํ |
Python์์ Ollama API๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ(OpenAI ๋ผ์ด๋ธ๋ฌ๋ฆฌ)?
OpenAI ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ค์นํ๊ณ localhost๋ฅผ ๊ฐ๋ฆฌํค๋๋ก ์ค์ ํ๋ฉด ๋ฉ๋๋ค.
๐ ์ ๋ฌธ๊ฐ ํ: `OPENAI_BASE_URL=http://localhost:11434/v1`์ ํ๊ฒฝ ๋ณ์๋ก ์ค์ ํ์ธ์. ๋ง์ ๋๊ตฌ(LangChain, LlamaIndex, aider)๊ฐ ์ด ๋ณ์๋ฅผ ์๋์ผ๋ก ์ฝ์ต๋๋ค. ์ฝ๋๋ฅผ ๋ณ๊ฒฝํ ํ์ ์์ด ํ๊ฒฝ ๋ณ์ ํ๋๋ง ๋ฐ๊ฟ์ OpenAI์ Ollama๋ฅผ ์ ํํ ์ ์์ต๋๋ค.
# 1. Install the OpenAI library
pip install openai
# 2. Connect to Ollama
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:11434/v1",
api_key="ollama" # dummy key; Ollama ignores it
)
# 3. Make a request
response = client.chat.completions.create(
model="llama4:scout", # Best quality on 12 GB VRAM (MoE)
# model="llama3.2:3b", # Lightweight alternative for 8 GB RAM
messages=[
{"role": "user", "content": "What is 2+2?"}
]
)
print(response.choices[0].message.content)Node.js์์ Ollama API๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์?
OpenAI SDK๋ฅผ ์ค์นํ๊ณ ๋ก์ปฌ Ollama ์ธ์คํด์ค์ ์ฐ๊ฒฐํ๋ฉด ๋ฉ๋๋ค.
// 1. Install
npm install openai
// 2. Connect to Ollama
const OpenAI = require("openai").default;
const client = new OpenAI({
baseURL: "http://localhost:11434/v1",
apiKey: "ollama"
});
// 3. Make a request
const response = await client.chat.completions.create({
model: "llama4:scout", // Best quality on 12 GB VRAM
// model: "llama3.2:3b", // Lightweight for 8 GB RAM
messages: [{
role: "user",
content: "What is 2+2?"
}]
});
console.log(response.choices[0].message.content);LM Studio OpenAI ํธํ ์๋ฒ ์ฌ์ฉ๋ฒ(localhost:1234)
**LM Studio๋ `http://localhost:1234/v1`์์ OpenAI ํธํ API๋ฅผ ์ ๊ณตํฉ๋๋ค.** ๋ก์ปฌ ์๋ฒ ํญ์์ ํ์ฑํํ๊ณ ๋ชจ๋ธ์ ๋ถ๋ฌ์จ ํ ์๋ฒ ์์์ ํด๋ฆญํ๋ฉด ๋ฉ๋๋ค. ๋์ผํ Python ๋ฐ Node.js ์ฝ๋๊ฐ LM Studio์์๋ ์๋ํฉ๋๋ค. ํฌํธ๋ง 11434์์ 1234๋ก ๋ณ๊ฒฝํ๋ฉด ๋ฉ๋๋ค.
LM Studio๋ GUI๋ฅผ ํตํด ๋ชจ๋ธ์ ํ์ํ๊ณ ์ฝ๊ฒ ์ ํํ๋ ค๋ ์ฌ์ฉ์์๊ฒ ์ ํฉํฉ๋๋ค. ์คํฌ๋ฆฝํ , ์๋ํ, CI ํ์ดํ๋ผ์ธ์๋ Ollama๊ฐ ๋ ์ ํฉํฉ๋๋ค.
| Platform | Port | Best For | GPU Required |
|---|---|---|---|
| LM Studio | localhost:1234 | GUI ์ฌ์ฉ์, ์๊ฐ์ ๋ชจ๋ธ ๊ด๋ฆฌ | ์๋์ค (CPU ๊ฐ๋ฅ) |
| Ollama | localhost:11434 | ์คํฌ๋ฆฝํ , ์๋ํ, ํ๋ก๋์ | ์๋์ค (CPU ๊ฐ๋ฅ) |
| vLLM | localhost:8000 | ๋ค์ค GPU, ๊ณ ์ฒ๋ฆฌ๋ ์๋ฒ | ๊ถ์ฅ |
# Python: Connect to LM Studio (localhost:1234)
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:1234/v1",
api_key="lm-studio" # any string; LM Studio ignores it
)
response = client.chat.completions.create(
model="llama-3.2-3b-instruct", # exact model name shown in LM Studio
messages=[
{"role": "user", "content": "What is 2+2?"}
]
)
print(response.choices[0].message.content)๋ธ๋ผ์ฐ์ JavaScript์์ Ollama API๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์?
๋ธ๋ผ์ฐ์ ์ธก JavaScript์์ Ollama๋ฅผ ํธ์ถํ๋ ค๋ฉด ๋ธ๋ผ์ฐ์ ์ ์๋ฒ๊ฐ ๊ฐ์ ๋จธ์ ์ ์์ด์ผ ํ๊ฑฐ๋ CORS๋ฅผ ํ์ฉํด์ผ ํฉ๋๋ค. ๋ณด์์์ ์ด์ ๋ก localhost์ ๋ํ ๋ธ๋ผ์ฐ์ ์์ฒญ์ JavaScript๊ฐ localhost์์ ์ ๊ณต๋ ๋๋ง ์๋ํฉ๋๋ค. CORS๋ฅผ ์ํํ๊ฒ ์ฒ๋ฆฌํ๋ ๋ธ๋ผ์ฐ์ ์ฉ UI๋ ์ต๊ณ ์ ๋ก์ปฌ LLM ํ๋ก ํธ์๋๋ฅผ ํ์ธํ์ธ์.
๋ค๋ฅธ IP์ ๋ธ๋ผ์ฐ์ ์์ Ollama๋ฅผ ํธ์ถํด์ผ ํ๋ ๊ฒฝ์ฐ CORS ํ๋ก์๋ฅผ ์ค์ ํ๊ฑฐ๋ ์๋ฒ ์ธก ๋ฏธ๋ค์จ์ด๋ฅผ ์ฌ์ฉํ์ธ์.
// Browser-side JavaScript (if server is localhost:3000, Ollama is localhost:11434)
fetch("http://localhost:11434/v1/chat/completions", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
model: "llama4:scout", // Best quality on 12 GB VRAM
// model: "llama3.2:3b", // Lightweight for 8 GB RAM
messages: [{ role: "user", content: "What is 2+2?" }]
})
})
.then(res => res.json())
.then(data => console.log(data.choices[0].message.content))ํ ํฐ๋ณ ์๋ต ์คํธ๋ฆฌ๋ฐ ๋ฐฉ๋ฒ์?
์คํธ๋ฆฌ๋ฐ์ ์ฌ์ฉํ๋ฉด ์ ์ฒด ์๋ต์ ๊ธฐ๋ค๋ฆฌ์ง ์๊ณ ์์ฑ๋๋ ๋๋ก ํ ํฐ ๋จ์๋ก ์๋ต์ ํ์ํ ์ ์์ต๋๋ค. 2026๋ 5์ ๊ธฐ์ค, ์คํธ๋ฆฌ๋ฐ์ OpenAI ํธํ API๋ฅผ ํตํ ๋ชจ๋ ๋ก์ปฌ ๋ชจ๋ธ์์ ์๋ํฉ๋๋ค.
# Python: streaming example
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:11434/v1",
api_key="ollama"
)
stream = client.chat.completions.create(
model="llama4:scout",
messages=[{"role": "user", "content": "Count to 10"}],
stream=True
)
for chunk in stream:
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)๋ก์ปฌ ๋ชจ๋ธ์์ ํจ์๋ฅผ ํธ์ถํ ์ ์์ต๋๊น?
๋ค, 2026๋ 5์ ๊ธฐ์ค์ผ๋ก OpenAI API๋ฅผ ํตํด ๋ก์ปฌ ๋ชจ๋ธ์์ ํจ์ ํธ์ถ์ด ๊ฐ๋ฅํฉ๋๋ค. ํจ์ ์คํค๋ง๋ฅผ ์ ์ํ๋ฉด ๋ชจ๋ธ์ด ํจ์์ ์ ๋ฌํ ์ธ์๋ก ์๋ตํ ์ ์์ต๋๋ค. ์ด๋ฅผ ํตํด ์ฝ๋ฉ์ ์ํ ์ต๊ณ ์ ๋ก์ปฌ LLM์ด ๋๊ตฌ ์ํ๊ณ์ ํตํฉ๋ ์ ์์ต๋๋ค.
ํจ์ ํธ์ถ ์ง์ ์ฌ๋ถ๋ ๋ชจ๋ธ์ ๋ฐ๋ผ ๋ค๋ฆ ๋๋ค. Llama 4 Scout, Qwen3 8B, Gemma 4 9B, Mistral Small 3.1 ๋ชจ๋ ๋๊ตฌ ํธ์ถ์ ์์ ์ ์ผ๋ก ์ง์ํฉ๋๋ค. Llama 3.3 8B์ Qwen3 7B๋ ์ง์๋ฉ๋๋ค(๋ ๊ฑฐ์). ๋ ์์ ๋ชจ๋ธ(3B)์ ๊ตฌ์กฐํ๋ ๋๊ตฌ ํธ์ถ JSON์ ์์ ์ ์ผ๋ก ์์ฑํ์ง ๋ชปํ ์ ์์ต๋๋ค.
2026๋ ์๋ Model Context Protocol(MCP)์ด ํจ์ ํธ์ถ์ ํ์คํ๋ ๋๊ตฌ ์ฐ๊ฒฐ ๋ ์ด์ด๋ก ํ์ฅํฉ๋๋ค. MCP๋ ๋ชจ๋ ํด๋ผ์ด์ธํธ(Claude Code, Cursor, ์ปค์คํ ์ฑ)๊ฐ ๋จ์ผ ํ๋กํ ์ฝ์ ํตํด ๋ชจ๋ ๋๊ตฌ ์๋ฒ์ ์ฐ๊ฒฐํ ์ ์๊ฒ ํฉ๋๋ค. ์์ ํ์๋ ์์ฒญ๋ณ ๋๊ตฌ ์ ์๋ฅผ ๋์ด์ญ๋๋ค. Ollama๋ ํ์ค OpenAI ํธํ ํจ์ ํธ์ถ API๋ฅผ ํตํด MCP ์คํ์ผ์ ๋๊ตฌ ํธ์ถ์ ์ง์ํฉ๋๋ค. ํ๋ก๋์ ๋๊ตฌ ํตํฉ์ ๊ฒฝ์ฐ MCP๊ฐ ํ์ค์ด ๋๊ณ ์์ผ๋ฉฐ, ์ฌ๊ธฐ์ ํจ์ ํธ์ถ ์์ ๋ ๊ทธ ๊ธฐ๋ฐ์ ๋๋ค.
OpenAI ํธํ API๋ฅผ ๋ก์ปฌ์์ ์ฌ์ฉํ ๋ ๊ตฌ์กฐํ๋ ์ถ๋ ฅ๊ณผ JSON ๋ชจ๋๋ ํด๋ผ์ฐ๋ API์ ๋์ผํ ๋ฐฉ์์ผ๋ก ์๋ํฉ๋๋ค. ๋ก์ปฌ ๋ฐ ํด๋ผ์ฐ๋ ๋ชจ๋ธ์์ ์คํค๋ง ์ค์ ๋ฐ ํ์ ์ ์ด๋ฅผ ์ํด ๊ตฌ์กฐํ๋ ์ถ๋ ฅ ๋ฐ JSON ๋ชจ๋๋ฅผ ์ฐธ์กฐํ์ธ์.
OpenAI ํธํ API๋ ํด๋ผ์ฐ๋ ๋ฒ์ ๊ณผ ๋์ผํ ํ๋กฌํํธ ํ์์ ์์ฉํฉ๋๋ค. ์์คํ ๋ฉ์์ง, ์ฌ์ฉ์ ๋ฉ์์ง, ๊ตฌ์กฐํ๋ ์ถ๋ ฅ์ด ๋ชจ๋ ํฌํจ๋ฉ๋๋ค. ํ๋กฌํํธ ์์ง๋์ด๋ง ๊ธฐ๋ฒ์ ์ ์ฒด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ๋ก์ปฌ API ํธ์ถ์ ์ง์ ์ ์ฉ๋ฉ๋๋ค.
# Example: local model calls a weather function
tools = [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get current weather",
"parameters": {
"type": "object",
"properties": {
"location": {"type": "string"}
}
}
}
}]
response = client.chat.completions.create(
model="llama4:scout",
messages=[{"role": "user", "content": "What is the weather in SF?"}],
tools=tools
)
# Check if model returned a function call
if response.choices[0].message.tool_calls:
call = response.choices[0].message.tool_calls[0]
print(f"Call function: {call.function.name} with {call.function.arguments}")์ง์ญ๋ณ ๋ก์ปฌ LLM OpenAI API
EU / GDPR ๋ฐ AI ๋ฒ: EU ๊ฐ๋ฐ์์ ๊ฒฝ์ฐ Ollama๋ฅผ ๋ก์ปฌ์์ ์คํํ๋ฉด GDPR ์ 5์กฐ ์ค์(๋ฐ์ดํฐ ์ต์ํ)๊ฐ ๋ณด์ฅ๋ฉ๋๋ค. ๋ชจ๋ ์ถ๋ก ์ด ํด๋ผ์ฐ๋ API๋ก์ ๋ฐ์ดํฐ ์ ์ถ ์์ด ๊ธฐ๊ธฐ์์ ์ฒ๋ฆฌ๋ฉ๋๋ค. Ollama๋ MIT ๋ผ์ด์ ์ค๋ก GitHub์์ ๋ค์ด๋ก๋ํ ์ ์์ด EU ๊ท์ ์ค์ ์๊ฑด์ ์ถฉ์กฑํฉ๋๋ค. EU AI ๋ฒ ๊ณ ์ํ ์์คํ ์๋ฌด๋ 2026๋ 8์ 2์ผ๋ถํฐ ์ ์ฉ๋ฉ๋๋ค(Digital Omnibus ๋๊ธฐ ์ค). ๋ก์ปฌ API ์ถ๋ก ์ ๊ธฐ๋ณธ์ ์ผ๋ก GDPR ๋ฐ์ดํฐ ๊ฑฐ์ฃผ ์๊ฑด์ ์ถฉ์กฑํฉ๋๋ค. ๊ธฐ์ ์ ๊ฒฝ์ฐ ๋ฒค๋ ์ข ์์ ์์ ๊ณ ๋ฐ์ดํฐ ๊ฑฐ์ฃผ๋ฅผ ๋ณด์ฅํฉ๋๋ค.
์ผ๋ณธ / APPI: ์ผ๋ณธ์ ๊ฐ์ธ์ ๋ณด๋ณดํธ๋ฒ(APPI)์ ๋ฐ๋ฅด๋ฉด ์จํ๋ ๋ฏธ์ค ๋ชจ๋ธ ์ถ๋ก ์ ํด๋ผ์ฐ๋ ๋ฐ์ดํฐ ์ ์ก ์๊ฑด์ ์ฐํํฉ๋๋ค. Ollama + Qwen3 8B๋ ํ์ค ๊ธฐ์ ๋ ธํธ๋ถ(8 GB RAM)์์ ์คํ ๊ฐ๋ฅํ๋ฉฐ Qwen3 ๋๋น ํฅ์๋ ์ผ๋ณธ์ด ์ง์๊ณผ 30-50 tok/sec ์ง์ฐ ์๊ฐ์ผ๋ก ์ผ๋ณธ์ด ์ฒ๋ฆฌ์ ์ค์๊ฐ ์๋ต ๊ธฐ๋์น๋ฅผ ์ถฉ์กฑํฉ๋๋ค.
์ค๊ตญ / CAC: ์ค๊ตญ ์ฌ์ด๋ฒ๋ณด์๋ฒ(CAC ์ 37์กฐ)์ ๋ฐ๋ฅธ ๋ฐฐํฌ ์ ๋ก์ปฌ ์ถ๋ก ์ด ๋ฐ์ดํฐ ํ์งํ ์๊ฑด์ ์ถฉ์กฑํฉ๋๋ค. Ollama + Qwen3๋ ์ธ๋ถ API ํธ์ถ ์์ด ๋ชจ๋ Linux ๊ธฐ๊ธฐ์์ ์คํ๋ฉ๋๋ค. Qwen3์ ๋ค์ดํฐ๋ธ ์ค๊ตญ์ด ํ ํฌ๋์ด์ ๋ Llama ๋๋น 30-40% ํจ์จ์ ๋์ฌ ๋ก์ปฌ ์ถ๋ก ์ค๋ฒํค๋๋ฅผ ์ค์ ๋๋ค.
๋ก์ปฌ LLM OpenAI API์์ ์์ฃผ ๋ฐ์ํ๋ ์ค์๋?
- API ํค๊ฐ ๋ฌด์๋๋ค๋ ๊ฒ์ ์๋ ๊ฒฝ์ฐ. Ollama๋ ์ธ์ฆํ์ง ์์ผ๋ฏ๋ก `api_key="ollama"`(์์์ ๋ฌธ์์ด ๊ฐ๋ฅ)๊ฐ ํ์ํฉ๋๋ค. ์ค์ ์ธ์ฆ์ ์์ฒญ์ด ์ธํฐ๋ท์ด ์๋ localhost๋ ๋ก์ปฌ ๋คํธ์ํฌ์์ ์จ๋ค๋ ๊ฒ์ ๋๋ค.
- ๋ชจ๋ธ ์ด๋ฆ์ด ์ค์ํ๋ค๋ ๊ฒ์ ์ธ์ํ์ง ๋ชปํ๋ ๊ฒฝ์ฐ. `/chat/completions`๋ฅผ `model="gpt-4"`๋ก ํธ์ถํ์ง๋ง Ollama์ `llama3.2:3b`๋ง ํ๋ง๋์ด ์๋ค๋ฉด ์์ฒญ์ด ์คํจํฉ๋๋ค. `ollama list`์์ ์ ํํ ๋ชจ๋ธ ์ด๋ฆ์ ์ฌ์ฉํ์ธ์.
- Ollama๊ฐ ์ธํฐ๋ท์ด ํ์ํ๋ค๊ณ ๊ฐ์ ํ๋ ๊ฒฝ์ฐ. ๊ทธ๋ ์ง ์์ต๋๋ค. API๋ ์์ ํ ๋ก์ปฌ์ ๋๋ค. ํ์ง๋ง Python ์ฝ๋๊ฐ ๊ธฐ๋ณธ์ ์ผ๋ก OpenAI ์๋ฒ์ ๋จผ์ ์ ๊ทผํ๋ ค ํ๋ฉด ์คํจํฉ๋๋ค. ํญ์ `base_url`์ ๋ช ์์ ์ผ๋ก ์ค์ ํ์ธ์.
- ๋ธ๋ผ์ฐ์ ์์์ CORS ์ค๋ฅ. ๋ธ๋ผ์ฐ์ ์ธก ์คํฌ๋ฆฝํธ์์ Ollama๋ฅผ ํธ์ถํ ๋ CORS ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ฉด ๋ณด์ ์ด์ ๋ก ๋ธ๋ผ์ฐ์ ๊ฐ ์์ฒญ์ ์ฐจ๋จํ ๊ฒ์ ๋๋ค. CORS๋ฅผ ์ฐํํ๋ ์๋ํฐ ๊ธฐ๋ฐ ์๋ฃจ์ ์ VS Code ๋ฐ Cursor๋ก ๋ก์ปฌ LLM ์ฌ์ฉํ๊ธฐ๋ฅผ ์ฐธ์กฐํ์ธ์.
- ์คํธ๋ฆฌ๋ฐ์ ์ํ ๋ stream=True๋ฅผ ์ค์ ํ์ง ์๋ ๊ฒฝ์ฐ. ํ ํฐ๋ณ ์๋ต์ ์ํ๋ค๋ฉด ์์ฒญ์ `stream=True`๋ฅผ ๋ช ์์ ์ผ๋ก ์ค์ ํด์ผ ํฉ๋๋ค. ๊ธฐ๋ณธ๊ฐ์ ์ ์ฒด ์๋ต์ ๊ธฐ๋ค๋ฆฝ๋๋ค.
- ๋ ๋์ ๋ชจ๋ธ์ด ์๋๋ฐ๋ ์์ ์์ `llama3.2:3b`๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ. ๋ง์ ํํ ๋ฆฌ์ผ์ด 8 GB RAM์์ ์คํ๋๊ธฐ ๋๋ฌธ์ ์์ง๋ Llama 3.2 3B๋ฅผ ์ฌ์ฉํฉ๋๋ค. 12+ GB VRAM์ด ์๋ค๋ฉด `llama4:scout`๋ก ์ ํํ์ธ์. ๋์ผํ API ์ฝ๋๋ก ํจ์ฌ ๋์ ํ์ง์ ์ป์ ์ ์์ต๋๋ค. 3B ๋ชจ๋ธ์ API ํตํฉ ํ ์คํธ์ฉ์ผ๋ก๋ง ์ฌ์ฉํ๊ณ ํ๋ก๋์ ์ํฌ๋ก๋์๋ ์ฌ์ฉํ์ง ๋ง์ธ์.
- ๋์ ์์ฒญ์ ์ํด `OLLAMA_NUM_PARALLEL`์ ์ค์ ํ์ง ์๋ ๊ฒฝ์ฐ. ๊ธฐ๋ณธ์ ์ผ๋ก Ollama๋ ํ ๋ฒ์ ํ๋์ ์์ฒญ๋ง ์ฒ๋ฆฌํฉ๋๋ค. ๋ค์ค ์ฌ์ฉ์ ์ฑ์ด๋ ๋ณ๋ ฌ ํ ์คํธ ์ค์ํธ์ ๊ฒฝ์ฐ ๋์ API ํธ์ถ์ ์ฒ๋ฆฌํ๊ธฐ ์ํด `OLLAMA_NUM_PARALLEL=4`(๋๋ ๋ ๋๊ฒ)๋ฅผ ์ค์ ํ์ธ์. ์ด๋ฅผ ์ค์ ํ์ง ์์ผ๋ฉด ์์ฒญ์ด ๋๊ธฐ์ด์ ์์ด๊ณ ์ง์ฐ ์๊ฐ์ด ๊ธ์ฆํฉ๋๋ค.
- ---
- โ ๏ธ ๊ฒฝ๊ณ : Ollama์ API๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์ธ์ฆ์ด ์์ต๋๋ค. ๋คํธ์ํฌ์ ๋ ธ์ถํ๋ฉด(`OLLAMA_HOST=0.0.0.0`) ํด๋น ๋คํธ์ํฌ์ ๋๊ตฌ๋ ์์ฒญ์ ๋ณด๋ด๊ณ , ๋ชจ๋ธ์ ๋ถ๋ฌ์ค๊ณ , GPU ๋ฆฌ์์ค๋ฅผ ์๋นํ ์ ์์ต๋๋ค. ๋ค์ค ์ฌ์ฉ์ ๋๋ ํ๋ก๋์ ์ค์ ์ ๊ฒฝ์ฐ ์ธ์ฆ์ด ์๋ ๋ฆฌ๋ฒ์ค ํ๋ก์(nginx, Caddy)๋ฅผ Ollama ์์ ๋ฐฐ์นํ์ธ์. ํฌํธ 11434๋ฅผ ์ธํฐ๋ท์ ์ง์ ๋ ธ์ถํ์ง ๋ง์ธ์.
๋ก์ปฌ LLM API์ ๊ดํ ์์ฃผ ๋ฌป๋ ์ง๋ฌธ
Ollama๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด OpenAI ์ฝ๋๋ฅผ ์์ ํด์ผ ํฉ๋๊น?
์๋์. `base_url="http://localhost:11434/v1"`์ `api_key="ollama"`๋ฅผ ์ค์ ํ๋ฉด ๋ฉ๋๋ค. ๋๋จธ์ง๋ ๊ทธ๋๋ก ์ ์ง๋ฉ๋๋ค. OpenAI ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ ์ฝ๋๊ฐ ์๋ค๋ฉด ์ด ๋ ์ค์ ๊ต์ฒดํ๋ฉด ๋ก์ปฌ ๋ชจ๋ธ์์ ์๋ํฉ๋๋ค.
๋คํธ์ํฌ์ ๋ค๋ฅธ ์ปดํจํฐ์์ API๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๊น?
๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก Ollama๋ localhost์์๋ง ์์ ํฉ๋๋ค. ๋คํธ์ํฌ ์ ๊ทผ์ ํ์ฉํ๋ ค๋ฉด Ollama๋ฅผ ์คํํ๊ธฐ ์ ์ ํ๊ฒฝ ๋ณ์ `OLLAMA_HOST=0.0.0.0:11434`๋ฅผ ์ค์ ํ์ธ์. ๊ทธ๋ฐ ๋ค์ ์ฝ๋์์ `http://<machine-ip>:11434/v1`๋ก ์ฐ๊ฒฐํ๋ฉด ๋ฉ๋๋ค. ๋ณด์์ ์ฃผ์ํ์ธ์. ํ๋ก๋์ ํ๊ฒฝ์ด๋ผ๋ฉด ๋ฐฉํ๋ฒฝ์ ์ฌ์ฉํ์ธ์.
LM Studio์๋ OpenAI ํธํ API๊ฐ ์์ต๋๊น?
๋ค. LM Studio๋ `http://localhost:1234/v1`์์ OpenAI ํธํ API๋ฅผ ์ ๊ณตํฉ๋๋ค. ๋ก์ปฌ ์๋ฒ ํญ์์ ํ์ฑํํ๊ณ ๋ชจ๋ธ์ ๋ถ๋ฌ์จ ํ ์๋ฒ ์์์ ํด๋ฆญํ์ธ์. Ollama์ ๋์ผํ Python ๋๋ Node.js ์ฝ๋๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฉ๋๋ค. ํฌํธ๋ง 11434์์ 1234๋ก ๋ณ๊ฒฝํ๋ฉด ๋ฉ๋๋ค.
์ฌ๋ฌ ๋ชจ๋ธ์ ๋์์ ํธ์ถํ ์ ์์ต๋๊น?
Ollama์ ๋ก๋๋์ด ์๋ค๋ฉด ๊ฐ๋ฅํฉ๋๋ค. ํ์ง๋ง ๋ ๋ชจ๋ธ์ ๋์์ ์คํํ๋ฉด VRAM ์ฌ์ฉ๋์ด ๋ ๋ฐฐ๊ฐ ๋ฉ๋๋ค. ์ถฉ๋ถํ GPU ๋ฉ๋ชจ๋ฆฌ๊ฐ ์์ด์ผ ํฉ๋๋ค.
API์ ์ธ์ฆ์ด ์์ต๋๊น?
์๋์. ๊ธฐ๋ณธ์ ์ผ๋ก Ollama API์๋ ์ธ์ฆ์ด ์์ต๋๋ค. localhost:11434์ ์ ๊ทผํ ์ ์๋ ๋๊ตฌ๋ ์ฌ์ฉํ ์ ์์ต๋๋ค. ๋คํธ์ํฌ ์ ๊ทผ์ด ์๋ ํ๋ก๋์ ํ๊ฒฝ์์๋ ๋ฆฌ๋ฒ์ค ํ๋ก์(nginx Basic Auth ๋ฑ)๋ฅผ ํตํด ์ธ์ฆ์ ์ถ๊ฐํ์ธ์.
Ollama OpenAI API์์ ์คํธ๋ฆฌ๋ฐ์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์?
OpenAI ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํธ์ถ์์ stream=True๋ฅผ ์ค์ ํ์ธ์. Ollama๋ ๊ฐ ํ ํฐ๊ณผ ํจ๊ป ์๋ฒ ์ ์ก ์ด๋ฒคํธ(SSE)๋ฅผ ๋ฐํํฉ๋๋ค. Python์์: for chunk in client.chat.completions.create(stream=True, ...): print(chunk.choices[0].delta.content).
Ollama๊ฐ API๋ฅผ ํตํ ํจ์ ํธ์ถ/๋๊ตฌ ์ฌ์ฉ์ ์ง์ํฉ๋๊น?
๋ค, ์ง์ํ๋ ๋ชจ๋ธ์์ ๊ฐ๋ฅํฉ๋๋ค(Llama 4 Scout, Qwen3 8B, Gemma 4 9B, Mistral Small 3.1). ๋ ๊ฑฐ์ ๋ชจ๋ธ(Llama 3.3 8B, Qwen3 7B)๋ ์ง์๋ฉ๋๋ค. OpenAI์ ๋์ผํ๊ฒ API ํธ์ถ์ tools=[]๋ฅผ ์ ๋ฌํ๋ฉด ๋ฉ๋๋ค. Ollama๋ ๋๊ตฌ ํธ์ถ์ ํ์ฑํ๊ณ ๊ตฌ์กฐํ๋ JSON์ ๋ฐํํฉ๋๋ค. ๋ชจ๋ ๋ชจ๋ธ์ด ์ด๋ฅผ ์ง์ํ๋ ๊ฒ์ ์๋๋ฏ๋ก ๋ชจ๋ธ ๋ฌธ์๋ฅผ ํ์ธํ์ธ์.
MCP๋ ๋ฌด์์ด๋ฉฐ OpenAI ํธํ API์ ์ด๋ค ๊ด๊ณ๊ฐ ์์ต๋๊น?
MCP(Model Context Protocol)๋ AI ๋ชจ๋ธ์ ์ธ๋ถ ๋๊ตฌ ๋ฐ ๋ฐ์ดํฐ ์์ค์ ์ฐ๊ฒฐํ๊ธฐ ์ํ ํ์คํ๋ ํ๋กํ ์ฝ์ ๋๋ค. ํจ์ ํธ์ถ ์์ ๊ตฌ์ถ๋ฉ๋๋ค. ์ ์์ ์ ๋์ผํ `tools=[]` ๋งค๊ฐ๋ณ์๋ฅผ ์ฌ์ฉํ์ง๋ง ํ์ค ์๋ฒ-ํด๋ผ์ด์ธํธ ์ํคํ ์ฒ๋ฅผ ์ถ๊ฐํ์ฌ ๋๊ตฌ๋ฅผ ๋ฐ๊ฒฌ ๊ฐ๋ฅํ๊ณ ์ ํ๋ฆฌ์ผ์ด์ ๊ฐ์ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ๊ฒ ํฉ๋๋ค. Ollama๋ OpenAI ํธํ ํจ์ ํธ์ถ ์๋ํฌ์ธํธ๋ฅผ ํตํด MCP ์คํ์ผ ๋๊ตฌ ์ํธ ์์ฉ์ ์ง์ํฉ๋๋ค. ๊ฐ๋จํ ํตํฉ์ ๊ฒฝ์ฐ ์ด ๋ฌธ์์ ํจ์ ํธ์ถ ์์ ๋ก ์ถฉ๋ถํฉ๋๋ค. ๋ณต์กํ ๋ค์ค ๋๊ตฌ ์ํฌํ๋ก์ ๊ฒฝ์ฐ MCP๊ฐ ๋ ๊ตฌ์กฐํ๋ ์ ๊ทผ ๋ฐฉ์์ ์ ๊ณตํฉ๋๋ค.
Ollama /api/generate์ /v1/chat/completions์ ์ฐจ์ด์ ์?
/api/generate๋ Ollama์ ๋ค์ดํฐ๋ธ ๋จ์ผ ํด ์๋ํฌ์ธํธ์ ๋๋ค. /v1/chat/completions๋ OpenAI ํธํ ๋ค์ค ํด ์๋ํฌ์ธํธ์ ๋๋ค. ๋ชจ๋ ์ ํ๋ก์ ํธ์์๋ /v1/chat/completions๋ฅผ ์ฌ์ฉํ์ธ์. ๋ํ ๊ธฐ๋ก์ ์ง์ํ๋ฉฐ OpenAI ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ํธํ๋ฉ๋๋ค.
vLLM์ OpenAI ํธํ API๋ก ์ฌ์ฉํ ์ ์์ต๋๊น?
๋ค. vLLM์ ๊ธฐ๋ณธ์ ์ผ๋ก http://localhost:8000/v1์์ OpenAI ํธํ ์๋ฒ๋ฅผ ์คํํฉ๋๋ค. ๋ค์ ๋ช ๋ น์ผ๋ก ์์ํ์ธ์: python -m vllm.entrypoints.openai.api_server --model mistralai/Mistral-7B-v0.1. Ollama์ ๋์ผํ ํด๋ผ์ด์ธํธ ์ฝ๋๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฉ๋๋ค.
Node.js openai ํจํค์ง๋ก Ollama API๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์?
openai์์ OpenAI๋ฅผ ๊ฐ์ ธ์ค์ธ์. ์์ฑ์์์ baseURL: "http://localhost:11434/v1"๊ณผ apiKey: "ollama"๋ฅผ ์ค์ ํ์ธ์. ๊ทธ๋ฐ ๋ค์ ์ค์ OpenAI API์ ๋์ผํ๊ฒ client.chat.completions.create()๋ฅผ ํธ์ถํ๋ฉด ๋ฉ๋๋ค. ๋ค๋ฅธ ๋ณ๊ฒฝ์ด ํ์ ์์ต๋๋ค.
๋์ผํ ์ฝ๋๋ฒ ์ด์ค์์ Ollama์ OpenAI๋ฅผ ์ด๋ป๊ฒ ์ ํํฉ๋๊น?
ํ๊ฒฝ ๋ณ์๋ฅผ ์ฌ์ฉํ์ธ์. Ollama์ ๊ฒฝ์ฐ USE_LOCAL=true๋ฅผ ์ค์ ํ๊ณ (base_url http://localhost:11434/v1, api_key "ollama"), OpenAI์ ๊ฒฝ์ฐ USE_LOCAL=false๋ฅผ ์ค์ ํฉ๋๋ค. OpenAI Python ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์์ฑ์ ์ธ์๋ก base_url์ ์์ฉํฉ๋๋ค. ํ๋ก๋์ ์์ USE_LOCAL=false๋ก ์ค์ ํ๋ฉด ๋ค๋ฅธ ์ฝ๋๋ฅผ ๋ณ๊ฒฝํ์ง ์๊ณ ๋ OpenAI๋ก ์ ํ๋ฉ๋๋ค.
LangChain๊ณผ ํจ๊ป OpenAI ํธํ API๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๊น?
๋ค. base_url="http://localhost:11434/v1"๊ณผ api_key="ollama"๋ฅผ ์ฌ์ฉํ์ฌ ChatOpenAI๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฉ๋๋ค. ์ด๋ฅผ ํตํด Ollama๊ฐ ๋ชจ๋ LangChain ํ์ดํ๋ผ์ธ์์ OpenAI์ ๋๋กญ์ธ ๋์ฒดํ์ด ๋ฉ๋๋ค. RAG ์ฒด์ธ, ์์ด์ ํธ, ๋๊ตฌ ๋ชจ๋ ์์ ์์ด ์๋ํฉ๋๋ค. LangChain์๋ Ollama ์ ์ฉ ๊ธฐ๋ฅ์ ์ํ ์ ์ฉ ChatOllama ํด๋์ค๋ ์์ต๋๋ค.
์ถ์ฒ
- Ollama. (2026). "Ollama OpenAI Compatibility." https://github.com/ollama/ollama/blob/main/docs/openai.md -- Ollama์ OpenAI ํธํ REST API ์๋ํฌ์ธํธ์ ๋ํ ๊ณต์ ๋ฌธ์.
- LM Studio. (2026). "LM Studio Local Server." https://lmstudio.ai/docs/local-server -- localhost:1234์ LM Studio OpenAI ํธํ ๋ก์ปฌ ์๋ฒ ๋ฌธ์.
- OpenAI. (2024). "OpenAI Python Library." https://github.com/openai/openai-python -- base_url ์ฌ์ ์๋ฅผ ํตํด OpenAI์ ๋ก์ปฌ LLM ๋ชจ๋์ ์ฐ๊ฒฐํ๋ ๋ฐ ์ฌ์ฉ๋๋ ๊ณต์ Python SDK.
- vLLM Team. (2024). "vLLM OpenAI-Compatible Server." https://docs.vllm.ai/en/latest/serving/openai_compatible_server.html -- vLLM์ OpenAI ํธํ API ์๋ฒ ๋ฌธ์(ํฌํธ 8000, ํ๋ก๋์ ์ฌ์ฉ).