반응형
LangChain 쓰려면 파이썬 배워야 하고, LangChain.js는 파이썬 포팅이라 DX가 어색합니다. Mastra는 Gatsby 팀이 만든 TypeScript 네이티브 에이전트 프레임워크입니다. Next.js 하던 방식 그대로 에이전트를 짭니다.
[핵심 요약]
→ Mastra: TypeScript 네이티브 AI 에이전트 프레임워크 (2026년 1월 v1.0 출시)
→ 만든 팀: Gatsby.js 창업팀 (YC W25, $13M 펀딩)
→ 현황: GitHub 22,000+ 스타 / npm 주간 다운로드 300,000+
→ 모델: Vercel AI SDK 기반 — Claude, GPT, Gemini, Ollama 3,300+ 모델 지원
→ 6가지 핵심 프리미티브: Agent, Workflow, Tool, Memory, RAG, Evals
→ Mastra Studio: 에이전트 테스트·트레이싱 내장 비주얼 IDE
→ 배포: Next.js, Express, Hono, Vercel, Cloudflare Workers 전부 지원
→ MCP 네이티브 지원: 툴을 MCP 서버로 노출 가능
Mastra vs LangChain vs LangGraph
LangChain.js:
→ 파이썬 포팅 — TypeScript 경험이 어색함
→ 타입 안전성 부족 (any 타입 남발)
→ 보일러플레이트 많음
→ Mastra Studio 같은 비주얼 IDE 없음
LangGraph (Python):
→ 상태 머신 기반 — 복잡한 에이전트 플로우에 강점
→ 파이썬 전용 → TypeScript 팀은 FastAPI 서비스 별도 필요
→ 학습 곡선 가파름
Mastra:
→ TypeScript 네이티브 — Zod 스키마가 툴 정의·출력 검증·API 응답 타입 전부 공유
→ 에이전트(자율) + 워크플로우(결정론적) 두 프리미티브 명확히 분리
→ Mastra Studio 내장 — 로컬에서 바로 트레이싱·테스트
→ Next.js 앱에 그대로 번들 가능
실전 1 — 설치 및 첫 번째 에이전트
# Node.js 18+ 필요
npm create mastra@latest my-agent-app
# 또는
pnpm create mastra
# 프롬프트에서 선택
# Provider: anthropic (claude) / openai / google / groq
# 프로젝트 구조 자동 생성
생성된 구조:
src/
└── mastra/
├── agents/ # 에이전트 정의
├── tools/ # 툴 정의
├── workflows/ # 워크플로우 정의
└── index.ts # Mastra 런타임 등록
// src/mastra/agents/weather-agent.ts
import { Agent } from '@mastra/core/agent';
import { anthropic } from '@ai-sdk/anthropic';
import { weatherTool } from '../tools/weather';
export const weatherAgent = new Agent({
id: 'weather-agent',
name: 'Weather Assistant',
instructions: `
당신은 날씨 정보를 제공하는 어시스턴트입니다.
사용자가 날씨를 물어보면 weatherTool을 사용해서 정확한 정보를 제공하세요.
항상 한국어로 답변하세요.
`,
model: anthropic('claude-sonnet-4-5'),
tools: { weatherTool },
});
// src/mastra/index.ts — Mastra 런타임에 등록
import { Mastra } from '@mastra/core';
import { weatherAgent } from './agents/weather-agent';
export const mastra = new Mastra({
agents: { weatherAgent },
});
# Mastra Studio 실행 (로컬 비주얼 IDE)
npx bgproc start -n my-agent-app -w -- npm run dev
# → http://localhost:4111 에서 에이전트 테스트 가능
[Mastra Studio 제공 기능]
→ 에이전트 채팅 인터페이스 (실시간 테스트)
→ 툴 호출 트레이싱 (입력/출력/소요시간)
→ 토큰 사용량·비용 추적
→ 프롬프트 편집 및 즉시 재실행
→ 워크플로우 실행 시각화
실전 2 — Tool 정의 (Zod 스키마 타입 공유)
Mastra의 툴은 Zod 스키마로 입출력을 정의합니다. 이 스키마가 모델 프롬프트 설명 + 런타임 검증 + TypeScript 타입을 동시에 담당합니다.
// src/mastra/tools/weather.ts
import { createTool } from '@mastra/core/tools';
import { z } from 'zod';
export const weatherTool = createTool({
id: 'get-weather',
description: '특정 도시의 현재 날씨를 가져옵니다',
inputSchema: z.object({
city: z.string().describe('날씨를 조회할 도시명 (예: Seoul, Tokyo)'),
unit: z.enum(['celsius', 'fahrenheit']).default('celsius'),
}),
outputSchema: z.object({
temperature: z.number(),
condition: z.string(),
humidity: z.number(),
city: z.string(),
}),
execute: async ({ context }) => {
const { city, unit } = context;
// 실제 날씨 API 호출
const res = await fetch(
`https://api.weatherapi.com/v1/current.json?key=${process.env.WEATHER_API_KEY}&q=${city}`
);
const data = await res.json();
return {
temperature: unit === 'celsius'
? data.current.temp_c
: data.current.temp_f,
condition: data.current.condition.text,
humidity: data.current.humidity,
city: data.location.name,
};
},
});
// src/mastra/tools/github.ts — GitHub MCP 서버 툴 연결
import { createTool } from '@mastra/core/tools';
import { z } from 'zod';
export const createIssueTool = createTool({
id: 'create-github-issue',
description: 'GitHub 저장소에 이슈를 생성합니다',
inputSchema: z.object({
repo: z.string().describe('저장소 (owner/repo 형식)'),
title: z.string(),
body: z.string(),
labels: z.array(z.string()).optional(),
}),
outputSchema: z.object({
issueNumber: z.number(),
url: z.string(),
}),
execute: async ({ context }) => {
const res = await fetch(
`https://api.github.com/repos/${context.repo}/issues`,
{
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.GITHUB_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
title: context.title,
body: context.body,
labels: context.labels,
}),
}
);
const data = await res.json();
return { issueNumber: data.number, url: data.html_url };
},
});
[Mastra Tool 핵심 개념]
→ inputSchema: 모델이 보는 툴 설명 + 런타임 입력 검증 + TS 타입 동시 처리
→ outputSchema: 모델 출력 검증 + 다음 스텝 타입 자동 추론
→ execute: context로 타입 안전하게 입력 접근
→ MCP 서버 툴도 동일한 인터페이스로 등록 가능
→ 여러 에이전트에서 같은 툴 공유 가능
실전 3 — Memory (대화 기억 + 관찰 메모리)
Mastra는 메모리를 두 가지로 분리합니다. 대화 메모리(메시지 히스토리)와 관찰 메모리(사용자에 대해 에이전트가 학습한 것)입니다.
// src/mastra/agents/support-agent.ts
import { Agent } from '@mastra/core/agent';
import { Memory } from '@mastra/memory';
import { LibSQLStore } from '@mastra/memory/storage/libsql';
import { anthropic } from '@ai-sdk/anthropic';
// 메모리 스토어 설정 (LibSQL — 로컬 SQLite 호환)
const memory = new Memory({
storage: new LibSQLStore({
url: 'file:./agent-memory.db', // 로컬 개발
// url: process.env.TURSO_URL, // 프로덕션 (Turso)
}),
options: {
lastMessages: 20, // 최근 20개 메시지 유지
semanticRecall: true, // 시맨틱 검색으로 관련 과거 대화 검색
workingMemory: {
enabled: true, // 관찰 메모리 활성화
},
},
});
export const supportAgent = new Agent({
id: 'support-agent',
name: '고객 지원 에이전트',
instructions: `
당신은 친절한 고객 지원 에이전트입니다.
사용자의 과거 대화와 관찰된 정보를 참고해서 개인화된 답변을 제공하세요.
`,
model: anthropic('claude-sonnet-4-5'),
memory,
});
// Next.js API Route에서 사용
// app/api/chat/route.ts
import { mastra } from '@/src/mastra';
export async function POST(req: Request) {
const { message, userId } = await req.json();
const agent = mastra.getAgent('supportAgent');
// threadId로 대화 세션 구분 — 같은 threadId면 메모리 이어받음
const response = await agent.stream(message, {
threadId: `user-${userId}`,
resourceId: userId, // 관찰 메모리 사용자 식별자
});
return response.toDataStreamResponse();
}
[Mastra Memory 구조]
→ 대화 메모리: lastMessages 개수만큼 최근 메시지 유지
→ 시맨틱 리콜: 관련 과거 대화 벡터 검색으로 자동 주입
→ 관찰 메모리: 에이전트가 사용자에 대해 학습한 것 자동 축적
→ threadId: 대화 세션 구분 (사용자별·채널별)
→ 스토리지: LibSQL(로컬), PostgreSQL, Upstash 등 선택 가능
→ 프롬프트 캐싱: 안정적인 컨텍스트 윈도우로 캐시 히트율 향상
실전 4 — Workflow (결정론적 파이프라인)
에이전트는 LLM이 툴 호출 순서를 결정합니다. 워크플로우는 개발자가 실행 순서를 직접 정의합니다. 비용이 크거나 순서가 중요한 작업에 사용합니다.
// src/mastra/workflows/pr-review.ts
import { createWorkflow, createStep } from '@mastra/core/workflows';
import { z } from 'zod';
// Step 1: PR 코드 가져오기
const fetchPRStep = createStep({
id: 'fetch-pr',
inputSchema: z.object({ prUrl: z.string() }),
outputSchema: z.object({
files: z.array(z.object({ filename: z.string(), patch: z.string() })),
description: z.string(),
}),
execute: async ({ inputData }) => {
// GitHub API로 PR diff 가져오기
const prData = await fetchPRFromGitHub(inputData.prUrl);
return prData;
},
});
// Step 2: 코드 리뷰 (LLM)
const reviewStep = createStep({
id: 'review-code',
inputSchema: fetchPRStep.outputSchema, // 이전 스텝 출력 타입 자동 연결
outputSchema: z.object({
issues: z.array(z.object({
severity: z.enum(['critical', 'warning', 'suggestion']),
file: z.string(),
comment: z.string(),
})),
summary: z.string(),
}),
execute: async ({ inputData, mastra }) => {
const agent = mastra?.getAgent('codeReviewAgent');
const result = await agent?.generate(
`다음 PR을 리뷰해줘:\n${JSON.stringify(inputData.files)}`
);
return JSON.parse(result?.text || '{}');
},
});
// Step 3: GitHub에 리뷰 코멘트 등록
const postReviewStep = createStep({
id: 'post-review',
inputSchema: reviewStep.outputSchema,
outputSchema: z.object({ reviewUrl: z.string() }),
execute: async ({ inputData }) => {
const url = await postGitHubReview(inputData);
return { reviewUrl: url };
},
});
// 워크플로우 조합
export const prReviewWorkflow = createWorkflow({
id: 'pr-review-workflow',
inputSchema: z.object({ prUrl: z.string() }),
outputSchema: z.object({ reviewUrl: z.string() }),
})
.then(fetchPRStep)
.then(reviewStep)
.then(postReviewStep)
.commit();
// 워크플로우 실행
const { runId, start } = prReviewWorkflow.createRun();
const result = await start({
inputData: { prUrl: 'https://github.com/owner/repo/pull/123' },
});
console.log(result.result.reviewUrl);
[Workflow vs Agent 선택 기준]
→ Workflow: 순서 중요 / 비용 큰 작업 / 중간 승인 필요 / 병렬 처리
→ Agent: 순서 불확실 / 툴 조합 자율 판단 / 열린 목표
→ 함께 쓰기: Workflow 스텝 안에서 Agent 호출 가능
→ Human-in-the-Loop: 워크플로우 중간 suspend → 승인 후 resume
→ 타임트래블: 특정 스텝으로 롤백해서 재실행 가능
마무리
✅ Mastra 써야 하는 경우
→ TypeScript/Next.js 메인 스택인 풀스택·프론트엔드 팀
→ 파이썬 서비스 별도 없이 에이전트 붙이고 싶을 때
→ Vercel, Cloudflare Workers 배포 환경
→ 에이전트 + 결정론적 워크플로우 둘 다 필요한 경우
→ 로컬 비주얼 IDE로 에이전트 빠르게 테스트하고 싶을 때
❌ Mastra가 안 맞는 경우
→ Python 팀 (Mastra는 TS 전용 — Python SDK 없음)
→ 복잡한 멀티에이전트 토론·협업 시뮬레이션 (AutoGen이 더 적합)
→ 연구용 실험적 에이전트 구조 (LangGraph가 더 유연)
→ 이미 LangChain 파이썬으로 구축된 레거시 스택
관련 글
반응형
'AI Agent' 카테고리의 다른 글
| Slopsquatting 완전 가이드 — AI가 추천한 패키지가 악성코드일 수 있다 (0) | 2026.05.18 |
|---|---|
| PydanticAI 완전 가이드 — LLM 출력을 문자열 말고 타입으로 받는 법 (0) | 2026.05.18 |
| Firebase Genkit + MCP 완전 가이드 — Gemini에 외부 툴을 붙이는 Google 공식 방법 (0) | 2026.05.18 |
| LangGraph 상태 영속성(Checkpointing) — 에이전트가 죽어도 이어서 실행하는 법 (0) | 2026.05.18 |
| 5개국 "에이전트 AI 보안 가이드" 완전 분석 — 정부가 경고한 AI 에이전트 5가지 위험과 개발자 체크리스트 (0) | 2026.05.06 |