라즈베리파이로 디스코드 봇 24시간 돌리기 - 제로 2 W·4·5 뭘 살까? 설치부터 systemd 자동 실행까지 🍓
목차31개 항목
안녕하세요! Mojangcam입니다 😎
봇 만드는 글을 스물세 편이나 쓰는 동안, 댓글이랑 검색 유입으로 제일 많이 들어온 질문이 이거예요.
"내 컴퓨터 끄면 봇도 죽는데, 이거 어떻게 24시간 켜두나요?"
지금까지 두 가지 답을 드렸었죠.
- 디스코드 봇 24시간 무료 호스팅 총정리 → 공짜지만 잠들고, 끊기고, 어느 날 서비스가 없어져요
- 파이썬 VPS 배포 입문 (Ubuntu + systemd) → 안정적이지만 매달 5천 원~1만 원이 계속 나가요
오늘은 세 번째 선택지예요. 한 번 사두면 월세가 안 나가는 방법, 라즈베리파이입니다 🍓
이번 글에서 배울 것
- 전기요금 계산 — 진짜로 VPS보다 싼가? (실제 숫자로)
- 제로 2 W vs 파이 4 vs 파이 5, 봇 돌리는 데 뭘 사야 하나
- ⚠️ 2026년 라즈베리파이 가격이 이상해진 이유 (이거 모르고 사면 손해봐요)
- 라즈베리파이 OS 설치 — 모니터·키보드 없이(헤드리스) 세팅하기
pip install이 막히는 함정 — externally-managed-environment- systemd 로 자동 실행·자동 재시작 등록하기 (오늘의 핵심)
- 봇이 며칠 뒤 조용히 죽는 4가지 원인과 예방법
한 번 세팅해두면 정전 나도 알아서 다시 켜지고, 봇이 죽어도 10초 뒤에 알아서 살아나요. 시작해볼게요!

