🤖

본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.

⚠️

본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.

이미지 로딩 중...

Function Calling 기초 완벽 가이드 - 슬라이드 1/7
A

AI Generated

2026. 2. 1. · 7 Views

Function Calling 기초 완벽 가이드

AI 모델이 외부 함수를 호출하여 실시간 데이터를 가져오고 실제 작업을 수행하는 Function Calling의 핵심 개념을 다룹니다. Spring AI를 활용한 실무 예제와 함께 초급 개발자도 쉽게 이해할 수 있도록 설명합니다.


목차

  1. Function Calling 개념
  2. 함수 정의와 등록
  3. @JsonClassDescription 활용
  4. 파라미터 스키마 정의
  5. 함수 실행 흐름
  6. 간단한 날씨 조회 함수 구현

1. Function Calling 개념

어느 날 김개발 씨가 ChatGPT API를 연동하던 중 이상한 현상을 발견했습니다. "오늘 서울 날씨 어때?"라고 물었더니 AI가 "저는 실시간 날씨 정보를 확인할 수 없습니다"라고 대답하는 것이었습니다.

분명 AI가 똑똑하다고 들었는데, 왜 간단한 날씨도 모르는 걸까요?

Function Calling은 한마디로 AI 모델이 외부 함수를 호출할 수 있게 해주는 기술입니다. 마치 비서가 필요한 정보를 직접 찾아오는 것처럼, AI가 스스로 판단하여 적절한 함수를 호출하고 그 결과를 활용합니다.

이를 통해 AI는 실시간 데이터 조회, 예약 시스템 연동, 데이터베이스 검색 등 실제 작업을 수행할 수 있게 됩니다.

다음 코드를 살펴봅시다.

// Function Calling의 기본 흐름을 보여주는 개념 코드
public class FunctionCallingConcept {

    // 1. AI에게 사용 가능한 함수 목록을 알려줍니다
    private List<FunctionDefinition> availableFunctions = List.of(
        new FunctionDefinition("getWeather", "현재 날씨를 조회합니다"),
        new FunctionDefinition("searchProduct", "상품을 검색합니다")
    );

    // 2. AI가 함수 호출이 필요하다고 판단하면
    // 3. 해당 함수를 실행하고 결과를 AI에게 전달합니다
    public String processUserQuery(String userMessage) {
        AIResponse response = ai.chat(userMessage, availableFunctions);
        if (response.hasFunctionCall()) {
            Object result = executeFunction(response.getFunctionCall());
            return ai.chatWithResult(userMessage, result);
        }
        return response.getMessage();
    }
}

김개발 씨는 입사 6개월 차 백엔드 개발자입니다. 최근 회사에서 AI 챗봇 프로젝트를 맡게 되었는데, 고객들이 "내 주문 상태가 어떻게 됐어?"라고 물으면 AI가 실제 주문 정보를 조회해서 답변해야 하는 상황이었습니다.

처음에 김개발 씨는 고민에 빠졌습니다. ChatGPT는 분명 똑똑한데, 어떻게 우리 회사 데이터베이스에 있는 주문 정보를 알 수 있을까요?

AI 모델은 학습된 지식만 가지고 있을 뿐, 실시간으로 변하는 외부 데이터에는 접근할 수 없기 때문입니다. 선배 개발자 박시니어 씨가 다가와 말했습니다.

"그래서 Function Calling이라는 게 있어요. AI한테 우리가 만든 함수를 쓸 수 있게 해주는 거죠." 그렇다면 Function Calling이란 정확히 무엇일까요?

쉽게 비유하자면, Function Calling은 마치 유능한 비서에게 전화번호부를 주는 것과 같습니다. 비서 혼자서는 거래처 담당자 연락처를 모르지만, 전화번호부가 있으면 직접 찾아서 전화를 걸 수 있습니다.

마찬가지로 AI 모델도 혼자서는 실시간 날씨나 주문 정보를 모르지만, 우리가 만든 함수를 사용할 수 있게 해주면 직접 조회해서 답변할 수 있게 됩니다. Function Calling이 없던 시절에는 어땠을까요?

개발자들은 사용자의 질문을 미리 분류하고, 각 분류에 맞는 처리 로직을 일일이 작성해야 했습니다. "날씨"라는 단어가 들어가면 날씨 API를 호출하고, "주문"이라는 단어가 들어가면 주문 조회 API를 호출하는 식이었습니다.

