Astro 어댑터 API
Astro는 SSR (서버 측 렌더링)을 위해 모든 클라우드 제공업체에 쉽게 배포할 수 있도록 설계되었습니다. 이 기능은 통합으로 제공되는 어댑터 를 통해 사용할 수 있습니다. 기존 어댑터를 사용하는 방법을 알아보려면 SSR 가이드를 참조하세요.
어댑터란 무엇입니까?
섹션 제목: 어댑터란 무엇입니까?어댑터는 서버 측 렌더링을 위한 엔트리포인트 제공하는 특별한 종류의 통합입니다. 어댑터는 두 가지 작업을 수행합니다.
- 요청 처리를 위한 호스트별 API를 구현합니다.
- 호스트 규칙에 따라 빌드를 구성합니다.
어댑터 빌드
섹션 제목: 어댑터 빌드어댑터는 통합이며 통합이 수행할 수 있는 모든 작업을 수행할 수 있습니다.
어댑터는 반드시 다음과 같이 astro:config:done
후크에서 setAdapter
API를 호출해야 합니다.
export default function createIntegration() { return { name: '@matthewp/my-adapter', hooks: { 'astro:config:done': ({ setAdapter }) => { setAdapter({ name: '@matthewp/my-adapter', serverEntrypoint: '@matthewp/my-adapter/server.js', supportedAstroFeatures: { staticOutput: 'stable' } }); }, }, };}
setAdapter
에 전달된 객체는 다음과 같이 정의됩니다.
interface AstroAdapter { name: string; serverEntrypoint?: string; exports?: string[]; adapterFeatures: AstroAdapterFeatures; supportedAstroFeatures: AstroFeatureMap;}
export interface AstroAdapterFeatures { /** * Astro 미들웨어와 통신할 에지 기능을 생성합니다. */ edgeMiddleware: boolean; /** * SSR 전용입니다. 각 경로는 자체 함수/파일이 됩니다. */ functionPerRoute: boolean;}
export type SupportsKind = 'unsupported' | 'stable' | 'experimental' | 'deprecated';
export type AstroFeatureMap = { /** * 어댑터는 정적 페이지를 제공할 수 있습니다. */ staticOutput?: SupportsKind; /** * 어댑터는 정적이거나 서버를 통해 렌더링되는 페이지를 제공할 수 있습니다. */ hybridOutput?: SupportsKind; /** * 어댑터는 SSR 페이지를 제공할 수 있습니다. */ serverOutput?: SupportsKind; /** * 어댑터는 정적 자산을 내보낼 수 있습니다. */ assets?: AstroAssetsFeature;};
export interface AstroAssetsFeature { supportKind?: SupportsKind; /** * 이 어댑터가 'sharp' 라이브러리와 호환되는 환경에 파일을 배포하는지 여부 */ isSharpCompatible?: boolean; /** * 이 어댑터가 'squoosh' 라이브러리와 호환되는 환경에 파일을 배포하는지 여부 */ isSquooshCompatible?: boolean;}
속성은 다음과 같습니다.
- name: 로깅에 사용되는 어댑터의 고유 이름입니다.
- serverEntrypoint: 서버 측 렌더링의 엔트리포인트입니다.
- exports:
createExports
와 함께 사용되는 경우 명명된 내보내기 배열입니다 (아래 설명 참조). - adapterFeatures: 어댑터에서 지원해야 하는 특정 기능을 활성화하는 객체입니다. 이러한 기능은 빌드된 출력을 변경하며 어댑터는 다양한 출력을 처리하기 위해 적절한 로직을 구현해야 합니다.
- supportedAstroFeatures: Astro 내장 기능 맵입니다. 이를 통해 Astro는 어댑터가 지원할 수 없거나 지원하지 않는 기능을 판단하여 적절한 오류 메시지를 제공할 수 있습니다.
서버 엔트리포인트
섹션 제목: 서버 엔트리포인트Astro의 어댑터 API는 모든 유형의 호스트와 작동하려고 시도하며 호스트 API를 준수하는 유연한 방법을 제공합니다.
Exports
섹션 제목: Exports일부 서버리스 호스트는 handler
와 같은 함수를 내보낼 것을 기대합니다.
export function handler(event, context) { // ...}
어댑터 API를 사용하면 serverEntrypoint
에 createExports
를 구현하여 이를 달성할 수 있습니다.
import { App } from 'astro/app';
export function createExports(manifest) { const app = new App(manifest);
const handler = (event, context) => { // ... };
return { handler };}
그런 다음 setAdapter
를 호출하는 통합에서 exports
에 이 이름을 제공합니다.
export default function createIntegration() { return { name: '@matthewp/my-adapter', hooks: { 'astro:config:done': ({ setAdapter }) => { setAdapter({ name: '@matthewp/my-adapter', serverEntrypoint: '@matthewp/my-adapter/server.js', exports: ['handler'], }); }, }, };}
Start
섹션 제목: Start일부 호스트는 포트를 수신하여 서버를 직접 시작하기를 기대합니다. 이러한 유형의 호스트의 경우 어댑터 API를 사용하면 번들 스크립트가 실행될 때 호출되는 start
함수를 내보낼 수 있습니다.
import { App } from 'astro/app';
export function start(manifest) { const app = new App(manifest);
addEventListener('fetch', event => { // ... });}
astro/app
섹션 제목: astro/app이 모듈은 astro build
를 통해 사전 빌드된 페이지를 렌더링하는 데 사용됩니다. Astro는 표준 Request 및 Response 객체를 사용합니다. 요청/응답에 대해 다른 API를 사용하는 호스트는 어댑터에서 이러한 유형으로 변환해야 합니다.
import { App } from 'astro/app';import http from 'http';
export function start(manifest) { const app = new App(manifest);
addEventListener('fetch', event => { event.respondWith( app.render(event.request) ); });}
다음과 같은 메서드가 제공됩니다.
app.render(request, { routeData, locals })
섹션 제목: app.render(request, { routeData, locals })이 메서드는 요청과 일치하는 Astro 페이지를 호출하고 렌더링한 후 Response 객체에 Promise를 반환합니다. 이는 페이지를 렌더링하지 않는 API 경로에도 적용됩니다.
const response = await app.render(request);
이 메서드는 필수 request
인수와 routeData
및 locals
에 대한 선택적 인수를 허용합니다.
렌더링할 경로를 이미 알고 있는 경우 routeData
에 대한 값을 제공하세요. 그렇게 하면 렌더링할 경로를 결정하기 위해 app.match
에 대한 내부 호출을 우회하게 됩니다.
아래 예시에서는 x-private-header
라는 헤더를 읽고 이를 객체로 구문 분석한 후 locals
에 전달하려고 시도합니다. 그런 다음 미들웨어 함수에 전달될 수 있습니다.
const privateHeader = request.headers.get("x-private-header");let locals = {};try { if (privateHeader) { locals = JSON.parse(privateHeader); }} finally { const response = await app.render(request, { locals });}
app.match(request)
섹션 제목: app.match(request)이 메서드는 요청이 Astro 앱의 라우팅 규칙과 일치하는지 확인하는 데 사용됩니다.
if(app.match(request)) { const response = await app.render(request);}
Astro가 404.astro
파일을 제공하면 404를 처리하기 때문에 일반적으로 .match
를 사용하지 않고 app.render(request)
를 호출할 수 있습니다. 404를 다른 방식으로 처리하려면 app.match(request)
를 사용하세요.
astro add
를 통한 설치 허용
섹션 제목: astro add를 통한 설치 허용astro add
명령을 사용하면 사용자가 프로젝트에 통합 및 어댑터를 쉽게 추가할 수 있습니다. 이 도구를 사용하여 여러분의 어댑터를 설치하려면 package.json
파일의 keywords
필드에 astro-adapter
를 추가하세요:
{ "name": "example", "keywords": ["astro-adapter"],}
어댑터를 npm에 게시한 후, astro add example
을 실행하면 package.json
파일에 지정된 피어 종속성과 함께 패키지가 설치됩니다. 또한 사용자에게 프로젝트 구성을 수동으로 업데이트하도록 지시할 것입니다.
Astro 기능
섹션 제목: Astro 기능
Added in:
astro@3.0.0
Astro 기능은 어댑터가 Astro에 기능을 지원할 수 있는지 여부와 어댑터의 지원 수준을 알려주는 방법입니다.
이러한 속성을 사용할 때 Astro는 다음을 수행합니다.
- 특정 검증을 실행합니다.
- 로그에 대한 상황에 맞는 정보를 내보냅니다.
이러한 작업은 지원되거나 지원되지 않는 기능, 지원 수준 및 사용자가 사용하는 구성을 기반으로 실행됩니다.
다음 구성은 Astro에 이 어댑터가 자산에 대한 실험적 지원을 제공하지만, 어댑터가 내장 서비스 Sharp 및 Squoosh와 호환되지 않음을 알려줍니다.
export default function createIntegration() { return { name: '@matthewp/my-adapter', hooks: { 'astro:config:done': ({ setAdapter }) => { setAdapter({ name: '@matthewp/my-adapter', serverEntrypoint: '@matthewp/my-adapter/server.js', supportedAstroFeatures: { assets: { supportKind: "experimental", isSharpCompatible: false, isSquooshCompatible: false } } }); }, }, };}
Astro는 터미널에 경고를 기록합니다.
[@matthewp/my-adapter] The feature is experimental and subject to issues or changes.
자산에 사용되는 서비스가 어댑터와 호환되지 않으면 오류가 발생합니다.
[@matthewp/my-adapter] The currently selected adapter `@matthewp/my-adapter` is not compatible with the service "Sharp". Your project will NOT be able to build.
어댑터 기능
섹션 제목: 어댑터 기능내보낸 파일의 출력을 변경하는 기능 세트입니다. 어댑터가 이러한 기능을 선택하면 특정 후크에서 추가 정보를 얻게 됩니다.
functionPerRoute
섹션 제목: functionPerRouteSSR만을 사용하는 경우에만 활성화되는 기능입니다. 기본적으로 Astro는 각 요청마다 렌더링된 페이지를 내보내는 역할을 하는 단일 entry.mjs
파일을 내보냅니다.
functionPerRoute
가 true
인 경우, Astro는 대신 프로젝트에 정의된 각 경로에 대해 별도의 파일을 생성합니다.
내보낸 각 파일은 한 페이지만 렌더링합니다. 페이지는 dist/pages/
디렉터리 (또는 outDir
에 지정된 디렉터리의 /pages/
디렉터리 아래)에 생성됩니다. 내보낸 파일은 src/pages/
디렉터리의 동일한 파일 경로를 유지합니다.
빌드의 pages/
디렉터리에 있는 파일은 src/pages/
에 있는 페이지 파일의 디렉터리 구조를 미러링합니다. 예를 들면 다음과 같습니다.
디렉터리dist/
디렉터리pages/
디렉터리blog/
- entry._slug_.astro.mjs
- entry.about.astro.mjs
- entry.index.astro.mjs
어댑터에 true
를 전달하여 기능을 활성화합니다.
export default function createIntegration() { return { name: '@matthewp/my-adapter', hooks: { 'astro:config:done': ({ setAdapter }) => { setAdapter({ name: '@matthewp/my-adapter', serverEntrypoint: '@matthewp/my-adapter/server.js', adapterFeatures: { functionPerRoute: true } }); }, }, };}
그런 다음 astro:build:ssr
후크를 사용하면 빌드 후 내보낸 실제 파일에 페이지 경로를 매핑하는 entryPoints
객체가 제공됩니다.
export default function createIntegration() { return { name: '@matthewp/my-adapter', hooks: { 'astro:config:done': ({ setAdapter }) => { setAdapter({ name: '@matthewp/my-adapter', serverEntrypoint: '@matthewp/my-adapter/server.js', adapterFeatures: { functionPerRoute: true } }); },
'astro:build:ssr': ({ entryPoints }) => { for (const [route, entryFile] of entryPoints) { // route 및 entryFile로 작업을 시작하세요. } } }, };}
entryFile
은 URL
타입이며 파일 시스템에 있는 파일의 실제 경로를 나타냅니다. 즉, 코드가 실행되는 OS에 따라 경로가 변경됩니다.
서버리스 환경
섹션 제목: 서버리스 환경서버리스 환경에서 functionPerRoute: true
를 설정하면 각 경로에 대한 JavaScript 파일 (핸들러)이 생성됩니다. 핸들러는 호스팅 플랫폼 (lambda, function, page, 등)에 따라 다른 이름을 가질 수 있습니다.
이러한 각 경로는 핸들러가 실행될 때 콜드 스타트가 발생하여 약간의 지연이 발생할 수 있습니다. 이 지연은 다양한 요인의 영향을 받습니다.
functionPerRoute: false
를 사용하면 모든 경로 렌더링을 담당하는 단일 핸들러만 존재합니다. 이 핸들러가 처음 트리거되면 콜드 스타트가 발생합니다. 그러면 다른 모든 경로가 지연 없이 작동해야 합니다. 그러나 functionPerRoute: true
가 제공하는 코드 분할의 이점을 잃게 됩니다.
프로젝트에 적합한 functionPerRoute
구성을 선택하려면 호스팅 플랫폼과 작동 방식을 이해하는 것이 중요합니다.
edgeMiddleware
섹션 제목: edgeMiddleware빌드 시 SSR 미들웨어 코드를 번들링할지 여부를 정의합니다.
활성화되면 미들웨어 코드가 빌드 중에 모든 페이지에서 번들링되고 가져오는 것을 방지합니다.
export default function createIntegration() { return { name: '@matthewp/my-adapter', hooks: { 'astro:config:done': ({ setAdapter }) => { setAdapter({ name: '@matthewp/my-adapter', serverEntrypoint: '@matthewp/my-adapter/server.js', adapterFeatures: { edgeMiddleware: true } }); }, }, };}
그런 다음 후크 astro:build:ssr
를 사용하면 파일 시스템의 실제 파일에 대한 middlewareEntryPoint
, URL
을 제공합니다.
export default function createIntegration() { return { name: '@matthewp/my-adapter', hooks: { 'astro:config:done': ({ setAdapter }) => { setAdapter({ name: '@matthewp/my-adapter', serverEntrypoint: '@matthewp/my-adapter/server.js', adapterFeatures: { edgeMiddleware: true } }); },
'astro:build:ssr': ({ middlewareEntryPoint }) => { // 이 속성이 존재하는지 확인하세요. 어댑터가 해당 기능을 선택하지 않으면 'undefined'가 됩니다. if (middlewareEntryPoint) { createEdgeMiddleware(middlewareEntryPoint) } } }, };}
function createEdgeMiddleware(middlewareEntryPoint) { // 번들러를 사용하여 새로운 실제 파일을 내보냅니다.}