GPT-5의 새로운 Freeform Tool Calling 기능으로 복잡한 JSON 구조 없이 Python 스크립트, SQL 쿼리, 설정 파일을 직접 외부 도구에 전송할 수 있게 되었습니다. 이제 AI가 개발자처럼 자연스럽게 코드를 작성하고 실행할 수 있어요.

기존 Tool Calling의 답답한 현실
지금까지 AI가 외부 도구와 소통하려면 모든 것을 JSON으로 포장해야 했습니다. 간단한 계산 하나에도 이런 복잡한 구조가 필요했죠:
{
"function_name": "code_executor",
"parameters": {
"language": "python",
"code": "import math\nradius = 5\narea = math.pi * radius**2\nprint(area)",
"timeout": 30
}
}
이런 방식은 여러 문제가 있었어요:
- 복잡한 스키마 설계: 매번 정확한 JSON 구조를 정의해야 함
- 에러 발생률 높음: 작은 형식 오류로도 전체 시스템 중단
- 가독성 저하: 실제 코드가 문자열 안에 숨겨져 보기 어려움
- 유지보수 부담: 스키마 변경 시 전체 시스템 수정 필요
Freeform Tool Calling의 혁신적 변화
GPT-5의 새로운 접근법은 놀랍도록 간단합니다. 위의 복잡한 JSON 대신 이렇게 하면 되거든요:
import math
radius = 5
area = math.pi * radius**2
print(area)
그냥 순수한 Python 코드 그 자체를 전송하는 거예요. 어떤 래핑도, 이스케이핑도, 복잡한 구조도 필요 없습니다.
핵심 특징
1. Raw Text 전송
- Python 스크립트, SQL 쿼리, 설정 파일을 원본 그대로 전송
- JSON 구조화나 이스케이핑 불필요
- 도구가 기대하는 정확한 형식으로 코드 생성
2. 활용 영역
- 코드 샌드박스: Python, C++, Java 등 다양한 언어
- 데이터베이스: SQL 쿼리 직접 실행
- 시스템 환경: Shell 명령어 실행
- 설정 관리: YAML, JSON, XML 등 설정 파일 생성
3. 제약사항
- 병렬 도구 호출 불가 (한 번에 하나씩만)
- 커스텀 도구만 지원 (
"type": "custom"
)
실제 구현 방법
OpenAI Cookbook의 예제를 따라 실제로 어떻게 구현하는지 살펴보겠습니다.
기본 설정
from openai import OpenAI
client = OpenAI()
# Freeform Tool 정의
tools = [
{
"type": "custom",
"name": "code_exec_python",
"description": "Python 코드를 실행합니다"
}
]
여기서 핵심은 "type": "custom"
입니다. 이것이 GPT-5에게 “이 도구는 JSON이 아닌 순수한 텍스트를 받는다”고 알려주는 신호거든요.
실제 사용 예시
response = client.responses.create(
model="gpt-5-mini",
input="딸기(strawberry)에서 'r' 개수만큼 반지름을 가진 원의 넓이를 계산해주세요",
text={"format": {"type": "text"}},
tools=tools
)
GPT-5가 생성한 실제 코드를 보면:
# GPT-5가 직접 생성한 코드
import math
r = "strawberry".count('r')
area = math.pi * r**2
{"radius": r, "area": area, "area_exact": f"{r}*pi"}
JSON 래핑 없이 순수한 Python 코드가 그대로 나왔네요! 사람이 작성한 것과 다를 바 없습니다.
다중 언어 지원의 실제 위력
OpenAI Cookbook의 흥미로운 예제를 살펴보겠습니다. GPT-5에게 “같은 배열을 Python, C++, Java로 각각 10번씩 정렬하고 시간을 측정해줘”라고 요청했더니 어떤 일이 일어났을까요?
Python 버전
import time
import random
arr = [448, 986, 255, 884, 632, ...] # 100개 숫자
for i in range(10):
test_arr = arr.copy()
start_time = time.perf_counter()
test_arr.sort()
end_time = time.perf_counter()
print(f"정렬 {i+1}: {(end_time - start_time) * 1000:.3f}ms")
C++ 버전
#include <iostream>
#include <vector>
#include <algorithm>
#include <chrono>
int main() {
std::vector<int> arr = {448, 986, 255, 884, 632, ...};
for(int i = 0; i < 10; i++) {
auto test_arr = arr;
auto start = std::chrono::high_resolution_clock::now();
std::sort(test_arr.begin(), test_arr.end());
auto end = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
std::cout << "정렬 " << (i+1) << ": " << duration.count()/1000.0 << "ms" << std::endl;
}
return 0;
}
Java 버전
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.ArrayList;
public class SortBenchmark {
public static void main(String[] args) {
Integer[] arr = {448, 986, 255, 884, 632, ...};
for(int i = 0; i < 10; i++) {
List<Integer> testList = new ArrayList<>(Arrays.asList(arr));
long startTime = System.nanoTime();
Collections.sort(testList);
long endTime = System.nanoTime();
double durationMs = (endTime - startTime) / 1000000.0;
System.out.println("정렬 " + (i+1) + ": " + String.format("%.3f", durationMs) + "ms");
}
}
}
놀라운 점은 GPT-5가 각 언어의 특성에 맞는 최적화된 코드를 생성했다는 것입니다. Python은 list.copy()
와 perf_counter()
, C++는 std::chrono
, Java는 ArrayList
와 Collections.sort()
를 적절히 활용했어요.
문법 제약으로 정확성 높이기
Freeform의 자유로움이 때로는 너무 자유로울 수 있어요. 그래서 OpenAI는 Context-Free Grammar (CFG) 기능을 제공합니다.
SQL 방언별 정확한 쿼리 생성
예를 들어, 같은 요청이라도 데이터베이스 종류에 따라 다른 SQL 문법을 사용해야 합니다:
Microsoft SQL Server용
SELECT TOP 5 customer_id, order_id, order_date, total_amount
FROM orders
WHERE total_amount > 500 AND order_date > '2025-01-01'
ORDER BY order_date DESC;
PostgreSQL용
SELECT customer_id, order_id, order_date, total_amount
FROM orders
WHERE total_amount > 500 AND order_date > '2025-01-01'
ORDER BY order_date DESC
LIMIT 5;
차이점이 보이시나요? SQL Server는 TOP 5
를, PostgreSQL은 LIMIT 5
를 사용합니다. GPT-5는 각각의 문법 규칙을 정확히 따라 다른 쿼리를 생성해줍니다.
정규식으로 형식 강제하기
특정 형식이 필요한 경우 정규식으로 제약을 걸 수 있어요:
timestamp_grammar = r"^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]) (?:[01]\d|2[0-3]):[0-5]\d$"
tools = [{
"type": "custom",
"name": "timestamp_tool",
"format": {
"type": "grammar",
"syntax": "regex",
"definition": timestamp_grammar
}
}]
“2025년 8월 7일 오전 10시를 저장해줘”라고 요청하면 정확히 2025-08-07 10:00
형식으로만 응답합니다.
성능과 효율성의 놀라운 개선
OpenAI의 공식 발표에 따르면, GPT-5는 기존 o3 모델과 비교해서:
- 22% 적은 출력 토큰 사용
- 45% 적은 도구 호출로 같은 작업 완성
- 더 빠른 처리 속도와 높은 정확도
이는 단순히 새로운 기능이 아니라 전체적인 시스템 효율성의 대폭 개선을 의미합니다.
실무 활용 시나리오
1. 자동화 파이프라인
복잡한 데이터 처리 워크플로우를 자연어로 설명하면, GPT-5가 각 단계에 맞는 스크립트를 생성하고 실행합니다.
2. 코드 리뷰 및 최적화
기존 코드를 분석하고 성능 개선 방안을 제시할 때, 실제로 작동하는 개선된 코드를 즉시 생성합니다.
3. 프로토타이핑 가속화
아이디어를 빠르게 검증하고 싶을 때, 여러 언어로 동일한 로직을 구현해 성능을 비교할 수 있습니다.
4. 교육 및 학습
프로그래밍을 배우는 학습자에게 같은 알고리즘을 다양한 언어로 보여주며 각 언어의 특성을 이해시킬 수 있습니다.
주의사항과 모범 사례
주의할 점들
- 병렬 처리 불가: 여러 도구를 동시에 호출할 수 없음
- 디버깅 복잡성: 자유로운 형식으로 인한 예상치 못한 출력 가능
- 보안 고려: 실행되는 코드에 대한 적절한 샌드박스 환경 필수
모범 사례
- 명확한 도구 설명: 각 도구가 무엇을 하는지 상세히 기술
- 적절한 제약 설정: 필요에 따라 문법 규칙이나 정규식 활용
- 점진적 도입: 기존 JSON 방식과 혼용하며 단계적으로 적용
개발자에게 주는 의미
Freeform Tool Calling은 단순한 기술 개선을 넘어 AI와 개발자의 협업 방식을 근본적으로 바꾸고 있습니다. 이제 AI는 진정한 의미에서 ‘코드를 이해하는’ 동료가 되었어요.
복잡한 JSON 스키마를 설계하고 디버깅하는 대신, 우리는 AI에게 자연어로 의도를 전달하고, AI는 각 도구와 환경에 맞는 완벽한 코드를 생성합니다. 마치 경험 많은 개발자와 페어 프로그래밍을 하는 것처럼요.
앞으로는 “이 데이터를 분석해서 시각화해줘”라고 말하면, AI가 데이터베이스 쿼리부터 Python 시각화 코드, 심지어 웹 대시보드까지 모든 것을 자연스럽게 생성하고 실행하는 시대가 올 것입니다.
참고자료:
Comments