본 포스팅은 "Do it! LLM을 활용한 AI 에이전트 개발 입문"을 독학하며 쓴 글입니다.
내돈내산 포스팅임을 참고해주시면 감사하겠습니다.
2026년 2월 13일 기준으로 작성되었습니다.
본 포스팅에서는 펑션 콜링에 대해 알아보고 이를 활용하는 코드를 작성해보겠습니다
'요새 코스피 지수가 얼마야?' 또는 '애플 주식을 팔아야 할까 사야 할까?'
이런 대화를 GPT와 하기 위해서는 GPT가 최신 주식 정보를 알 수 있어야 한다
이제부터 yfinance 라는 파이썬 라이브러리를 사용해 미국 주식 정보를 쉽게 가져와서 GPT와 대화해보자
yfinance를 사용하면 주가, 재무제표, 거래량 등 다양한 데이터를 데이터 프레임 형태로 가져올 수 있다
일단 터미널 창에서 yfinance를 설치하도록 하자
pip install yfinance
을 이용하여 가상환경에 yfinance를 설치한다
yfinance.ipynb 파일을 생성한 후 다음과 같은 코드를 실행시켜 보자
- 에러 발생
기본적으로 난 코딩하는 파일들을 바탕화면의 "코딩" 폴더에 넣어놓고 있다
그런데 이렇게 하니까 [Failed to perform, curl: (77) error setting certificate verify locations:] 이런 에러가 발생했다
구글링을 하면서 원인을 찾아보다가 폴더명이 특수문자가 들어가면 이런 경우가 종종 있다고 한다
참고한 링크 : 깃허브
import yfinance as yf
# 마이크로소프트(MSFT)에 대한 Ticker 객체 요청
msft = yf.Ticker("MSFT")
# Ticker 객체의 정보 출력
display(msft.info)

코드를 실행해보니 마이크로소프트의 기본 정보들이 출력된다
이제 최근 5일간의 주가 정보만 확인해보자
여기서 period는 가져올 데이터의 기간을 의미한다
예를들어. 3일간의 데이터는 '3d', 2개월간의 데이터는 '2mo' , 1년간의 데이터는 '1y'로 입력한다
hist = msft.history(period= "5d")
display(hist)

이제 우리는 주가 정보를 데이터프레임의 형태로 확인할 수 있게 되었다!!
이 데이터 프레임에서 각 열의 정보는 아래 표와 같다
| 열 이름 | 설명 |
|---|---|
| Open(시가) | 거래 시작 시점의 주가 |
| High(고가) | 해당 거래일 동안의 최고 가격 |
| Low(저가) | 해당 거래일 동안의 최저 가격 |
| Close(종가) | 해당 거래일 마지막 시점의 주가 |
| Volume(거래량) | 해당 거래일 동안 거래된 주식의 총 수량 |
| Dividends(배당금) | 주식 배당금 |
| Stock Splits(주식 분할) | 해당 거래일에 발생한 주식 분할 비율, 없으면 0으로 표기 |
해당 종목에 대한 애널리스트들의 분석 결과도 찾아볼 수 있다!!
아래 코드는 msft 객체의 recommendations 속성을 표기한다
recommendations yfinance에서 제공하는 속성으로 주식 분석가들이 이 주식에 대해 내린 추천을 포함하는 판다스 데이터프레임을 보여준다
msft.recommendations

사진에서 period는 분석가들이 추천한 시점을 의미한다
0m 은 현재, -1m은 1개월 전을 의미하고 등급은 strongBuy 부터 strongSell까지 총 5등급으로 분류된다
GPT가 최신 주가 정보에 기반해서 답변하도록 하려면 필요한 기능을 함수로 만들어서 펑션 콜링을 활용해야 한다
이전 포스팅에서 만든 gpt_functions.py 파일을 활용해서 회사의 기본 정보와 최신 주가 정보를 가져 오고 투자 의견을 알려 주는 함수를 만들어보자
우선 회사의 기본정보를 가져오는 get_yf_stock_info 함수를 생성하자
# gpt_functions.py
import yfinance as yf
def get_yf_stock_info(ticker : str):
stock = yf.Ticker(ticker)
info = stock.info
print(info)
return str(info)
if __name__ == "__main__":
# get_current_time('America/New_York')
info = get_yf_stock_info('AAPL')
- stock = yf.Ticker(ticker)
정보를 가져올 회사를 선택한다
- return str(info)
.info는 딕션너리 형태로 반환되어서 GPT에 바로 전달할 수 없다
따라서 str(info)를 이용해서 딕셔너리를 string으로 캐스팅해서 전달한다
위의 코드는 애플의 정보를 출력해준다 결과를 확인해보자
되게 복잡하게 다양한 내용이 들어가있는것을 볼 수 있다