💰 진짜 싼가? 전기요금부터 계산해봤어요
"전기요금 더 나오는 거 아니에요?" 이거 먼저 털고 갈게요.
라즈베리파이는 유휴 상태 소비전력이 W(와트) 단위예요. 봇은 대부분의 시간을 그냥 대기하니까 유휴 전력이 곧 실사용 전력이라고 봐도 됩니다.
| 모델 | 유휴 소비전력 | 한 달(24시간×30일) | 전기요금(대략) |
|---|---|---|---|
| 제로 2 W | 약 0.6W | 0.43 kWh | 월 100원 안팎 |
| 파이 4 | 약 3~4W | 2.2~2.9 kWh | 월 300~600원 |
| 파이 5 | 약 2.7~3W | 1.9~2.2 kWh | 월 300~500원 |
💡 전기요금은 주택용 누진구간에 따라 달라져요. kWh당 120~215원으로 잡고 계산한 값이라 정확한 금액이 아니라 자릿수로 봐주세요. 핵심은 "한 달에 커피값도 안 나온다"는 거예요 ☕
VPS는 가장 싼 게 월 5천 원 정도예요. 파이 5를 10만 원에 샀다고 쳐도 약 1년 8개월이면 본전이고, 그 뒤로는 계속 이득이에요. 게다가 파이는 봇만 돌리는 게 아니라 예약 실행 자동화, 크롤링, NAS까지 같이 시킬 수 있고요.
단점도 솔직히 말씀드릴게요.
- 우리 집 인터넷이 끊기면 봇도 끊겨요 (VPS는 데이터센터라 이럴 일이 거의 없죠)
- 정전 나면 꺼져요 (부팅 시 자동 실행은 오늘 설정해둘 거예요)
- 초기 비용이 한 번에 나가요
🎯 정리하면 — 개인·소규모 서버 봇이면 라즈베리파이가 정답, 수백 개 서버에 들어간 봇이면 VPS가 맞아요.
🍓 어떤 모델을 사야 할까요?
여기서부터가 오늘 글에서 제일 중요한 부분이에요. 2026년엔 특히요.
⚠️ 먼저 알아야 할 것 — 2026년 라즈베리파이 가격 대란
AI 데이터센터가 메모리를 쓸어가면서 LPDDR4 가격이 폭등했어요. 라즈베리파이 재단은 2025년 12월부터 2026년까지 세 번이나 가격을 올렸습니다. 2026년 2월 인상분만 봐도 이래요.
| 메모리 용량 | 인상액 |
|---|---|
| 1GB | 인상 없음 |
| 2GB | +$10 |
| 4GB | +$15 |
| 8GB | +$30 |
| 16GB | +$60 |
여기서 우리한테 중요한 포인트가 두 개예요.
- 1GB 모델은 가격을 지켰어요. 파이 4 1GB는 $35, 2025년 12월에 나온 파이 5 1GB는 $45 그대로예요
- 제로 시리즈와 파이 3는 아예 영향이 없어요. 이 모델들은 구형 LPDDR2를 쓰는데, 재단이 몇 년치 재고를 갖고 있거든요
🔥 그러니까 지금은 "봇 돌리려고 8GB 사는" 게 제일 손해 보는 선택이에요. 봇은 램을 거의 안 씁니다. 이유는 바로 아래에서 숫자로 보여드릴게요.
봇은 램을 얼마나 쓸까요? (실측)
말로만 "적게 쓴다"고 하면 안 믿기시죠. 제가 직접 재봤어요. discord.py 2.7.1을 올린 봇의 메모리 사용량이에요.
파이썬만 실행했을 때 : 9.8 MB
+ discord.py import 후 : 37.7 MB (+27.9)
+ Bot 객체·슬래시 명령어 : 37.8 MB (+0.1)봇 하나가 40MB 남짓이에요. 제로 2 W의 512MB 안에서도 열 개는 돌릴 수 있는 양이죠.
📌 이 값은 리눅스 x86 환경에서 잰 거라 파이(ARM)에선 몇 MB 차이가 날 수 있어요. 하지만 "수십 MB 수준"이라는 자릿수는 그대로입니다.
추가 - 파이에서 구동시 PSS 40.3MB, RSS 48.4MB, Swap 0MB 입니다!
그래서 뭘 사면 되나요?
| 제로 2 W | 파이 4 | 파이 5 | |
|---|---|---|---|
| CPU | 4코어 1GHz (A53) | 4코어 1.5GHz (A72) | 4코어 2.4GHz (A76) |
| 메모리 | 512MB 고정 | 1~8GB | 1~16GB |
| 유휴 전력 | 약 0.6W | 약 3~4W | 약 2.7~3W |
| 랜선 포트 | ❌ 와이파이만 | ✅ 기가비트 | ✅ 기가비트 |
| USB 부팅 | ❌ SD카드만 | ✅ | ✅ (NVMe도 가능) |
| 2026 가격 영향 | 없음 | 1GB만 안전 | 1GB만 안전 |
| 봇 돌리기 | ⭕ 충분 | ◎ 넉넉 | ◎ 과할 정도 |
제 추천은 이래요.
- 🥇 봇 1~3개만 돌릴 거예요 → 제로 2 W. 512MB로 충분하고, 전기도 거의 안 먹고, 가격 인상도 안 겪었어요. 손바닥보다 작아서 공유기 옆에 붙여두면 끝
- 🥈 봇 + 자동화 스크립트 + 가끔 다른 것도 → 파이 4 또는 파이 5의 1GB/2GB. 랜선을 꽂을 수 있다는 게 진짜 큰 장점이에요 (와이파이 끊김 걱정이 사라져요)
- 🥉 음악 봇을 만들 거예요 → 파이 4 이상 필수. 음성 스트리밍은 CPU를 실제로 씁니다. 제로 2 W는 여기서 버거워요
- ❌ 8GB·16GB → 봇 용도로는 돈 낭비예요. 지금은 특히요
💬 제로 2 W의 진짜 단점은 램이 아니라 속도예요. 1GHz A53이라
pip install한 번에 몇 분씩 걸립니다. 돌아가는 건 문제없는데 세팅할 때 인내심이 좀 필요해요 😅
🧰 준비물
- 라즈베리파이 본체 (제로 2 W / 4 / 5 중 하나)
- microSD 카드 16GB 이상 — ⭐ 여기서 아끼지 마세요. 값싼 카드가 봇이 죽는 1등 원인이에요 (아래에서 설명)
- 전원 어댑터 — 제로 2 W는 5V 2.5A, 파이 4는 5V 3A(USB-C), 파이 5는 5V 5A 정품 권장
- SD카드 리더기가 달린 PC
- 디스코드 봇 토큰 — 개발자 포털에서 발급받은 그거요. 토큰이나 인텐트 때문에 막히면 디스코드 봇 오류 해결 총정리 글을 먼저 보고 오세요
- 모니터·키보드는 필요 없어요 👍 오늘은 헤드리스로 갑니다
⚡ 파이 5는 전원이 까다로워요. 5V 5A(25W) 정품 어댑터가 아니면 부팅할 때 "저전압" 경고가 뜨고, 심하면 USB 장치를 못 씁니다. 폰 충전기 꽂았다가 원인 모를 재부팅 반복하는 사례가 정말 많아요.
1단계 - 라즈베리파이 OS 설치 (모니터 없이!)
Imager 로 굽기
라즈베리파이 공식 사이트에서 Raspberry Pi Imager를 받아 설치하세요. SD카드를 꽂고 실행합니다.
- 장치 선택 : 갖고 계신 모델을 고르세요
- OS 선택 :
Raspberry Pi OS (other)→Raspberry Pi OS Lite (64-bit) - 저장소 : SD카드
🎯 꼭 Lite 버전을 고르세요! 데스크톱 버전은 화면·브라우저 때문에 램을 수백 MB 잡아먹어요. 봇은 화면이 필요 없습니다. 제로 2 W는 Lite가 사실상 필수예요.
⭐ 여기가 헤드리스의 핵심 — 설정 미리 넣기
"다음"을 누르면 OS 커스터마이징 설정을 하겠냐고 물어봐요. 꼭 "설정을 편집하기"를 누르세요. 여기서 안 하면 모니터를 연결해야 합니다.
일반 탭
- 호스트명 :
pibot(나중에pibot.local로 접속해요) - 사용자 이름·비밀번호 :
pi/ 원하는 비밀번호 - 무선 LAN 설정 : 집 와이파이 이름(SSID)과 비밀번호, 국가는
KR - 지역 설정 : 시간대
Asia/Seoul
서비스 탭
- ☑️ SSH 사용 체크 → "비밀번호 인증 사용" 선택
이렇게 하고 굽기를 누르면 끝이에요. 카드를 빼서 파이에 꽂고 전원을 넣습니다.
⚠️ 제로 2 W는 2.4GHz 와이파이만 지원해요. 공유기가 5GHz 전용 SSID로 잡혀 있으면 아무리 기다려도 안 붙습니다. 2.4GHz SSID를 입력하세요.
2단계 - SSH 로 접속하기
파이에 전원을 넣고 1~2분 기다린 뒤(첫 부팅은 오래 걸려요), PC의 터미널(윈도우는 PowerShell)에서 접속합니다.
ssh pi@pibot.localpibot.local 로 안 되면 공유기 관리 페이지에서 IP를 찾아 ssh pi@192.168.0.xx 처럼 접속하세요.
접속했으면 먼저 업데이트부터 합니다.
sudo apt update && sudo apt full-upgrade -y
sudo apt install -y python3-venv python3-pip git💡 제로 2 W면 여기서 커피 한 잔 하고 오세요. 정말 오래 걸립니다 ☕
파이썬 버전을 확인해볼게요.
python3 -V2025년 10월부터 라즈베리파이 OS는 Debian 13 "Trixie" 기반이고, 여기 들어 있는 시스템 파이썬은 3.13이에요. discord.py 2.7.x 를 돌리기에 충분합니다.
3단계 - ⚠️ pip 이 막히는 함정 (externally-managed-environment)
여기서 90%가 한 번은 막혀요. 신나게 봇 라이브러리를 깔려고 하면 이런 게 뜹니다.
pip install discord.pyerror: externally-managed-environment
× This environment is externally managed
╰─> To install Python packages system-wide, try apt install
python3-xyz, where xyz is the package you are trying to
install.
If you wish to install a non-Debian-packaged Python package,
create a virtual environment using python3 -m venv path/to/venv.고장난 게 아니에요. Debian 12(Bookworm)부터 적용된 PEP 668 이라는 규칙이에요. pip으로 시스템 전체에 패키지를 깔면 OS가 관리하는 파이썬 패키지와 충돌해서 시스템이 깨질 수 있으니까, 아예 막아둔 거예요.
정답은 가상환경(venv) 입니다. venv 완벽 정리 글에서 다룬 그 venv 맞아요.
mkdir ~/pi-bot && cd ~/pi-bot
python3 -m venv .venv
source .venv/bin/activate
pip install -U pip
pip install discord.py python-dotenv프롬프트 앞에 (.venv) 가 붙으면 성공이에요.
python -c "import discord; print(discord.__version__)"
# 2.7.1❌
--break-system-packages는 쓰지 마세요. 검색하면 "이 옵션 붙이면 된다"는 글이 많은데, 이름 그대로 시스템 패키지를 깨뜨리는 옵션이에요. 나중에apt upgrade하다가 파이썬이 통째로 꼬입니다. venv가 정답이에요.
4단계 - 봇 코드 올리기
파일 만들기
nano 로 직접 만들어도 되고, PC에서 작성한 파일을 올려도 돼요.
# PC에서 파이로 파일 보내기 (PC 터미널에서 실행)
scp bot.py .env pi@pibot.local:~/pi-bot/
# 또는 깃허브에 올려뒀다면
cd ~/pi-bot && git clone https://github.com/내계정/내봇.git ..env 에 토큰 넣기
nano ~/pi-bot/.envDISCORD_TOKEN=여기에_봇_토큰을_붙여넣으세요Ctrl+O → Enter → Ctrl+X 로 저장하고 나옵니다. 그리고 권한을 반드시 조여주세요.
chmod 600 ~/pi-bot/.env🔒 토큰은 비밀번호와 똑같아요. 깃허브에 실수로 올리면 봇이 통째로 털립니다.
.gitignore에.env를 꼭 넣으세요.
손으로 한 번 돌려보기
systemd에 등록하기 전에 반드시 손으로 실행해서 되는지 확인하세요.
cd ~/pi-bot
source .venv/bin/activate
python bot.py2026-08-15 21:04:11 [INFO] pi-bot: 슬래시 명령어 동기화 완료
2026-08-15 21:04:12 [INFO] pi-bot: MojangBot#1234 로그인 성공 (지연 78ms)디스코드에서 /핑 을 쳐보고 응답이 오면 성공이에요! Ctrl+C 로 끄고 다음 단계로 갑니다.

