Discord 봇을 운영하려면 반드시 상시 실행되는 서버가 필요할까요? 슬래시 명령어를 중심으로 봇을 개발한다면 AWS Lambda와 API Gateway를 활용해 별도의 서버를 상시 운영하지 않고도 사용자 요청에 반응하는 봇을 구현할 수 있습니다.
이 글에서는 Discord Developer Portal에서 애플리케이션을 생성하는 단계부터 AWS 인프라 구성, 요청 서명 검증, 슬래시 명령어 등록 및 최종 테스트까지 전체 구축 과정을 살펴봅니다. Python과 AWS 서비스를 처음 접하는 개발자도 단계별로 따라 할 수 있도록 주요 개념과 설정 방법을 함께 설명합니다.

1. 서버리스 아키텍처가 Discord 봇 개발에 적합한 이유
서버리스(Serverless) 는 개발자가 서버를 직접 프로비저닝하거나 운영하는 부담을 줄이고, 실제 요청이 발생할 때 필요한 코드를 실행하는 방식입니다. 특히 슬래시 명령어처럼 명확한 요청과 응답으로 구성된 기능에 효과적입니다.
기존 Discord 봇 운영 방식의 한계
전통적인 Discord 봇은 Discord 서버와 지속적으로 연결을 유지하면서 이벤트를 수신합니다. 이러한 방식에서는 EC2와 같은 가상 서버나 별도의 호스팅 환경이 필요하며, 프로세스가 중단되지 않도록 관리해야 합니다.
상시 실행 환경은 메시지 이벤트나 음성 채널 상태처럼 지속적인 연결이 필요한 기능에 적합합니다. 그러나 간단한 명령어 처리만을 목적으로 한다면 실제 요청이 없는 시간에도 컴퓨팅 자원을 유지해야 한다는 단점이 있습니다.
개인 프로젝트나 소규모 서비스에서는 서버 비용뿐 아니라 운영 환경 업데이트, 장애 대응, 프로세스 재시작 등의 관리 작업도 부담이 될 수 있습니다.
AWS Lambda와 API Gateway의 역할
서버리스 방식에서는 Discord의 상호작용 요청을 HTTPS 엔드포인트로 전달하고, 해당 요청을 AWS Lambda 함수에서 처리합니다.
각 서비스의 역할은 다음과 같습니다.
- Discord: 사용자가 실행한 슬래시 명령어를 상호작용 요청으로 전달합니다.
- Amazon API Gateway: HTTPS 요청을 수신하고 연결된 Lambda 함수를 호출합니다.
- AWS Lambda: 요청의 유효성을 검사하고 명령어에 해당하는 코드를 실행합니다.
- Discord: Lambda가 반환한 응답을 바탕으로 사용자에게 결과를 표시합니다.
이 구조에서는 요청이 들어올 때 함수가 실행되므로, 별도의 서버 프로세스를 계속 실행할 필요가 없습니다.
서버리스 방식의 비용과 확장성
AWS Lambda는 요청 수와 실행 시간 등에 따라 과금되는 구조이며, 일정 수준의 무료 사용량을 제공합니다. API Gateway 역시 사용량과 API 유형에 따라 요금이 결정됩니다.
무료 사용량과 과금 조건은 계정 유형, 서비스 종류 및 시점에 따라 달라질 수 있으므로 배포 전 AWS Lambda 요금 안내와 Amazon API Gateway 요금 안내를 확인하는 것이 좋습니다.
다만 서버리스라고 해서 모든 환경이 무료인 것은 아닙니다. 로그 저장, 네트워크 전송, 추가 AWS 서비스 이용 등에 따라 비용이 발생할 수 있습니다.
2. Discord 애플리케이션과 테스트 서버 준비하기
AWS 인프라를 구성하기 전에 Discord 애플리케이션을 생성하고, 요청을 검증하는 데 필요한 인증 정보를 확보해야 합니다.
개발자 모드 활성화 및 테스트 서버 생성
먼저 Discord 클라이언트의 사용자 설정에서 개발자 모드를 활성화합니다. 개발자 모드는 서버나 채널의 ID를 확인하는 등 개발 과정에서 필요한 기능을 제공합니다.