이제 get_yf_stock_info 함수의 설명을 tools에 추가해서 GPT에서 이 함수를 사용할 수 있도록 만들어보자
또한 description에 함수의 설명을 적고 ticker는 필수 항목으로 지정한다
tools = [
{
"type" : "function",
"function" :
{"name" : "get_yf_stock_info",
"description" : "해당 종목의 Yahoo Finance 정보를 반환합니다",
"parameters" : {
"type" : "object",
"properties" : {
'ticker' : {
'type' : 'string',
'description' : 'Yahoo Finance 정보를 반환할 종목의 티커를 입력하세요. (예 : AAPL)',
}
},
"required" : ['ticker']
}
}
}
]
그리고 스트림릿에 연결된 GPT에서 get_yf_stock_info 함수를 사용할 수 있도록 지난 포스팅에서 만든 what_time_is_it_streamlit.py 파일에서 코드를 수정해보자
# stock_info_streamlit.py
from gpt_functions import get_current_time, tools, get_yf_stock_info
from openai import OpenAI
from dotenv import load_dotenv
import os
import json # GPT가 JSON 형태의 문자열을 반환할때 읽기 위한 라이브러리
import streamlit as st
load_dotenv()
api_key = os.getenv('OPENAI_API_KEY')
client = OpenAI(api_key = api_key)
def get_ai_response(messages, tools = None):
response = client.chat.completions.create(
model = "gpt-4o",
messages = messages,
tools = tools
)
return response
st.title("💬 Chatbot")
if "messages" not in st.session_state:
st.session_state["messages"] = [
{"role" : "system", "content" : "너는 사용자를 도와주는 상담사야"}
]
for msg in st.session_state.messages:
if msg["role"] == "assistant" or msg["role"] == "user":
st.chat_message(msg["role"]).write(msg["content"])
if user_input := st.chat_input():
st.session_state.messages.append({"role": "user", "content": user_input})
st.chat_message("user").write(user_input)
ai_response = get_ai_response(st.session_state.messages, tools = tools)
ai_message = ai_response.choices[0].message
print(ai_message)
tool_calls = ai_message.tool_calls
if tool_calls:
# 반복문을 이용해서 함수를 차례대로 실행할 수 있도록 함
for tool_call in tool_calls:
tool_name = tool_call.function.name
tool_call_id = tool_call.id
# 추가된 부분
arguments = json.loads(tool_call.function.arguments)
if tool_name == "get_current_time":
st.session_state.messages.append({
"role" : "function",
"tool_call_id" : tool_call_id,
"name" : tool_name,
"content" : get_current_time(timezone = arguments['timezone']), # 함수 실행 결과를 content로 설정
})
## 기존 코드에서 추가된 부분
elif tool_name == "get_yf_stock_info":
st.session_state.messages.append({
"role" : "function",
"tool_call_id" : tool_call_id,
"name" : tool_name,
"content" : get_yf_stock_info(ticker = arguments['ticker']), # 함수 실행 결과를 content로 설정
})
st.session_state.messages.append({"role" : "system", "content" : "이제 주어진 결과를 바탕으로 답변할 차례다"})
ai_response = get_ai_response(st.session_state.messages)
ai_message = ai_response.choices[0].message
st.session_state.messages.append({
"role" : "assistant",
"content" : ai_message.content
})
print("AI\t: " + ai_message.content)
st.chat_message("assistant").write(ai_message.content)
기존의 코드와 달라진 점은
elif tool_name == "get_yf_stock_info":
부분을 추가해서 우리가 만든 get_yf_stock_info도 GPT가 사용할 수 있도록 했다는 점이다
이제 streamlit run (파일명).py 로 코드를 실행하고 질문을 해보자