5단계 - ⭐ systemd 로 자동 실행 등록하기 (오늘의 핵심)
지금 상태는 SSH를 끊으면 봇도 같이 죽어요. 이걸 리눅스의 서비스로 등록해서 "부팅하면 알아서 켜지고, 죽으면 알아서 살아나게" 만듭니다.
sudo nano /etc/systemd/system/discordbot.service[Unit]
Description=Discord Bot (Raspberry Pi)
Wants=network-online.target
After=network-online.target
[Service]
Type=simple
User=pi
Group=pi
WorkingDirectory=/home/pi/pi-bot
ExecStart=/home/pi/pi-bot/.venv/bin/python /home/pi/pi-bot/bot.py
Restart=always
RestartSec=10
Environment=PYTHONUNBUFFERED=1
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target하나씩 뜯어볼게요 🔍
After=network-online.target: ⚠️ 여기 정말 중요해요. 흔히 쓰는network.target은 "네트워크 장치가 올라옴"까지만 보장하고 IP가 잡혔는지는 안 봐요. 그래서 부팅 직후 DNS 조회에 실패하면서 봇이 죽습니다.network-online.target과Wants=를 둘 다 써야 제대로 기다려요User=pi: 이걸 빼면 root로 실행돼요. 봇이 뚫렸을 때 피해가 커지니 반드시 일반 계정으로 돌리세요ExecStart의 절대경로 : ⭐ 1등 실수 지점. systemd는source .venv/bin/activate를 모르고PATH도 우리 셸과 달라요. venv 안의 python을 절대경로로 직접 가리켜야 합니다Restart=always+RestartSec=10: 봇이 어떤 이유로든 죽으면 10초 뒤에 다시 켜요. 인터넷이 잠깐 끊겨서 죽어도 알아서 복구됩니다PYTHONUNBUFFERED=1: 파이썬은 출력을 모아뒀다 한 번에 내보내요. 이걸 안 켜면 로그가 한참 뒤에야 보여서 디버깅할 때 미쳐버립니다
이제 등록하고 켭니다.
sudo systemctl daemon-reload
sudo systemctl enable --now discordbot
sudo systemctl status discordbot● discordbot.service - Discord Bot (Raspberry Pi)
Loaded: loaded (/etc/systemd/system/discordbot.service; enabled; preset: enabled)
Active: active (running) since Sat 2026-08-15 21:10:33 KST; 8s ago
Main PID: 1041 (python)
Tasks: 4 (limit: 384)
CPU: 3.221s
CGroup: /system.slice/discordbot.service
└─1041 /home/pi/pi-bot/.venv/bin/python /home/pi/pi-bot/bot.pyActive: active (running) 초록불이 뜨면 끝났어요! 이제 SSH를 끊어도, 정전이 나고 전원이 돌아와도 봇은 알아서 켜집니다 🎉
💡
enable은 "부팅 시 자동 시작",start는 "지금 켜기"예요.enable --now는 둘을 한 번에 합니다.
자주 쓰는 명령어
sudo systemctl restart discordbot # 코드 고친 뒤 재시작
sudo systemctl stop discordbot # 잠깐 끄기
sudo systemctl disable discordbot # 부팅 자동 시작 해제6단계 - 로그 보기 (journalctl)
print 로 찍은 것도, 에러 메시지도 전부 journald가 모아둬요.
journalctl -u discordbot -f # 실시간으로 따라가기 (제일 많이 씀)
journalctl -u discordbot -n 50 # 최근 50줄
journalctl -u discordbot --since "1 hour ago"
journalctl -u discordbot -p err # 에러만-f 는 tail -f 랑 같아요. 봇을 고치는 동안 이 창을 하나 띄워두면 편합니다.
7단계 - 며칠 뒤 조용히 죽지 않게 만드는 4가지
여기까지만 해도 돌아가요. 그런데 일주일쯤 지나면 봇이 소리소문 없이 멈춰 있는 경우가 있어요. 원인은 거의 이 넷 중 하나입니다.
① 와이파이 절전 모드 (제로 2 W에서 특히!)
라즈베리파이의 와이파이는 기본적으로 절전 모드가 켜져 있어요. 트래픽이 뜸하면 무선 칩이 살짝 조는데, 봇처럼 조용히 대기하는 프로그램은 이때 연결이 끊깁니다.
# 지금 상태 확인 (Power Management:on 이면 켜져 있는 것)
iwconfig wlan0 | grep -i power
# 즉시 끄기
sudo iw dev wlan0 set power_save off재부팅해도 유지되게 서비스로 만들어둘게요.
sudo nano /etc/systemd/system/wifi-powersave-off.service[Unit]
Description=Disable WiFi power save
After=network.target
[Service]
Type=oneshot
ExecStart=/usr/sbin/iw dev wlan0 set power_save off
[Install]
WantedBy=multi-user.targetsudo systemctl enable --now wifi-powersave-off🥇 랜선을 꽂을 수 있다면 그게 최고의 해결책이에요. 파이 4·5를 추천한 이유가 바로 이겁니다.
② SD카드 수명 — 로그가 카드를 갉아먹어요
microSD는 쓰기 횟수에 수명이 있어요. 봇 로그가 24시간 계속 쌓이면 싸구려 카드는 몇 달 만에 맛이 갑니다. 로그 용량에 상한을 걸어두세요.
sudo nano /etc/systemd/journald.conf[Journal]
SystemMaxUse=50M
SystemMaxFileSize=10Msudo systemctl restart systemd-journald💾 카드는 정품 SanDisk·Samsung의 A1/A2 등급을 쓰세요. 이름 모를 저가 카드가 "봇이 갑자기 파일을 못 읽어요" 사태의 진짜 범인인 경우가 정말 많아요. 파이 4·5라면 아예 USB SSD로 부팅하는 게 수명·속도 둘 다 훨씬 낫습니다.
③ 하드웨어 워치독 — 파이가 통째로 얼었을 때
Restart=always 는 봇 프로세스가 죽었을 때만 살려요. 커널이 얼어버리면 systemd도 같이 멈추죠. 이럴 때 파이를 강제로 재부팅시키는 하드웨어 워치독이 있어요.
sudo nano /boot/firmware/config.txt맨 아래에 추가합니다.
dtparam=watchdog=onsudo apt install -y watchdog
sudo systemctl enable --now watchdog
sudo reboot⚠️ 파일 경로가 예전엔
/boot/config.txt였는데 최근 OS에선/boot/firmware/config.txt로 바뀌었어요. 옛날 블로그 글 보고 따라 하다 "파일이 없다"고 헤매는 분이 많습니다.
④ 토큰 만료·인텐트 문제
이건 파이 문제가 아니라 봇 문제예요. 개발자 포털에서 토큰을 재발급하면 예전 토큰은 즉시 죽어요. 로그에 LoginFailure 가 보이면 .env 를 확인하세요. 자세한 건 디스코드 봇 오류 해결 총정리 글에 정리해뒀어요.
📦 전체 코드 (복붙 OK)
1) bot.py
# bot.py - 라즈베리파이 24시간 구동용 최소 봇
# discord.py 2.7.1 / python-dotenv 1.x / Python 3.9+
# 라즈베리파이 OS Trixie(Debian 13) 기준 - 시스템 파이썬 3.13
import logging
import os
import platform
import sys
from pathlib import Path
import discord
from discord.ext import commands
from dotenv import load_dotenv
BASE_DIR = Path(__file__).resolve().parent
load_dotenv(BASE_DIR / ".env")
TOKEN = os.getenv("DISCORD_TOKEN")
# systemd 로 돌릴 땐 print 대신 logging 을 쓰세요.
# stdout 으로 나간 로그를 journald 가 그대로 주워 담습니다.
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
stream=sys.stdout,
)
log = logging.getLogger("pi-bot")
intents = discord.Intents.default()
intents.message_content = True # 개발자 포털에서도 켜야 해요!
class PiBot(commands.Bot):
def __init__(self):
super().__init__(command_prefix="!", intents=intents)
async def setup_hook(self):
await self.tree.sync()
log.info("슬래시 명령어 동기화 완료")
bot = PiBot()
@bot.event
async def on_ready():
log.info("%s 로그인 성공 (지연 %.0fms)", bot.user, bot.latency * 1000)
@bot.tree.command(name="핑", description="봇 응답 속도를 확인해요")
async def ping(interaction: discord.Interaction):
await interaction.response.send_message(f"퐁! {bot.latency * 1000:.0f}ms")
@bot.tree.command(name="파이상태", description="라즈베리파이 상태를 보여줘요")
async def pi_status(interaction: discord.Interaction):
embed = discord.Embed(title="라즈베리파이 상태", color=0xC51A4A)
embed.add_field(name="모델", value=read_model(), inline=False)
embed.add_field(name="CPU 온도", value=f"{read_cpu_temp():.1f}도", inline=True)
embed.add_field(name="메모리", value=read_memory(), inline=True)
embed.add_field(name="가동 시간", value=read_uptime(), inline=True)
embed.set_footer(text=f"Python {platform.python_version()}")
await interaction.response.send_message(embed=embed)
def read_model() -> str:
"""/proc/device-tree/model 에 보드 이름이 그대로 들어 있어요."""
try:
raw = Path("/proc/device-tree/model").read_bytes()
return raw.decode("utf-8").rstrip("\x00")
except OSError:
return "알 수 없음 (라즈베리파이가 아님)"
def read_cpu_temp() -> float:
"""밀리도(1/1000도) 단위라 1000 으로 나눠야 해요."""
try:
milli = Path("/sys/class/thermal/thermal_zone0/temp").read_text()
return int(milli.strip()) / 1000
except (OSError, ValueError):
return 0.0
def read_memory() -> str:
"""psutil 없이 /proc/meminfo 로 읽어요. Zero 2 W 에선 이 몇 MB가 아깝습니다."""
try:
info = {}
for line in Path("/proc/meminfo").read_text().splitlines():
key, _, value = line.partition(":")
info[key] = int(value.strip().split()[0]) # kB
total = info["MemTotal"] / 1024
available = info["MemAvailable"] / 1024
return f"{total - available:.0f} / {total:.0f} MB"
except (OSError, KeyError, ValueError):
return "알 수 없음"
def read_uptime() -> str:
try:
seconds = float(Path("/proc/uptime").read_text().split()[0])
except (OSError, ValueError):
return "알 수 없음"
days, rest = divmod(int(seconds), 86400)
hours, rest = divmod(rest, 3600)
minutes = rest // 60
if days:
return f"{days}일 {hours}시간 {minutes}분"
return f"{hours}시간 {minutes}분"
if __name__ == "__main__":
if not TOKEN:
log.error(".env 에 DISCORD_TOKEN 이 없습니다. 종료합니다.")
raise SystemExit(1)
bot.run(TOKEN, log_handler=None) # 위에서 만든 logging 설정을 그대로 사용💡
/파이상태명령어는psutil같은 추가 라이브러리 없이 리눅스의/proc,/sys파일을 직접 읽어요. 파이에서 아낄 수 있는 건 다 아끼는 게 좋으니까요. 파이가 아닌 곳에서 돌리면 모델 이름 대신 안내 문구가 나오게 해뒀습니다.
2) 폴더 구조
/home/pi/pi-bot/
├─ .venv/ # 가상환경 (python3 -m venv .venv)
├─ .env # DISCORD_TOKEN (chmod 600!)
├─ .gitignore # .venv/, .env
├─ bot.py
└─ requirements.txt3) requirements.txt
discord.py==2.7.1
python-dotenv==1.1.1새 파이에 옮길 땐 이거 한 줄이면 끝이에요.
python3 -m venv .venv && .venv/bin/pip install -r requirements.txt🚨 자주 나는 에러
1. systemctl status 에 status=203/EXEC 가 떠요
- 원인 :
ExecStart경로가 틀렸어요. 1등 원인입니다 - 해결 :
ls -l /home/pi/pi-bot/.venv/bin/python로 파일이 진짜 있는지 확인하세요. 사용자 이름이pi가 아니라면 경로도 같이 바꿔야 해요
2. ModuleNotFoundError: No module named 'discord'
- 원인 : systemd가 시스템 파이썬으로 실행했어요. venv 밖에는 discord.py가 없죠
- 해결 :
ExecStart를/usr/bin/python3가 아니라.venv/bin/python으로 바꾸세요
3. 부팅 직후에만 죽고, 손으로 켜면 잘 돼요
- 원인 : 와이파이가 붙기 전에 봇이 먼저 떠서 DNS 조회에 실패했어요
- 해결 :
Wants=network-online.target과After=network-online.target을 둘 다 넣으세요. 그래도 불안하면ExecStartPre=/bin/sleep 15를 추가해 여유를 주면 확실합니다
4. error: externally-managed-environment
- 원인 : PEP 668. 시스템 파이썬에 직접 설치하려고 했어요
- 해결 : venv를 만들어 그 안에서 설치하세요.
--break-system-packages로 우회하지 마세요
5. .env 를 읽어도 토큰이 None 이에요
- 원인 : systemd는
WorkingDirectory기준으로 도는데,load_dotenv()를 인자 없이 부르면 현재 폴더에서.env를 찾아요 - 해결 : 위 코드처럼
load_dotenv(BASE_DIR / ".env")로 파일 위치를 명시하세요. 스크립트 옆에 있는.env를 확실하게 집습니다
6. 로그가 실시간으로 안 보여요
- 원인 : 파이썬 출력 버퍼링
- 해결 :
Environment=PYTHONUNBUFFERED=1을 서비스 파일에 추가하세요
7. 화면에 "Undervoltage detected" 경고가 떠요
- 원인 : 전원이 부족해요. 특히 파이 5 + 폰 충전기 조합
- 해결 : 정품 어댑터를 쓰세요 (파이 5는 5V 5A). 저전압 상태에선 SD카드 오류·랜덤 재부팅이 계속 납니다
8. 제로 2 W에서 pip install 이 멈춘 것 같아요
- 원인 : 안 멈췄어요. 진짜로 느린 거예요 😅 빌드가 필요한 패키지면 수십 분도 걸립니다
- 해결 : 기다리세요. 자꾸 그러면
pip install --prefer-binary로 미리 빌드된 휠을 우선 받게 하거나, 스왑을 늘리세요
9. ssh pi@pibot.local 이 안 돼요
- 원인 : mDNS(
.local)가 네트워크에 따라 안 잡혀요 - 해결 : 공유기 관리 페이지에서 파이의 IP를 찾아 IP로 접속하세요. 찾았으면 고정 IP로 할당해두면 편해요
💬 마무리
오늘은 봇을 내 손 안의 서버에 올렸어요 🍓
오늘의 요약
- 전기요금은 월 100~500원 수준 — VPS 1년 반이면 본전이에요
- 봇 하나는 램을 40MB 남짓 써요. 8GB 살 필요 전혀 없습니다. 2026년엔 특히 1GB·제로 시리즈가 가격 방어가 잘 돼 있어요
- OS는 Lite 64-bit, Imager에서 SSH·와이파이를 미리 넣어 헤드리스로 세팅
pip이 막히면 그건 고장이 아니라 PEP 668 — 답은 venv- systemd의 핵심 3종 : venv python 절대경로,
network-online.target,Restart=always - 며칠 뒤 죽는 이유는 대개 와이파이 절전 아니면 SD카드예요
다음 #24편에서는 서버 로그·감사(Audit) 채널을 만들어요. 오늘 파이에 올린 봇이 24시간 지켜보면서 메시지 삭제·수정, 입퇴장을 전부 임베드 로그로 남길 거예요. #23편에서 만든 DB에 로그 채널 설정을 저장하면서 바로 써먹습니다. 기대해주세요! 🙌
🍓 파이를 사실 거면 본체보다 전원 어댑터와 SD카드에서 아끼지 마세요. 오늘 정리한 문제의 절반은 이 둘에서 나옵니다. 장비 고르는 기준은 코딩용 노트북 고르는 기준 글처럼 따로 정리해볼게요.
📚 봇을 24시간 돌리는 세 가지 방법
- 무료 호스팅 총정리 - 아직 되는 곳 vs 이제 안 되는 곳 — 돈 안 쓰고 시작하기
- VPS 배포 입문 (Ubuntu + systemd) — 제일 안정적인 방법
- 라즈베리파이로 돌리기 ← 지금 이 글! — 월세 없는 방법
📚 디스코드 봇 만들기 시리즈
- #1 ~ #16 — 첫 봇 만들기부터 리마인더까지
- #17 RAG로 문서 기반 답변봇 만들기
- #18 투표(Poll) 기능 만들기
- #19 Cog로 코드 쪼개기
- #20 자동 환영 메시지·온보딩
- #21 키워드 자동응답·금지어 필터
- #22 슬래시 명령어 자동완성(Autocomplete)
- #23 aiosqlite로 비동기 DB 설계하기
- #24 서버 로그·감사(Audit) 채널 만들기 (예정)

