devOmnivore

챗봇 프로젝트의 진화 Dialogflow에서 GPT까지의 3년 여정

devOMNIVORE 2025. 3. 14. 00:06
반응형

프로젝트 현장에서의 실제 코드 예시와 설계를 덧붙였습니다. 챗봇 프로젝트를 새롭게 시작하거나, 기존 챗봇을 업그레이드하려는 분들이 참고하시면 좋겠습니다.

챗봇 프로젝트의 진화 Dialogflow에서 GPT까지의 3년 여정

챗봇 프로젝트 3년, 그리고 갑작스러운 GPT의 등장

3년 전, 회사에서 챗봇 프로젝트를 맡았습니다. 처음에는 도서관 정보를 키오스크 형태로 제공하는 챗봇을 납품하는 것으로 출발했죠. 텍스트 기반 질문에 대해, 인텐트(Intent)와 엔티티(Entity)를 사전에 정의해두고, 거기에 맞춰 답변해주는 전형적인 구조였습니다. 그러나 사람들의 질문 패턴은 생각보다 더 다양했고, 예상치 못한 질문에는 대답하지 못하거나 엉뚱한 답변을 내놓는 일이 잦았습니다.

그래서 두 번째 버전에서는 Dialogflow의 기능을 보다 적극적으로 활용해, 엔티티나 컨텍스트(Context) 관리를 확장하고 대화 흐름을 단계적으로 처리하도록 개선했습니다. 나아가 도서관의 특정 서비스를 API로 호출해, 챗봇이 단순 답변에 그치지 않고 실제 업무를 진행할 수 있게 만들었죠.

그렇게 제품을 어느 정도 완성도 높게 마무리했다고 생각했지만, GPT가 등장하면서 챗봇 기술 지형이 급격히 바뀌었습니다. GPT로 인해, 자연어 처리와 질의응답 능력이 이전보다 훨씬 매끄럽고 ‘사람다운’ 응답을 제공하게 되었으니까요.

 

 

🍳여기서 잠깐! Dialogflow 더 많이 알아보기

그렇다면, 기존에 우리가 쓰던 Dialogflow는 이제 “무쓸모”가 된 걸까요?
전혀 그렇지 않습니다. 현재 시점에서 GPT가 아무리 대단해도, ‘단계별 정보 습득과 수행’ 같은 작업에는 Dialogflow가 여전히 강점이 있습니다. 무엇보다 GPT만 쓰는 것은 비용 부담이 훨씬 클 수 있죠. 그래서 두 기술을 적절히 연동하여 서로의 장점을 살리는 것이 중요합니다.


1. Dialogflow를 활용한 챗봇 개발의 흐름

1) 초기 챗봇: 인텐트·키워드 매칭

  • 도서관 챗봇: 사용자 질문이 들어오면, 특정 키워드·인텐트를 매칭해 답변 제공.
  • 문제점: 사전에 정의되지 않은 질문에는 적절히 대응하지 못하거나, 아무런 답변을 못 하는 경우가 많았음.

2) Dialogflow 기능 확장

  • 엔티티(Entity)·컨텍스트(Context) 활용: 사용자의 대화 맥락을 기억해, 단계별로 정보를 축적하고 처리.
  • 자체 관리 툴 제작: 엔티티나 컨텍스트를 등록·수정·삭제하는 기능을 갖춘 백오피스 개발.

3) 서비스 API 연동

  • 도서관 특정 업무(도서 대출, 반납, 검색)를 챗봇에서 직접 처리할 수 있게 구현.
  • 단순 질의응답에서 벗어나, 업무 처리 프로세스까지 챗봇에 탑재.

이렇게 Dialogflow를 고도화해서 챗봇의 활용 범위를 확장했습니다. 그러나 자연어 처리 능력 자체는 GPT 이전과는 비교하기 어려웠죠.


2. GPT의 등장: 챗봇의 새로운 국면

1) GPT 연계의 의미

  • 원활한 질의응답: GPT가 탑재되면 예측 불가능한 질문에도 어느 정도 그럴싸한 답을 생성.
  • 기존 Dialogflow와의 차이: Dialogflow는 규칙과 인텐트 기반으로 “구조화된” 대화 흐름을 유도하기 좋지만, GPT는 “예측적이고 유연한” 대화에 강점이 있음.

2) Dialogflow vs. GPT: 여전히 공존 가능한 이유

  • 비용 측면: GPT API를 무작정 호출하면 비용이 만만치 않음.
  • 프로그램 같은 단계 처리: GPT는 자율적 대화는 잘하지만, 특정 업무 로직을 ‘단계별로’ 수행하는 데는 아직 약점이 있음(세션 관리, 액션, 맥락 유지 등).
  • AGI(Artificial General Intelligence) 시대가 오면 또 이야기가 달라질 수 있지만, 현재로서는 두 기술의 강점이 서로 다르기 때문에 결합이 최적.