문제는 사람들이 같은 의도를 수백 가지 다른 방식으로 표현한다는 것입니다. "비 올 거야?", "우산 챙겨야 해?", "오늘 날씨 춥니?" 이 모든 질문이 사실은 날씨를 묻는 것인데, 이를 모두 처리하려면 끔찍하게 복잡한 규칙을 만들어야 했습니다.

바로 이런 문제를 해결하기 위해 Function Calling이 등장했습니다. Function Calling을 사용하면 AI가 자연어를 이해하고 스스로 적절한 함수를 선택합니다.

개발자는 "날씨 조회 함수가 있다"는 것만 알려주면, AI가 알아서 "우산 챙겨야 해?"라는 질문에 날씨 함수를 호출해야 한다고 판단합니다. 더 이상 복잡한 의도 분류 로직을 작성할 필요가 없어진 것입니다.

위의 코드를 살펴보면 Function Calling의 핵심 흐름을 이해할 수 있습니다. 먼저 AI에게 사용 가능한 함수 목록을 알려줍니다.

이것은 마치 비서에게 "이런 일들을 할 수 있어요"라고 알려주는 것과 같습니다. 그 다음 사용자의 질문을 AI에게 전달하면, AI는 질문을 분석하고 함수 호출이 필요한지 판단합니다.

필요하다면 어떤 함수를 어떤 파라미터로 호출할지까지 결정해서 알려줍니다. 실제 현업에서는 다양한 곳에서 Function Calling을 활용합니다.

고객 서비스 챗봇에서는 주문 조회, 배송 추적, 환불 처리 등의 함수를 연결합니다. 업무 자동화 도구에서는 이메일 발송, 캘린더 등록, 문서 생성 등의 함수를 활용합니다.

심지어 스마트홈 시스템에서도 "불 꺼줘"라는 말에 조명 제어 함수를 호출하는 방식으로 동작합니다. 다시 김개발 씨의 이야기로 돌아가 봅시다.

박시니어 씨의 설명을 들은 김개발 씨는 눈이 반짝였습니다. "아, 그러니까 AI한테 우리 API를 쓸 수 있게 연결해주면 되는 거군요!" Function Calling을 이해하면 AI를 단순한 대화 도구가 아닌, 실제 업무를 수행하는 강력한 도구로 활용할 수 있습니다.

실전 팁

💡 - Function Calling은 AI가 함수를 직접 실행하는 것이 아니라, 어떤 함수를 호출해야 하는지 결정만 합니다. 실제 실행은 개발자의 코드에서 이루어집니다.

  • 함수 설명을 명확하게 작성할수록 AI가 더 정확하게 함수를 선택합니다.

2. 함수 정의와 등록

Function Calling의 개념을 이해한 김개발 씨는 이제 직접 구현을 시작하려고 합니다. 하지만 막상 코드를 작성하려니 어디서부터 시작해야 할지 막막했습니다.

"함수를 만들긴 했는데, 이걸 어떻게 AI한테 연결하지?"

Spring AI에서 함수를 등록하는 방법은 놀랍도록 간단합니다. 일반 자바 메서드를 작성하고, 이를 Bean으로 등록하기만 하면 됩니다.

Spring AI가 자동으로 함수의 구조를 분석하여 AI 모델이 이해할 수 있는 형태로 변환해줍니다. 마치 통역사가 한국어를 영어로 바꿔주는 것처럼, Spring AI가 자바 함수를 AI가 이해하는 언어로 번역해주는 것입니다.

다음 코드를 살펴봅시다.

@Configuration
public class FunctionConfig {

    // 함수를 Bean으로 등록합니다
    @Bean
    @Description("주어진 도시의 현재 날씨 정보를 조회합니다")
    public Function<WeatherRequest, WeatherResponse> getWeather() {
        return request -> {
            // 실제 날씨 API를 호출하는 로직
            String city = request.city();
            String weather = weatherService.getCurrentWeather(city);
            return new WeatherResponse(city, weather, "20°C");
        };
    }

    // 요청 객체 정의
    public record WeatherRequest(String city) {}

    // 응답 객체 정의
    public record WeatherResponse(String city, String condition, String temperature) {}
}

