디스코드 봇을 24시간 돌리는 법 — 노트북을 켜두지 않고

discord.js로 봇을 만들어서 node index.js를 돌리면 잘 작동합니다. 문제는 노트북을 닫는 순간 봇이 오프라인이 된다는 겁니다.

그래서 무료로 올릴 곳을 찾게 되고, 대개 이런 순서를 밟습니다. 무료 호스팅에 올린다 → 한두 시간 뒤 봇이 오프라인이 된다 → “keepAlive”를 검색한다 → 우회법을 붙인다 → 며칠 뒤 또 오프라인이 된다.

봇이 오프라인이 되는 진짜 이유

먼저 구조를 알아야 우회법이 왜 실패하는지 이해가 됩니다.

디스코드 봇은 웹서버가 아닙니다. 봇이 디스코드 게이트웨이로 웹소켓 연결을 걸고, 그 연결을 계속 붙들고 있으면서 메시지 이벤트를 받습니다. 누가 봇에게 HTTP 요청을 보내는 게 아니라, 봇이 먼저 연결해서 기다리는 구조입니다.

그런데 무료 호스팅의 슬립 정책은 대부분 “인바운드 HTTP 요청이 일정 시간 없으면 컨테이너를 내린다”입니다.

여기서 어긋납니다. 봇에는 인바운드 HTTP 요청이 애초에 들어오지 않습니다. 봇이 아무리 열심히 일하고 있어도, 호스팅 입장에서는 “아무도 안 쓰는 앱”으로 보입니다. 그래서 내려버립니다. 그리고 컨테이너가 내려가면 웹소켓 연결이 끊기고, 봇을 다시 깨울 인바운드 요청도 영영 오지 않습니다.

봇은 무료 슬립 정책과 가장 궁합이 나쁜 워크로드입니다.

keepAlive와 UptimeRobot이 실패하는 지점

가장 널리 퍼진 우회법은 이겁니다. 봇 안에 작은 Express 서버를 하나 띄우고(keepAlive()), UptimeRobot 같은 외부 모니터링으로 5분마다 그 주소를 찔러서 “인바운드 요청이 있는 것처럼” 만드는 방법입니다.

이건 실제로 한동안은 동작합니다. 그래서 널리 퍼졌습니다. 다만 세 가지 이유로 결국 무너집니다.

첫째, 재시작을 못 막습니다. 슬립만 막을 뿐입니다. 호스팅이 주기적으로 컨테이너를 재활용하거나, 배포가 다시 돌거나, 리소스 초과로 프로세스가 죽으면 그 순간부터 봇은 오프라인입니다. 핑은 죽은 앱을 깨우지 못합니다 — 요청을 받아줄 프로세스 자체가 없으니까요.

둘째, 대개 이용약관 위반입니다. 무료 티어의 존재 이유가 “안 쓰는 앱은 내려서 원가를 줄인다”인데, 안 쓰는 앱을 억지로 깨어 있게 만드는 행위입니다. 적발되면 계정이 정지되고, 봇과 데이터를 함께 잃습니다.

셋째, 언제 죽었는지 모릅니다. 이게 제일 나쁩니다. 봇은 조용히 오프라인이 되고, 며칠 뒤 누가 “봇 안 돼요”라고 말해줘야 알게 됩니다. 그 사이 쌓였어야 할 기록이나 알림은 이미 사라진 뒤입니다.

그래서 뭐가 필요한가

정리하면 봇에 필요한 건 딱 하나입니다. 요청이 없어도 내려가지 않는 프로세스.

이걸 얻는 방법은 셋뿐입니다.

집에 서버를 둔다. 라즈베리파이나 안 쓰는 노트북을 24시간 켜둡니다. 전기요금 외에 돈이 안 들고 성능도 넉넉합니다. 대신 정전·인터넷 끊김·집을 비우는 동안의 관리가 전부 본인 몫입니다. 공유기 설정이나 동적 IP 문제도 따라옵니다.

VPS를 빌린다. 가장 자유도가 높습니다. 대신 OS 업데이트, 방화벽, 프로세스 관리자(pm2 등), 재부팅 시 자동 시작을 직접 챙겨야 합니다. “봇 하나 돌리려고 리눅스 관리까지” 하는 셈이라 부담을 느끼는 사람이 많습니다.

슬립 없는 컨테이너 호스팅을 쓴다. 서버 관리 없이 프로세스만 계속 켜두는 방식입니다. 무료 티어가 없는 대신 슬립도 없습니다.

봇은 자원을 얼마나 쓰나

의외로 아주 적게 씁니다. 이게 봇 호스팅에서 가장 중요한 사실입니다.

트래픽이 거의 0입니다. 봇은 웹소켓 하나를 유지하면서 이벤트를 주고받을 뿐이라, 웹사이트처럼 이미지·CSS를 내려보내지 않습니다. 명령어 몇 개 처리하는 봇이라면 월 수십 MB도 안 나옵니다.

메모리도 적게 씁니다. discord.js 봇은 보통 100~200MB 안쪽입니다. 캐시를 많이 쌓는 큰 봇이 아니라면 300MB로 충분합니다.

지연은 사실상 무의미합니다. 서버가 유럽에 있어서 왕복 300ms가 걸린다 해도, 사용자는 봇 서버에 직접 접속하는 게 아니라 디스코드를 거칩니다. 명령어 응답이 0.3초 늦는 정도인데, 사람이 타이핑하고 읽는 시간에 비하면 체감되지 않습니다.

즉 봇은 가장 싼 플랜으로도 충분한 워크로드입니다. 비싼 사양이 필요해서가 아니라, 그냥 안 꺼지기만 하면 됩니다.

판단 기준

봇을 어디에 올릴지는 이 질문 하나로 갈립니다.

봇이 꺼져 있는 걸 며칠 뒤에 알아도 괜찮은가?

취미로 만든 밈 봇이고 안 되면 그때 고치면 되는 정도라면, 무료 티어에 핑을 붙여 쓰셔도 됩니다. 실제로 그렇게 몇 달씩 잘 쓰는 사람도 있습니다.

반대로 알림을 보내는 봇이거나, 다른 사람들이 쓰고 있거나, 기록을 쌓는 봇이라면 — 우회법을 붙였다 떼었다 하면서 “지금 살아 있나” 걱정하는 시간이 결국 월 몇천 원보다 비쌉니다.

참고: 여기서 돌린다면

이 글을 쓴 곳은 슬립이 없는 Node.js 호스팅을 운영합니다. 봇 용도로는 가장 싼 스타터 플랜(메모리 300MB, 월 트래픽 30GB)이면 충분하고, 지금은 출시 기념으로 무료입니다.

먼저 밝혀둘 것도 있습니다. 서버는 유럽(핀란드·독일)에 있고, 장애 보상(SLA)을 약속하지 않습니다. 그리고 컨테이너가 예고 없이 초기화되므로, 봇 데이터를 컨테이너 안에 저장하면 안 됩니다 — 외부 DB를 쓰세요. 봇은 원래 그렇게 만드는 경우가 대부분이라 대개 문제가 되지 않습니다.

봇처럼 “안 꺼지기만 하면 되는” 워크로드에는 이 조건들이 대부분 문제가 되지 않아서, 저희가 가장 자신 있게 권하는 용도가 봇입니다.

← 글 목록으로