지금 실제로 그것을 구축할 수 있을까?
요약
본 글은 두 가지 프레임워크(Strands와 Google ADK)를 사용하여 학습 시스템을 구축하고 비교하는 과정을 다룹니다. 이 시스템은 사용자가 원하는 주제에 맞춰 커리큘럼을 구성하고, 실제 업무 환경과 유사한 방식으로 실습 및 테스트를 제공합니다. 이를 통해 최신 기술 스택으로 효과적인 온보딩 경험을 설계할 수 있음을 보여줍니다.
핵심 포인트
- Strands와 Google ADK 두 프레임워크 비교 분석
- 사용자 맞춤형 학습 시스템 구축 방법 제시
- 실제 업무 환경과 유사한 실습 및 테스트 제공
- 최신 기술 스택으로 효과적인 온보딩 경험 설계
Part 1은 "이제 우리는 실제로 그것을 구축할 수 있다"로 끝났습니다. 그래서 Part 2에서는 두 프레임워크 모두에 이를 구축하고, 각 프레임워크가 만든 과정을 비교하도록 동일한 요청을 주었습니다.
저(Claude Opus 5.5)가 처음 시도하여 구축한 버전은 235개의 테스트를 포함했고, 모든 테스트가 통과했습니다. 하지만 제가 파고들기 시작했을 때 (좋습니다, 이것이 Claude의 큰 한계였습니다. 제가 파고들기 전까지는 격차를 드러내지 않습니다), 그 테스트 중 어느 것도 실제 모델과 대화한 적이 없다는 것을 깨달았습니다 🙃
실제 모델을 가리키자마자 첫 번째 호출에서 실패했습니다. 그리고 마침내 Terraform 과정을 생성했을 때, 퀴즈 답안은 질문 바로 아래에 있었고 모든 연습 문제에는 완성된 파일이 함께 제공되었습니다.
그래서 저는 전체 폴더를 삭제하고 처음부터 다시 시작했습니다. 재구축된 버전은 훨씬 더 좋았으며, 이 게시물에서 다룰 내용입니다.
잠깐의 잡담. 정확도가 저에게 매우 중요하기 때문에, 새로운 것을 배울 때마다 "가장 최신 자료"를 검색하며, 한 번 이상 코스를 구매했다가 몇 개의 레슨만 진행해 보니 이미 구식이라는 것을 깨달았습니다. 대표적인 예로: 저는 몇 주 전에 Part 1을 시작했는데, Strands가 이미 전체 에이전트 하네스를 출시했습니다.
우리는 그것을 사용하는 모습부터 시작한 다음, Part 1에서 했던 것처럼 나란히 구축할 것입니다.
여기에 있는 모든 것은 2026년 9월 27일에서 29일 사이에 진행되었으며, Part 1과 동일한 버전(strands-agents 1.55.1 및 google-adk 2.9.0)을 사용했습니다. 코드는 동반 레포에 있습니다. 두 프레임워크 모두 활발하게 개발되고 있으며, 이 글이 올라올 무렵에는 strands-agents 1.61.1과 google-adk 2.12.0이 출시되었으므로 일부 API는 변경되었을 수 있습니다.
학습 시스템은 실제로 무엇을 해야 할까요?
제가 처음부터 다시 시작하면서, 이 것(시스템)에게서 실제로 원하는 것이 무엇인지 적어보았습니다:
- 제가 배우고 싶은 것을 말하면, 코스가 제대로 구성되도록 몇 가지 질문을 합니다.
- 실제로 직장에서 사람들이 그것으로 무엇을 하는지 다룹니다. 예를 들어, 공유 모듈의 버전을 고정하는 것 같은 것입니다.
- 구축되는 날짜 기준으로 문서만큼 최신입니다.
- 저는 직접 해보면서 배웁니다. 그리고 제 작업물을 검증하는 테스트가 있습니다.
- 답을 보기 전에 시도해야 합니다.
- 구축하는 데 큰 비용이 들지 않으며, 얼마나 사용했는지 알려줍니다.
사용해보면 어떤 모습일까요?
uv가 필요합니다. 그런 다음 레포지토리에서 한 번 설치하면 됩니다:
uv tool install "git+https://github.com/coolchigi/strands-vs-adk#subdirectory=part2-learning-system"```
그리고 어디서든 코스를 시작할 수 있습니다:
learn "I want to learn TypeScript so I can build a small web app"
처음에는 [Gemini API key](https://aistudio.google.com/apikey)를 요청하고 저장하여, 다시 설정할 필요가 없습니다. 이 키는 Gemini에서 실행되는 ADK 빌드용이며 기본값입니다. Claude를 Amazon Bedrock에서 실행하는 Strands로 구축하려면 `--engine strands`를 추가합니다. AWS 자격 증명과 [Bedrock의 Claude 접근](https://docs.aws.amazon.com/bedrock/latest/userguide/model-access.html)이 필요하며, [Strands Python 퀵스타트](https://strandsagents.com/docs/user-guide/sdk/quickstart/python/)에서 둘 다 설정하는 방법을 안내합니다:
learn --engine strands "I want to learn TypeScript so I can build a small web app"
이미 AWS 자격 증명이 있고 Gemini 키가 없다면, Strands를 자동으로 선택하고 키를 요청하지 않습니다.
모든 코스는 기본적으로 Gemini에서 $5, Claude에서 $10의 지출 한도를 가지며, 작동 방식은 청구(bill) 섹션에서 다루겠습니다.
그런 다음 무엇을 알아야 하는지 질문하며, 그 자리에서 답변합니다:
A few questions first, so I build the right course:
What is your background with programming, particularly JavaScript?
I know JavaScript well but have never used TypeScript
...
이것은 실제 실행의 간소화된 출력입니다. 빌드가 완료되면, 각 레슨별로 `README.md`가 포함된 폴더를 받게 됩니다. 이 파일들에는 설명과 모든 사실에 출처 페이지 링크가 연결되어 있으며, 그 다음으로 예제 문제, 그리고 여러분이 수정할 수 있는 파일을 포함한 연습 문제가 있습니다.
여러분은 `learn` 명령어로 진행합니다:
cd ~/courses/typescript
learn next # 현재 위치와 다음에 무엇을 배울지 확인
learn check # 연습 문제의 테스트 실행
...
레슨 1의 연습 문제는 두 개의 TODO 주석이 포함된 `formatter.ts` 파일을 제공하며, 이 주석들은 여러분이 작성해야 할 코드를 표시합니다. 그중 하나는 매개변수에 타입을 지정하는 것입니다. 만약 코드는 수정했지만 타입을 건너뛴다면, `learn check`가 다음과 같이 알려줍니다:
$ learn check
Checking units/u1-strict-compiler-configuration-and-compilation/u1-l1-compiler-cli-and-strict-type-validation/exercise ...
...
여기에 타입을 추가하면 통과하고, 다음으로 `learn quiz`를 안내합니다.
이 오류는 TypeScript 컴파일러 자체에서 발생하는데, 왜냐하면 `learn check`가 각 과목의 실제 도구들을 실행하기 때문입니다. 따라서 여러분에게 필요한 설치 항목은 무엇을 배우는지에 따라 달라집니다. Terraform 과정에는 Terraform이 필요하고, Python 과정에는 Python 3.9 이상이 필요하며, JavaScript 또는 TypeScript 과정에는 Node가 필요합니다. 그 외의 것은 테스트가 없으므로, 해결책과 여러분의 작업을 비교하게 됩니다.
## 어떻게 구축되나요?
`learn` 명령어 뒤에는 파트 1에서 스케치한 시스템이 있으며, 앞에 새로운 에이전트가 추가되었습니다:
learner ─▶ intake ─▶ researcher ─▶ curriculum builder ─▶ teacher ─▶ 여러분의 과정
▲ ▲ ▲
└──── 피드백 에이전트가 각 단계를 검토하고, 이유와 함께 다시 보냅니다
- **정보 수집 담당자(The intake)**는 어디서 시작하는지, 무엇을 만들고 싶은지 등 알아야 할 것을 질문합니다.
- **연구원(The researcher)**은 공식 문서를 읽고 과정이 가르쳐야 할 내용(즉, 목표) 목록을 작성합니다. 이들은 라이브 페이지의 사실만을 유지합니다.
- **커리큘럼 빌더(The curriculum builder)**는 그 목록을 단위와 레슨으로 변환하고, 각 단위를 확인하기 위한 연습 문제나 퀴즈를 선택합니다.
- **교사(The teacher)**는 여러분의 연습 문제를 확인하는 테스트를 포함하여 각 레슨을 작성합니다.
- **피드백 에이전트(The feedback agent)**는 각 단계의 작업물을 확인하고, 잘못된 부분이 있으면 되돌려 보냅니다. 코드는 모든 연습 문제를 실행하는 것과 같이 할 수 있는 것을 확인하며, 모델은 나머지 부분을 검토합니다.
시스템의 대부분, 예를 들어 페이지 가져오기나 테스트 실행 같은 부분은 양쪽 모두가 공유하는 일반 Python으로 작성되어 있습니다. 프레임워크는 이 게시물에서 비교하는 부분들, 즉 문서에 접근하고, 타이핑된 답변을 받고, 피드백 루프를 실행하며 비용을 절감하는 부분을 처리합니다.
두 프레임워크 모두 하나의 메서드를 통해 플러그인됩니다:
class Brain(Protocol):
def ask(self, name: str, instruction: str, prompt: str, schema: type[T], research: bool = False) -> T:
"""하나의 에이전트 호출로 schema를 반환합니다. research=True일 경우 에이전트는 검색하고 읽을 수 있습니다."""
각 프레임워크는 자신만의 방식으로 `ask`를 구현하고 자체 그래프에서 단계를 실행합니다. Strands 측은 Amazon Bedrock의 Claude Sonnet 4.6을 사용하며, 이는 [Strands의 기본값](https://strandsagents.com/docs/user-guide/sdk/model-providers/amazon-bedrock/#basic-usage)이고, ADK 측은 Gemini 3.8 Flash를 사용합니다. 따라서 두 측이 다르게 동작할 때, 그것이 프레임워크 때문인지 모델 때문인지 알 수 있으며, 우리는 그때마다 어느 쪽이었는지 말해줄 것입니다.
## 연구원은 어떻게 문서에 접근하는가?
연구원은 올바른 페이지를 찾고 읽기 위한 도구가 필요합니다. 이 도구들 중 일부는 MCP 서버에서 옵니다. [MCP](https://modelcontextprotocol.io) (Model Context Protocol)는 AI 앱을 외부 도구 및 데이터와 연결하기 위한 오픈 소스 표준이므로, 동일한 서버가 Strands와 ADK 모두에 작동합니다.
두 방식 모두 다음과 같이 합니다:
### Strands
Strands는 페이지를 가져오는 도구(tools for fetching pages)만 제공하고 검색 기능은 제공하지 않기 때문에 저는 MCP 서버를 사용했습니다. 여기서는 `MCPClient`를 생성하여 `tools`에 바로 전달했고, Strands가 연결을 열고 닫아줍니다. 이것이 AWS 문서 서버와 연결하는 방식입니다:
```python
from strands import Agent
from strands.tools.mcp import MCPClient
...
A single Amazon S3 object can be a maximum of **5 terabytes (TB)** in size, though the largest
object that can be uploaded in a single PUT request is **5 GB** ...
이 5 TB를 염두에 두세요. 왜냐하면 ADK 측에도 같은 질문을 할 것이기 때문입니다.
일반 웹 검색의 경우 API 키가 필요 없는 Exa의 호스팅 MCP 서버(hosted MCP server)를 사용했습니다. 무료 등급(free tier)이 단일 과정 구축 도중에 소진되었기 때문에, Strands에서는 Exa 또는 Tavily 키를 추가하지 않으면 웹 검색 기능이 비활성화됩니다. 현재로서는 list_docs_pages가 문서 사이트 자체의 페이지를 찾기 때문에 키가 필요하지 않습니다.
페이지를 읽기 위해, web_fetch는 두 가지 모드를 가지고 있습니다. 기본값인 agentic은 페이지를 두 번째 에이전트에게 전달하고 그 에이전트의 요약을 반환하며, markdown은 페이지 자체를 반환합니다. 저희는 마크다운 모드(markdown mode)를 사용하는데, 연구원이 모든 사실에 대해 이를 뒷받침하는 페이지의 문장을 복사해야 하고, 저희 코드는 그 문장이 실제로 존재하는지 확인하기 때문입니다.
from strands.vended_tools.web_fetch import make_web_fetch
fetch = make_web_fetch(mode="markdown", max_content_chars=50_000)
이것은 web-fetch 추가 기능을 필요로 하므로, pip install "strands-agents[web-fetch]"를 실행해야 합니다.
ADK
ADK는 검색을 google_search로 제공하며, Gemini에서만 작동합니다. Claude와 같은 다른 모델에서는 에이전트는 여전히 구축되지만, 첫 번째 호출에서 ValueError: Google search tool is not supported for model ... 오류가 발생합니다.
MCP 서버는 McpToolset를 통해 제공됩니다. 이것은 google_search 옆에 연결된 동일한 AWS 문서 서버입니다:
import asyncio
from google.adk.agents import Agent
...
According to AWS documentation, a single Amazon S3 object can be up to 50 TB in size ...
Strands 에이전트는 5 TB라고 말했고 ADK 에이전트는 50 TB라고 말했으며, AWS 자체 페이지에는 "각 객체는 최대 50 TB 크기일 수 있습니다(each object can be up to 50 TB in size)"라고 나와 있습니다. 두 에이전트 모두 동일한 AWS 문서 서버를 사용했습니다. Claude가 한 번 검색하여 5 TB와 50 TB를 모두 언급하는 결과를 얻었고, 5 TB로 답변했습니다. Gemini는 더 많은 검색을 계속했고, 두 실행에서 저는 S3 FAQ 페이지 자체를 읽은 후에 답변한다는 것을 추적했습니다. 이것이 바로 모델이 말하는 어떤 것도 라이브 페이지의 인용문과 함께 오지 않으면 과정에 포함되지 않는 이유입니다.
만약 직접 McpToolset을 사용한다면, 모든 에이전트 호출을 하나의 이벤트 루프에서 실행해야 합니다. 이 툴셋은 처음 실행된 루프에 MCP 세션을 유지합니다. 제가 만든 첫 번째 버전에서는 모든 에이전트 호출마다 asyncio.run을 호출했는데, asyncio.run은 작업을 마치면 루프를 닫기 때문에, 첫 번째 호출 이후의 모든 호출들은 이미 닫힌 루프에서 세션을 찾게 되었습니다.
ADK에는 자체 페이지 로더인 load_web_page가 있지만, 필요한 페이지들을 계속해서 잃어버렸습니다. Terraform 문서들은 리디렉션(redirect)을 많이 하는데, 이는 리디렉션을 따라가지 못하고 페이지 대신 Failed to fetch url: ...라는 메시지를 반환했습니다. 페이지 로드가 되더라도, 세 단어 이하의 모든 줄을 버려버려서 하나의 튜토리얼 코드 예제에서 181줄 중 84줄이 사라졌고, 여기에는 $ terraform init과 required_providers { 같은 내용도 포함되었습니다. 따라서 ADK 측면에서는 에이전트들이 페이지를 찾지만, 저희 자체 코드가 전체 내용을 가져와야 했습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기