테슬라에 대해 질문을 하고 이전 포스팅에서 만든 get_current_time 함수도 적절하게 잘 실행하는지 확인하기 위해 테슬라 본사 기준으로 지금 몇시인지도 물어보고 올바르게 대답하는 것을 확인해보았다
물론 이 포스팅을 적고 있는 현재 테슬라의 본사는 텍사스에 위치하는데 이 부분에 대해서는 GPT에서 오류가 난 것 같다
재질문을하니 텍사스의 시간을 다시 알려주긴 함...ㅎㅎ
사용할 함수가 앞으로 점점 많아질것 같으니 미리 코드를 리팩토링해보자
지금까지의 코드에서는 tool_name이 get_current_time인지 get_yf_stock_info 인지에 따라 매번 st.session_state_messages에 추가하는 부분이 반복되었다
하지만 호출하는 함수만 다르고 거의 모든 구조가 비슷하니까 이를 좀 더 간단하게 바꿔보도록 하자
stock_info_streamlit.py 파일에서 if 문 안에서 함수를 실행한 결과를 func_result에 담고
st.session_state_messages에 추가하는 내용은 따로 분리한다
if tool_calls:
# 반복문을 이용해서 함수를 차례대로 실행할 수 있도록 함
for tool_call in tool_calls:
tool_name = tool_call.function.name
tool_call_id = tool_call.id
arguments = json.loads(tool_call.function.arguments)
# 리팩토링된 부분
if tool_name == "get_current_time":
func_result = get_current_time(timezone = arguments['timezone'])
elif tool_name == "get_yf_stock_info":
func_result = get_yf_stock_info(ticker = arguments['ticker'])
st.session_state.messages.append({
"role" : "function",
"tool_call_id" : tool_call_id,
"name" : tool_name,
"content" : func_result,
})
st.session_state.messages.append({"role" : "system", "content" : "이제 주어진 결과를 바탕으로 답변할 차례다"})
ai_response = get_ai_response(st.session_state.messages)
ai_message = ai_response.choices[0].message
if 문을 위와 같이 변경하면 더욱 많은 함수가 추가 되어도 elif 구문만 추가하면 된다는 점이다
이렇게 코드를 리팩토링하면 줄 수도 줄어들고 훨씬 가독성이 좋아진다
같은 방식으로 최근 주가 기록을 가져오는 함수 get_yf_stock_history 와 추천 정보를 가져오는 함수 get_yf_stock_recommendations을 만들어보자
함수들을 모아놓은 gpt_functions.py에서 작업하면 된다
def get_yf_stock_history(ticker : str, period : str):
stock = yf.Ticker(ticker)
history = stock.history(period = period)
history_md = history.to_markdown() #데이터프레임을 마크다운 형식으로 변환
print(history_md)
return history_md
def get_yf_stock_recommendations(ticker : str):
stock = yf.Ticker(ticker)
recommendations = stock.recommendations
recommendations_md = recommendations.to_markdown() #데이터프레임을 마크다운 형식으로 변환
print(recommendations_md)
return recommendations_md
if __name__ == "__main__":
# get_current_time('America/New_York')
# info = get_yf_stock_info('AAPL')
get_yf_stock_history('AAPL', '5d')
print('---------------')
get_yf_stock_recommendations('AAPL')
위와 같이 함수를 추가하고 터미널에서 코드를 실행시켜보자
처음 코드를 실행시키면 tabulate 모듈이 없어서 에러가 발생하는데
pip install tabulate
를 이용해서 라이브러리를 설치하면 정상적으로 코드가 실행된다