김개발 씨가 Spring AI 문서를 펼쳤을 때, 처음에는 조금 당황했습니다. 다른 프레임워크들은 복잡한 설정 파일을 작성해야 했는데, Spring AI는 너무 간단해 보였기 때문입니다.

"이게 정말 다야?"라고 생각할 정도였습니다. 박시니어 씨가 웃으며 말했습니다.

"Spring의 철학이 원래 그래요. 복잡한 건 프레임워크가 알아서 처리하고, 개발자는 비즈니스 로직에만 집중하게 해주는 거죠." 함수 등록의 핵심은 java.util.function.Function 인터페이스입니다.

이 인터페이스는 입력을 받아서 출력을 반환하는 가장 기본적인 함수 형태를 정의합니다. Spring AI는 이 인터페이스를 구현한 Bean을 자동으로 감지하여 AI가 호출할 수 있는 함수 목록에 추가합니다.

마치 회사에 새로운 직원이 입사하면 자동으로 사내 전화번호부에 등록되는 것과 같습니다. @Description 어노테이션은 매우 중요한 역할을 합니다.

이 어노테이션에 작성한 설명이 AI 모델에게 전달되어, AI가 언제 이 함수를 호출해야 하는지 판단하는 기준이 됩니다. 설명이 모호하면 AI가 잘못된 상황에서 함수를 호출할 수 있고, 반대로 설명이 너무 제한적이면 필요한 상황에서도 함수를 호출하지 않을 수 있습니다.

코드를 자세히 살펴보겠습니다. getWeather 메서드는 WeatherRequest를 받아서 WeatherResponse를 반환하는 함수를 생성합니다.

여기서 주목할 점은 record를 사용했다는 것입니다. Java의 record는 불변 데이터 클래스를 간결하게 정의할 수 있게 해주며, Spring AI가 자동으로 이 구조를 분석하여 AI에게 "이 함수는 city라는 문자열 파라미터가 필요해"라고 알려줍니다.

함수 내부의 람다 표현식에서 실제 비즈니스 로직이 실행됩니다. 이 예제에서는 weatherService를 통해 실제 날씨 정보를 조회하고 있습니다.

실무에서는 여기에 외부 API 호출, 데이터베이스 조회, 캐시 처리 등 다양한 로직이 들어갈 수 있습니다. 중요한 것은 이 함수가 일반적인 자바 코드와 전혀 다르지 않다는 점입니다.

Bean 이름도 중요한 의미를 가집니다. 메서드 이름인 getWeather가 자동으로 함수의 이름이 됩니다.

AI 모델은 이 이름을 보고 함수의 용도를 추측하기도 합니다. 따라서 함수 이름은 그 기능을 잘 설명하는 동사형으로 작성하는 것이 좋습니다.

getWeather, searchProducts, createOrder 같은 형태가 이상적입니다. 김개발 씨는 이제 이해가 되기 시작했습니다.

"그러니까 평소에 서비스 클래스 만들듯이 함수를 만들고, Bean으로 등록하고, 설명만 잘 달아주면 되는 거네요!" 박시니어 씨가 고개를 끄덕였습니다. "맞아요.

Spring AI가 나머지는 다 알아서 해줘요."

실전 팁

💡 - 함수 이름은 동사로 시작하고, 기능을 명확히 나타내도록 작성하세요.

  • @Description은 한글로 작성해도 됩니다. AI 모델은 다국어를 잘 이해합니다.
  • 하나의 함수는 하나의 명확한 기능만 수행하도록 설계하세요.

3. @JsonClassDescription 활용

김개발 씨가 첫 번째 함수를 만들고 테스트해보았습니다. 그런데 이상한 일이 벌어졌습니다.

"서울 날씨 알려줘"라고 물으면 잘 동작하는데, "내일 비 올까?"라고 물으면 함수가 호출되지 않는 것이었습니다. AI가 이 질문이 날씨와 관련있다는 것을 인식하지 못한 것입니다.

@JsonClassDescription은 요청 객체에 상세한 설명을 추가하여 AI가 함수를 더 정확하게 이해하도록 도와줍니다. 마치 상품 설명서를 상세하게 작성하면 고객이 상품을 더 잘 이해하는 것처럼, 파라미터에 대한 설명이 풍부할수록 AI는 언제 이 함수를 사용해야 하는지 더 정확하게 판단합니다.

