나의 첫 Proof of Concept 그리고 감상 젖은 회고

pigpgw·2025년 11월 14일

PoC

목록 보기
1/1

이번에는 회사 프로젝트를 통해 처음으로 POC(Proof of Concept)를 직접 진행해보았습니다. 제가 맡은 주제는 Amazon Lex V2였고그 과정에서 얻은 경험과 인사이트를 정리한 내용입니다.

Amazon Lex란?

Amazon Lex는 Amazon Alexa와 동일한 딥러닝 기술을 기반으로 자연어 음성/텍스트 인터페이스를 손쉽게 구축할 수 있는 AWS 서비스입니다. AWS 관리형 서비스로, 음성을 텍스트로 변환하는 ASR(Automatic Speech Recognition) 과 입력 텍스트의 의도를 추론하는 NLU(Natural Language Understanding) 기능을 제공합니다.

간단히 말해, Lex는 자연어 처리(NLP) 기술을 활용하여 간단한 대화형 인터페이스부터 복잡한 대화 흐름을 처리하는 지능형 챗봇까지 손쉽게 구축할 수 있게 해주는 서비스입니다.

Amazon Lex의 주요 특징

  • 음성과 텍스트 기반 대화형 인터페이스: Alexa와 동일한 대화형 엔진을 사용하여 고품질 음성 인식 및 언어 이해 기능 제공
  • 다중 플랫폼 지원: 모바일 기기 및 Facebook Messenger, Slack, Kik, Twilio SMS 등 다양한 채팅 서비스에 게시가 가능합니다
  • AWS 서비스 통합: Lambda, CloudWatch, Cognito, DynamoDB, Polly(TTS) 등과 간편한 통합

Amazon Lex의 주요 사용 사례

  • 셀프 서비스 음성 지원 및 챗봇: 콜센터 봇 구축
  • 정보 봇: 질문에 답변하는 자동화된 고객 지원 에이전트
  • 애플리케이션/트랜잭션 봇: 독립형 주문 에이전트 또는 여행 봇
  • 엔터프라이즈 생산성 봇: 엔터프라이즈 데이터 리소스에 연결하기 위한 맞춤형 봇
  • 장치 제어 봇: 연결된 장치에 제어 명령 전달

Amazon Lex 봇 기본 지식

Lex는 규칙 기반 챗봇으로, 정해진 응답을 제공하는 구조입니다. Amazon Lex 구성 요소는 크게 5가지로 나뉩니다.

의도(Intent)

사용자가 수행하고자 하는 작업을 의미합니다. 예를 들어 사용자가 "영화 추천을 받고 싶어 합니다"는 의도를 가집니다.

발화(Utterance)

사용자가 입력할 수 있는 자연어 문장으로, 의도를 트리거합니다. 예: "영화 추천해줘", "재밌는 영화 추천해줘"

확인 프롬프트(Prompt)

요청된 작업을 완료하는데 필요한 데이터를 가져오도록 설계된 봇 메시지입니다. 예: "장르를 선택해주세요"

슬롯(Slot)

의도를 처리하기 위해 사용자가 입력해야 하는 데이터입니다. 프롬프트에 대한 대답으로 "액션"을 입력하면 "장르"라는 슬롯에 사용자가 입력한 "액션"이 채워집니다.

이행(Fulfillment)

슬롯의 데이터를 통해 사용자의 요청을 처리하고 응답을 생성하는 단계입니다. 예: AWS Lambda를 사용해 추천 영화를 반환합니다.

Lex 콘솔에서는 이 5가지 요소를 정의하여 챗봇의 흐름을 구성합니다. 예를 들어 사용자가 "영화 추천해줘"라고 입력하면 미리 정의한 영화추천 Intent가 실행되고, 필요한 슬롯 "장르"가 없을 경우 "장르를 선택해주세요"와 같은 프롬프트를 통해 정보를 더 수집합니다.

Lex 봇은 개발자가 제공한 샘플 발화들을 기반으로 작동하며, 사전에 정의된 응답을 제공하는 규칙 기반 구조입니다.

지원 언어