이렇게 데이터 프레임을 마크다운 형식으로 바꿔진 것을 터미널에서 확인할 수 있다
이제 추가한 함수 두개를 스트림릿에서 채팅할 때 활용할 수 있도록 tools에 설명을 넣어야 한다
{
"type" : "function",
"function" :
{"name" : "get_yf_stock_history",
"description" : "해당 종목의 Yahoo Finance 주가 정보를 반환합니다",
"parameters" : {
"type" : "object",
"properties" : {
'ticker' : {
'type' : 'string',
'description' : 'Yahoo Finance 주가 정보를 반환할 종목의 티커를 입력하세요. (예 : AAPL)',
},
'period' : {
'type' : 'string',
'description' : 'Yahoo Finance 정보를 반환할 조회할 기간을 입력하세요. (예 : 1d, 5d, 1mo, 1y, 5y)',
}
},
"required" : ['ticker', 'period']
}
}
},
{
"type" : "function",
"function" :
{"name" : "get_yf_stock_recommendations",
"description" : "해당 종목의 Yahoo Finance 추천 정보를 반환합니다",
"parameters" : {
"type" : "object",
"properties" : {
'ticker' : {
'type' : 'string',
'description' : 'Yahoo Finance 추천 정보를 반환할 종목의 티커를 입력하세요. (예 : AAPL)',
}
},
"required" : ['ticker']
}
}
}
해당 코드를 기존의 tools에 추가해보도록 하자
그리고 stock_into_streamlit.py에 get_yf_stock_history와 get_yf_recommendations 도 import 해준다
또한 함수가 추가되었으니 if~elif 구문에 해당 함수들도 추가해준다
# 리팩토링된 부분
if tool_name == "get_current_time":
func_result = get_current_time(timezone = arguments['timezone'])
elif tool_name == "get_yf_stock_info":
func_result = get_yf_stock_info(ticker = arguments['ticker'])
elif tool_name == "get_yf_stock_history":
func_result = get_yf_stock_history(ticker = arguments['ticker'], period = arguments['period'])
elif tool_name == "get_yf_recommendations":
func_result = get_yf_recommendations(ticker = arguments['ticker'])
이제 streamlit run (파일명).py 로 코드를 실행시켜보자


질문을 했을 때 내용은 올바르게 받아왔지만 터미널에서 보이던 표는 스트림릿에서 보이지 않았다
그래서 GPT를 이용해서 어떻게 해결하면 좋을지 물어봤다
우선 gpt_functions.py에서 get_yf_stock_history의 return값을 변경한다
def get_yf_stock_history(ticker : str, period : str):
stock = yf.Ticker(ticker)
history = stock.history(period = period)
history_md = history.to_markdown() #데이터프레임을 마크다운 형식으로 변환
print(history_md)
return history
또한 stock_info_streamlit.py에서 함수 이름이 get_yf_stock_history일 때 처리부분을 아래와 같이 수정한다
elif tool_name == "get_yf_stock_history":
func_result = get_yf_stock_history(ticker = arguments['ticker'],
period = arguments['period'])
#스트림릿에서는 데이터 프레임으로 출력시킴
st.dataframe(func_result)
#GPT에는 마크다운으로 변형시켜서 전달
func_result = func_result.to_markdown()
이렇게 코드를 수정하고 다시 스트림릿을 실행하면 사진과 같이 스트림릿에서도 표를 확인할 수 있다

그리고 해당 주식의 매수를 추천하는지 물어보면....

get_yf_stock_recommendations 함수를 호출하고 알맞게 답변해준다
이렇게 yfinance를 이용해서 미국 주식 정보를 얻어오고 사용하는 방법에 대해 알아보았다
예전에 AI 자동 주식 투자 봇 만들기를 해보려다가 포기한 적이 있었는데
(국내 주식 정보를 다 컴퓨터에 다운로드 받아서 저장하고 하루하루 지날 때 마다 갱신했어야 했는데 DB만 해도 용량이 매우 컸다..)
이런 라이브러리가 있었다면 조금 더 편하게 개발할 수 있었을까 라는 생각이 들었다
다음 포스팅에서는 지금까지와는 관계가 없어보이지만...?
스트림 출력하기를 실습해보려고 한다
(근데 진짜 왜 갑자기 주식 다루다가 스트림 출력하기로 가는걸까)