Jackson 라이브러리의 어노테이션을 활용하여 JSON 스키마를 풍부하게 만드는 것이 핵심입니다.

다음 코드를 살펴봅시다.

import com.fasterxml.jackson.annotation.JsonClassDescription;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;

@JsonClassDescription("날씨 정보 조회 요청. 특정 도시의 현재 날씨, " +
    "기온, 강수 확률 등을 확인할 때 사용합니다. " +
    "비가 올지, 우산이 필요한지 등의 질문에도 활용됩니다.")
public record WeatherRequest(

    @JsonProperty(required = true)
    @JsonPropertyDescription("날씨를 조회할 도시 이름. " +
        "예: 서울, 부산, 뉴욕, Tokyo")
    String city,

    @JsonPropertyDescription("조회 단위. celsius 또는 fahrenheit. " +
        "기본값은 celsius입니다.")
    String unit
) {}

김개발 씨의 문제는 AI가 "비 올까?"라는 질문을 날씨 조회 함수와 연결하지 못한 것이었습니다. 함수의 @Description만으로는 충분한 맥락을 제공하지 못했던 것입니다.

박시니어 씨가 해결책을 알려주었습니다. "함수 설명도 중요하지만, 파라미터에 대한 설명도 그만큼 중요해요.

AI는 이 모든 정보를 종합해서 판단하거든요." @JsonClassDescription은 클래스 레벨에서 전체적인 맥락을 설명합니다. 위 코드를 보면 "날씨 정보 조회 요청"이라는 기본 설명에 더해, "비가 올지, 우산이 필요한지 등의 질문에도 활용됩니다"라는 문구를 추가했습니다.

이렇게 하면 AI는 "우산 챙겨야 해?"라는 질문도 날씨 함수와 연결할 수 있게 됩니다. @JsonPropertyDescription은 각 필드가 무엇을 의미하는지 설명합니다.

city 필드에 "예: 서울, 부산, 뉴욕, Tokyo"라는 예시를 포함시킨 것에 주목하세요. AI는 이런 예시를 통해 어떤 형태의 값이 들어가야 하는지 더 잘 이해합니다.

사용자가 "도쿄 날씨"라고 물었을 때 Tokyo를 추출해야 한다는 것을 AI가 파악하는 데 도움이 됩니다. **@JsonProperty(required = true)**는 필수 파라미터를 표시합니다.

이 어노테이션이 있으면 AI는 반드시 이 값을 채워서 함수를 호출합니다. 사용자가 도시 이름을 언급하지 않았다면, AI는 함수를 호출하기 전에 "어느 도시의 날씨를 알려드릴까요?"라고 되물을 수 있습니다.

선택적 파라미터는 이 어노테이션 없이 @JsonPropertyDescription만 사용하면 됩니다. 이 모든 설명은 JSON Schema로 변환되어 AI에게 전달됩니다.

Spring AI는 이 어노테이션들을 분석하여 다음과 같은 형태의 스키마를 생성합니다. AI 모델은 이 스키마를 읽고 함수의 구조와 용도를 파악합니다.

설명이 풍부할수록 AI의 이해도가 높아지고, 결과적으로 더 정확한 함수 호출이 이루어집니다. 실무에서는 설명을 작성할 때 사용자의 언어를 고려해야 합니다.

한국어 서비스라면 설명도 한국어로 작성하는 것이 좋습니다. AI 모델들은 다국어를 잘 이해하며, 사용자의 질문과 같은 언어로 설명이 작성되어 있을 때 더 정확하게 매칭합니다.

"비 올까?"라는 한국어 질문은 "강수 확률"이라는 한국어 설명과 더 잘 연결됩니다. 김개발 씨는 기존 코드에 상세한 설명을 추가했습니다.

다시 테스트해보니 "내일 비 올까?"라는 질문에도 날씨 함수가 정상적으로 호출되었습니다. "설명 하나 잘 적는 게 이렇게 중요한 거였군요." 김개발 씨가 감탄했습니다.

실전 팁

💡 - 설명에 다양한 사용 시나리오와 예시를 포함하면 AI의 인식률이 높아집니다.

  • 필수 파라미터와 선택 파라미터를 명확히 구분하세요.
  • 기본값이 있는 파라미터는 설명에 "기본값은 ~입니다"라고 명시하세요.

4. 파라미터 스키마 정의