3. Node.js (Nest.js) 기반 Dialogflow API 구현 예시

Dialogflow API를 Node.js로 연동한 예시 코드를 살펴봅시다. 프레임워크는 Nest.js를 사용해, Node.js의 단점을 줄이고 구조화된 코드를 작성했습니다.

import { Injectable, Inject } from '@nestjs/common';
import * as dialogflow from '@google-cloud/dialogflow';
import { readFileSync } from 'fs';
import { Logger } from 'winston';

@Injectable()
export class DialogflowService {
  private projectId: string;
  private sessionClient: any;

  constructor(@Inject('winston') private readonly logger: Logger) {
    // Google Cloud Platform에서 제공하는 키 파일 로드
    const keyFilePath = 'path/to/your/dialogflow-key.json';
    const keyFile = JSON.parse(readFileSync(keyFilePath, { encoding: 'utf-8' }));
    const credentials = {
      private_key: keyFile['private_key'],
      client_email: keyFile['client_email'],
    };

    this.projectId = keyFile['project_id'];
    this.sessionClient = new dialogflow.SessionsClient({ credentials });
  }

  /**
   * Dialogflow의 인텐트를 감지하여 사용자 입력에 응답
   * @param {string} sessionId - 세션 ID
   * @param {string} text - 사용자 입력 텍스트
   * @returns {Promise<object>} - Dialogflow 응답 결과
   */
  async detectIntent(sessionId: string, text: string): Promise<object> {
    try {
      const sessionPath = this.sessionClient.projectAgentSessionPath(this.projectId, sessionId);

      const request = {
        session: sessionPath,
        queryInput: {
          text: {
            text,
            languageCode: 'ko', // 한국어 설정
          },
        },
      };

      const [response] = await this.sessionClient.detectIntent(request);
      const result = response.queryResult;

      this.logger.info(`Query Text: ${result.queryText}`);
      this.logger.info(`Detected Intent: ${result.intent.displayName}`);
      this.logger.info(`Response Text: ${result.fulfillmentText}`);

      return result;
    } catch (error) {
      this.logger.error('Error detecting intent:', error);
      throw error;
    }
  }
}
  • 핵심 포인트: detectIntent 메서드에서 사용자 입력 텍스트를 Dialogflow에 전달, 해당 인텐트응답을 얻음.
  • 세션 관리: sessionId를 통해 사용자별 세션을 구분하여 대화 맥락을 유지.
  • 로그: winston 라이브러리로 질의 텍스트, 인텐트, 결과 응답을 로깅.

이를 통해, 특정 인텐트에 대응하는 로직(예: 데이터베이스 조회, 외부 API 호출)을 수행하고, 답변을 사용자에게 반환합니다.


4. GPT 연동으로 더욱 풍부해진 답변

1) Dialogflow + GPT 시나리오

  • Dialogflow: 사용자가 지금 무엇을 원하는지, 어떤 인텐트로 분류할지, 혹은 단계별 대화 흐름 중 어디에 있는지 파악.
  • GPT: Dialogflow에서도 처리하기 어려운(사전에 정의되지 않은) 자유로운 질문이 들어왔을 때 GPT API를 호출, 좀 더 ‘인간다운’ 답변을 생성.

아래 예시는 Dialogflow 상에서 인텐트 식별이 애매하거나, 특정 인텐트에 GPT를 활용하고자 할 때 사용되는 코드입니다. (Nest.js/Node.js 기반 가정)

async function handleDialogResponse(dialogInfo) {
    try {
        // 조건: dialogInfo.id가 존재하고 'gptCheckNeeds'가 아닌 경우만 실행
        if (dialogInfo.id && dialogInfo.id !== 'gptCheckNeeds') {
            console.log('dialogInfo.id:', dialogInfo.id);

            // API 엔드포인트 URL (환경 변수로 관리 권장)
            const url = process.env.API_URL || "http://gptservice.botfire:8029/datset";

            const requestBody = {
                msg: dialogInfo.msg, // 사용자 입력 메시지
                type: dialogInfo.id, // 인텐트 ID
                stream: false
            };

            const requestHeaders = {
                headers: {
                    'Content-Type': 'application/json'
                }
            };

            // GPT API 등 외부 서비스로 POST 요청
            const response = await this.httpService.axiosRef.post(url, requestBody, requestHeaders);
            const textResult = response.data['answer'];
            console.log('API 응답 메시지:', textResult);

            return textResult;
        } else {
            console.log('dialogInfo.id가 없거나 gptCheckNeeds와 일치합니다.');
            return null;
        }
    } catch (error) {
        console.error('API 요청 중 오류 발생:', error.message);
        throw error;
    }
}
  • 동작 원리:
    1. Dialogflow로부터 받은 dialogInfo에 따라, 특정 조건이면 GPT API 서비스에 요청을 보냄.
    2. GPT가 생성한 답변(answer)을 받아 사용자에게 전달.
    3. 만약 사전에 정의된 인텐트 흐름에서 크게 벗어나지 않는 상황이면, 굳이 GPT API를 호출할 필요가 없을 수도 있음 → 비용 절감.

