⚡ AI 인텔리전스 레이더
🧪 전문가반 · 코드로 만드는 AI 엔지니어

19회차 · LLM을 코드로 직접 호출 — 구조화 출력 & 멀티 프로바이더

백두산 (Doosan Baek) · 게시 2026-06-13 · 최종 수정 2026-07-10

이 회차에서 배우는 것

🎯 목표도구·노코드 없이 LLM을 코드로 직접 부르기
🔌 API 직접 호출Anthropic·OpenAI SDK로 요청→응답 다루기
📐 구조화 출력JSON 스키마로 결과를 '항상 같은 틀'로 강제
🔁 멀티 프로바이더환경변수 하나로 두 회사 모델 전환
✅ 완료 기준같은 작업을 2개 프로바이더로, JSON 파싱 성공

18회차에서 외부 API를 코드로 다뤘으니, 이번엔 그 대상이 LLM입니다. 1회차에서 토큰·temperature 같은 개념은 잡았으니, 여기선 그걸 '코드 파라미터'로 직접 만집니다. 만들 것은 '주제 요약기' — 글이나 주제를 넣으면 정해진 JSON 틀로 요약을 돌려줍니다. 이게 20회차 '내 자료로 답하는 챗봇'의 LLM 호출 부품이 됩니다. (AI로 빠르게 짜되, 각 줄이 무엇을 하는지는 내가 안다.)

💸 잠깐 — 이 트랙부터는 'API 종량제'입니다 (비용 주의)

1~3트랙은 ChatGPT Plus·Claude Pro 같은 '정액 구독'이라 아무리 써도 월정액이었죠. 하지만 코드로 직접 부르는 API는 '쓴 만큼 내는' 종량제예요 — 호출 한 번 한 번이 토큰 단위로 과금됩니다. 겁낼 정도는 아니지만(트랙 전체 실습이 보통 책 한 권 값 수준), '모르고 많이 돌리는' 사고는 미리 막아야 합니다.

🧠 먼저 감 — 1회차 개념을 코드 손잡이로

🔌 LLM을 코드로 호출하기

노코드(Make)나 GPTs를 거치지 않고, 내 코드가 직접 모델에 메시지를 보내고 답을 받습니다. 형태는 18회차 API 호출과 똑같아요 — 요청 → 응답 → 값 꺼내기.

  1. pip install anthropic (또는 openai)
  2. .env에 키 저장 → load_dotenv()로 로드 (18회차 그대로)
  3. client.messages.create(...)로 호출 → 응답에서 텍스트만 추출
# llm.py — Anthropic으로 한 번 호출해보기
import os
from dotenv import load_dotenv
from anthropic import Anthropic

load_dotenv()
client = Anthropic(api_key=os.environ['ANTHROPIC_API_KEY'])

res = client.messages.create(
    model='claude-sonnet-4-6',
    max_tokens=300,
    temperature=0,
    messages=[{'role': 'user', 'content': '한국 1인 가구 소비 트렌드를 3줄로 요약해줘'}],
)
print(res.content[0].text)   # 응답에서 텍스트만 꺼내기

📐 구조화 출력 — '항상 같은 틀'로 받기

자유 문장으로 받으면 코드가 파싱하다 깨집니다. '결과를 이 JSON 모양으로 달라'고 강제하면, 다음 단계 코드가 안정적으로 값을 꺼낼 수 있어요. 'AI를 부품으로 쓰는' 모든 코드의 핵심입니다.

  1. 원하는 출력 모양을 JSON 스키마로 정의 (예: title, bullets[], sentiment)
  2. 프롬프트에 '아래 JSON 형식으로만 답하라'고 명시 (또는 tool/structured output 기능 사용)
  3. 받은 문자열을 json.loads로 파싱 → 실패하면 재시도 로직
# 출력 틀을 강제하면 파싱이 안정적이다
SCHEMA_HINT = '''아래 JSON 형식으로만 답하라(설명 금지):
{"title": "...", "bullets": ["...", "..."], "sentiment": "긍정|중립|부정"}'''

msg = f'{SCHEMA_HINT}\n\n원문:\n{text}'
# 호출 후:
import json
data = json.loads(res.content[0].text)   # 이제 dict로 안전하게 사용

🔁 멀티 프로바이더 — 한 코드, 여러 회사

회사마다 SDK는 조금씩 달라도 '메시지 넣고 텍스트 받기'는 같습니다. 얇은 래퍼 함수 하나로 감싸두면, 환경변수만 바꿔 Anthropic·OpenAI를 갈아끼울 수 있어요. 15회차 게이트웨이(LiteLLM)가 하던 일을 작게 직접 만드는 셈입니다.

# provider.py — 환경변수 PROVIDER로 회사 전환
import os

def ask(prompt: str) -> str:
    provider = os.environ.get('PROVIDER', 'anthropic')
    if provider == 'anthropic':
        from anthropic import Anthropic
        c = Anthropic()
        r = c.messages.create(model='claude-sonnet-4-6', max_tokens=300,
                              messages=[{'role': 'user', 'content': prompt}])
        return r.content[0].text
    else:   # openai
        from openai import OpenAI
        c = OpenAI()
        r = c.chat.completions.create(model='gpt-5.5',
                                      messages=[{'role': 'user', 'content': prompt}])
        return r.choices[0].message.content

🔧 만들 것 — 주제 요약기

  1. 주제/텍스트를 입력받아 ask()로 호출
  2. 출력을 JSON 스키마(title·bullets·sentiment)로 강제해 파싱
  3. PROVIDER를 바꿔 두 회사 결과를 같은 코드로 비교

✅ 완료 기준 (체크포인트)

📌 19회차 핵심