이어서 봇의 동작을 확인할 테스트용 Discord 서버를 생성합니다. 운영 중인 서버에서 바로 테스트하기보다는 별도의 테스트 서버를 사용하는 편이 안전합니다.

Discord 애플리케이션 생성
Discord Developer Portal에 접속한 후 새 애플리케이션을 생성합니다.
애플리케이션 이름은 봇의 초기 이름으로 활용할 수 있으며, 필요에 따라 이후 변경할 수 있습니다.
애플리케이션을 생성했다면 다음 정보를 확인합니다.
- Application ID: 애플리케이션을 식별하는 고유 ID입니다.
- Public Key: Discord에서 전달한 요청의 서명을 검증할 때 사용합니다.
- Bot Token: 봇 API 인증에 사용되는 비밀 토큰입니다.
Application ID와 Public Key는 애플리케이션 설정에서 확인할 수 있습니다. Bot Token은 Bot 설정에서 발급받습니다. 기존 토큰을 재발급하거나 초기화하는 경우 이전 토큰이 무효화될 수 있으므로 주의해야 합니다.
특히 Bot Token은 공개 저장소나 블로그 코드에 노출해서는 안 됩니다. 실제 서비스에서는 환경 변수나 AWS Secrets Manager와 같은 비밀 정보 관리 수단을 사용하는 것이 바람직합니다.
봇 초대 링크 생성
OAuth2 설정에서 application.commands 권한 범위를 선택하고 생성된 초대 링크를 이용해 봇을 테스트 서버에 추가합니다.
슬래시 명령어를 등록하고 사용할 수 있도록 필요한 범위를 설정하는 것이 중요합니다. 다른 서버 권한이 필요한 기능을 구현하지 않는다면 불필요한 권한을 추가하지 않는 편이 안전합니다.
3. AWS 서울 리전에 Lambda 함수 생성하기
AWS Lambda는 이벤트가 발생했을 때 코드를 실행하는 관리형 컴퓨팅 서비스입니다. 이번 프로젝트에서는 Discord가 전달한 HTTP 요청을 처리하도록 Python 기반 함수를 구성합니다.
AWS 계정과 리전 설정
AWS 공식 홈페이지에서 계정을 준비한 다음 AWS Management Console에 로그인합니다.
콘솔의 리전 선택 메뉴에서 서울 리전인 ap-northeast-2를 선택합니다. API Gateway와 Lambda를 같은 리전에 구성하면 관리가 편리하고 서비스 간 연결 설정도 단순해집니다.
Lambda 함수 생성
AWS 콘솔 검색창에서 Lambda를 찾아 서비스 화면으로 이동합니다. 이후 함수 생성 메뉴에서 새로 작성을 선택하고 함수 이름을 입력합니다.
예를 들어 discord-event-handler라는 이름을 사용할 수 있습니다.
런타임은 프로젝트에서 사용하는 Python 버전과 의존성의 호환성을 고려해 선택합니다. 기존 튜토리얼에서는 Python 3.10을 사용했지만, 이는 2024년 당시의 환경을 기준으로 한 설정입니다. 현재는 지원 상태와 필요한 라이브러리의 호환성을 확인한 뒤 적절한 런타임을 선택해야 합니다.
특정 Python 버전에서 패키지가 정상적으로 실행되지 않는다면 해당 라이브러리의 지원 버전과 Lambda 실행 환경의 운영체제 및 아키텍처를 함께 확인해야 합니다.
Lambda 함수가 처리해야 하는 두 가지 작업
이번 함수의 기본적인 역할은 다음과 같습니다.
- Discord가 보내는 PING 요청에 PONG 응답을 반환합니다.
- 요청에 포함된 서명을 검사해 요청의 출처와 무결성을 검증합니다.
Discord는 상호작용 엔드포인트가 정상적으로 작동하는지 확인하기 위해 PING 요청을 전송합니다. 이때 요청 본문의 type 값이 1이면 다음과 같은 JSON 응답을 반환해야 합니다.
{
"type": 1
}
여기서 type: 1은 PONG 응답을 의미합니다. 이 검증 절차가 정상적으로 완료되어야 Discord에서 상호작용 엔드포인트를 유효한 주소로 등록할 수 있습니다.
4. PyNaCl을 Lambda Layer로 구성하기
Discord 요청의 서명을 검증하려면 Ed25519 서명 검증을 지원하는 라이브러리가 필요합니다. Python 환경에서는 PyNaCl을 활용할 수 있으며, 이를 Lambda Layer로 분리하면 함수 코드와 외부 라이브러리를 별도로 관리할 수 있습니다.
Lambda Layer를 사용하는 이유
Lambda 함수에 외부 패키지를 포함하는 방법은 여러 가지입니다. 코드와 패키지를 하나의 배포 ZIP 파일로 묶거나, Lambda Layer에 의존성을 분리해 관리할 수 있습니다.
Layer는 여러 함수에서 공통 라이브러리를 재사용할 때 유용합니다. 다만 Layer를 사용하더라도 Python 버전, 운영체제, CPU 아키텍처 및 네이티브 라이브러리 호환성을 고려해야 합니다.
PyNaCl 패키지 준비
Linux 기반의 호환 환경에서 Python 가상환경을 생성하고 PyNaCl을 설치합니다.
python -m pip install --upgrade pip
python -m venv venv
source venv/bin/activate
pip install PyNaCl
설치가 완료되면 가상환경의 site-packages 디렉터리에 PyNaCl과 관련 의존성 파일이 생성됩니다.
Layer용 ZIP 파일을 만들 때는 가상환경 전체를 그대로 압축하는 것이 아니라, 패키지 파일을 Lambda Layer가 인식할 수 있는 디렉터리 구조로 배치해야 합니다.
Python Layer의 일반적인 디렉터리 구조는 다음과 같습니다.
layer/
└── python/
├── nacl/
├── _cffi_backend*.so
└── 관련 의존성 파일
실제 파일 구성은 설치된 패키지와 환경에 따라 달라질 수 있습니다. 호환되지 않는 바이너리가 포함되면 함수 실행 시 모듈을 불러오지 못할 수 있으므로, 가능하면 Lambda와 호환되는 Linux 환경에서 패키지를 준비합니다.
Lambda Layer 등록 및 연결
AWS Lambda 콘솔의 계층 메뉴에서 새 Layer를 생성하고 준비한 ZIP 파일을 업로드합니다.
이때 Layer 이름을 pynacl로 지정할 수 있습니다. 호환 런타임과 아키텍처도 실제 Lambda 함수 설정과 일치하도록 선택합니다.
Layer를 생성했다면 대상 Lambda 함수로 이동해 계층 추가 메뉴를 선택합니다. 사용자 지정 계층에서 앞서 생성한 Layer와 버전을 선택하면 설정이 완료됩니다.
참고로 기존 예제 ZIP 파일을 활용하는 방법도 있지만, 외부에서 내려받은 바이너리나 패키지는 출처와 호환성을 확인한 후 사용해야 합니다.
5. Discord 요청 서명 검증 코드 작성하기
Discord의 요청은 외부에서 접근할 수 있는 HTTPS 엔드포인트를 통해 전달되므로, 요청 본문만 믿고 명령어를 실행해서는 안 됩니다. Ed25519 서명 검증을 통해 요청이 Discord에서 생성되었는지 확인해야 합니다.
서명 검증의 기본 원리
Discord는 상호작용 요청에 서명과 타임스탬프를 포함합니다. 일반적으로 다음 HTTP 헤더를 확인합니다.
- X-Signature-Ed25519
- X-Signature-Timestamp
검증 과정에서는 타임스탬프 문자열과 요청 본문을 정해진 순서로 결합한 뒤, 애플리케이션의 Public Key를 사용해 서명을 검증합니다.
서명 검증에 실패하면 요청을 거부해야 합니다. 이 과정을 생략하면 공격자가 위조한 HTTP 요청을 통해 봇의 기능을 실행하려고 시도할 수 있습니다.
타임스탬프를 사용한 재전송 공격 방어도 별도로 고려할 필요가 있습니다. 서명 검증만으로 모든 재전송 위험이 자동으로 해결되는 것은 아니므로, 서비스의 특성에 맞춰 요청 시간 검증과 중복 처리 방식을 설계하는 것이 좋습니다.
Lambda 코드 배포
기본적인 PING 처리와 서명 검증을 구현한 예제 코드는 다음 저장소에서 확인할 수 있습니다.
코드를 Lambda 함수 편집기에 적용한 다음 DISCORD_PUBLIC_KEY 설정에 Developer Portal에서 확인한 Public Key를 연결합니다.
실제 운영 환경에서는 인증 정보를 코드에 직접 입력하기보다 환경 변수 또는 적절한 비밀 정보 관리 기능을 활용하는 것이 좋습니다.
코드 적용을 마쳤다면 배포 버튼을 눌러 변경 사항을 반영합니다. 이후 API Gateway와 연결할 준비가 완료됩니다.
6. API Gateway에서 HTTPS 엔드포인트 만들기
API Gateway는 외부에서 전달되는 HTTP 요청을 수신하고 Lambda 함수로 전달하는 진입점입니다. Discord가 호출할 수 있는 공개 HTTPS 주소를 제공하는 역할을 담당합니다.
REST API 생성
AWS 콘솔에서 API Gateway를 검색한 후 REST API 생성 메뉴를 선택합니다.
API 이름을 지정하고 API를 생성한 다음 리소스 메뉴에서 새 리소스를 추가합니다. 예를 들어 리소스 이름을 event로 지정하면 실제 경로는 /event가 됩니다.
리소스 이름을 입력할 때 철자를 정확하게 확인해야 합니다. API Gateway에 등록한 경로와 Discord에 입력하는 URL이 다르면 요청이 정상적으로 전달되지 않습니다.
POST 메서드와 Lambda 연결
생성한 /event 리소스에서 메서드를 추가합니다. 메서드 유형은 POST로 지정하고 통합 유형은 Lambda 함수로 설정합니다.
앞서 생성한 discord-event-handler 함수를 연결하고 Lambda 프록시 통합을 활성화합니다.
이 설정을 적용하면 API Gateway가 전달받은 요청 정보를 Lambda 이벤트 객체에 포함해 전달합니다. Lambda에서는 이벤트 객체의 HTTP 헤더와 본문을 읽어 서명을 검증하고 명령어를 처리할 수 있습니다.
CORS는 주로 브라우저의 교차 출처 요청을 제어하기 위한 기능입니다. Discord가 서버 간 HTTPS 요청을 보내는 이번 구조에서는 일반적으로 CORS 설정 자체가 필수 요건은 아닙니다. 다른 웹 클라이언트도 API를 호출한다면 해당 사용 사례에 맞춰 설정합니다.
API 배포 및 스테이지 생성
메서드 구성이 끝나면 API 배포 메뉴를 선택합니다. 새 스테이지를 만들고 이름을 Prod로 지정할 수 있습니다.
배포가 완료되면 API Gateway가 제공하는 호출 URL을 확인합니다. 예를 들어 다음과 같은 주소가 생성될 수 있습니다.
https://example.execute-api.ap-northeast-2.amazonaws.com/Prod
위 주소는 형식을 설명하기 위한 예시입니다. 실제 배포에서는 본인의 API Gateway에 표시되는 URL을 사용해야 합니다.
7. Discord에 상호작용 엔드포인트 등록하기
API Gateway를 생성했다면 Discord 애플리케이션 설정에 실제 요청을 전달할 주소를 등록해야 합니다.
Interactions Endpoint URL 설정
Discord Developer Portal에서 대상 애플리케이션을 열고 General Information 설정으로 이동합니다.
INTERACTIONS ENDPOINT URL 항목에 API Gateway의 기본 URL과 리소스 경로를 결합한 주소를 입력합니다.
예를 들어 기본 URL이 다음과 같다면,
https://example.execute-api.ap-northeast-2.amazonaws.com/Prod
최종 엔드포인트는 다음과 같습니다.
https://example.execute-api.ap-northeast-2.amazonaws.com/Prod/event
API Gateway의 기본 URL만 입력하면 /event 경로로 요청이 전달되지 않으므로 주의해야 합니다.
엔드포인트 검증 결과 확인
설정한 URL이 정상적으로 작동하고 Lambda가 PING 요청에 올바른 응답을 반환하면 Discord에서 엔드포인트를 검증할 수 있습니다.
검증에 성공하면 설정 화면에 정상 상태가 표시됩니다. 반대로 오류가 발생한다면 다음 항목을 순서대로 확인합니다.
- 입력한 URL에 /event 경로가 포함되어 있는지 확인합니다.
- API Gateway가 올바른 스테이지에 배포되었는지 확인합니다.
- POST 메서드가 Lambda 함수에 연결되어 있는지 확인합니다.
- Lambda 함수가 type: 1 요청에 {"type": 1}을 반환하는지 확인합니다.
- 서명 검증에 사용한 Public Key와 헤더 이름이 올바른지 확인합니다.
오류가 지속된다면 Lambda 콘솔의 모니터링 메뉴에서 CloudWatch 로그를 확인합니다. 요청 본문 처리 오류, 서명 검증 실패, 패키지 로딩 오류 등을 로그로 구분하면 원인을 찾기 수월합니다.
8. Discord 슬래시 명령어 등록하기
상호작용 엔드포인트를 연결했다고 해서 슬래시 명령어가 자동으로 생성되는 것은 아닙니다. 사용자가 실행할 명령어의 이름과 옵션 등을 Discord API에 별도로 등록해야 합니다.
명령어 등록 스크립트 실행
예제 저장소의 register_command.py 파일을 사용하면 로컬 환경에서 슬래시 명령어를 등록할 수 있습니다.
스크립트를 실행하기 전에 다음 정보를 실제 애플리케이션의 값으로 설정합니다.
- APPLICATION_ID: Discord 애플리케이션의 고유 ID
- BOT_TOKEN: 봇 API 인증에 사용하는 토큰

