Astro는 콘텐츠가 풍부한 웹사이트의 완벽한 사용 사례로 설계되었습니다. 콘텐츠가 풍부한 웹사이트는 주로 프론트엔드 코드로 구성됩니다. 그 반대는 백엔드 서버이며, 이 가이드에서는 아고 비디오 통화용 백엔드 토큰 생성기를 구축할 것입니다.
Astro로 웹사이트를 구축하는 것을 좋아합니다. 이는 제 가장 좋아하는 웹 프레임워크이며, 다른 것을 사용하고 싶지 않습니다. 그러나 이를 철저히 테스트하고 Astro가 충분히 유연하여 완전히 의존할 수 있는지 확인해야 합니다.
스포일러. Astro에 대한 제 사랑은 더욱 깊어졌습니다.

필수 조건
- NodeJS 및 Astro가 설치되어 있어야 합니다.
- Agora 개발자 계정 (Agora)
프로젝트 설정
새로운 Astro 프로젝트를 생성하려면 npm create astro@latest
를 실행합니다. 설정 과정에서 모든 기본 옵션을 따라가되, 빈 템플릿을 사용하지 않도록 합니다. 이 방법으로 프로젝트가 방해 요소 없이 시작됩니다. 그 다음, 토큰을 생성하기 위해 Agora Token 패키지를 설치해야 합니다. 이를 위해 npm i agora-token
를 실행합니다.
토큰을 생성하려면 Agora App ID와 App Certificate가 필요합니다. App Certificate는 우리의 “비밀” 키이며 공개적으로 노출되지 않도록 해야 합니다. 이 민감한 데이터를 ‘.env’ 파일에 저장하는 것이 일반적인 관행입니다. Astro 프로젝트를 생성할 때 .env
는 이미 .gitignore
에 목록에 포함되어 있으므로 GitHub에 푸시되지 않습니다. .env
파일에 프로젝트 APP_ID
와 APP_CERTIFICATE
를 추가하세요. 이 값은 Agora 콘솔에서 확인할 수 있습니다.
토큰이란 무엇인가요?
토큰은 사용자가 애플리케이션의 특정 부분에 접근할 수 있는지 확인하는 인증 방식입니다. 이 경우, 우리는 비디오 통화 내에서 사용자와 그 권한을 인증하기 위해 토큰을 사용합니다.
토큰은 HMAC-SHA256 암호화 알고리즘을 기반으로 생성됩니다. 사이버 보안 이론에 깊이 들어가지는 않겠습니다. 단순히 이는 인증을 위한 산업 표준이며, 사용자의 신원을 확인하는 코드를 제공합니다. 이 토큰은 Node에서 agora-token
패키지를 사용하여 생성할 수 있습니다.
Astro에서 엔드포인트 설정
Astro에서 엔드포인트를 생성하려면 Javascript 또는 Typescript 파일을 pages
디렉토리에 추가합니다. 파일 이름에는 데이터 유형 확장자가 포함되어야 합니다. 따라서 파일 이름은 <name>.<return-type>.ts
형식이 됩니다. Javascript 및 Typescript 확장자는 빌드 과정에서 제거됩니다.
토큰을 생성하기 위해 사용할 파일 경로는 pages/api/token.json.ts
입니다. 이 엔드포인트는 JSON 데이터를 반환하므로 파일 이름은 .json.ts
로 끝납니다. 저는 모든 엔드포인트를 api
폴더에 넣어 프론트엔드 경로와 분리하도록 합니다. Typescript 확장자가 제거되고 pages
디렉토리가 URL에 표시되지 않기 때문에 최종 엔드포인트는 api/token.json
이 됩니다.
엔드포인트 정의
엔드포인트가 입력 정보를 필요로 하기 때문에, 입력 정보를 요청 본문에 전달하기 위해 POST
요청을 사용합니다. Astro에서는 POST
함수를 수출하고 Response 객체를 반환하는 방식으로 이를 정의할 수 있습니다.
import type { APIContext } from "astro";
export async function POST({ request }: APIContext) {
const { channel, role, uid, expireTime } = await request.json()
return new Response(JSON.stringify({
token: "token"
}), { status: 200 })
}
응답 헬퍼 함수
응답 객체를 추상화하기 위해 utils/sendResponse.ts
파일을 생성하여 엔드포인트를 간소화하고 응답 간의 일관성을 보장합니다.
이 파일 내에서 CORS 문제를 방지하기 위해 헤더를 설정해야 합니다.
- “Access-Control-Allow-Origin”: “*”는 모든 도메인이 서버에 액세스할 수 있도록 허용하며, API 또는 개발 시 유용합니다.
- “Access-Control-Allow-Methods”: “POST, OPTIONS”는 POST 및 OPTIONS 메서드만 허용하며, 다른 사이트가 서버와 상호작용하는 방식을 제어합니다.
이 헤더는 모든 도메인을 허용함으로써 API가 생산 환경과 개발 환경에서 잘 작동하도록 합니다. 생산 환경에서는 허용해야 할 원본만 제한해야 합니다.
그런 다음, 정의한 헤더를 사용하여 응답을 생성하는 두 개의 함수를 정의합니다:
sendBadRequest
– 요청이 잘못되었음을 나타내는 상태 코드400
와 함께 반환합니다sendSuccessfulResponse
– 상태 코드200
와 함께 데이터를 반환합니다
const headers = new Headers({
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "POST, OPTIONS",
});
export const sendBadRequest = (reason: string) => {
return new Response(reason, { status: 400, headers });
}
export const sendSuccessfulResponse = (data: any) => {
return new Response(JSON.stringify(data), { status: 200, headers });
}
입력 검증
토큰 생성 기능은 channel
, role
, uid
, 및 expireTime
를 요구합니다. 이 값들은 토큰에 올바른 인증 및 권한이 포함되었는지 확인하는 데 사용됩니다. 정확한 데이터를 전달하기 위해 channel
, uid
, 및 expireTime
가 빈 값이 아닌지 확인하세요. 만약 빈 값이라면 헬퍼 함수를 사용하여 Bad Request를 반환하세요.
role은 토큰을 요청하는 사용자가 가질 수 있는 액세스 유형을 결정합니다. 두 가지 역할이 가능합니다:
- publisher — 채널에 데이터를 게시할 수 있습니다. 또한 채널에서 데이터를 수신할 수 있습니다.
- subscriber — 데이터를 수신할 수만 있으며, 데이터를 게시할 수 없습니다.
이 두 가지가 역할에 대한 유효한 입력 값입니다. 요청 본문에 이 중 하나가 포함되어 있다면, agora-token
패키지 내 사전 정의된 열거형에 agoraRole
변수를 할당할 수 있습니다. 요청에 이 중 하나가 포함되어 있지 않으면, 헬퍼 함수를 사용하여 Bad Request를 반환합니다.
import agoraToken from "agora-token";
export async function POST({ request }: APIContext) {
const { channel, role, uid, expireTime } = await request.json()
if (!channel) {
return sendBadRequest("channel is required")
}
if (!uid) {
return sendBadRequest("uid is required")
}
if (!expireTime) {
return sendBadRequest("expireTime is required")
}
let agoraRole;
if (role === 'publisher') {
agoraRole = agoraToken.RtcRole.PUBLISHER;
} else if (role === 'subscriber') {
agoraRole = agoraToken.RtcRole.SUBSCRIBER
} else {
return sendBadRequest("role is incorrect")
}
return new Response(JSON.stringify({
token: "token"
}), { status: 200 })
}
토큰 생성
토큰을 생성하기 위해 별도의 handleGenerateToken
함수를 생성합니다. 이 함수는 POST
요청 및 응답 논리와 토큰 생성 논리를 분리합니다. 이로 인해 두 가지 이점이 있습니다:
- 코드를 더 쉽게 읽을 수 있습니다
- 동일한 백엔드에 추가 기능을 추가할 경우(예: 클라우드 녹화), 네트워크 호출을 수행하지 않고 토큰을 직접 생성할 수 있습니다.
토큰을 생성하기 위해 agora-token
패키지의 buildTokenWithUid
함수를 사용합니다. expireTime
을 토큰 및 권한 만료 필드에 전달합니다.
권한 만료 시간은 사용자가 채널 내에서 권한을 유지할 수 있는 시간을 정의하며, 토큰 만료 시간은 사용자가 채널에 머물 수 있는 시간을 정의합니다. 권한 시간이 만료되면 사용자는 통화 내용을 듣는 것은 가능하지만 게시할 수 없습니다. 토큰이 만료되면 사용자는 채널에 대한 액세스를 완전히 잃게 됩니다. 우리 경우 토큰과 권한 만료 시간을 동일한 기간으로 설정합니다.
토큰이 생성되면 헬퍼 함수를 사용하여 성공적인 응답을 전송할 수 있습니다.
const APP_ID = import.meta.env.APP_ID;
const APP_CERTIFICATE = import.meta.env.APP_CERTIFICATE;
export async function POST({ request }: APIContext) {
// ...
const token = await handleGenerateToken({ channel, role: agoraRole, uid, expireTime })
return sendSuccessfulResponse({ token })
}
export async function handleGenerateToken({ channel, role, uid, expireTime }: { channel: string, role: number, uid: string, expireTime: number }) {
return agoraToken.RtcTokenBuilder.buildTokenWithUid(APP_ID, APP_CERTIFICATE, channel, uid, role, expireTime, expireTime);
}
백엔드 실행
npm run dev
를 사용하여 이 토큰 생성기를 실행하세요.터미널에서 cURL을 사용하여 POST
요청을 전송할 수 있습니다. 요청 본문에는 channel
, role
, uid
, 및 expireTime
가 포함되어야 합니다.
curl -X POST http://localhost:4321/api/token.json \
-H "Content-Type: application/json" \
-d '{
"uid": "20",
"channel": "test",
"role": "publisher",
"expireTime": "3600"
}'
POST
요청에 정보가 누락된 경우, 누락된 정보를 알려주는 Bad Request 응답을 받게 됩니다. 필요한 모든 정보를 전송하면 다음과 같은 성공 응답을 받게 됩니다:
{"token":"<a long string of letters and numbers>"}
이제 완전히 작동하는 토큰 생성기를 사용할 수 있게 되었습니다. 이 토큰 생성기는 주로 개발 목적으로 사용해야 합니다. 생산 환경에서 구축 중인 경우, 통화 참여자가 허용된 사용자만 될 수 있도록 사용자 인증 및 기타 보안 조치를 추가해야 합니다.

Astro는 스트레스 테스트를 완벽히 통과했습니다. 콘텐츠가 풍부한 사이트를 지원하기 위해 설계되었지만, 백엔드 프로젝트에서도 동일한 성능을 발휘합니다. Astro는 풀스택 웹사이트를 위한 우수한 솔루션입니다. 이제 Astro에 토큰 생성기가 내장되어 있으므로, 프론트엔드를 추가하고 단일 코드베이스에서 안전한 비디오 통화를 구현할 수 있습니다. Astro를 사용해 비디오 통화 프론트엔드를 구축하는 방법에 대한 가이드를 아래에 제공합니다.