2) 기대 효과

  • 기존 챗봇의 맥락 흐름: 여전히 Dialogflow가 관리(예: 도서관 예약 → 날짜 선택 → 인원 선택 → 완료 등).
  • GPT가 보강하는 자연스러운 대화: 사전에 없는 엉뚱한 질문에도 AI가 즉흥적으로 대답해줄 수 있음.
  • 사용자 경험(UX): “기획된 스텝”과 “자유 응답”이 동시에 가능해, 무작정 대화를 종료하지 않고 유연하게 이어감.

5. 프로젝트 회고: 3년간의 챗봇 개발

  • 처음 1년: 단순 키오스크 형태, 사전에 정해둔 키워드·인텐트만 대응 → 질문 범위가 제한적.
  • 2년 차: Dialogflow 엔티티·컨텍스트 확장, 단계적 대화 흐름, 서비스 API 연동 → 실제 업무 프로세스 처리 가능.
  • 3년 차: GPT 연동을 통해 기존 챗봇의 약점을 보완. AI가 더욱 자유로운 문맥 이해와 답변을 제공.

이제는 GPT의 출현으로 AGI(Artificial General Intelligence)에 대한 기대도 커지고 있습니다. 하지만 그 시기가 오기 전까지는, Dialogflow의 구조화된 흐름GPT의 유연한 응답을 병행하는 것이 가장 효율적이란 결론에 도달했습니다.


6. 마무리: 챗봇의 현재와 미래

  • Dialogflow가 무쓸모? 아니다. 단계별 처리, 구조화된 대화, 비용 효율 면에서 여전히 중요.
  • GPT 연동 가치: Open-domain 질의응답이나 사전에 정의되지 않은 질문 대응 등, 사용자 경험을 대폭 끌어올림.
  • 장기적 전망: 만약 AGI가 현실화되면, 대화형 에이전트가 기업 업무 전반을 자동화할 가능성도 있지만, 현재로서는 두 기술을 적절히 결합하는 것이 현실적으로 최선.

챗봇 프로젝트 3년을 돌아보면, 기술 발전이 얼마나 빠른지 실감합니다. “이제 완성!” 이라고 생각할 때쯤, 새로운 AI 모델이 등장해 개발 방향을 다시 재설정해야 하니까요. 그러나 그 과정에서 얻은 인사이트는 분명합니다.

인사이트

  • 구조화된 흐름(=Dialogflow)과 자연스러운 자유 응답(=GPT)을 어떻게 조화시키느냐가 현대 챗봇 프로젝트의 핵심.
  • 갑작스런 기술 변화에도 유연한 아키텍처확장 가능한 설계를 유지하면, 새로운 기능을 빠르게 붙일 수 있음.

지금까지의 경험을 토대로, 앞으로 챗봇이 더 다채로운 역할을 할 수 있으리라 기대합니다. GPT로 인해 많은 서비스가 큰 변화를 맞이하고 있지만, 챗봇만큼은 그 변화의 한복판에서 가장 흥미로운 진화를 거듭할 것입니다. 앞으로도 새로운 AI 모델이나 프레임워크가 나오면, 프로젝트 구조에 어떻게 적용할지 계속 고민하고 시도해야겠죠.

 

기획자·개발자·디자이너 모두가 함께 협력해 유연하면서도 견고한 챗봇을 만들어 나가길 바랍니다. 3년간의 경험을 바탕으로, 또 다른 혁신이 찾아올 때마다 빠르게 대응할 수 있을 것이고, 이 또한 챗봇 프로젝트가 계속 발전해가는 원동력이 될 것입니다.



Disclaimer: 본 블로그의 정보는 개인의 단순 참고 및 기록용으로 작성된 것이며, 개인적인 조사와 생각을 담은 내용이기에 오류가 있거나 편향된 내용이 있을 수 있습니다.

반응형