설정이 끝나면 Python 환경에서 스크립트를 실행합니다. API 요청이 정상적으로 처리되면 등록한 명령어가 Discord 클라이언트에 표시됩니다.
Bot Token은 비밀 정보이므로 명령어 등록이 끝난 후에도 안전하게 관리해야 합니다. 토큰을 코드에 직접 기록했다면 공개 저장소에 커밋하지 않도록 주의합니다.
명령어 등록 범위 이해하기
Discord의 애플리케이션 명령어는 전역 명령어와 특정 서버에 등록하는 길드 명령어로 구분할 수 있습니다.
개발 단계에서는 테스트 서버에 길드 명령어를 등록하는 방식이 편리할 수 있습니다. 테스트가 끝난 뒤 실제 사용자에게 제공할 명령어는 서비스 목적에 맞는 등록 범위를 선택하면 됩니다.
명령어 정의를 변경하거나 삭제할 때는 Discord API에 등록된 명령어도 함께 갱신해야 합니다.
9. 서버리스 Discord 봇의 최종 동작 테스트
필요한 인프라와 명령어 등록을 마쳤다면 실제 Discord 클라이언트에서 요청과 응답이 정상적으로 이어지는지 확인합니다.
기본 명령어 실행
테스트 서버에서 등록한 슬래시 명령어를 입력하고 실행합니다.
정상적인 흐름은 다음과 같습니다.
- 사용자가 Discord에서 슬래시 명령어를 실행합니다.
- Discord가 등록된 HTTPS 엔드포인트로 상호작용 요청을 보냅니다.
- API Gateway가 요청을 수신하고 Lambda 함수를 호출합니다.
- Lambda가 요청 서명을 검증하고 명령어 유형을 확인합니다.
- 함수가 Discord 응답 규격에 맞는 결과를 반환합니다.
- Discord 클라이언트에 명령어 실행 결과가 표시됩니다.
기본 명령어가 정상적으로 작동한다면, 동일한 구조를 기반으로 사용자 정보 조회, 간단한 데이터 처리, 외부 API 호출 등 다양한 기능을 추가할 수 있습니다.
오류 발생 시 확인할 사항
명령어를 실행해도 응답이 나타나지 않는다면 Lambda의 CloudWatch 로그와 API Gateway 설정을 함께 확인합니다.
특히 Lambda 함수가 정상적으로 실행되더라도 Discord가 요구하는 응답 형식을 반환하지 않으면 명령어가 실패할 수 있습니다. 응답 JSON의 구조와 HTTP 상태 코드, 처리 시간 등을 점검하는 것이 중요합니다.
Discord 상호작용은 응답 시간 제한이 있으므로 시간이 오래 걸리는 작업은 즉시 응답한 뒤 후속 작업을 처리하거나 별도의 비동기 구조를 사용하는 방법을 고려해야 합니다.
10. AWS Lambda 기반 Discord 봇의 장점과 고려 사항
AWS Lambda와 API Gateway를 활용하면 작은 규모의 Discord 봇을 비교적 간단하게 운영할 수 있습니다. 다만 모든 유형의 봇에 적합한 구조는 아니므로 서비스 특성에 맞는 선택이 필요합니다.
서버리스 아키텍처의 주요 장점
첫째, 상시 실행 서버가 필요하지 않습니다. 요청이 들어올 때 함수를 실행하므로 서버 프로세스를 직접 유지할 필요가 줄어듭니다.
둘째, 운영 관리 부담을 낮출 수 있습니다. 운영체제 업데이트, 서버 프로세스 재시작 등 전통적인 서버 관리 작업을 줄이고 애플리케이션 로직에 집중할 수 있습니다.
셋째, 트래픽 변화에 유연하게 대응할 수 있습니다. Lambda는 요청량에 따라 실행 환경을 확장할 수 있어 사용량이 일정하지 않은 서비스에 유리합니다. 다만 동시 실행 한도와 서비스 할당량은 별도로 확인해야 합니다.
넷째, 사용량 기반 비용 구조를 활용할 수 있습니다. 요청이 적은 프로젝트에서는 상시 실행 서버보다 경제적일 수 있습니다. 실제 비용은 API 유형, 요청 수, 실행 시간 및 기타 사용량에 따라 달라집니다.
서버리스 구조에서 주의할 점
초기 인프라 설정과 외부 라이브러리 배포는 초보자에게 다소 복잡할 수 있습니다. 특히 네이티브 바이너리를 포함하는 패키지는 Lambda 런타임과 호환되는 환경에서 준비해야 합니다.
또한 Lambda는 호출마다 실행 환경이 달라질 수 있으므로 메모리 내 변수에 영구 데이터를 저장해서는 안 됩니다. 상태가 필요한 기능은 데이터베이스나 외부 저장소를 사용해야 합니다.
지속적인 WebSocket 연결, 음성 채널 참여, 실시간 이벤트 수신처럼 장시간 연결을 유지해야 하는 기능은 Lambda 기반 HTTP 상호작용 구조만으로 구현하기 어렵습니다. 이런 기능에는 별도의 상시 실행 환경이 더 적합할 수 있습니다.
마지막으로 AWS 비용과 보안 설정을 정기적으로 확인해야 합니다. CloudWatch 로그 보존 기간, Lambda 권한, 비밀 정보 관리, API 요청 검증 등을 함께 고려하면 더욱 안정적인 서비스를 운영할 수 있습니다.
AWS 서버리스 기술로 Discord 봇 개발 범위 확장하기
AWS Lambda와 API Gateway를 조합하면 상시 실행 서버를 직접 관리하지 않고도 Discord 슬래시 명령어를 처리하는 환경을 만들 수 있습니다. 핵심은 API Gateway를 통해 요청을 전달하고, Lambda에서 서명 검증과 명령어 처리를 수행한 뒤 Discord가 요구하는 형식으로 응답하는 것입니다.
이 구조는 단순한 명령어 봇뿐 아니라 외부 API 연동, 데이터 조회, 알림 처리 등 다양한 기능의 기반으로 활용할 수 있습니다. 다만 지속적인 연결이 필요한 기능이나 실행 시간이 긴 작업은 별도의 아키텍처를 검토해야 합니다.
처음에는 PING 처리와 기본 명령어처럼 작은 기능부터 구현하고, 로그와 오류 처리를 확인하면서 기능을 확장하는 것이 좋습니다. 이를 통해 서버리스 환경의 작동 원리를 익히는 동시에 실제 운영에 필요한 배포, 보안, 비용 관리 경험까지 쌓을 수 있습니다.