본문으로 바로가기 본문 바로가기
WIKI 기술 지식 베이스

Arcjet으로 애플리케이션 보안

원문 보기 위키 갱신

이 문서는 Arcjet을 사용해 앱을 보호하는 방법을 설명해요. Arcjet은 몇 줄의 코드로 앱에 레이트 리밋, 봇 보호, 이메일 검증, 일반 공격 방어를 구현할 수 있는 보안 계층이에요. 현재 JS 및 Python 앱을 지원하며, 곧 다른 언어도 지원할 예정이에요.

출처: 문서

본문

Arcjet은 개발자가 단 몇 줄의 코드로 앱을 보호할 수 있게 해 주는 보안 계층이에요. 레이트 리밋, 봇 보호, 이메일 검증, 일반적인 공격에 대한 방어를 구현해 보아요.

Arcjet은 애플리케이션의 의존성으로 설치되며 에이전트나 추가 인프라가 필요 없어요. SDK는 현재 JS & Python 앱에서 사용할 수 있고, 다른 언어 지원이 곧 제공될 예정이에요.

빠른 시작 (Next.js)

Arcjet이 무엇을 할 수 있는지 빠르게 보는 방법은 예시 앱을 배포하는 것이에요. example.arcjet.com에서도 볼 수 있어요.

GitHub 저장소를 클론해요:

git clone git@github.com:arcjet/arcjet-example-nextjs-fly.git

새 Fly 앱을 설정해요:

fly launch --no-deploy

이 명령이 여러분을 위해 Dockerfile과 fly.toml을 생성해요.

Arcjet 계정을 만들고 Fly 앱에 연결해요:

fly ext arcjet create

이 명령은:

  • Fly 계정에 연결된 Arcjet 계정을 만들어요.
  • Fly 조직에 매핑된 Arcjet 팀을 만들어요.
  • Fly 애플리케이션에 대한 Arcjet 사이트를 만들어요.
  • ARCJET_KEY를 Fly 애플리케이션의 시크릿으로 설정해요.

Fly에 배포해요:

fly deploy

브라우저에서 앱을 열고 기능을 시도해 보아요.

Arcjet 대시보드에서 요청 세부 사항을 검토해요:

fly ext arcjet dashboard

로컬에서 실행

Arcjet 보호는 Fly에 배포했을 때뿐 아니라 로컬에서도 실행돼요. 이 덕분에 보안 규칙을 쉽게 테스트하고 디버깅할 수 있어요.

예시를 이미 클론하고 Arcjet을 Fly 앱에 연결했다고 가정할게요(위 참고):

Arcjet 대시보드에 로그인해 앱의 ARCJET_KEY를 가져와요.

fly ext arcjet dashboard

의존성을 설치해요:

npm ci

.env.local.example을 .env.local로 이름을 바꾸고 Arcjet 키를 추가해요. 레이트 리밋 인증을 테스트하고 싶다면 Auth.js 시크릿도 추가하고 GitHub OAuth 앱을 만들어야 해요.

dev 서버를 시작해요

npm run dev

브라우저에서 http://localhost:3000을 열어요.

Arcjet으로 애플리케이션 보호

ARCJET_KEY 시크릿을 설정하면 Arcjet을 사용해 애플리케이션을 보호할 수 있어요. Arcjet은 Bun, Next.js, Node.js, SvelteKit 등 많은 웹 프레임워크를 지원해요.

Node.js 예시