Lex V2는 한국어(ko-KR)를 포함한 27개 언어를 지원합니다:

  1. Arabic (AE) – 아랍어 (아랍에미리트)
  2. Cantonese (HK) – 광둥어 (홍콩)
  3. Catalan (ES) – 카탈루냐어 (스페인)
  4. Dutch (NL) – 네덜란드어
  5. English (AU) – 영어 (호주)
  6. English (GB) – 영어 (영국)
  7. English (IN) – 영어 (인도)
  8. English (US) – 영어 (미국)
  9. English (ZA) – 영어 (남아프리카공화국)
  10. Finnish (FI) – 핀란드어
  11. French (CA) – 프랑스어 (캐나다)
  12. French (FR) – 프랑스어 (프랑스)
  13. German (AT) – 독일어 (오스트리아)
  14. German (DE) – 독일어 (독일)
  15. Hindi (IN) – 힌디어 (인도)
  16. Italian (IT) – 이탈리아어
  17. Japanese (JP) – 일본어
  18. Korean (KR) – 한국어
  19. Mandarin (PRC) – 중국 표준어 (중국 본토)
  20. Norwegian (NO) – 노르웨이어
  21. Polish (PL) – 폴란드어
  22. Portuguese (BR) – 포르투갈어 (브라질)
  23. Portuguese (PT) – 포르투갈어 (포르투갈)
  24. Spanish (ES) – 스페인어 (스페인)
  25. Spanish (LATAM) – 스페인어 (라틴아메리카)
  26. Spanish (US) – 스페인어 (미국)
  27. Swedish (SE) – 스웨덴어

API 호출 방법

  • PoC를 진행하면서 문득 Api로 붙여서 해보고싶다! 라는 생각이 들어서 이번 기회에 aws를 api로 붙이는 방법을 조금 공부해 보았습니다.

엔드포인트 구조

AWS Runtime API는 지역별 endpoint + 서비스별 경로 조합으로 구성됩니다.

지역별 엔드포인트

${protocol}://${service-code}.${region-code}.amazonaws.com
  • ${protocol}https
  • ${service-code} → 서비스 코드 (Lex V2 Runtime은 runtime-v2-lex)
  • ${region-code}ap-northeast-2 등 리전

예: https://runtime-v2-lex.ap-northeast-2.amazonaws.com

RecognizeText API 경로

  • Method: POST
  • Headers: Content-Type: application/json
  • Path: /bots/{botId}/botAliases/{botAliasId}/botLocales/{localeId}/sessions/{sessionId}/text

Postman에서 AWS API 호출하기

AWS API를 처음 연동할 때 가장 헷갈렸던 부분이 바로 Authorization 설정이었습니다. AWS API는 AWS Signature를 사용한 인증이 필요합니다.

Authorization 설정

Postman에서 AWS API를 호출하려면 다음 설정이 필요합니다:

  • Auth Type: AWS Signature
  • AccessKey: IAM 사용자 Access Key ID
  • SecretKey: IAM 사용자 Secret Access Key
  • AWS Region: ap-northeast-2 등 리전 코드
  • Service Name: lex (Lex V2 Runtime의 경우)

Postman이 자동으로 AWS Signature V4를 생성하여 요청 헤더에 추가해줍니다. 이를 통해 별도의 SDK 없이도 AWS API를 직접 호출할 수 있습니다.

Lex가 대화를 처리하는 방식

Lex가 사용자 입력을 어떻게 처리하는지 간단히 설명하면 다음과 같습니다.

사용자 입력

사용자가 텍스트를 입력하면 (RecognizeText 또는 음성 입력 시 RecognizeUtterance), 입력된 텍스트는 Lex의 머신러닝 모델로 분석됩니다.

Intent 분석

Lex가 입력을 분석하여 가장 근접한 Intent를 결정합니다. 예: GreetingIntent, ReportIssueIntent, AskInfoIntent

Intent 상태(sessionState.intent.state):

  • InProgress: 슬롯이 아직 채워지지 않은 상태
  • ReadyForFulfillment: 모든 슬롯이 채워져 이행 준비 완료
  • Fulfilled: 모든 슬롯이 채워지고, 기본 응답까지 완료된 상태

슬롯(Slot) 처리

Intent를 수행하는 데 필요한 정보 조각입니다. Lex가 등록된 순서대로 슬롯 질문을 사용자에게 던집니다. 사용자 답변으로 슬롯 값이 채워지고, 모든 슬롯이 채워지면 Intent 상태가 Fulfilled로 변경됩니다.

세션(Session) 관리

