AI 개발 독학 4주 - 2주차 데이터 다루기와 LLM API

타리스만에서는 유익한 AI 기술을 전달합니다
제휴 링크로 판매시 수수료를 제공받습니다

1주차에서는 파이썬 기초 문법을 익혔습니다. 변수와 조건문, 반복문은 데이터를 다루기 위한 최소한의 도구예요.

이번 주에는 두 가지 핵심을 다룹니다. 첫째, 딕셔너리와 JSON, 엑셀처럼 실제로 자주 만나는 데이터를 구조적으로 다루는 방법이에요. 둘째, 챗봇 화면이 아니라 코드로 LLM을 호출하는 API 사용법입니다. 표로 된 데이터를 자동으로 요약하거나 특정 항목을 뽑아내는 작업을 자동화하려면, API 호출 구조를 이해해 두는 것이 큰 도움이 됩니다.

이번 주 목표

중첩 딕셔너리와 JSON을 자유롭게 읽고 다룹니다. LLM chat completions API의 요청과 응답 구조를 이해합니다. 표로 된 데이터를 읽기 쉬운 요약 문장으로 바꾸는 프롬프트를 직접 설계해 봅니다.

이번 주 계획

요일학습 내용시간
딕셔너리·JSON 심화1시간
엑셀 데이터 처리 (pandas 개념, 집PC 실습)1시간
LLM chat completions 구조 (messages, 역할, temperature, max_tokens)1.5시간
프롬프트 설계 및 구조화 출력 (JSON 강제)1.5시간
표→보고서 요약 실습1시간
토·일주말 프로젝트: 신청서 필드 추출기3시간
시간 없으면 이것만

LLM API의 messages 구조를 이해하고, 데이터 분석용 '좋은 프롬프트'를 하나 작성해 봅니다. 브라우저에서 JSON 파싱 위젯을 실행해 데이터 추출 흐름을 확인해 보세요.

중첩 딕셔너리와 JSON 심화

하나의 장바구니에는 여러 상품이 담깁니다. 장바구니 정보 안에 상품 리스트가 들어 있는 중첩 구조를 순회하면서 전체 금액을 합산해 볼게요.

import json
cart = {"name": "이번 주 장보기", "items": [{"name": "우유", "price": 2500}, {"name": "달걀", "price": 4000}]}
total = 0
for item in cart["items"]:
    total += item["price"]
cart["total"] = total
print(json.dumps(cart, ensure_ascii=False, indent=2))

API 요청과 응답은 모두 JSON 문자열 형태입니다. 파이썬 딕셔너리는 json.dumps()로 JSON 문자열로 직렬화하고, 받은 JSON 문자열은 json.loads()로 다시 딕셔너리로 되돌립니다. 이 변환 과정이 API 통신의 핵심이에요.

pandas로 엑셀 읽기

집 PC에서

브라우저 위젯에서는 무거운 pandas 라이브러리를 실행할 수 없어요. 집 PC의 파이썬 환경에서 다음 코드로 엑셀 데이터를 읽어, 카테고리별 평균 금액을 계산해 봅니다.

import pandas as pd

df = pd.read_excel("expenses.xlsx")
avg = df.groupby("카테고리")["금액"].mean()
print(avg)

LLM chat completions 구조

LLM API는 대화 기록을 messages 배열로 받습니다. system은 AI의 역할과 규칙을, user는 사용자의 질문을, assistant는 AI의 이전 답변을 의미해요. temperature는 0에 가까울수록 일관된 답변을 만들어 내므로, 정확한 정보 추출이 필요할 때는 0.1~0.2를 권장합니다. max_tokens는 응답의 최대 길이를 제한해요. API 응답 JSON에서 실제 답변은 choices[0]["message"]["content"] 경로에 들어 있습니다.

집 PC에서

API 키가 필요하므로 로컬 환경에서 실행합니다. 알리바바 Qwen처럼 OpenAI 호환 엔드포인트를 사용하는 예시예요. YOUR_API_KEY를 본인 키로 바꿔서 실행해 보세요.

import requests
import json

