
30분 만에 나만의 AI 채팅 앱 만들기
요약
Strands SDK와 AgentCore를 사용하여 30분 만에 AWS 기반의 AI 채팅 앱을 구축하는 튜토리얼입니다. Amazon Bedrock의 Nova Micro 모델을 활용하여 저렴한 비용으로 작동하는 에이전트 인프라를 구성하는 방법을 다룹니다.
핵심 포인트
- Strands SDK와 AgentCore를 이용한 간편한 에이전트 배포
- Amazon Bedrock(Nova Micro)을 활용한 저비용 AI 백엔드 구축
- TypeScript와 CLI 명령어를 통한 서버리스 환경 구성
- 코딩 에이전트를 활용한 AWS 환경 설정 자동화 방법
모든 개발자의 첫 번째 웹사이트는 Hello World였습니다. 약간의 HTML, 아마도 CSS 파일 하나를 작성하고 어딘가에 배포하면, 자신의 작업물이 인터넷에 라이브로 올라가는 것을 보며 짜릿함을 느꼈을 것입니다.
AI 시대에 새로운 Hello World는 채팅 앱입니다.
여전히 기본적인 index.html로 시작합니다. 하지만 정적인 텍스트 대신, 이를 백엔드 AI에 연결하면 갑자기 실제로 대답을 하는 무언가를 갖게 됩니다. 그것이 바로 오늘 우리가 만들 것입니다.
기술 스택: 에이전트(Agent)를 위한 Strands SDK, 이를 AWS에 호스팅하기 위한 AgentCore, 모델 선택을 위한 Bedrock, 그리고 AI와 통신하기 위해 프록시(Proxy)를 호출하는 간단한 HTML 프론트엔드입니다. 하나의 TypeScript 파일, 몇 가지 CLI 명령어, 그리고 index.html 하나면 충분합니다.
마지막에는 Amazon Bedrock의 모델(매우 저렴한 Amazon Nova Micro를 사용할 것입니다)을 백엔드로 사용하며, 호스팅된 엔드포인트(Endpoint)에 배포되어 대화당 1센트의 아주 적은 비용만 발생하는 작동 가능한 채팅 인터페이스를 갖게 될 것입니다. 그리고 이것은 메모리(Memory), 인증(Authentication), 문서 Q&A, 가드레일(Guardrails) 등 다음에 올 모든 것의 기초가 됩니다. 하지만 오늘은 아주 단순하게 유지하겠습니다.
사고 모델 (Mental Model): 에이전트는 모델 + 프롬프트이다
코드를 만지기 전에, 우리가 무엇을 만들고 있는지 살펴보겠습니다:
브라우저 (HTML + JS) → AgentCore 런타임 (호스팅된 엔드포인트) → Strands 에이전트 → Bedrock (Nova Micro)
TypeScript로 Strands 에이전트를 작성합니다. AgentCore CLI가 이를 호스팅된 엔드포인트로 배포합니다. 프론트엔드는 해당 엔드포인트로 메시지를 보냅니다.
Lambda 함수도 필요 없고, API Gateway도 필요 없으며, Docker도 필요 없습니다. 오직 TypeScript와 몇 가지 CLI 명령어뿐입니다.
1단계: 환경 설정
AWS 계정, Node.js 22 이상, 그리고 npm이 필요합니다.
빠른 경로: 코딩 에이전트(Claude Code, Cursor, Kiro, Codex)를 사용한다면, Agent Toolkit for AWS가 자격 증명(Credentials), CLI 도구 및 아래의 모든 과정을 대신 처리해 줍니다. 에이전트에게 AWS 액세스 설정을 요청하기만 하면 단계별로 진행할 것입니다.
# 코딩 에이전트가 다음과 유사한 명령을 실행할 것입니다:
aws configure agent-toolkit
또는, 수동으로 진행하기:
AWS 자격 증명을 설정하세요:
# AWS CLI 설치 (설치되어 있지 않은 경우)
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip && sudo ./aws/install
...
자격 증명(credentials) 설정이 완료되면, AgentCore CLI와 AWS CDK를 설치하세요 (AgentCore는 인프라 배포를 위해 내부적으로 CDK를 사용합니다):
# AgentCore CLI
npm install -g @aws/agentcore
...
이것으로 툴체인(toolchain) 준비가 끝났습니다.
Step 2: 프로젝트 스캐폴딩 (Scaffold the project)
단 한 번의 명령어로 전체 프로젝트의 스캐폴딩(scaffold)을 수행할 수 있습니다:
agentcore create --name MyAgent --no-agent
cd MyAgent
agentcore add agent \
...
각 플래그(flag)의 역할:
--name– 프로젝트/에이전트 이름 (영문자 및 숫자 조합, 문자로 시작, 최대 36자).--build– 배포 아티팩트(artifact) 유형.CodeZip은 직접적인 코드 배포를 의미합니다 (Docker 미사용).--framework– 에이전트 프레임워크 (agent framework). 지원되는 값:Strands,LangChain_LangGraph,GoogleADK,OpenAIAgents.--language– 생성될 코드의 언어. 지원되는 값:TypeScript,Python.--model-provider– 모델 제공자 (model provider). 지원되는 값:Bedrock,Anthropic,OpenAI,Gemini.--memory– 메모리 설정 (memory configuration). 지원되는 값:none,shortTerm,longAndShortTerm.
또는 플래그를 완전히 생략하고 인자 없이 agentcore create를 실행할 수 있습니다. 그러면 각 옵션을 안내하는 대화형 위저드(interactive wizard)가 시작됩니다.
다음과 같은 구조를 얻게 됩니다:
MyAgent/
├── agentcore/
│ ├── agentcore.json # 프로젝트 설정 (Project config)
...
Step 3: 에이전트 작성하기
스캐폴딩을 통해 즉시 실행 가능한 에이전트를 얻을 수 있습니다.
// app/MyAgent/main.ts
import { BedrockAgentCoreApp } from 'bedrock-agentcore/runtime';
...
이것이 전부입니다. 약 20줄 정도입니다.
세 가지 핵심 요소:
- 에이전트 생성 (Create an agent): 모델과 시스템 프롬프트(system prompt)를 사용하여 에이전트를 생성합니다.
- 서버 연결 (Wire it to the server):
BedrockAgentCoreApp을 사용하여 서버에 연결합니다. 이는 런타임(runtime)이 기대하는 HTTP 엔드포인트(endpoints)를 처리합니다. - 토큰 스트리밍 (Stream tokens back):
agent.stream()을 반복(iterate)하고 각 텍스트 델타(text delta)를 생성(yield)하여 토큰을 다시 스트리밍합니다.
loadModel()은 기본적으로 Amazon Nova Micro(Bedrock에서 가장 저렴한 텍스트 모델로, 대화당 비용이 1센트의 아주 작은 일부 수준임)를 가리킵니다. Claude Sonnet이나 더 무거운 모델을 사용하고 싶다면 model/load.ts에서 모델 ID를 교체하세요. 저장소(repo)의 전체 버전에는 각 대화가 자체 기록을 유지할 수 있도록 세션별 캐싱(per-session caching) 기능이 추가되어 있지만, 응답을 스트리밍(streaming)하기 위해서는 이 정도만 있어도 충분합니다.
Step 4: 로컬에서 테스트하기
어딘가에 배포하기 전에, 사용자의 컴퓨터에서 실행해 보세요:
agentcore dev
별도의 터미널에서:
agentcore dev "What is the capital of France?"
이 명령은 의존성(dependencies)을 설치하고, TypeScript를 컴파일하며, 8080 포트에서 로컬 서버를 시작합니다. 또한 에이전트와 채팅할 수 있는 브라우저 기반 인스펙터(inspector)를 엽니다. 두 번째 터미널에서 응답이 스트리밍되는 것을 볼 수 있어야 합니다. 이것이 작동한다면 에이전트가 정상적으로 실행되는 것입니다.
패키지를 가져오고 컴파일하는 동안 첫 실행에는 시간이 약간 소요됩니다. 그 이후에는 핫 리로드(hot reload)를 통해 거의 즉각적으로 작동합니다.
Step 5: AWS에 배포하기
단 한 줄의 명령으로 가능합니다:
agentcore deploy
CLI는 다음 작업을 수행합니다:
- TypeScript를 컴파일하고 CodeZip 아카이브로 패키징합니다.
- CDK를 사용하여 CloudFormation (Infrastructure as Code) 리소스를 합성(synthesize)하고 배포합니다.
- IAM 역할(roles)과 AgentCore 런타임(Runtime) 엔드포인트를 생성합니다.
- CloudWatch 로깅을 구성합니다.
CDK가 계정을 부트스트랩(bootstrap)하는 동안 첫 배포에는 몇 분이 소요됩니다. 이후의 배포는 더 빠릅니다. agentcore deploy --dry-run을 실행하여 배포 없이 변경 사항을 미리 볼 수 있습니다.
배포된 에이전트를 테스트하세요:
agentcore invoke "Hello! What can you help me with?"
실시간으로 응답을 스트리밍하세요:
agentcore invoke "Tell me a joke" --stream
응답이 보인다면, 에이전트가 AWS에서 라이브 상태로 작동 중인 것입니다.
Step 6: 프론트엔드
단 하나의 HTML 파일입니다. 빌드 단계도, npm install도 필요 없습니다.
로컬 개발 중에는 이 프론트엔드가 개발 서버(agentcore dev, 8080 포트)와 통신합니다. 프로덕션(production) 환경의 경우, 저장소에는 브라우저가 배포된 에이전트에 접속할 수 있도록 SigV4 서명(signing)을 처리하는 Lambda 프록시(proxy)가 포함되어 있습니다. 이에 대한 내용은 Step 7에서 다룹니다.
프론트엔드의 핵심은 하나의 함수입니다:
// 에이전트를 호출하고 응답을 스트리밍합니다
async function send(text, onToken) {
const res = await fetch("http://localhost:8080/invocations", {
...
이 과정에서 제가 겪었던 두 가지 문제가 있어 짚고 넘어갈 가치가 있습니다. 서버는 Accept: text/event-stream 헤더를 필수적으로 요구합니다. 이 헤더가 없으면 스트림 대신 JSON 에러 객체를 받게 됩니다. 또한 응답은 단일 JSON 블록이 아닙니다. JSON으로 인코딩된 토큰 문자열의 SSE (Server-Sent Events) 스트림입니다. 그 대가로 ChatGPT 스타일의 토큰 단위 렌더링을 무료로 얻을 수 있습니다.
나머지는 채팅창처럼 보이게 만들기 위한 HTML과 CSS일 뿐입니다. 전체 index.html (다크 테마, 채팅 버블, 엔터 키로 전송 기능 포함)은 리포지토리(repo)에 있습니다. 클론(Clone)한 뒤, agentcore dev를 실행하고 브라우저에서 파일을 여세요. 그것이 바로 당신의 ChatGPT입니다.
# 프론트엔드 가져오기
git clone https://github.com/tmoreton/tutorials
open tutorials/index.html
Step 7: GitHub Pages로 프론트엔드 배포하기
리포지토리를 GitHub에 푸시(Push)하세요:
git init
git add .
git commit -m "initial commit"
...
그 다음 GitHub의 리포지토리로 가서 Settings > Pages를 클릭하고, 소스(source)를 "Deploy from a branch"로 설정한 뒤, main과 / (root)를 선택하고 Save를 누르세요:
잠시 기다리면 당신의 앱이 https://YOUR_USERNAME.github.io/my-ai-chat에서 라이브 상태가 됩니다. HTTPS, 무료 호스팅, 그리고 푸시할 때마다 자동으로 배포됩니다.
리포지토리에는 브라우저를 대신하여 AgentCore Runtime으로의 요청에 서명(sign)을 수행하는 CloudFront 뒤의 작은 스트리밍 Lambda 프록시(proxy/)가 포함되어 있습니다. 호스팅된 프론트엔드는 localhost 대신 이 프록시와 통신합니다. cd proxy && cdk deploy로 배포하고, index.html의 ENDPOINT 상수를 당신의 CloudFront URL로 업데이트하세요.
CloudFront OAC 설정에는 몇 가지 까다로운 점이 있습니다. 바로 x-amz-content-sha256 헤더와 이중 호출 권한(double invoke permission) 문제입니다. 프록시(proxy) README에서 이 두 가지를 모두 다룹니다. 제가 오후 시간을 통째로 써서 해결했으니, 여러분은 그럴 필요 없도록 정리해 두었습니다.
주의해야 할 몇 가지 사항
응답은 JSON이 아니라 스트림(stream)입니다. 에이전트 서버는 서버 전송 이벤트(Server-Sent Events, SSE) 방식으로 통신하며, Accept: text/event-stream 헤더를 필요로 합니다. 만약 프론트엔드에서 깔끔한 {result: "..."} 객체를 기대하며 res.json()을 호출하려고 하면, 대신 에러를 받게 될 것입니다. 스트림을 읽어야 합니다 (단계 6 참조).
배포된 엔드포인트는 프록시를 통해서만 접근할 수 있습니다. AgentCore는 SigV4 서명된 요청을 요구하는데, 브라우저는 이를 기본적으로 수행할 수 없습니다. proxy/에 있는 Lambda 프록시가 이 작업을 대신 처리해 줍니다. 클라이언트 측 JS에서 직접 서명하려고 하지 마세요. 페이지 소스 코드에 AWS 자격 증명(credentials)을 포함해 배포하는 꼴이 됩니다.
동시 호출을 제한하세요. 이 엔드포인트는 인증을 거치지 않으므로, URL을 아는 사람이라면 누구나 호출할 수 있습니다. 예상치 못한 청구서를 받지 않도록 Lambda 프록시에 동시성 제한(concurrency limit)을 설정하거나 CloudFront에 스로틀링(throttling)을 추가하세요.
전체 구조
| 계층 (Layer) | 내용 | 방식 |
|---|---|---|
| 모델 (Model) | Amazon Nova Micro (교체 가능) | Amazon Bedrock |
| ... |
현재 대화 기록은 메모리(memory)에 저장되므로, 프로세스가 재시작되면 사라집니다. 다음 포스트에서는 세션과 재시작 간에도 지속적인 유지가 가능하도록 AgentCore Memory를 추가해 보겠습니다.
정리하기
작업을 마친 후 AWS 리소스를 삭제하고 싶다면 다음 명령어를 사용하세요:
agentcore remove all
agentcore deploy
첫 번째 명령은 설정을 초기화합니다. 두 번째 명령은 빈 상태를 배포하여 CloudFormation 스택을 제거합니다.
소스 코드
이 튜토리얼의 전체 코드는 GitHub에서 확인할 수 있습니다 →
이 내용이 도움이 되었다면 계속 팔로우해 주세요. 다음 포스트는 다음 주에 올라옵니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기