이 예시는 GitHub에서도 찾을 수 있어요.

  1. Arcjet SDK를 설치해요:

    npm i @arcjet/node
    
  2. index.ts의 한 경로에 레이트 리밋을 추가해요:

    import arcjet, { tokenBucket } from "@arcjet/node";
    import http from "node:http";
    
    const aj = arcjet({
      key: process.env.ARCJET_KEY!, // Set as a secret on your Fly app
      rules: [
        // Create a token bucket rate limit. Other algorithms are supported.
        tokenBucket({
          mode: "LIVE", // will block requests. Use "DRY_RUN" to log only
          characteristics: ["userId"], // track requests by a custom user ID
          refillRate: 5, // refill 5 tokens per interval
          interval: 10, // refill every 10 seconds
          capacity: 10, // bucket maximum capacity of 10 tokens
        }),
      ],
    });
    
    const server = http.createServer(async function (
      req: http.IncomingMessage,
      res: http.ServerResponse,
    ) {
      const userId = "user123"; // Replace with your authenticated user ID
      const decision = await aj.protect(req, { userId, requested: 5 }); // Deduct 5 tokens from the bucket
      console.log("Arcjet decision", decision);
    
      if (decision.isDenied()) {
        res.writeHead(429, { "Content-Type": "application/json" });
        res.end(
          JSON.stringify({ error: "Too Many Requests", reason: decision.reason }),
        );
      } else {
        res.writeHead(200, { "Content-Type": "application/json" });
        res.end(JSON.stringify({ message: "Hello world" }));
      }
    });
    
    server.listen(8000);
    
  3. 애플리케이션을 실행해요:

    npx tsx --env-file .env.local index.ts
    

앱을 로드하고 페이지를 몇 번 새로 고쳐 레이트 리밋이 작동하는지 확인해 보아요.

Python + FastAPI 예시

이 예시는 GitHub에서도 찾을 수 있어요.

  1. Arcjet SDK를 설치해요:

    mkdir arcjet-fastapi
    cd arcjet-fastapi
    uv init
    uv add arcjet "fastapi[standard]" uvicorn
    
  2. main.py에 새 파일을 만들어요:

    import os
    from fastapi import FastAPI, Request
    from fastapi.responses import JSONResponse
    
    from arcjet import (
        arcjet,
        shield,
        detect_bot,
        token_bucket,
        Mode,
        BotCategory,
    )
    
    app = FastAPI()
    
    aj = arcjet(
        key=os.environ["ARCJET_KEY"],  # Get your key from https://app.arcjet.com
        rules=[
            # Shield protects your app from common attacks e.g. SQL injection
            shield(mode=Mode.LIVE),
            # Create a bot detection rule
            detect_bot(
                mode=Mode.LIVE,
                allow=[
                    BotCategory.SEARCH_ENGINE,  # Google, Bing, etc
                    # Uncomment to allow these other common bot categories
                    # See the full list at https://arcjet.com/bot-list
                    # BotCategory.MONITOR, # Uptime monitoring services
                    # BotCategory.PREVIEW, # Link previews e.g. Slack, Discord
                ],
            ),
            # Create a token bucket rate limit. Other algorithms are supported
            token_bucket(
                # Tracked by IP address by default, but this can be customized
                # See https://docs.arcjet.com/fingerprints
                # characteristics: ["ip.src"],
                mode=Mode.LIVE,
                refill_rate=5,  # Refill 5 tokens per interval
                interval=10,  # Refill every 10 seconds
                capacity=10,  # Bucket capacity of 10 tokens
            ),
        ],
    )
    
    
    @app.get("/")
    async def hello(request: Request):
        # Call protect() to evaluate the request against the rules
        decision = await aj.protect(
            request,
            requested=5,  # Deduct 5 tokens from the bucket
        )
    
        # Handle denied requests
        if decision.is_denied():
            status = 429 if decision.reason.is_rate_limit() else 403
            return JSONResponse(
                {"error": "Denied", "reason": decision.reason.to_dict()},
                status_code=status,
            )
    
        # Check IP metadata (VPNs, hosting, geolocation, etc)
        if decision.ip.is_hosting():
            # Requests from hosting IPs are likely from bots, so they can usually be
            # blocked. However, consider your use case - if this is an API endpoint
            # then hosting IPs might be legitimate.
            # https://docs.arcjet.com/blueprints/vpn-proxy-detection
    
            return JSONResponse(
                {"error": "Denied from hosting IP"},
                status_code=403,
            )
    
        return {"message": "Hello world", "decision": decision.to_dict()}
    
  3. 환경에 Arcjet 키를 넣고 애플리케이션을 실행해요:

    export ARCJET_ENV=development
    export ARCJET_KEY=ajkey_yourkey
    uv run uvicorn main:app --reload
    

가격

Arcjet 가격 페이지를 참고해 보아요.

지원

이메일: support@arcjet.com

Discord: 참여하기.

전체 지원 정책은 Arcjet 문서를 참고해 보아요.

더 알아보기 (Learn more)