Lex가 자동으로 관리하며, sessionState 객체에 현재 상태를 저장합니다:

  • 진행 중인 Intent
  • 채워진 슬롯
  • 세션 속성(sessionAttributes)
  • 컨텍스트(activeContexts)

세션 ID를 사용하면 같은 사용자가 대화를 이어갈 수 있습니다. 예: 하루 뒤, 일주일 뒤에도 같은 세션 ID로 대화 가능합니다. 필요 시 PutSession API를 사용해 세션 상태를 강제로 수정할 수 있습니다.

전체 흐름 요약

사용자 입력
    ↓
[RecognizeText]
    ↓
Intent 판단
    ↓
슬롯 질문 → 사용자 답변 반복
    ↓
Intent Fulfilled
    ↓
(Optional) Lambda 호출

세션 타임아웃과 지속성 문제

Lex V2의 세션은 기본적으로 세션 타임아웃(Session Timeout)이 설정되어 있습니다. 기본 세션 타임아웃은 5분이며, 설정 시 최대 24시간(1,440분)까지 연장이 가능합니다.

세션이 만료되면 Intent/Slot 상태가 모두 초기화되며, 과거 정보를 유지하려면 외부 저장소(DB 등)에 별도로 상태를 저장해야 합니다.

예를 들어, 쇼핑 챗봇에서 사용자가 제품 색상만 입력한 후 5분 동안 응답하지 않으면 세션이 종료되고 상태가 리셋됩니다.

Fulfillment(백엔드 처리) 중에도 별도 타임아웃이 존재하며, 최대 15분(900초)까지 가능합니다.

세션 만료 시 문제점

  • 기본값: 5~10분
  • 타임아웃 이후 세션은 자동으로 종료되고, 세션 상태(sessionState)는 사라집니다.

즉, 같은 sessionId를 사용한다고 해도, 세션이 만료되면 이전 대화 상태는 유지되지 않습니다.

만약 하루, 일주일 뒤에도 이어서 대화를 하고 싶다면, PutSession API로 이전 상태를 저장해두고 복원해야 합니다.

예: sessionStatesessionAttributes를 DB에 저장 → 사용자가 돌아왔을 때 PutSession으로 복원

핵심 포인트:

  • 단순히 같은 세션 ID를 쓰는 것만으로는 오래 지난 대화 이어가기가 불가능합니다
  • 세션 상태를 외부 저장소(DB 등)에 저장 후 복원해야 가능합니다

영구 대화 저장의 필요성

Lex의 한계점

Lex 자체는 "이전 대화 불러오기" 기능을 내장하지 않습니다. 세션이 만료되면 Lex 내부 상태는 사라지므로, 장기 대화 저장 및 "이전 대화 이어가기"를 위해서는 외부 저장소가 필요합니다.

예시: DynamoDB 또는 S3에 sessionId, user_input, bot_response, timestamp 등을 저장 → 사용자 재입장 시 이전 이력 불러오기

Lex의 sessionAttributes는 세션 만료 후 보존되지 않습니다.

영구 저장 구현 전략

이력 기반 대화나 AI 응답 생성을 하려면 다음이 필요합니다:

  1. Lex → Lambda → 외부 저장소(DynamoDB, S3 등)에 대화 로그 저장
  2. LLM 호출 시 최근 N개 대화 이력 전달
  3. 세션 만료 후 재입장 시 이전 로그 불러와 세션 복원 API로 복원

Lex API + 외부 데이터 저장소 조합으로 구현이 가능한것으로 보였습니다.

다중 채널/세션 관리

세션별 기록은 가능하고 세션 ID가 제공됩니다. 그러나 다음과 같은 기능은 자동 제공되지 않습니다:

  • "채널 1에서 한 대화를 채널 2로 이어서 한다"
  • "여러 과거 세션을 조회해 이어간다"

구현 방법 예시:

  1. 로그 데이터를 DB 또는 별도 저장소에 적재
  2. 사용자·세션 ID 기반으로 조회 가능하게 관리
  3. 조회 데이터를 PutSession 또는 RecognizeText 호출 시 포함하여 이어지는 대화처럼 처리
  4. 프론트엔드/백엔드에서 채널, 사용자, 세션 매핑 및 관리 로직 구현

세션 만료 후 대화 이어가기 구현

"사용자가 중간에 이탈해도 이전 대화를 이어갈 수 있는 챗봇"을 목표로 구현했습니다.