김개발 씨의 날씨 함수가 점점 발전하고 있었습니다. 이번에는 조금 더 복잡한 요구사항이 생겼습니다.

상품 검색 함수를 만들어야 하는데, 카테고리, 가격 범위, 정렬 방식 등 다양한 조건을 받아야 했습니다. "파라미터가 많아지면 AI가 헷갈리지 않을까?"

복잡한 파라미터 구조도 record와 enum을 활용하면 깔끔하게 정의할 수 있습니다. Spring AI는 중첩된 객체, 배열, 열거형 등 다양한 타입을 자동으로 JSON Schema로 변환합니다.

마치 건물의 설계도가 상세할수록 시공이 정확해지는 것처럼, 파라미터 스키마가 명확할수록 AI가 정확한 값을 추출하여 함수를 호출합니다.

다음 코드를 살펴봅시다.

public record ProductSearchRequest(
    @JsonProperty(required = true)
    @JsonPropertyDescription("검색할 상품 키워드")
    String keyword,

    @JsonPropertyDescription("상품 카테고리")
    Category category,

    @JsonPropertyDescription("가격 범위 조건")
    PriceRange priceRange,

    @JsonPropertyDescription("정렬 방식. 기본값은 RELEVANCE")
    SortOrder sortOrder
) {
    // 열거형으로 허용된 값을 제한
    public enum Category { ELECTRONICS, FASHION, FOOD, BOOKS }
    public enum SortOrder { RELEVANCE, PRICE_LOW, PRICE_HIGH, NEWEST }

    // 중첩 객체로 복잡한 조건 표현
    public record PriceRange(
        @JsonPropertyDescription("최소 가격 (원)")
        Integer minPrice,
        @JsonPropertyDescription("최대 가격 (원)")
        Integer maxPrice
    ) {}
}

상품 검색처럼 복잡한 기능은 파라미터도 복잡해질 수밖에 없습니다. 하지만 복잡하다고 해서 어렵게 구현해야 하는 것은 아닙니다.

Java의 recordenum을 잘 활용하면 복잡한 구조도 깔끔하게 표현할 수 있습니다. 먼저 enum의 역할을 살펴보겠습니다.

Category와 SortOrder를 enum으로 정의한 것에 주목하세요. 이렇게 하면 AI에게 "카테고리는 ELECTRONICS, FASHION, FOOD, BOOKS 중 하나만 가능해"라고 명확하게 알려주는 것과 같습니다.

AI는 사용자가 "노트북 찾아줘"라고 하면 자동으로 ELECTRONICS를 선택하고, "청바지 검색해줘"라고 하면 FASHION을 선택합니다. 중첩 객체는 연관된 파라미터를 그룹화합니다.

가격 범위를 표현할 때 minPrice와 maxPrice를 별도의 파라미터로 만들 수도 있었지만, PriceRange라는 중첩 record로 묶었습니다. 이렇게 하면 AI가 "가격 범위"라는 개념을 하나의 단위로 이해합니다.

"10만원에서 20만원 사이"라는 사용자 입력을 minPrice: 100000, maxPrice: 200000으로 정확하게 변환할 수 있습니다. Spring AI가 이 구조를 어떻게 처리하는지 살펴보면 더 이해가 쉽습니다.

Spring AI는 이 record 구조를 분석하여 JSON Schema를 자동 생성합니다. 생성된 스키마에는 각 필드의 타입, 설명, 필수 여부, enum의 경우 허용된 값 목록까지 모두 포함됩니다.

AI 모델은 이 스키마를 보고 어떤 값을 어떤 형태로 전달해야 하는지 정확히 알 수 있습니다. 파라미터의 기본값 처리도 중요합니다.

코드에서 sortOrder의 설명에 "기본값은 RELEVANCE"라고 명시한 것을 보세요. 사용자가 정렬 방식을 언급하지 않으면 AI는 이 필드를 비워두거나 기본값인 RELEVANCE를 넣을 수 있습니다.

함수 내부에서도 null 체크 후 기본값을 적용하는 로직을 넣어두면 더 안전합니다. 실무에서 자주 사용하는 패턴들이 있습니다.

날짜 범위는 startDate와 endDate를 가진 DateRange record로, 페이징은 page와 size를 가진 PageRequest record로 정의하는 식입니다. 이런 공통 구조를 미리 정의해두면 여러 함수에서 재사용할 수 있어 일관성도 높아지고 개발 속도도 빨라집니다.

