> Discover all available pages from the documentation index: https://mastra.zisheng.pro/ko/llms.txt # 맞춤형 어댑터 사전 구축된 서버 어댑터(Hono, Express, Fastify, Koa)가 프레임워크를 지원하지 않거나 특정 요청/응답 처리 요구 사항이 있는 경우 사용자 지정 어댑터를 만듭니다. 사용자 정의 어댑터는 Mastra의 경로 정의와 프레임워크의 라우팅 시스템 간을 변환합니다. 프레임워크의 API를 사용하여 미들웨어를 등록하고, 요청을 처리하고, 응답을 보내는 메서드를 구현하게 됩니다. > **정보:** 다음과 같은 사전 구축된 서버 어댑터를 사용하세요. > > - [@마스트라/호노](https://mastra.zisheng.pro/ko/reference/server/hono-adapter) > - [@마스트라/익스프레스](https://mastra.zisheng.pro/ko/reference/server/express-adapter) > - [@mastra/fastify](https://mastra.zisheng.pro/ko/reference/server/fastify-adapter) > - [@마스트라/코아](https://mastra.zisheng.pro/ko/reference/server/koa-adapter) ## 추상 수업 `@mastra/server/server-adapter`의 `MastraServer` 추상 클래스는 모든 어댑터의 기반을 제공합니다. 경로 등록 로직, 매개변수 검증 및 기타 공통 기능을 처리합니다. 사용자 지정 어댑터는 이 클래스를 확장하고 프레임워크별 부분을 구현합니다. 클래스는 프레임워크의 유형을 나타내는 세 가지 유형 매개변수를 사용합니다. ```typescript import { MastraServer } from '@mastra/server/server-adapter' export class MyFrameworkServer extends MastraServer< // Your framework's app type (e.g., FastifyInstance) MyApp, // Your framework's request type (e.g., FastifyRequest) MyRequest, // Your framework's response type (e.g., FastifyReply) MyResponse > { // Implement abstract methods } ``` 이러한 유형 매개변수는 어댑터 구현 전체에서 유형 안전성을 보장하고 프레임워크별 API에 액세스할 때 적절한 입력을 가능하게 합니다. ## 필수 방법 이러한 6가지 추상 메서드를 구현해야 합니다. 각각은 컨텍스트 첨부부터 응답 전송까지 요청 수명주기의 특정 부분을 처리합니다. ### `registerContextMiddleware()` 이 메서드는 가장 먼저 실행되며 들어오는 모든 요청에 Mastra 컨텍스트를 연결합니다. 경로 핸들러가 작동하려면 Mastra 인스턴스, Tool 및 기타 컨텍스트에 접근할 수 있어야 합니다. 이 컨텍스트를 연결하는 방법은 프레임워크마다 다릅니다. Express는 `res.locals`를 사용하고, Hono는 `c.set()`을 사용하며, 다른 프레임워크에는 각자의 패턴이 있습니다. ```typescript registerContextMiddleware(): void { this.app.use('*', (req, res, next) => { // Attach context to your framework's request/response res.locals.mastra = this.mastra; res.locals.requestContext = new RequestContext(); res.locals.tools = this.tools; res.locals.abortSignal = createAbortSignal(req); next(); }); } ``` 첨부할 컨텍스트: | 키 | 유형 | 설명 | | ---------------- | ---------------------- | ------------------ | | `mastra` | `Mastra` | Mastra 인스턴스 | | `requestContext` | `RequestContext` | 요청 범위 컨텍스트 맵 | | `tools` | `Record` | 사용 가능한 Tool | | `abortSignal` | `AbortSignal` | 요청 취소 신호 | | `taskStore` | `InMemoryTaskStore` | A2A 작업 저장소(구성된 경우) | ### `registerAuthMiddleware()` 인증 및 승인 미들웨어를 등록합니다. 이 방법은 Mastra 인스턴스에 인증이 구성되어 있는지 확인하고 그렇지 않은 경우 등록을 완전히 건너뛰어야 합니다. 인증이 구성되면 일반적으로 두 개의 미들웨어 기능, 즉 인증(토큰 유효성 검사 및 사용자 설정)과 권한 부여(사용자가 요청한 리소스에 액세스할 수 있는지 확인) 기능을 등록하게 됩니다. ```typescript registerAuthMiddleware(): void { const authConfig = this.mastra.getServer()?.auth; if (!authConfig) return; // Register authentication (validate token, set user) this.app.use('*', async (req, res, next) => { const token = extractToken(req); const user = await authConfig.authenticateToken?.(token, req); if (!user) { return res.status(401).json({ error: 'Unauthorized' }); } res.locals.user = user; next(); }); // Register authorization (check permissions) this.app.use('*', async (req, res, next) => { const allowed = await authConfig.authorize?.( req.path, req.method, res.locals.user, res ); if (!allowed) { return res.status(403).json({ error: 'Forbidden' }); } next(); }); } ``` ### `registerRoute()` 프레임워크에 단일 경로를 등록합니다. 이 메서드는 초기화 중 각 Mastra 경로에 대해 한 번씩 호출됩니다. 경로, HTTP 메서드, 핸들러 함수 및 검증용 Zod 스키마가 포함된 `ServerRoute` 객체를 받습니다. 구현에서는 이를 프레임워크의 라우팅 시스템에 연결해야 합니다. ```typescript async registerRoute( app: MyApp, route: ServerRoute, { prefix }: { prefix?: string } ): Promise { const path = `${prefix || ''}${route.path}`; const method = route.method.toLowerCase(); app[method](path, async (req, res) => { try { // 1. Extract parameters const params = await this.getParams(route, req); // 2. Validate with Zod schemas const queryParams = await this.parseQueryParams(route, params.queryParams); const body = await this.parseBody(route, params.body); // 3. Build handler params const handlerParams = { ...params.urlParams, ...queryParams, ...(typeof body === 'object' ? body : {}), mastra: this.mastra, requestContext: res.locals.requestContext, tools: res.locals.tools, abortSignal: res.locals.abortSignal, taskStore: this.taskStore, }; // 4. Call handler const result = await route.handler(handlerParams); // 5. Send response return this.sendResponse(route, res, result); } catch (error) { const status = error.status ?? error.details?.status ?? 500; return res.status(status).json({ error: error.message }); } }); } ``` ### `getParams()` 수신 요청에서 URL 매개변수, 쿼리 매개변수 및 요청 본문을 추출합니다. 프레임워크마다 이러한 값을 서로 다른 방식으로 노출합니다. Express는 `req.params`, `req.query`, `req.body`를 사용하지만, 다른 프레임워크는 다른 속성 이름을 사용하거나 메서드 호출이 필요할 수 있습니다. 이 메서드는 프레임워크의 추출 방식을 정규화합니다. ```typescript async getParams( route: ServerRoute, request: MyRequest ): Promise<{ urlParams: Record; queryParams: Record; body: unknown; }> { return { // From route path (e.g., :agentId) urlParams: request.params, // From URL query string queryParams: request.query, // From request body body: request.body, }; } ``` ### `sendResponse()` 경로의 응답 유형에 따라 클라이언트에 응답을 다시 보냅니다. Mastra 경로는 대부분의 API 응답에 대한 JSON, Agent 생성에 대한 스트림, MCP 전송에 대한 특수 유형 등 다양한 응답 유형을 반환할 수 있습니다. 구현에서는 프레임워크에 맞게 각 유형을 적절하게 처리해야 합니다. ```typescript async sendResponse( route: ServerRoute, response: MyResponse, result: unknown ): Promise { switch (route.responseType) { case 'json': return response.json(result); case 'stream': return this.stream(route, response, result); case 'datastream-response': // Return AI SDK Response directly return result; case 'mcp-http': // Handle MCP HTTP transport return this.handleMcpHttp(response, result); case 'mcp-sse': // Handle MCP SSE transport return this.handleMcpSse(response, result); default: return response.json(result); } } ``` ### `stream()` Agent 생성을 위한 스트리밍 응답을 처리합니다. Agent가 응답을 생성할 때 사용 가능해지면 클라이언트에 전송해야 하는 청크 스트림을 생성합니다. 이 메서드는 스트림에서 읽고, 선택적으로 수정을 적용하여 민감한 데이터를 숨기고, 적절한 형식(SSE 또는 줄 바꿈으로 구분된 JSON)으로 응답에 청크를 씁니다. ```typescript async stream( route: ServerRoute, response: MyResponse, result: unknown ): Promise { const isSSE = route.streamFormat === 'sse'; // Set streaming headers based on format response.setHeader('Content-Type', isSSE ? 'text/event-stream' : 'text/plain'); response.setHeader('Transfer-Encoding', 'chunked'); const reader = result.fullStream.getReader(); try { while (true) { const { done, value } = await reader.read(); if (done) break; // Apply redaction if enabled const chunk = this.streamOptions.redact ? redactChunk(value) : value; // Format based on stream format if (isSSE) { response.write(`data: ${JSON.stringify(chunk)}\n\n`); } else { response.write(JSON.stringify(chunk) + '\x1E'); } } // Send completion marker (SSE uses data: [DONE], other formats use record separator) if (isSSE) { response.write('data: [DONE]\n\n'); } response.end(); } catch (error) { reader.cancel(); throw error; } } ``` ## 도우미 방법 기본 클래스는 구현에 사용할 수 있는 도우미 메서드를 제공합니다. 이는 매개변수 유효성 검사 및 경로 등록과 같은 일반적인 작업을 처리하므로 다시 구현할 필요가 없습니다. | 메서드 | 설명 | | ---------------------------------------------------------------------------------------------------------------- | -------------------------------------------- | | `parsePathParams(route, params)` | Zod 스키마로 경로 매개변수 검증 | | `parseQueryParams(route, params)` | Zod 스키마로 쿼리 매개변수 검증 | | `parseBody(route, body)` | Zod 스키마로 본문 검증 | | `mergeRequestContext({ paramsRequestContext, bodyRequestContext })` | 여러 소스의 요청 컨텍스트 병합 | | `registerRoutes()` | 모든 Mastra 경로 등록(각 경로에 대해 `registerRoute` 호출) | | `registerOpenAPIRoute(app, config, { prefix })` | OpenAPI 사양 엔드포인트 등록 | | `parse*` 메서드는 각 경로에 정의된 Zod 스키마를 사용하여 입력을 검증하고 유형이 지정된 결과를 반환합니다. 검증에 실패하면 무엇이 잘못되었는지에 관한 세부 정보가 포함된 오류를 발생시킵니다. | | ## 건설자 어댑터의 생성자는 기본 클래스와 동일한 옵션을 받아 `super()`에 전달해야 합니다. 필요한 경우 프레임워크별 옵션을 추가할 수 있습니다. ```typescript constructor(options: { app: MyApp; mastra: Mastra; prefix?: string; openapiPath?: string; bodyLimitOptions?: BodyLimitOptions; streamOptions?: StreamOptions; customRouteAuthConfig?: Map; }) { super(options); } ``` 각 옵션의 전체 문서는 [서버 어댑터](https://mastra.zisheng.pro/ko/docs/server/server-adapters)를 참조하세요. ## 전체 예시 다음은 필요한 모든 메서드를 보여주는 뼈대 구현입니다. 이는 프레임워크별 부분에 의사코드를 사용하고 프레임워크의 실제 API로 바꿉니다. ```typescript import { MastraServer, ServerRoute } from '@mastra/server/server-adapter' import type { Mastra } from '@mastra/core' export class MyFrameworkServer extends MastraServer { constructor(options: { app: MyApp; mastra: Mastra; prefix?: string }) { super(options) } registerContextMiddleware(): void { this.app.use('*', (req, res, next) => { res.locals.mastra = this.mastra res.locals.requestContext = this.mergeRequestContext({ paramsRequestContext: req.query.requestContext, bodyRequestContext: req.body?.requestContext, }) res.locals.tools = this.tools ?? {} res.locals.abortSignal = createAbortSignal(req) next() }) } registerAuthMiddleware(): void { const authConfig = this.mastra.getServer()?.auth if (!authConfig) return // ... implement auth middleware } async registerRoute( app: MyApp, route: ServerRoute, { prefix }: { prefix?: string }, ): Promise { // ... implement route registration } async getParams(route: ServerRoute, request: MyRequest) { return { urlParams: request.params, queryParams: request.query, body: request.body, } } async sendResponse(route: ServerRoute, response: MyResponse, result: unknown) { if (route.responseType === 'stream') { return this.stream(route, response, result) } return response.json(result) } async stream(route: ServerRoute, response: MyResponse, result: unknown) { // ... implement streaming } } ``` ## 용법 어댑터가 구현되면 제공된 어댑터와 동일한 방식으로 사용하십시오. ```typescript import { MyFrameworkServer } from './my-framework-adapter' import { mastra } from './mastra' const app = createMyFrameworkApp() const server = new MyFrameworkServer({ app, mastra }) await server.init() app.listen(4111) ``` > **팁:** 사용자 지정 어댑터를 구축할 때 기존 [@mastra/hono](https://github.com/mastra-ai/mastra/blob/main/server-adapters/hono/src/index.ts) 및 [@mastra/express](https://github.com/mastra-ai/mastra/blob/main/server-adapters/express/src/index.ts) 구현을 참고하면 좋습니다. 이러한 구현은 컨텍스트 저장, 미들웨어 등록 및 응답 처리와 관련된 프레임워크별 패턴을 처리하는 방법을 보여 줍니다. 서버 어댑터와 함께 [Studio](https://mastra.zisheng.pro/ko/docs/studio/overview)를 사용하려면 [`mastra studio`](https://mastra.zisheng.pro/ko/reference/cli/mastra)를 사용하여 Studio UI만 실행하세요. ## 관련된 - [서버 어댑터](https://mastra.zisheng.pro/ko/docs/server/server-adapters): 개요 및 공유 개념 - [호노 어댑터](https://mastra.zisheng.pro/ko/reference/server/hono-adapter): 참조 구현 - [익스프레스 어댑터](https://mastra.zisheng.pro/ko/reference/server/express-adapter): 참조 구현 - [Mastra서버 참조](https://mastra.zisheng.pro/ko/reference/server/mastra-server): 전체 API 참조 - [createRoute() 참조](https://mastra.zisheng.pro/ko/reference/server/create-route): 유형이 안전한 사용자 지정 경로 만들기