사용자의 메시지를 GPT API로 전달했는데, 자연어 응답 대신 모델이 어떤 함수를 어떤 인수와 함께 호출해야 하는지 정확히 알려 주는 구조화된 JSON 객체를 돌려줍니다. 그게 바로 기능 호출(function calling)이며, LLM으로 구축할 수 있는 애플리케이션의 종류를 바꿉니다.
대부분의 개발자는 “function calling”이라는 말을 듣고 모델이 대신 코드를 실행한다고 생각합니다. 그렇지 않습니다.
함수 호출을 사용할 때, LLM 자체는 함수를 실행하지 않습니다. 대신 적절한 함수를 식별하고 필요한 모든 매개변수를 수집한 뒤, 그 정보를 구조화된 JSON 형식으로 제공합니다.
실제 로직을 실행하는 책임은 여전히 애플리케이션에 있습니다. 모델은 무엇을 어떤 입력으로 실행할지 알려 줄 뿐입니다.
이 구분은 생각보다 중요하며, 통합 아키텍처부터 보안에 대한 사고방식까지 모든 것을 좌우합니다.
함수 호출의 실제 의미 — 사람들이 흔히 오해하는 것들
함수 호출(툴 호출이라고도 함)은 OpenAI 모델이 외부 시스템과 인터페이스하고, 학습 데이터 밖의 데이터에 접근할 수 있게 해 주는 강력하고 유연한 방법을 제공합니다.
이름부터가 혼란의 출발점입니다. 사람들은 모델이 무엇인가를 실행한다고 생각합니다. 그렇지 않습니다.
함수 호출에 대한 명칭과 설명은 다양하지만, 결국 한 문장으로 요약됩니다. “함수 호출은 대형 언어 모델의 구조화된 출력 능력의 한 형태다.” LLM은 스스로 어떤 함수도 호출하지 않습니다. 여러분이 프롬프트로 제공한 사전 정의 함수 중에서 어떤 함수를 호출해야 하는지 제안할 뿐입니다.
두 번째 혼란은 예전 API 표면과 관련이 있습니다.
functions와 function_call 파라미터는 2023-12-01-preview 버전 API의 출시와 함께 더 이상 사용되지 않습니다. functions를 대체하는 것은 tools 파라미터입니다.
만약 여전히 예전 functions 파라미터를 쓰는 튜토리얼을 따라 하고 있다면, 이미 폐기된 문법을 사용하고 있는 것입니다. 대신 tools와 tool_choice를 사용하세요.
함수는 JSON 스키마로 정의되는 특정 종류의 도구입니다. 함수 정의는 모델이 여러분의 애플리케이션에 데이터를 전달할 수 있게 해 주며, 그곳에서 코드가 데이터에 액세스하거나 모델이 제안한 작업을 수행할 수 있습니다.
이 스키마가 함수 호출이 일반 프롬프팅 대비 신뢰성 우위를 갖게 하는 핵심입니다. 모델이 올바른 형식으로 출력을 내주길 바라는 것이 아니라, API 차원에서 구조를 강제하는 것입니다.
OpenAI API에서 함수 호출이 작동하는 방식 — 단계별
도구 호출은 애플리케이션과 모델 간에 OpenAI API를 통해 이루어지는 다단계 대화입니다. 도구 호출 흐름은 다섯 가지 상위 단계로 이루어집니다. 모델이 호출할 수 있는 도구들을 포함해 요청을 보내고…
각 단계가 실제로 어떻게 생겼는지 살펴보겠습니다.
Step 1: Define your function schemas. 각 사용 가능한 함수를 tools 파라미터 내부의 JSON 객체로 설명합니다. 스키마에는 함수 이름, 모델이 언제 호출해야 하는지를 판단하는 자연어 설명, JSON Schema 규약을 따르는 parameters 블록이 포함됩니다.
description은 언제, 어떤 상황에서 함수를 호출해야 하는지에 관해 구체적일수록 좋습니다. 다만 함수 설명도 프롬프트의 일부이므로 토큰을 소비한다는 점을 유념하세요.
Step 2: Send the request. 사용자의 메시지와 tools 목록을 포함해 Chat Completions API를 호출합니다. 모델은 둘 다 볼 수 있습니다.
Step 3: The model decides whether to call a function.
함수 호출은 모델이 프롬프트를 검토한 뒤 지시를 따르기 위해 제공된 도구 중 하나를 호출해야 한다고 판단할 때 반환하는 특별한 종류의 응답을 의미합니다. 예컨대 “파리의 날씨는 어때?”와 같은 프롬프트를 받으면, 모델은 위치 인수로 파리를 설정해 get_weather 도구 호출을 반환할 수 있습니다.
Step 4: Your code executes the function. 모델의 응답을 파싱해 함수 이름과 인수를 추출한 뒤, 실제 실행 환경에서 코드를 실행합니다. API는 구조화된 JSON을 반환했을 뿐이고, 무엇을 할지는 여러분이 결정합니다.
Step 5: Send the result back.
그런 다음 모든 도구 정의, 원래 프롬프트, 모델의 도구 호출, 그리고 도구 호출의 출력을 모델에게 다시 보내 최종 텍스트 응답을 받습니다
— 이를테면 “오늘 파리의 날씨는 25°C입니다.” 같은 응답입니다.
대부분의 튜토리얼이 건너뛰는 한 가지 디테일:
함수 정의에서 strict: true를 설정하면, Structured Outputs는 모델이 생성하는 함수 호출 인수가 여러분이 제공한 JSON 스키마와 정확히 일치하도록 보장합니다.
strict를 true로 설정하면, 최선의 노력 수준이 아니라 스키마를 확실히 준수하는 함수 호출을 보장합니다. OpenAI는 항상 strict 모드 사용을 권장합니다.
항상. 사용하지 않을 이유가 없습니다.
또 병렬 함수 호출도 알아두어야 합니다.
사용자 쿼리에 따라, 2023년 11월 6일 이후 출시된 최신 모델을 사용할 경우 모델은 병렬 함수 호출을 수행합니다.
즉, “런던과 도쿄의 날씨는 어때?” 같은 단일 요청이 순차적으로 연결하는 대신 두 개의 도구 호출을 동시에 트리거할 수 있습니다.
함수 호출의 실제 사용 사례
날씨 예시는 깔끔해서 자주 등장합니다. 실제 프로덕션 사례는 더 복잡하지만 더 흥미롭습니다.
실시간 데이터가 연결된 고객 지원 파이프라인
함수 호출은 매우 다양한 용도에 유용합니다. 예를 들어 사용자가 “내 최근 주문은?”이라고 물으면 최신 고객 데이터를 내부 시스템에서 가져와야만 응답을 생성하는 AI 어시스턴트 같은 경우입니다.
모델은 의도를 파악하고, 컨텍스트에서 고객 ID를 추출한 뒤, 여러분의 CRM 내부 API를 호출합니다. 깨지기 쉬운 정규식도, 쉼표 하나 빠져서 무너지는 취약한 프롬프트 템플릿도 필요 없습니다.
대규모 구조화 데이터 추출
원시 텍스트를 가져와 구조화된 데이터로 변환하고 데이터베이스에 저장하는 데이터 추출 파이프라인도 강력한 적합 사례입니다. 문서 유형마다 파싱 로직을 미세 조정하지 않고도 수천 개 문서 전반에 걸쳐 일관된 스키마를 얻을 수 있습니다.
자연어를 API로 변환
데이터 추출과 태깅을 위한 LLM 기반 솔루션, 자연어를 API 호출이나 유효한 데이터베이스 쿼리로 변환하는 애플리케이션, 지식 기반과 상호작용하는 대화형 검색 엔진—이 모두가 함수 호출의 출력 형식 보장 덕을 봅니다. 출력이 다운스트림 시스템을 구동해야 하는 경우 변동성을 허용할 수 없습니다.
다중 도구를 활용하는 에이전트형 워크플로
개발자에게 함수 호출은 학습 컷오프를 실시간 데이터 접근으로 보완하게 해 줍니다. 최신 주가, 날씨, 최근 데이터베이스 엔트리를 가져오는 식이죠. 또한 함수 호출은 액션 실행도 가능하게 하여, LLM을 수동 관찰자에서 이메일 발송, CRM 업데이트, 코드 배포처럼 상태를 변경하는 능동적 참여자로 전환합니다.
단순 챗봇과의 핵심 차이점은, 모델이 텍스트만 생성하는 것이 아니라 시스템 전반의 실제 작업을 오케스트레이션한다는 점입니다.
함수 호출 베스트 프랙티스 — 개발자가 흔히 놓치는 것들
대부분의 튜토리얼이 통째로 건너뛰는 섹션이며, 그 결과 팀이 새벽 2시에 이상한 프로덕션 장애를 디버깅하게 됩니다.
설명을 너무 모호하게 적기. 모델은 함수 설명을 바탕으로 호출 여부를 결정합니다. “사용자 요청을 처리함” 같은 일반적인 설명만으로는 언제 호출해야 할지 신뢰할 수 있는 신호가 없습니다. 트리거 조건과 예상 입력 형태를 구체적으로 명시하세요. 설명은 라벨이 아니라 계약이라고 생각하세요.
한 번에 너무 많은 함수를 노출
함수 설명은 입력 프롬프트의 토큰을 상당히 소모할 수 있습니다.
50개 이상의 도구 정의를 시스템 프롬프트에 로드하면 두 가지 문제가 생깁니다. 비용과 지연 시간(도구 정의가 입력 토큰을 소비하므로), 그리고 정확도 저하(도구 선택지가 많아질수록 모델이 올바른 것을 고르는 능력이 떨어짐)입니다.
사용 사례에 실제로 필요한 최소한의 함수 집합으로 시작하세요.
모델이 매개변수를 지어내지 않을 거라고 가정하기. 지어냅니다.
모델은 매개변수를 지어낼 수 있습니다
— 특히 선택 필드인데 열거형으로 명확히 제한되지 않은 경우에 그렇습니다. 이 때문에 strict: true가 중요합니다. 스키마 밖의 필드를 모델이 만들어내지 못하게 막습니다.
다중 턴 루프를 처리하지 않기. 개발자들은 종종 해피 패스만 구축합니다—사용자가 묻고, 모델이 함수를 호출하고, 끝.
모델이 정의한 스키마와 맞지 않는 함수 호출을 생성하거나, 포함되지 않은 함수를 호출하려 시도할 수 있습니다. 모델이 예상치 못한 함수 호출을 생성한다면 시스템 메시지에 “제공된 함수만 사용하세요.” 같은 문장을 포함해 보세요.
엣지 케이스를 대비해 구축하세요.
쓰기 작업 전에 확인 단계를 생략하기.
특히 코드 실행, 데이터베이스 업데이트, 알림 전송처럼 실제로 액션을 트리거하는 함수 호출의 현실적인 영향을 인지해야 합니다. 액션을 수반하는 함수의 경우, 실행 전에 사용자 확인 단계를 구현하는 것을 강력히 권장합니다.
데이터를 삭제하거나, 돈을 보내거나, 외부 상태를 수정할 수 있는 함수 호출이라면 사람이 먼저 승인해야 합니다.
보안과 신뢰성 고려사항
함수 호출은 LLM이 할 수 있는 일을 확장합니다. 동시에 공격자가 LLM으로 하도록 만들 수 있는 일도 확장합니다.
여기서 주된 위협은 프롬프트 인젝션입니다.
프롬프트 인젝션의 최종 목표는 다양하지만, 다운스트림 도구 호출을 통한 민감 데이터 유출, 의도와 다른 액션 수행, 또는 모델의 동작을 원치 않는 방식으로 바꾸는 것을 포함할 수 있습니다.
함수 호출이 이메일 발송, 데이터베이스 조회, 웹훅 트리거 등을 할 수 있다면, 인젝션 공격은 단순히 챗봇이 엉뚱한 소리를 하는 수준을 넘어 잠재적 침해가 됩니다.
AI 시스템이 채팅을 넘어 도구를 호출하고 액션을 수행하기 시작하면, 프롬프트 인젝션은 훨씬 더 심각한 문제로 변합니다. 웹페이지나 문서, 외부 도구에 숨겨진 악의적 지시가 시스템 동작을 덮어쓰고, 민감 정보를 노출시키거나, 모델이 결코 수행해서는 안 되는 액션을 트리거하려 할 수 있습니다.
대응 전략은 몇 가지 구체적 층위로 구성됩니다.
신뢰할 수 없는 데이터가 에이전트의 동작을 직접적으로 주도하지 못하도록 워크플로를 설계하세요. 외부 입력에서 열거형 또는 검증된 JSON 같은 특정 구조 필드만 추출해, 노드 간에 인젝션 리스크가 흘러가지 않도록 제한합니다.
그 위에,
모델이 생성한 함수 호출을 항상 검증하세요. 파라미터, 호출되는 함수, 의도한 액션과 일치하는지 여부를 확인합니다.
불편한 진실 하나:
“프롬프트 인젝션은 웹상의 사기나 사회공학과 마찬가지로, 완전히 ‘해결’되지는 않을 것입니다.”
이는 OpenAI 자체의 평가입니다. 실질적 함의는, 모델이 항상 의도대로 행동할 것이라는 가정을 전제로 에이전트형 함수 호출 시스템을 설계하지 말라는 것입니다. 심층 방어—검증, 범위가 제한된 권한, 파괴적 작업에 대한 인간 개입—만이 합리적 자세입니다.
함수 호출 vs. 프롬프트 엔지니어링 — 언제 무엇을 쓸까
이 비교는 끊임없이 제기됩니다. 짧은 답은 이렇습니다. 두 방법은 서로 다른 문제를 해결합니다. 둘을 혼동하면 함수 호출로 충분한 문제를 과도한 프롬프트로 해결하려 하거나, 잘 만든 시스템 프롬프트로 충분한 문제를 취약한 함수 스키마로 풀려다 실패하게 됩니다.
프롬프트 엔지니어링은 모델의 내부 추론을 유도하는 텍스트 입력을 작성하는 일—예컨대 “단계별로 생각해 보라”고 요청하는 것—입니다.
이것은 모델의 추론 방식을 형성합니다. 반면 함수 호출은 모델이 출력으로 무엇을 생성하고 그것이 시스템에 어떻게 라우팅되는지를 형성합니다.
도구 호출은 LLM이 외부 시스템과 상호작용할 수 있게 해 주는 능력입니다. 프롬프트 엔지니어링을 통해 모델이 어떤 도구를 사용할지 결정하도록 돕는 반면, 도구 호출은 실제로 액션을 실행하게 하는 메커니즘입니다. 둘 다 필요할 가능성이 크지만, 목적은 다릅니다.
프롬프트 기반 구조화 출력 대비 함수 호출의 핵심 기술적 우위:
도구 호출은 모델에 그대로 내장된 개념입니다. 모델에게 특정 형식으로 답을 반환하라고 장황하게 설명하면서 토큰을 낭비할 필요가 없습니다.
프롬프트에서 “X, Y, Z 필드를 가진 JSON으로 답을 반환하라”고 지시하면, 모델이 그 지시를 일관되게 따르지 않을 수 있고 토큰도 소모됩니다. 함수 호출에서는 스키마 강제가 API 차원에서 이루어집니다.
함수 호출 API는 이제 많은 LLM 플랫폼에서 기본적으로 지원되며, 엄격한 데이터 검증과 프로그래밍적 워크플로와의 통합을 가능케 하는 형식적 스키마 기반 인터페이스를 제공합니다.
이것이 프로덕션에서 다운스트림 시스템으로 흘러야 하는 데이터에 프롬프트 엔지니어링 대신 함수 호출을 선택해야 하는 실제 이유입니다. 일단 프로덕션에 들어가면 신뢰성은 선택 사항이 아닙니다.
| Dimension | Prompt Engineering | Function Calling |
|---|---|---|
| Primary purpose | 모델의 추론과 톤을 조정 | 시스템 연계를 위한 구조화된 출력 생성 |
| Output format | 자유 형식 텍스트(또는 텍스트로 흉내낸 JSON) | 강제되는 JSON 스키마 |
| Schema reliability | 최선의 노력; 드리프트 발생 가능 | strict: true로 보장 |
| Token cost | 단순 출력에선 낮음 | 높음(함수 정의가 토큰을 소모) |
| When to use | 추론 작업, 텍스트 생성, 스타일 제어 | 구조화 데이터 추출, API 오케스트레이션, 에이전트형 액션 |
| Prompt injection exposure | 낮음(외부 도구 실행 없음) | 높음(함수 호출이 실제 동작을 촉발) |
실무적 휴리스틱: 출력이 데이터베이스 쓰기, API 호출, 코드의 분기 결정처럼 다운스트림 시스템을 구동해야 한다면 함수 호출을 사용하세요. 출력이 사람에게 보여주기 위한 것이라면 프롬프트 엔지니어링이 대체로 충분하고 더 저렴합니다.
핵심 요약
| Topic | What to Remember |
|---|---|
| What it is | 모델은 어떤 함수를 호출할지와 인수를 담은 구조화된 JSON을 출력할 뿐, 함수를 실행하지는 않는다 |
| Current API surface | tools와 tool_choice를 사용하고, 예전 functions와 function_call 파라미터는 폐기되었다 |
| Strict mode | 스키마 준수를 강제하기 위해 항상 strict: true를 함수 정의에 설정하라 |
| Parallel calling | 2023년 11월 이후 공개된 모델에서 지원; 하나의 요청이 여러 도구 호출을 트리거할 수 있다 |
| Token cost | 함수 스키마는 입력 토큰을 소모하므로 노출하는 함수 수를 최소화하라 |
| Security | 모든 함수 호출 출력을 검증하고, 신뢰할 수 없는 외부 콘텐츠가 도구 호출을 직접 유도하지 못하게 하라 |
| vs. Prompt Engineering | 함수 호출은 API 차원에서 출력 구조를 강제하고, 프롬프트 엔지니어링은 내부 추론을 형성한다 |
| Confirmation steps | 실제 부작용(쓰기, 전송, 삭제)을 유발하는 함수는 실행 전에 사용자 확인을 요구해야 한다 |
여러 모델—GPT-5.4, claude opus 4.7, gemini 3.1 pro—에서 함수 호출을 실험해 보고 싶지만 모델마다 별도 API 자격 증명을 유지하고 싶지 않다면, CometAPI를 통해 단일 엔드포인트와 키로 모두 접근해 모델 간 테스트의 마찰을 크게 줄일 수 있습니다.
CometAPI는 인프라 오버헤드를 해결합니다:
✅ 통합 함수 호출 문법, 15개+ 모델 공통
✅ 단일 API 키 — OpenAI/Anthropic/Google 계정 개별 관리 불필요
✅ 자동 스키마 변환 — 한 번 정의로 어디서나 테스트
✅ 내장 비용 추적 — 모델별 토큰 사용량 실시간 비교
무료 크레딧으로 테스트 시작 → 접속하기