김개발 씨는 이제 복잡한 검색 조건도 자신있게 정의할 수 있게 되었습니다. "타입 시스템의 도움을 받으니까 훨씬 안전하고 명확하네요."

실전 팁

💡 - enum을 사용하면 AI가 잘못된 값을 전달하는 것을 방지할 수 있습니다.

  • 중첩 객체는 2단계까지만 사용하세요. 너무 깊으면 AI가 혼란스러워할 수 있습니다.
  • 숫자 타입은 Integer를 사용하여 null을 허용하면 선택적 파라미터로 처리하기 쉽습니다.

5. 함수 실행 흐름

함수 정의는 완료했는데, 김개발 씨에게 새로운 궁금증이 생겼습니다. "AI가 함수를 호출한다고 했는데, 정확히 어떤 순서로 동작하는 거지?

사용자가 질문하면 바로 함수가 실행되는 건가?" 박시니어 씨가 화이트보드를 꺼내 그림을 그리기 시작했습니다.

Function Calling의 실행 흐름은 4단계로 이루어집니다. 첫째, 사용자 질문과 함수 정의를 AI에게 전달합니다.

둘째, AI가 함수 호출이 필요하다고 판단하면 함수 이름과 파라미터를 반환합니다. 셋째, 애플리케이션이 실제로 함수를 실행합니다.

넷째, 실행 결과를 AI에게 다시 전달하면 AI가 최종 응답을 생성합니다. 핵심은 AI가 함수를 직접 실행하지 않고, 어떤 함수를 호출할지 결정만 한다는 점입니다.

다음 코드를 살펴봅시다.

@Service
public class ChatService {
    private final ChatClient chatClient;

    public String processMessage(String userMessage) {
        // 1단계: 함수 목록과 함께 AI에게 질문 전달
        ChatResponse response = chatClient.prompt()
            .user(userMessage)
            .functions("getWeather", "searchProduct")  // 사용 가능한 함수 지정
            .call();

        // Spring AI가 2~4단계를 자동으로 처리:
        // 2단계: AI가 함수 호출 결정 (예: getWeather, city="서울")
        // 3단계: Spring AI가 실제 함수 실행
        // 4단계: 결과를 AI에게 전달, 최종 응답 생성

        return response.getResult().getOutput().getContent();
    }
}

박시니어 씨가 화이트보드에 4개의 상자를 그렸습니다. "Function Calling은 이렇게 4단계로 동작해요." 1단계: 요청 전달 사용자가 "서울 날씨 어때?"라고 질문하면, 애플리케이션은 이 질문을 AI 모델에게 전달합니다.

이때 중요한 것은 질문만 보내는 게 아니라, 사용 가능한 함수 목록도 함께 보낸다는 점입니다. "너는 이런 함수들을 쓸 수 있어"라고 알려주는 것이죠.

2단계: AI의 판단 AI 모델은 질문을 분석하고, 답변을 위해 함수 호출이 필요한지 판단합니다. "서울 날씨"를 물었으니 getWeather 함수가 필요하다고 결정합니다.

그리고 파라미터도 추출합니다. city는 "서울"이 되어야 한다고 판단하죠.

AI는 이 정보를 담은 특별한 응답을 반환합니다. 3단계: 함수 실행 여기서 중요한 점이 있습니다.

AI가 직접 함수를 실행하지 않습니다. AI는 "getWeather 함수를 서울이라는 파라미터로 호출해줘"라고 요청할 뿐입니다. 실제 실행은 우리 애플리케이션에서 이루어집니다.

이것이 보안상 매우 중요한 포인트입니다. 우리가 정의한 함수만, 우리 서버에서, 우리가 통제하는 방식으로 실행됩니다.

4단계: 최종 응답 생성 함수 실행 결과(예: "맑음, 20도")를 AI에게 다시 전달합니다. AI는 이 결과를 바탕으로 자연스러운 문장을 만들어 사용자에게 전달합니다.

"서울의 현재 날씨는 맑고, 기온은 20도입니다. 오늘 외출하시기 좋은 날씨네요!" 코드를 보면 이 복잡한 과정이 매우 간단하게 표현되어 있습니다.