url = "https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions"
headers = {
    "Authorization": "Bearer YOUR_API_KEY",
    "Content-Type": "application/json"
}
payload = {
    "model": "qwen-plus",
    "messages": [{"role": "user", "content": "이번 달 지출 내역을 3가지로 요약해."}],
    "temperature": 0.2
}
response = requests.post(url, headers=headers, json=payload)
print(response.json()["choices"][0]["message"]["content"])

메시지 구조를 코드로 조립하기

API에 보낼 요청 몸통(payload)을 파이썬 코드로 만들어 봅니다. 실제 전송은 하지 않고 구조만 확인해 볼게요.

import json
system_msg = {"role": "system", "content": "너는 데이터 분석 전문가다."}
user_msg = {"role": "user", "content": "이번 달 지출에서 줄일 수 있는 항목은?"}
payload = {
    "model": "qwen-plus",
    "messages": [system_msg, user_msg],
    "temperature": 0.1,
    "max_tokens": 500
}
print(json.dumps(payload, ensure_ascii=False, indent=2))

프롬프트 설계 기본

좋은 프롬프트에는 역할 지정, 구체적인 지시, 출력 형식 명시, 예시(few-shot) 제공, 낮은 온도 설정이 담겨 있습니다. 모호한 지시는 AI의 환각을 유발하기 쉬워요.

구분프롬프트 예시
나쁜 프롬프트이 표 요약해 줘.
좋은 프롬프트너는 데이터 분석가다. 아래 표에서 변동률이 5% 이상인 항목만 추출하고, 각 항목의 변동 원인을 1문장으로 추정해. 결과는 JSON 배열로만 출력해.

구조화 출력(JSON 강제)

LLM에게 "반드시 JSON 형식으로만 출력하라"고 지시하면, 결과를 코드로 바로 파싱해서 데이터베이스에 저장하거나 다음 단계로 넘길 수 있습니다.

import json
llm_response = '{"item": "노트북", "price": 450, "status": "승인"}'
data = json.loads(llm_response)
if data["price"] > 400:
    print(f"{data['item']} 예산 초과, 재검토 필요")
주의

LLM이 JSON 앞뒤에 "네, 결과는 다음과 같습니다." 같은 군더더기를 붙이면 json.loads() 파싱이 깨질 수 있어요. 프롬프트에서 "JSON만 출력하라"고 분명히 지시하고, 코드 쪽에서도 정규식으로 JSON 부분만 뽑아내는 검증 로직을 함께 두는 것이 안전합니다.

표를 보고서로 요약하기

마크다운 표를 LLM에게 주고 3줄 요약을 요청할 수 있습니다. 집 PC의 Qwen API에서 temperature를 0.2로 설정해 다음 프롬프트를 실행해 보세요.

[입력 표]

항목지난달 금액이번달 금액변동률
식비300280-6.6%
교통비5055+10.0%

[프롬프트]
"위 금액 변동 표를 바탕으로 3줄 요약을 작성해. 변동률이 가장 큰 항목을 중심으로 원인을 추정해."

  • temperature를 0.2와 1.0으로 변경하며 응답의 일관성을 비교한다.
  • max_tokens를 20으로 제한해 응답이 중간에 잘리는 현상을 관찰한다.

주말 미니프로젝트 — 신청서 필드 추출기

정규식(re)을 사용해 자유 형식 텍스트에서 원하는 필드를 뽑아내 봅니다. 정해진 양식이 없는 글을 구조화된 데이터로 바꾸는 기본기예요.

import re
import json
text = """이름: 홍길동
지역: 서울
신청 항목: 세미나실 대여
변경 사항: (As-is) 3시간 → (To-be) 5시간"""
result = {}
for line in text.split('\n'):
    match = re.search(r'(.+?):\s*(.+)', line)
    if match:
        result[match.group(1).strip()] = match.group(2).strip()
change = re.search(r'\(As-is\)\s*(.+?)\s*→\s*\(To-be\)\s*(.+)', text)
if change:
    result["변경전"] = change.group(1)
    result["변경후"] = change.group(2)
