๐ฏ Strands ํ๋ก๋์
์บ์ฑ, ์คํธ๋ฆฌ๋ฐ, ๋ฐฐํฌ
Strands ํ๋ก๋์
์บ์ฑ ยท ์คํธ๋ฆฌ๋ฐ ยท ๋ฐฐํฌ
์์ด์ ํธ๋ฅผ ํ๋ก๋์ ์ ์ฌ๋ฆฐ๋ค
ํ๋กฌํํธ ์บ์ฑยท์คํธ๋ฆฌ๋ฐยท๋ฐฐํฌ ํ๊ฒ โ ๋น์ฉ๊ณผ ์๋ ์ต์ ํ
ํ๋ก๋์ ์ ํ
๋น์ฉ ยท ์๋ ยท ์ธํ๋ผ 3์ถ ์ต์ ํ
ํ๋ก๋์ ์ ํ
PoC๋ฅผ ํ๋ก๋์ ์ผ๋ก ์ฌ๋ฆด ๋ ๋ง์ฃผํ๋ ์ธ ๊ฐ์ง ์ต์ ํ ๊ณผ์
๋น์ฉ ยท ์๋ ยท ์ธํ๋ผ
PoC์์ ํ๋ก๋์ ์ผ๋ก ์ ํํ ๋ ๋น์ฉยท์๋ยท์ธํ๋ผ ์ธ ์ถ์ ํจ๊ป ์ต์ ํํฉ๋๋ค.
- ํ๋กฌํํธ ์บ์ฑ โ cache hit ์ ์ ๋ ฅ ํ ํฐ 90% ์ ๊ฐ
- ์คํธ๋ฆฌ๋ฐ โ TTFT(Time To First Token) ์ต์ํ
- ๋ฐฐํฌ ํ๊ฒ โ Lambda ยท Fargate ยท AgentCore Runtime
- ๊ณต์ 15์ข ํ๋ก๋ฐ์ด๋ โ ๋ฒค๋ ์ข ์ ์๋ ๋ฐฐํฌ ์ ๋ต
์บ์ฑ์ด ๋น์ฉ์, ์คํธ๋ฆฌ๋ฐ์ด ์๋๋ฅผ, ๋ฐฐํฌ ํ๊ฒ์ด ์ธํ๋ผ๋ฅผ ๋ด๋นํฉ๋๋ค โ ํํธ 2 ยท 3 ยท 4๊ฐ ์ถ ํ๋์ฉ ๋ค๋ฃน๋๋ค.
ํ๋ก๋์ ์ต์ ํ 3์ถ
PoC์์ ํ๋ก๋์ ์ผ๋ก ์ ํํ ๋ ๋ฐ๋์ ํด๊ฒฐํด์ผ ํ๋ ๋น์ฉยท์๋ยท์ธํ๋ผ ๊ณผ์
-
1
๋น์ฉ ์ต์ ํ
ํ๋กฌํํธ ์บ์ฑ์ผ๋ก ๋ฐ๋ณต ํ ํฐ ๋น์ฉ 90% ์ ๊ฐ. ์์คํ ํ๋กฌํํธยท๋๊ตฌ ์ ์์ฒ๋ผ ๋งค ํธ์ถ ๋์ผํ prefix๋ฅผ ์บ์ํ์ฌ ์ ๋ ฅ ํ ํฐ ๊ณผ๊ธ ์ต์ํ.
-
2
์๋ ์ต์ ํ
์คํธ๋ฆฌ๋ฐ์ผ๋ก TTFT(Time To First Token)๋ฅผ ์ต์ํ. ์ ์ฒด ์๋ต ์๋ฃ๋ฅผ ๊ธฐ๋ค๋ฆฌ์ง ์๊ณ ํ ํฐ ๋จ์๋ก ์ฆ์ ์ ๋ฌํ์ฌ ์ฒด๊ฐ ์ง์ฐ ์ ๊ฑฐ.
-
3
์ธํ๋ผ ์ต์ ํ
์ํฌ๋ก๋ ํน์ฑ์ ๋ง๋ ๋ฐฐํฌ ํ๊ฒ ์ ํ. LambdaยทFargateยทAgentCore Runtime ์ค ์ฝ๋์คํํธยท๋น์ฉยทํ์ฅ์ฑ ๊ท ํ์ ์ ์ฐพ์ ์ด์ ๋ถ๋ด ์ต์ํ.
์บ์ฑ์ ๋ฐ๋ณต prefix์ ์ฌ์ฒ๋ฆฌ๋ฅผ ์์ ๊ณ , ์คํธ๋ฆฌ๋ฐ์ ์ฒซ ํ ํฐ์ ์๋น๊ธฐ๋ฉฐ, ๋ฐฐํฌ ํ๊ฒ์ ์ํฌ๋ก๋์ ๋ง๋ ๊ท ํ์ ์ ์ฐพ์ต๋๋ค.
ํ๋ก๋์ ํต์ฌ ์งํ
์บ์ฑยท์คํธ๋ฆฌ๋ฐยท๋ฉํฐ ํ๋ก๋ฐ์ด๋๊ฐ ๋ง๋๋ ์ ๋์ ๊ฐ์ ํจ๊ณผ
์ต์ ํ ์ถ๋ณ ๋๊ตฌ ๋งคํ
๊ฐ ์ถ์์ Strands SDK๊ฐ ์ ๊ณตํ๋ ๊ตฌ์ฒด์ ๋ฉ์ปค๋์ฆ๊ณผ ์ ์ฉ ๋์
| ์ต์ ํ ์ถ | ๋ฉ์ปค๋์ฆ | ์ ์ฉ ๋์ | ํจ๊ณผ |
|---|---|---|---|
| ๋น์ฉ | Prompt Caching (cachePoint) | ์์คํ ํ๋กฌํํธ ยท ๋๊ตฌ ์ ์ | ์ ๋ ฅ ํ ํฐ 90% ์ ๊ฐ |
| ๋น์ฉ | cache_tools="default" | ๋๊ตฌ ์คํค๋ง ์ ์ฒด | ๋๊ตฌ ๋ง์์๋ก ์ ๊ฐ ํญ ์ฆ๊ฐ |
| ์๋ | AsyncIterator ์คํธ๋ฆฌ๋ฐ | ๋ชจ๋ ๋ชจ๋ธ ์๋ต | ์ฒซ ํ ํฐ ์ง์ฐ ์ต์ํ |
| ์๋ | Callback Handler | UI ์ ๋ฐ์ดํธ ยท ๋ก๊น | ์ด๋ฒคํธ ๊ธฐ๋ฐ ์ค์๊ฐ ์ฒ๋ฆฌ |
| ์ธํ๋ผ | Lambda ๋ฐฐํฌ | ์ด๋ฒคํธ ๊ธฐ๋ฐ ๋จ๋ฐ ํธ์ถ | ์ ๋ก ์ ํด ๋น์ฉ |
| ์ธํ๋ผ | Fargate / AgentCore | ์ฅ์๊ฐ ์ธ์ ยท ๋ฉํฐํด | ์์ ์ฐ๊ฒฐ ยท ์คํ ์ค์ผ์ผ |
๋น์ฉ ์ถ์ ์บ์ฑ ์ต์ ๋ ๊ฐ์ง, ์๋ ์ถ์ ์คํธ๋ฆฌ๋ฐ ์ธํฐํ์ด์ค ๋ ๊ฐ์ง๋ก ๋์ํฉ๋๋ค โ ์ธํ๋ผ ์ถ๋ง ์ฝ๋ ๋ฐ์ ๋ฐฐํฌ ๊ฒฐ์ ์ ๋๋ค.
ํธ์ถ ๋จ์ ๋ชจ๋ธ ๋ผ์ฐํ
๊ฐ์ ์์ด์ ํธ์์ ์์ฒญ๋ณ๋ก ๋ค๋ฅธ ๋ชจ๋ธ ์ง์ โ ๊ฒฝ๋ ์์ ์ ์ผ ๋ชจ๋ธ, ๋ณต์กํ ์์ ๋ง ๋น์ผ ๋ชจ๋ธ
ํต์ฌ ํฌ์ธํธ
- agent(prompt, model=)
- ํธ์ถ ์์ ์ ๋ชจ๋ธ ์ค๋ฒ๋ผ์ด๋ โ ์์ด์ ํธ ์ฌ์์ฑ ์์ด ์์ฒญ๋ณ ์ง์ (v1.50 ์ดํ ์ฌ์ฉ ๊ฐ๋ฅ)
- ๊ธฐ๋ณธ ๋ชจ๋ธ ์ ์ง
- model= ์๋ ํธ์ถ์ Agent ์์ฑ ์ ์ง์ ํ ๋ชจ๋ธ ๊ทธ๋๋ก
- ๋งฅ๋ฝ ๊ณต์
- ๊ฐ์ ์์ด์ ํธ์ messages[]๋ฅผ ์ด์ด ์ โ ๋ชจ๋ธ๋ง ๋ฐ๋๊ณ ๋ํ๋ ์ ์ง
- ๋น์ฉ ์ต์ ํ
- ๋ถ๋ฅยท์์ฝ ๊ฐ์ ๊ฒฝ๋ ์์ฒญ์ ์ ๊ฐ ๋ชจ๋ธ๋ก ๋ผ์ฐํ โ ์บ์ฑ๊ณผ ๊ฒน์ณ ์ฐ๋ ๋ณ๊ฐ์ ์ ๊ฐ ์ถ
์ฝ๋
from strands import Agent
from strands.models import BedrockModel
cheap = BedrockModel(model_id="us.anthropic.claude-haiku-4-5")
smart = BedrockModel(model_id="us.anthropic.claude-sonnet-4-6")
# ๊ธฐ๋ณธ ๋ชจ๋ธ์ smart โ toolsยทsystem_prompt๋ ํ๋๋ก ์ ์ง
agent = Agent(model=smart, tools=[search_docs])
# ๊ฒฝ๋ ์์
โ ์ด ํธ์ถ๋ง ์ผ ๋ชจ๋ธ๋ก ๋ผ์ฐํ
agent("์ด ๋ฌธ์๋ฅผ ์นดํ
๊ณ ๋ฆฌ๋ก ๋ถ๋ฅํด์ค", model=cheap)
# ๋ณต์กํ ์์
โ ๊ธฐ๋ณธ ๋ชจ๋ธ ๊ทธ๋๋ก (๊ฐ์ ๋ํ ๋งฅ๋ฝ ๊ณต์ )
agent("๋ถ๋ฅ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํ์ผ๋ก ๋์ ๋ฐฉ์์ ์ค๊ณํด์ค")
ํ๋กฌํํธ ์บ์ฑ
SystemContentBlock ยท cache_tools ยท ๋น์ฉ 90% ์ ๊ฐ
ํ๋กฌํํธ ์บ์ฑ
๋งค ํธ์ถ ๋ฐ๋ณต๋๋ prefix๋ฅผ ์บ์ํด ์ ๋ ฅ ํ ํฐ ๋น์ฉ์ ์ ๊ฐํ๋ ๋ฉ์ปค๋์ฆ
ํ๋กฌํํธ ์บ์ฑ
์์คํ ํ๋กฌํํธยท๋๊ตฌ ์ ์์ฒ๋ผ ๋งค ํธ์ถ ๋์ผํ prefix๋ฅผ ์บ์ํ์ฌ ์ ๋ ฅ ํ ํฐ ๊ณผ๊ธ์ ์ต์ํํฉ๋๋ค.
- cache_tools="default" โ ๋๊ตฌ ์ ์ ์ ์ฒด ์บ์ (5๋ถ TTL)
- cache_config=CacheConfig(strategy="auto") โ ๋ฉํฐํด ๋ฉ์์ง ์๋ ์บ์ฑ
- ์์คํ ํ๋กฌํํธ ๋ช ์ ์บ์ฑ โ SystemContentBlock์ cachePoint ๋ง์ปค
- cache hit โ ์บ์ ์ฝ๊ธฐ ๋น์ฉ์ ์ ๋ ฅ ํ ํฐ์ 10%
์ฒซ ํธ์ถ์ cache write ๋น์ฉ์ด ์ถ๊ฐ๋์ง๋ง, ์ดํ hit๋ถํฐ๋ prefix ์ฌ์ฒ๋ฆฌ ์์ด ์ ๊ฐ๋ ๋น์ฉ์ผ๋ก ์ฒ๋ฆฌ๋ฉ๋๋ค.
cache_tools๋ก ๋๊ตฌ ์ ์ ์บ์ฑ
๋๊ตฌ ์ ์๋ ํ ์ค ์ต์ โ ๋ฉํฐํด ์๋(CacheConfig)ยท์์คํ ํ๋กฌํํธ ๋ช ์(cachePoint)๊น์ง ๋์๋ณ ์ ์ธ
from strands import Agent
from strands.models import BedrockModel, CacheConfig
from strands.types.content import SystemContentBlock
model = BedrockModel(
model_id="us.anthropic.claude-sonnet-4-6",
cache_tools="default", # ๋๊ตฌ ์ ์ ์ ์ฒด๋ฅผ ์บ์ (5๋ถ TTL)
# ๋ฉํฐํด ๋ฉ์์ง ์๋ ์บ์ฑ โ ๋ง์ง๋ง user ๋ฉ์์ง ๋์ ์บ์ ํฌ์ธํธ ์๋ ๋ฐฐ์น
cache_config=CacheConfig(strategy="auto"),
)
agent = Agent(
model=model,
# ์์คํ
ํ๋กฌํํธ ๋ช
์ ์บ์ฑ โ cachePoint ๋ง์ปค๊น์ง๊ฐ ์บ์ prefix
system_prompt=[
SystemContentBlock(text="""You are a production data analyst.
You have access to SQL databases, S3 data lakes, and monitoring dashboards.
Always validate queries before execution and explain your reasoning."""),
SystemContentBlock(cachePoint={"type": "default"}),
],
tools=[query_database, read_s3, check_metrics, generate_report],
)
# ์ฒซ ํธ์ถ: cache write (์ฝ๊ฐ์ ์ถ๊ฐ ๋น์ฉ)
# ์ดํ ํธ์ถ: cache hit โ ์์คํ
ํ๋กฌํํธ + ๋๊ตฌ ์ ์ ๋น์ฉ 90% ์ ๊ฐ
result = agent("์ง๋์ฃผ ๋งค์ถ ๋ฆฌํฌํธ๋ฅผ ์์ฑํด์ค")
์บ์ฑ ๋์ ์๋ฆฌ
Cache Point ๋ง์ปค ๊ธฐ์ค์ผ๋ก prefix ์ผ์น ์ฌ๋ถ๋ฅผ ํ๋จํ๋ hit/miss ํ๋ฆ
-
1
Cache Point ์ ์ธ
SystemContentBlock์ cachePoint: { type: "default" }๋ฅผ ์ฝ์ . ์ด ๋ง์ปค๊น์ง์ ํ ํฐ์ด ์บ์ ํค์ prefix๊ฐ ๋จ.
-
2
Prefix ํด์ฑ
ํ๋ก๋ฐ์ด๋๊ฐ ์์คํ ํ๋กฌํํธ + ๋๊ตฌ ์ ์๋ฅผ ํด์ฑํ์ฌ ์บ์ ํค ์์ฑ. ๋์ผ prefix๋ฉด ๊ฐ์ ํค๋ก ๋งคํ.
-
3
Cache Hit ํ์
TTL ๋ด์ ๋์ผ ํค๊ฐ ์กด์ฌํ๋ฉด hit โ ์บ์๋ KV ์ํ๋ฅผ ์ฌ์ฌ์ฉํ์ฌ prefix ํ ํฐ ์ฌ์ฒ๋ฆฌ ์๋ต.
-
4
๋น์ฉ ์ ์ฐ
Hit ์ ์บ์ ์ฝ๊ธฐ ๋น์ฉ๋ง ๊ณผ๊ธ (์ผ๋ฐ ์ ๋ ฅ ํ ํฐ์ 10%). Miss ์ cache write ๋น์ฉ 25% ์ถ๊ฐ ํ ๋ค์ ํธ์ถ๋ถํฐ ์ ๊ฐ.
hit์ด๋ฉด ์บ์ ์ฝ๊ธฐ ๋น์ฉ 10%๋ง ๊ณผ๊ธ๋๊ณ , miss๋ฉด write ๋น์ฉ 25%๊ฐ ์ถ๊ฐ๋ฉ๋๋ค โ TTL ์์ ๊ฐ์ prefix๋ก ๋ค์ ํธ์ถํ๋ ๊ฒ์ด ์ ๊ฐ์ ์กฐ๊ฑด์ ๋๋ค.
์บ์ฑ ์กฐ๊ฑด ๋น๊ต
Anthropic API ์ง์ ํธ์ถ๊ณผ Bedrock ๊ฒฝ์ ์ ์บ์ฑ ๋์ ์ฐจ์ด
| ์กฐ๊ฑด | Anthropic API | Amazon Bedrock |
|---|---|---|
| ์ต์ ํ ํฐ | 1,024 ์ด์ (Sonnet 4.6 ๊ธฐ์ค) | ๋ชจ๋ธ๋ณ ์ต์ ํ ํฐ ์กด์ฌ (1,024/4,096 โ Bedrock ๋ฌธ์ ๊ธฐ์ค) |
| TTL | 5๋ถ (์ฌ์ฉ ์ ๊ฐฑ์ ) | 5๋ถ~1์๊ฐ (๋ชจ๋ธ๋ณ ์์ด) |
| cache_tools="default" | โ ์ง์ (5๋ถ TTL) | โ ์ง์ |
| cache_config (๋ฉํฐํด ๋ฉ์์ง ์๋) | โ CacheConfig(strategy="auto") | โ ๋์ผ ์ธํฐํ์ด์ค |
| ์์คํ ํ๋กฌํํธ (์๋ cachePoint) | โ SystemContentBlock | โ ๋์ผ ์ธํฐํ์ด์ค |
| Cache Write ๋น์ฉ | ์ ๋ ฅ ํ ํฐ์ 25% ์ถ๊ฐ (5๋ถ TTL ๊ธฐ์ค โ 1์๊ฐ TTL์ +100%) | ์ ๋ ฅ ํ ํฐ์ 25% ์ถ๊ฐ (5๋ถ TTL ๊ธฐ์ค) |
| Cache Read ๋น์ฉ | ์ ๋ ฅ ํ ํฐ์ 10% | ์ ๋ ฅ ํ ํฐ์ 10% |
| ๊ต์ฐจ ์ธ์ ๊ณต์ | ๋์ผ workspace ๋ด ๊ณต์ (2026-02 ๋ณ๊ฒฝ) | ๋์ผ ๊ณ์ ๋ด ๊ณต์ |
Strands ์บ์ฑ ์ธํฐํ์ด์ค๋ Anthropic API์ Bedrock์์ ๋์ผํฉ๋๋ค โ ์ต์ ํ ํฐ๊ณผ TTL ๊ฐ์ ์บ์ฑ ์กฐ๊ฑด๋ง ํ๋ก๋ฐ์ด๋๋ณ๋ก ๋ค๋ฆ ๋๋ค.
์คํธ๋ฆฌ๋ฐ
AsyncIterator ยท Callback ยท SSE ยท Retry
์คํธ๋ฆฌ๋ฐ
ํ ํฐ ๋จ์ ์์ ์ธํฐํ์ด์ค๋ถํฐ ๋ธ๋ผ์ฐ์ ์ ๋ฌ๊น์ง์ ์ค์๊ฐ ๊ฒฝ๋ก
์คํธ๋ฆฌ๋ฐ
์ ์ฒด ์๋ต ์๋ฃ๋ฅผ ๊ธฐ๋ค๋ฆฌ์ง ์๊ณ ์์ฑ ์ฆ์ ํ ํฐ์ ์ ๋ฌํ์ฌ ์ฒด๊ฐ ์ง์ฐ์ ์ ๊ฑฐํฉ๋๋ค.
- Callback Handler โ callable ํ๋๋ก ์ด๋ฒคํธ ์์
- stream_async โ async for ๋ฃจํ์ AsyncIterator
- SSE ํ์ดํ๋ผ์ธ โ Agent โ Callback โ Transport โ ๋ธ๋ผ์ฐ์
- TTFT ์ต์ํ โ ์ฒซ ํ ํฐ ์ฆ์ ํ์
AsyncIterator์ Callback ์ด์ค ์ธํฐํ์ด์ค๋ก ํ ํฐ์ ๋ฐ๊ณ , SSE ํ์ดํ๋ผ์ธ์ด ๋ธ๋ผ์ฐ์ ๊น์ง ์ค์๊ฐ ์ ๋ฌํฉ๋๋ค.
AsyncIterator + Callback ์คํธ๋ฆฌ๋ฐ
ํ ํฐ ๋จ์ ์์ ์ ์ํ ๋ ๊ฐ์ง ์ธํฐํ์ด์ค โ ์ดํฐ๋ ์ดํฐ์ ์ด๋ฒคํธ ์ฝ๋ฐฑ
import asyncio
from strands import Agent
queue = asyncio.Queue()
# ๋ฐฉ๋ฒ 1: Callback Handler โ callable ํ๋๋ก ์ด๋ฒคํธ ์์
def sse_handler(**kwargs):
"""ํ ํฐ์ SSE ํ์์ผ๋ก ํด๋ผ์ด์ธํธ์ ํธ์"""
if "data" in kwargs: # ํ
์คํธ ๋ธํ
queue.put_nowait(f"data: {kwargs['data']}\n\n")
tool_use = kwargs.get("current_tool_use")
if tool_use: # ๋๊ตฌ ํธ์ถ ์ด๋ฒคํธ
queue.put_nowait(f"event: tool\ndata: {tool_use['name']}\n\n")
agent = Agent(callback_handler=sse_handler)
# ๋ฐฉ๋ฒ 2: AsyncIterator โ async for ๋ฃจํ (์ด๋ฒคํธ๋ dict)
async def stream_response(agent: Agent, prompt: str):
async for event in agent.stream_async(prompt):
if "data" in event:
yield f"data: {event['data']}\n\n"
elif event.get("current_tool_use"):
name = event["current_tool_use"]["name"]
yield f"event: tool\ndata: {name}\n\n"
yield "data: [DONE]\n\n"
Polling vs Streaming ๋น๊ต
์๋ต ์์ ๋ฐฉ์์ ๋ฐ๋ฅธ ์ง์ฐยท๋ฆฌ์์คยทUX ์ฐจ์ด
Polling (๋๊ธฐ ๋๊ธฐ)
์ ์ฒด ์๋ต ์๋ฃ ํ ๋ฐํ
- TTFT = ์ ์ฒด ์์ฑ ์๊ฐ (์ ์ด~์์ญ ์ด)
- ํด๋ผ์ด์ธํธ๊ฐ ๋น ํ๋ฉด์์ ๋๊ธฐ
- ๊ตฌํ ๋จ์ โ request/response ํ ์
- ๋คํธ์ํฌ ํ์์์ ์ํ (30์ด+ ์๋ต)
Streaming (ํ ํฐ ๋จ์)
์์ฑ ์ฆ์ ํ ํฐ ์ ๋ฌ
- TTFT ์ต์ํ โ ์ฒซ ํ ํฐ ์ฆ์ ํ์
- ํ์ดํ ํจ๊ณผ๋ก ์ฒด๊ฐ ์ง์ฐ ์ ๊ฑฐ
- SSE/WebSocket ์ฐ๊ฒฐ ๊ด๋ฆฌ ํ์
- ๊ธด ์๋ต๋ ํ์์์ ์์ด ์์ ์์
์คํธ๋ฆฌ๋ฐ์ SSE/WebSocket ์ฐ๊ฒฐ ๊ด๋ฆฌ ๋น์ฉ์ ์น๋ฅด๋ ๋์ ์ฒซ ํ ํฐ ์ง์ฐ๊ณผ ํ์์์ ์ํ์ ๋์์ ์ ๊ฑฐํฉ๋๋ค.
SSE ํ์ดํ๋ผ์ธ ๊ตฌ์กฐ
Agent์์ ๋ธ๋ผ์ฐ์ ๊น์ง ํ ํฐ์ด ์ ๋ฌ๋๋ 4๋จ๊ณ ํ๋ฆ
-
1
Agent ์ถ๋ก
Strands Agent๊ฐ ๋ชจ๋ธ API๋ฅผ ์คํธ๋ฆฌ๋ฐ ๋ชจ๋๋ก ํธ์ถ. ๋ชจ๋ธ์ด ํ ํฐ์ ์์ฑํ ๋๋ง๋ค chunk ์ด๋ฒคํธ ๋ฐ์.
-
2
Token Callback
callback_handler๋ก ์ ๋ฌํ ํจ์๊ฐ "data" ํค์ ํ ์คํธ ๋ธํ๋ฅผ ์์ . SSE ํ์(data: ...)์ผ๋ก ๋ณํํ์ฌ ์๋ต ํ์ ์ ์ฌ.
-
3
SSE Transport
FastAPI StreamingResponse / Lambda Function URL์ด Content-Type: text/event-stream์ผ๋ก ์ฒญํฌ ์ ์ก. Keep-alive ์ ์ง.
-
4
Client Render
EventSource API๊ฐ ํ ํฐ์ ์์ ํ ๋๋ง๋ค DOM์ append. ํ์ดํ ํจ๊ณผ๋ก ์ค์๊ฐ ํ์. ์ฐ๊ฒฐ ๋๊น ์ ์๋ ์ฌ์ฐ๊ฒฐ.
๋ค ๋จ๊ณ ์ค ๊ฐ๋ฐ์๊ฐ ์์ฑํ๋ ๊ฒ์ callback ํจ์์ SSE ์๋ํฌ์ธํธ๋ฟ์ ๋๋ค โ ๋๋จธ์ง๋ ๋ชจ๋ธ๊ณผ ๋ธ๋ผ์ฐ์ ๊ฐ ์ฒ๋ฆฌํฉ๋๋ค.
SSE ์ฅ๋ฉด โ ํ ํฐ์ด ํ๋ฅด๋ ํ๋ฉด
๊ฐ์ ์๊ฐ์ ์์ชฝ ๋ชจ์ต โ ์์ด์ด์ ๋ธํ ์ด๋ฒคํธ์ ๋ธ๋ผ์ฐ์ ์ ๋ถ๋ถ ์ถ๋ ฅ
์์ด์ด โ GET /chat/stream
app.example.com/chat
๋ฐฐํฌ ํ๊ฒ ์ ํ
Lambda vs Fargate vs AgentCore Runtime
๋ฐฐํฌ ํ๊ฒ
์ํฌ๋ก๋ ํน์ฑ์ ๋ง์ถ ์ธ ๊ฐ์ง ์ปดํจํ ํ๊ฒ์ ์ ํ ๊ธฐ์ค
Lambda ยท Fargate ยท AgentCore Runtime
์ฝ๋์คํํธยท๋น์ฉยทํ์ฅ์ฑ ๊ท ํ์ ์ ์ฐพ์ ์ํฌ๋ก๋๋ณ ์ต์ ํ๊ฒ์ ์ ํํฉ๋๋ค.
- Lambda โ ์ด๋ฒคํธ ๊ธฐ๋ฐ ๋จ๋ฐ ํธ์ถ, ์ ๋ก ์ ํด ๋น์ฉ
- Fargate โ ์ฅ์๊ฐ ์ธ์ ยท ๋ฉํฐํด, ํ์์์ ๋ฌด์ ํ
- AgentCore Runtime โ ๊ด๋ฆฌํ ์คํ ์ค์ผ์ผ ยท ๋ด์ฅ ๊ด์ธก์ฑ
- agentcore create โ deploy โ CLI ๋ฐฐํฌ ์ํฌํ๋ก์ฐ
๋ง๋ฅ ํ๊ฒ์ ์์ต๋๋ค โ ์ฝ๋์คํํธ ยท ๋น์ฉ ๋ชจ๋ธ ยท ํ์ฅ์ฑ 3์ถ์ผ๋ก ์ํฌ๋ก๋๋ง๋ค ํ๋จํฉ๋๋ค.
๋ฐฐํฌ ์ต์ 3์ข
Lambda๋ ๊ฒฝ๋ ๋จ๋ฐ, Fargate๋ ์ฅ์๊ฐ ์ธ์ , AgentCore Runtime์ ๊ด๋ฆฌํ โ ๊ฐ์ ๊ณผ ์ ์ฝ์ ๋๋น
AWS Lambda
์ด๋ฒคํธ ๊ธฐ๋ฐ ๋จ๋ฐ ํธ์ถ์ ์ต์ . 15๋ถ ํ์์์ ์ด๋ด์ ๊ฒฝ๋ ์์ด์ ํธ์ ์ ํฉ.
- โ ์ ๋ก ์ ํด ๋น์ฉ โ ํธ์ถ ์์๋ง ๊ณผ๊ธ
- โ ์๋ ์ค์ผ์ผ๋ง โ ๋์์ฑ ์์ฒ ์ฆ์ ํ์ฅ
- โ Function URL๋ก SSE ์คํธ๋ฆฌ๋ฐ ์ง์
- โ ์ฝ๋์คํํธ โ ๋ณดํต 1์ด ๋ฏธ๋ง์ด์ง๋ง ๋ฌด๊ฑฐ์ด ์์กด์ฑ ์ ์ ์ด
- โ 15๋ถ ํ์์์ โ ์ฅ์๊ฐ ์์ด์ ํฑ ๋ฃจํ ๋ถ๊ฐ
- โ ๋ฉ๋ชจ๋ฆฌ 10GB ์ ํ โ ๋ํ ์ปจํ ์คํธ ์ฒ๋ฆฌ ํ๊ณ
์ธ์ โ ๋น๋๊ธฐ ์ด๋ฒคํธ ์ฒ๋ฆฌ, ์งง์ ๋จ์ผ ํด ์์ด์ ํธ, API Gateway ๋ค ๊ฒฝ๋ ์ถ๋ก
AWS Fargate
์ฅ์๊ฐ ์ธ์ ๊ณผ ๋ฉํฐํด ๋ํ์ ์ ํฉ. ์ปจํ ์ด๋ ๊ธฐ๋ฐ์ผ๋ก ํ๊ฒฝ ์์ ์ ์ด.
- โ ํ์์์ ๋ฌด์ ํ โ ์ ์๊ฐ ์์ด์ ํฑ ๋ฃจํ ๊ฐ๋ฅ
- โ ์ปจํ ์ด๋ ํ๊ฒฝ ์์ ์ ์ด โ GPU ์ ๊ทผ ๊ฐ๋ฅ
- โ ALB/NLB ์ฐ๋์ผ๋ก WebSocket ์์ ์ง์
- โ ์ต์ 1 ํ์คํฌ ์์ ๊ณผ๊ธ (์ ํด ๋น์ฉ ๋ฐ์)
- โ ์ค์ผ์ผ์์ ์์ญ ์ด ์์ โ ๊ธ๊ฒฉํ ํธ๋ํฝ ์คํ์ดํฌ ๋์ ์ง์ฐ
- โ ECS ํ์คํฌ ์ ์ยท์๋น์ค ์ค์ ๊ด๋ฆฌ ํ์
์ธ์ โ ๋ฉํฐํด ๋ํํ ์์ด์ ํธ, ์ฅ์๊ฐ ์ฝ๋ ์์ฑ, GPU ํ์ ์ํฌ๋ก๋
AgentCore Runtime
ํ๋ ์์ํฌ ๋ถ๋ฌธ ๊ด๋ฆฌํ ๋ฐํ์. ๋ฐฐํฌยท์ค์ผ์ผยท๋ชจ๋ํฐ๋ง์ ์์คํฑ ์ ๊ณต.
- โ ์์ด์ ํธ ํนํ ์คํ ์ค์ผ์ผ โ ๋์ ์ธ์ ๊ธฐ๋ฐ ํ์ฅ
- โ ๋ด์ฅ ๊ด์ธก์ฑ โ ํธ๋ ์ด์คยท๋ฉํธ๋ฆญยท๋ก๊ทธ ์๋ ์์ง
- โ ๋ฒ์ ยท์๋ํฌ์ธํธ ๊ด๋ฆฌ๋ก ์์ ํ ๋กค์์
- โ AgentCore ์ข ์ โ ํ ํด๋ผ์ฐ๋ ์ด์ ๋ถ๊ฐ
- โ ๋ฐํ์ ์ ์ฝ โ Python 3.12+/Node 22, ARM64, ์ปจํ ์ด๋ ์ด๋ฏธ์ง 2GB
- โ ์ ๊ท ์๋น์ค โ ๋ฆฌ์ ๊ฐ์ฉ์ฑ ์ ํ์
์ธ์ โ ํ๋ก๋์ ์์ด์ ํธ ์ ์ฉ ์ธํ๋ผ, ์ด์ ๋ถ๋ด ์ต์ํ, Strands ๋ค์ดํฐ๋ธ ๋ฐฐํฌ
๊ฐ๋ฆผ๊ธธ์ ์คํ ์๊ฐ ํ๋ ยท ์ ํด ๋น์ฉ ยท ์ด์ ๋ถ๋ด์ ๋๋ค โ ์งง์ ๋จ๋ฐ์ด๋ฉด Lambda, ์ฅ์๊ฐ ์ธ์ ์ด๋ฉด Fargate, ์ด์ ์ต์ํ๋ฉด AgentCore Runtime์ ์ ํํฉ๋๋ค.
๋ฐฐํฌ ํ๊ฒ ๋น๊ตํ
์ฝ๋์คํํธยท๋น์ฉ ๋ชจ๋ธยทํ์ฅ์ฑยท์ด์ ๋ถ๋ด 4์ถ ์ ๋ ๋น๊ต
| ํญ๋ชฉ | Lambda | Fargate | AgentCore Runtime |
|---|---|---|---|
| ์ฝ๋์คํํธ | 100ms~1์ด+ (ํธ์ถ์ 1% ๋ฏธ๋ง, ์์กด์ฑ ํฌ๊ธฐ์ ์ข์ฐ) | ํ์คํฌ ํ๋ก๋น์ ๋ ์ฝ 30์ด | ์ ํ ์ ์ง๋ก ์ฝ๋์คํํธ ์ต์ํ |
| ์ต๋ ์คํ ์๊ฐ | 15๋ถ | ๋ฌด์ ํ | ์ธ์ ์ต๋ 8์๊ฐ |
| ๋น์ฉ ๋ชจ๋ธ | ํธ์ถ๋น ๊ณผ๊ธ (์ ํด ๋ฌด๋ฃ) | ํ์คํฌ ์๊ฐ๋น ๊ณผ๊ธ | ์๋น ๊ธฐ๋ฐ โ ํ์ฑ ์ฒ๋ฆฌ CPU + ๋ฉ๋ชจ๋ฆฌ(GB-h), ์์ฒญ๋น ๊ณผ๊ธ ์์ |
| ์ค์ผ์ผ ๋จ์ | ๋์ ์คํ 1,000 (๊ธฐ๋ณธ ์ฟผํฐ, ์ํฅ ๊ฐ๋ฅ) | ํ์คํฌ ์ (๋ถ ๋จ์) | ์์ด์ ํธ ์ธ์คํด์ค (์ด ๋จ์) |
| ์ด์ ๋ถ๋ด | ๋ฎ์ (์๋ฒ๋ฆฌ์ค) | ์ค๊ฐ (ECS ์ค์ ) | ๋ฎ์ (๊ด๋ฆฌํ) |
| ์คํธ๋ฆฌ๋ฐ | Function URL SSE | ALB + WebSocket | ๋ค์ดํฐ๋ธ SSE/WS |
| ๊ด์ธก์ฑ | CloudWatch + X-Ray ์๋ | Container Insights | ๋ด์ฅ ํธ๋ ์ด์คยท๋ฉํธ๋ฆญ |
Lambda์ 15๋ถ ํ๋์ Fargate์ ์ ํด ๊ณผ๊ธ์ด ๊ฐ์์ ์ฝ์ ์ ๋๋ค โ AgentCore Runtime์ ์๋น ๊ธฐ๋ฐ ๊ณผ๊ธ๊ณผ ์ธ์ ์ต๋ 8์๊ฐ์ผ๋ก ๊ทธ ์ฌ์ด๋ฅผ ๋ฉ์๋๋ค.
AgentCore Runtime ๋ฐฐํฌ ์์
Strands ์์ด์ ํธ๋ฅผ AgentCore์ ๋ฐฐํฌํ๋ ์ต์ ์ค์ ๊ณผ CLI ์ํฌํ๋ก์ฐ
# app/MyProdAgent/main.py โ agentcore create๊ฐ ์์ฑํ ์ค์บํด๋๋ฅผ ์๋์ฒ๋ผ ์์
from strands import Agent
from strands.models import BedrockModel
from bedrock_agentcore import BedrockAgentCoreApp
app = BedrockAgentCoreApp()
agent = Agent(
model=BedrockModel(
model_id="us.anthropic.claude-sonnet-4-6",
cache_tools="default",
streaming=True,
),
system_prompt="You are a production assistant.",
tools=[search_docs, query_db, send_notification],
)
# @app.entrypoint โ AgentCore Runtime์ด ํธ์ถํ๋ ์ง์
์
@app.entrypoint
def handler(payload):
result = agent(payload.get("prompt"))
return {"result": str(result)}
# โโโ CLI ๋ฐฐํฌ ์ํฌํ๋ก์ฐ โโโ
# 1. agentcore create --name MyProdAgent โ ์ค์บํด๋ ์์ฑ(main.py + pyproject.toml)
# 2. ์์ฑ๋ app/MyProdAgent/main.py๋ฅผ ์ ๋ด์ฉ์ผ๋ก ์์
# 3. agentcore deploy โ ์ฝ๋ ํจํค์ง + ๋ฐฐํฌ(๋ฒ์ ยท์๋ํฌ์ธํธ๋ Runtime์ด ๊ด๋ฆฌ)
์บ์ฑ ยท ์คํธ๋ฆฌ๋ฐ ยท ๋ฐฐํฌ โ ํ๋ก๋์ ์์ด์ ํธ์ 3๋ ์์