chatClient.prompt().user(userMessage).functions("getWeather").call() 이 한 줄이 4단계 전체를 처리합니다. Spring AI가 내부적으로 AI와의 통신, 함수 호출 감지, 실제 함수 실행, 결과 재전달을 모두 자동으로 수행합니다.

개발자는 비즈니스 로직에만 집중하면 됩니다. 한 가지 더 알아둘 점이 있습니다.

AI가 여러 함수를 연속으로 호출해야 할 때도 있습니다. 예를 들어 "서울 날씨랑 부산 날씨 비교해줘"라고 하면, AI는 getWeather를 두 번 호출해야 한다고 판단할 수 있습니다.

Spring AI는 이런 다중 호출도 자동으로 처리합니다. 김개발 씨가 고개를 끄덕였습니다.

"아, AI가 직접 실행하는 게 아니라 우리 코드에서 실행하는 거군요. 그래서 보안도 우리가 통제할 수 있고요." "정확해요.

그래서 함수 내부에서 권한 체크나 입력 검증도 할 수 있어요." 박시니어 씨가 덧붙였습니다.

실전 팁

💡 - functions() 메서드에는 실제로 사용할 함수만 지정하세요. 불필요한 함수가 많으면 AI가 혼란스러워할 수 있습니다.

  • 함수 실행 시간이 길면 사용자 경험이 나빠질 수 있으니, 비동기 처리나 타임아웃을 고려하세요.
  • 함수 내부에서 반드시 입력값 검증과 에러 처리를 해야 합니다.

6. 간단한 날씨 조회 함수 구현

이론은 충분히 배웠습니다. 이제 김개발 씨가 직접 처음부터 끝까지 날씨 조회 함수를 구현해볼 차례입니다.

Spring AI 의존성 추가부터 실제 테스트까지, 완전한 예제를 함께 만들어보겠습니다.

실제 동작하는 날씨 조회 기능을 구현해보겠습니다. 함수 정의, 서비스 클래스, 컨트롤러까지 전체 코드를 작성합니다.

외부 날씨 API 대신 간단한 Mock 데이터를 사용하여 Function Calling의 동작 원리에 집중합니다. 이 예제를 바탕으로 실제 API 연동이나 데이터베이스 조회로 확장할 수 있습니다.

다음 코드를 살펴봅시다.

@Configuration
public class WeatherFunctionConfig {

    @Bean
    @Description("특정 도시의 현재 날씨 정보를 조회합니다. " +
                 "기온, 날씨 상태, 습도 정보를 제공합니다.")
    public Function<WeatherRequest, WeatherResponse> getWeather() {
        return request -> {
            // 실제로는 외부 API를 호출하지만, 예제에서는 Mock 데이터 사용
            Map<String, WeatherData> mockData = Map.of(
                "서울", new WeatherData("맑음", 22, 45),
                "부산", new WeatherData("흐림", 19, 65),
                "제주", new WeatherData("비", 18, 80)
            );

            WeatherData data = mockData.getOrDefault(
                request.city(),
                new WeatherData("정보없음", 0, 0)
            );

            return new WeatherResponse(
                request.city(),
                data.condition(),
                data.temperature() + "°C",
                data.humidity() + "%"
            );
        };
    }

    record WeatherData(String condition, int temperature, int humidity) {}
}

드디어 모든 조각을 맞춰볼 시간입니다. 김개발 씨가 처음부터 차근차근 날씨 조회 기능을 구현해봅니다.

먼저 의존성 설정부터 시작합니다. Spring AI를 사용하려면 build.gradle이나 pom.xml에 spring-ai-openai-spring-boot-starter 같은 의존성을 추가해야 합니다.

그리고 application.yml에 OpenAI API 키를 설정합니다. 이 부분은 프로젝트마다 다를 수 있으니 공식 문서를 참고하세요.

WeatherRequestWeatherResponse를 정의합니다. 앞서 배운 대로 @JsonClassDescription과 @JsonPropertyDescription을 활용하여 상세한 설명을 추가합니다.

AI가 이 함수를 언제 사용해야 하는지, 어떤 파라미터가 필요한지 명확하게 알 수 있도록 합니다. 함수 Bean을 등록합니다.

위 코드가 핵심입니다. @Configuration 클래스 안에 @Bean으로 함수를 정의합니다.