print(json.dumps(result, ensure_ascii=False, indent=2))
실무 응용

이렇게 규칙 기반(정규식)만으로도 자유 형식 텍스트에서 필요한 필드를 안정적으로 뽑아낼 수 있습니다. 신청서, 주문 내역, 설문 응답처럼 형식이 어느 정도 일정한 텍스트라면 LLM 없이도 순수 규칙엔진으로 충분히 자동화할 수 있어요. 특히 "(As-is) X → (To-be) Y" 같은 변경 전후 패턴을 뽑아내는 작업은 정규식이 아주 잘 어울립니다. 규칙으로 풀 수 있는 부분은 규칙에 맡기고, 판단이 필요한 부분에만 LLM을 쓰는 것이 비용과 안정성 모두에 유리합니다.

자가 체크리스트

  • 중첩 딕셔너리에서 for문을 사용해 내부 리스트의 값을 합산할 수 있다.
  • LLM API의 messages 배열에서 system, user, assistant의 역할을 설명할 수 있다.
  • 프롬프트를 작성할 때 역할 지정, 구체적 지시, 출력 형식 명시 3요소를 포함한다.
  • LLM이 반환한 JSON 문자열을 json.loads()로 파싱해 특정 필드 값을 조건문으로 검증한다.
  • 정규식을 사용해 비정형 텍스트에서 라벨과 값을 분리해 딕셔너리로 구조화한다.
  • temperature와 max_tokens 파라미터가 LLM 응답에 미치는 영향을 이해한다.
안전하게 쓰기

LLM API를 실무에 쓸 때 가장 중요한 원칙 하나는 민감한 데이터의 취급입니다. 개인정보나 대외비 자료를 외부 LLM 서비스에 그대로 보내는 것은 위험할 수 있어요. 안전하게 쓰려면, 먼저 외부에 보내도 되는 데이터인지 분류하고, 민감한 값은 가리거나(마스킹) 규칙 기반 처리로 대체하며, 꼭 필요한 최소한의 정보만 프롬프트에 담는 습관을 들이는 것이 좋습니다. 규칙으로 풀 수 있는 일은 규칙엔진에 맡기고, 자연어 판단이 필요한 부분에만 LLM을 호출하도록 설계하면 비용과 보안을 모두 챙길 수 있습니다.

이번 주 용어

용어설명
JSONJavaScript Object Notation. 경량의 데이터 교환 형식.
직렬화(serialize)파이썬 딕셔너리 등 객체를 JSON 문자열로 변환하는 과정.
APIApplication Programming Interface. 소프트웨어 간 통신 규약.
엔드포인트API 요청을 보내는 특정 URL 주소.
헤더/인증(Bearer)API 요청 시 신원을 증명하기 위해 HTTP 헤더에 포함하는 토큰 정보.
chat completionsOpenAI 호환 LLM API에서 대화형 텍스트 생성을 담당하는 엔드포인트.
system/user 메시지system은 AI의 전역 규칙, user는 사용자의 입력을 나타내는 메시지 역할.
temperatureLLM 응답의 무작위성을 조절하는 파라미터. 0에 가까울수록 일관됨.
max_tokensLLM이 생성할 응답의 최대 토큰(길이) 제한.
토큰LLM이 텍스트를 처리하는 최소 단위. 단어 또는 단어의 일부.
프롬프트LLM에게 작업을 지시하는 입력 텍스트.
few-shot프롬프트에 입력-출력 예시를 몇 개 제공해 AI의 응답 형식을 유도하는 기법.
구조화 출력LLM에게 JSON 등 특정 포맷으로만 답변하도록 강제하는 것.
정규식(regex)문자열에서 특정 패턴을 검색하거나 추출하기 위한 형식 언어.

3주차에서는 RAG(검색 증강 생성)를 다룹니다. 문서를 검색해 LLM에 근거로 넣어 주는 구조를 배우고, 긴 문서를 제목(H2) 단위로 잘라 메타데이터로 검색을 제어하는 방법을 하나씩 살펴봅니다.

댓글 남기기