1단계: 대화 및 세션 상태 수집

사용자가 입력하면 RecognizeText 응답으로 Intent/Slot/sessionAttributes를 수집합니다. 이 정보가 세션 복원의 핵심이 됩니다.

2단계: 외부 저장소에 저장

DynamoDB 등에 { userId, sessionId, intent, slots, attributes, userUtterance, botResponse, timestamp } 형태로 저장합니다.

Lex는 대화 이력을 내부에 저장하지 않기 때문에, 기록은 개발자가 직접 수행해야 합니다.

3단계: 세션 복원

사용자가 재접속하면 DB에서 마지막 SessionState를 읽어 PutSession으로 Lex에 전달하여 그대로 복원합니다.

이렇게 하면 만료된 세션도 외부 저장 상태를 기반으로 다시 이어갈 수 있습니다.

구현 결과

• 사용자가 슬롯을 입력하다 나가도, 돌아오면 이전 슬롯 값이 그대로 복원됩니다
• Lex 기본 세션 기능을 확장하여 "지속적 대화(Persistent Conversation)"을 구현할 수 있음을 확인했습니다

Lex의 특성과 한계점

Lex로 GPT 같은 자유로운 챗봇을 만들 수 없는 이유

  • Lex는 사전 정의된 의도/슬롯 기반 구조와 정형화된 응답 중심으로 동작한다.
  • 반면 GPT와 같은 LLM은 수십억~수조 파라미터로 학습된 대규모 언어 모델로, 자유로운 문맥 이해, 새로운 문장 생성, 장기적인 대화 흐름 추적 등이 가능하여 정의되지 않은 범위 내에서도 자연스러운 대화가 가능해야한다.
  • 따라서 Lex는 IVR, 콜센터 챗봇, FAQ 자동화처럼 업무용 의도 기반 챗봇에는 최적화되어 있지만, GPT처럼 자유로운 언어 생성과 범용 대화 기능을 구현하기에는 구조적 한계가 있었습니다.

마무리 및 배운 점

이번 PoC를 진행하기 전에는 걱정이 많았습니다.
잘 알지 못하는 분야에서, 익숙하지 않은 서비스를 활용해 제한된 시간 안에 과연 결과를 만들어낼 수 있을지에 대한 불안이 컸습니다. 이러한 고민을 극복하기 위해, 이번 PoC에서는 AI를 적극적으로 활용해 보자는 결정을 내렸습니다.

저는 GPT 출시 초기부터 AI를 학습 도구로 활용해 왔습니다. 그만큼 AI 활용에 대해서는 나름의 가치관도 가지고 있었습니다.
AI를 사용하는 과정에서는 편리하지만, 막상 결과를 돌아보면 내 지식으로 온전히 남는 것이 있는가?라는 고민을 자주 했고, AI에 의존하면 지식과 경험의 깊이가 얕아질 수 있다는 생각에 다소 보수적인 태도를 갖고 있었습니다.

하지만 이번 경험을 통해 생각이 많이 바뀌었습니다.
AI를 부정적으로 바라보기보다는, 나만의 기준을 세우고 AI를 활용하는 방법을 계속 다듬어 나가는 것이 중요하다는 점을 깨달았습니다. 무작정 의존하는 것이 아니라, 방향을 판단하고 검증하는 역할은 결국 사람이 해야 한다는 것을 몸소 느꼈습니다.

프론트엔드 개발자로 잘 알려진 테오님의 블로그에서

“인간이 먼저 AI에게 대체되려고 하는 것은 아닐까?” 라는 문장을 접한 적이 있는데, 이 말이 이번 PoC 경험과 맞물리며 많은 생각을 하게 되었습니다.

개인적으로 테오님께 이력서 피드백을 받은 경험이 있는데, “잘하고있고 열심히하는 멋진 친구”라는 말씀을 들었을 때 큰 자극과 동기부여가 되었습니다.(자랑입니다 ㅎㅎ)
이번 PoC를 통해 느낀 배움과 고민을 바탕으로, 앞으로도 기술을 두려워하기보다 올바르게 활용하는 개발자로 성장해 나가고 싶습니다.

참고 링크

profile
https://www.pigpgw.cloud 로 이전합니다~

1개의 댓글

comment-user-thumbnail
2025년 12월 31일

POC를 맡다니...대단...ㄷㄷ

답글 달기