@Description으로 함수의 용도를 설명하고, 실제 로직은 람다 표현식 안에 작성합니다. 이 예제에서는 Mock 데이터를 사용했지만, 실무에서는 RestTemplate이나 WebClient로 외부 날씨 API를 호출하면 됩니다.

에러 처리도 고려해야 합니다. mockData.getOrDefault를 사용하여 지원하지 않는 도시에 대한 요청도 처리하고 있습니다.

실제 API를 사용할 때는 네트워크 오류, 타임아웃, 잘못된 응답 등 다양한 예외 상황을 처리해야 합니다. try-catch로 감싸고, 사용자에게 친절한 에러 메시지를 반환하도록 합니다.

컨트롤러에서 이 함수를 사용하는 방법은 간단합니다. ChatClient를 주입받고, prompt().user(message).functions("getWeather").call()을 호출하면 됩니다.

Spring AI가 나머지를 모두 처리해줍니다. 사용자가 "서울 날씨 알려줘"라고 하면 getWeather 함수가 자동으로 호출되고, 결과가 자연스러운 문장으로 변환되어 반환됩니다.

테스트도 잊지 마세요. @SpringBootTest로 통합 테스트를 작성하거나, 함수 자체를 단위 테스트할 수 있습니다.

함수 로직이 복잡해지면 별도의 서비스 클래스로 분리하고, 그 서비스를 테스트하는 것이 좋습니다. 김개발 씨가 처음으로 완성한 Function Calling 기능을 테스트해봅니다.

"서울 날씨 어때?"라고 입력하니, "서울의 현재 날씨는 맑고, 기온은 22도, 습도는 45%입니다"라는 응답이 돌아왔습니다. "드디어 됐다!" 김개발 씨의 얼굴에 미소가 번졌습니다.

박시니어 씨가 어깨를 두드리며 말했습니다. "축하해요.

이제 이 패턴을 응용해서 주문 조회, 상품 검색, 예약 시스템 등 다양한 기능을 만들 수 있어요. 기본기를 잘 익혀놨으니 확장은 어렵지 않을 거예요."

실전 팁

💡 - 처음에는 Mock 데이터로 시작하고, 로직이 안정되면 실제 API로 교체하세요.

  • 함수가 많아지면 별도의 패키지로 분리하여 관리하는 것이 좋습니다.
  • 로그를 남겨서 AI가 어떤 함수를 어떤 파라미터로 호출했는지 추적할 수 있게 하세요.

이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!

#Spring#FunctionCalling#SpringAI#ChatGPT#LLM#Spring,AI,FunctionCalling

댓글 (0)

댓글을 작성하려면 로그인이 필요합니다.

함께 보면 좋은 카드 뉴스

vLLM 통합 완벽 가이드

대규모 언어 모델 추론을 획기적으로 가속화하는 vLLM의 설치부터 실전 서비스 구축까지 다룹니다. PagedAttention과 연속 배칭 기술로 GPU 메모리를 효율적으로 활용하는 방법을 배웁니다.

AI 에이전트 스킬 라이브러리와 도구 학습 완벽 가이드

AI 에이전트가 다양한 스킬을 동적으로 로드하고 조합하여 복잡한 작업을 수행하는 방법을 알아봅니다. 스킬 아키텍처 설계부터 도메인 특화 개발까지, 실무에서 바로 적용할 수 있는 패턴을 다룹니다.

Context & Memory 패턴 기초 완벽 가이드

AI 에이전트의 핵심인 컨텍스트와 메모리 관리 패턴을 초급자도 이해할 수 있도록 설명합니다. 슬라이딩 윈도우부터 장기 메모리까지, 실무에서 바로 적용할 수 있는 6가지 핵심 패턴을 다룹니다.

AI 에이전트 패턴 완벽 가이드

LLM 기반 AI 에이전트를 프로덕션 환경에서 성공적으로 구축하기 위한 핵심 패턴들을 소개합니다. 튜토리얼과 실제 제품 사이의 간극을 메우고, 8가지 카테고리로 정리된 패턴들을 통해 실무에서 바로 적용할 수 있는 지식을 전달합니다.

MCP Sampling 완벽 가이드

Model Context Protocol의 Sampling 기능을 통해 AI 응답의 품질과 다양성을 제어하는 방법을 알아봅니다. 프롬프트 샘플링부터 A/B 테스팅까지 실무에서 바로 적용할 수 있는 기법을 다룹니다.