바이브코딩2026-10-21·9분 읽기

Cursor·Claude가 짠 코드를 서버에 올릴 때 가장 자주 터지는 에러들과 해결법

내 컴퓨터에선 분명 잘 돌아갔는데 서버에만 올리면 왜 죽을까요? AI가 생성한 봇 코드를 클라우드에 배포할 때 마주치는 5대 에러와 확실한 해결법을 정리했어요.

Cursor·Claude가 짠 코드를 서버에 올릴 때 가장 자주 터지는 에러들과 해결법

Cursor나 Claude, ChatGPT로 텔레그램이나 디스코드 봇을 만들었어요.

노트북 터미널에서 python main.py를 실행했을 땐 아무 문제 없이 메시지도 척척 주고받았죠. 드디어 완성했다는 생각에 클라우드 서버에 코드를 올렸습니다.

그런데 배포 버튼을 누르자마자 콘솔 창에 시뻘건 에러 메시지가 쏟아지며 봇이 조용히 꺼져버립니다.

"내 컴퓨터에선 방금 전까지 잘 돌아갔는데, 서버가 이상한 걸까?"

처음엔 호스팅 플랫폼이나 서버 인프라 문제라고 생각하기 쉬워요. 하지만 콘솔 로그를 한 줄씩 뜯어보면, 원인은 대부분 AI가 코드를 짤 때 로컬 환경의 편리함에 속아 빠뜨린 사소한 설정 차이 때문이거든요.

Cursor나 Claude가 만든 봇 코드를 서버에 올릴 때 가장 자주 터지는 대표적인 에러 5가지와, 그 자리에서 바로잡는 방법을 정리했어요.

1. ModuleNotFoundError: 내 컴퓨터엔 있었지만 서버엔 없어요

가장 압도적으로 많이 터지는 에러예요.

Traceback (most recent call last):
  File "/app/main.py", line 3, in <module>
    import requests
ModuleNotFoundError: No module named 'requests'

왜 내 컴퓨터에선 잘 돌아갔을까요?

내 노트북에는 과거에 다른 프로젝트를 하면서 깔아둔 라이브러리(requests, telebot, discord 등)가 이미 전역 환경에 설치되어 있었기 때문이에요.

AI는 코드를 짤 때 내 컴퓨터에 패키지가 깔려 있는지 아닌지 알지 못해요. 그냥 import requests를 적어줄 뿐이죠. 내 노트북에서는 이미 있던 패키지를 읽어서 잘 돌았지만, 깨끗한 상태로 시작하는 서버 컴퓨터는 어떤 라이브러리가 필요한지 알 턱이 없거든요.

의외의 함정: 패키지 이름과 import 이름이 달라요

더 얄미운 경우는 requirements.txt를 분명 적었는데도 에러가 나는 경우예요. 바로 설치하는 패키지 이름과 코드에서 불러오는 이름이 다른 경우입니다.

코드에서 불러오는 이름requirements.txt에 적어야 할 진짜 이름
import telegrampython-telegram-bot
import telebotpyTelegramBotAPI
import discorddiscord.py
import PILPillow
import bs4beautifulsoup4

AI에게 "필요한 라이브러리 목록 만들어줘"라고 요청하면, 코드 첫 머리의 import telebot을 보고 requirements.txt에 그대로 telebot이라고 적어주는 실수를 자주 저질러요.

어떻게 해결할까요?

작업하던 로컬 터미널에서 현재 가상환경의 의존성을 뽑아내거나, 프로젝트 폴더 안에 requirements.txt를 만들고 진짜 패키지 이름을 정확히 적어주면 돼요.

# requirements.txt 예시
python-telegram-bot==21.10
requests==2.32.3

Node.js 환경이라면 package.json의 dependencies에 해당 패키지가 누락되지 않았는지 확인하면 됩니다.

2. Improper token has been passed: 복사 실수 3총사

디스코드나 텔레그램 봇을 켤 때 토큰 인증이 실패하는 에러예요.

# 디스코드 (discord.py)
discord.errors.LoginFailure: Improper token has been passed.
 
# 텔레그램
telegram.error.InvalidToken: Invalid token

왜 이런 일이 생길까요?

토큰을 분명 제대로 복사해서 넣었다고 생각하지만, 실상은 다음 3가지 실수 중 하나인 경우가 대부분이에요.

  1. 봇 토큰이 아니라 다른 값을 복사함: 디스코드 개발자 포털에서 'Bot' 탭의 진짜 토큰이 아니라, 'General Information'의 Application ID나 Client Secret을 복사해 넣은 경우예요.
  2. 따옴표나 줄바꿈이 섞여 들어감: 대시보드 환경변수 설정창에 값을 넣을 때 앞뒤에 공백이나 따옴표("..."), 엔터 줄바꿈이 같이 들어간 경우입니다.
  3. 환경변수 이름 오타: 파이썬 코드는 os.getenv("TELEGRAM_BOT_TOKEN")을 찾고 있는데, 대시보드에는 TELEGRAM_TOKEN이나 BOT_TOKEN처럼 한 글자 다르게 등록해서 None 값이 넘어간 경우예요.

어떻게 해결할까요?

코드 첫 머리에 환경변수가 제대로 들어왔는지 검증하는 안전장치를 2줄만 넣어두면, 원인을 몰라 헤매는 시간을 아낄 수 있어요.

import os
import sys
 
BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN")
if not BOT_TOKEN:
    print("에러: TELEGRAM_BOT_TOKEN 환경변수가 설정되지 않았습니다.", file=sys.stderr)
    sys.exit(1)

이렇게 해두면 토큰 이름이 틀렸을 때 대시보드 로그에 친절하게 안내 문구가 찍히며 즉시 원인을 알 수 있습니다.

3. Conflict: terminated by other getUpdates: 봇이 두 번 켜졌어요

텔레그램 봇을 클라우드에 배포했을 때 가장 흔하게 마주치는 악명 높은 에러예요.

telegram.error.Conflict: Conflict: terminated by other getUpdates request; 
make sure that only one bot instance is running

"하나의 봇 토큰으로는 한 번에 단 하나의 프로세스만 메시지를 받아올 수 있다"는 텔레그램 API 규칙을 위반했을 때 발생해요.

분명 서버에 1개만 올렸는데 왜 충돌이 날까요?

원인은 크게 세 가지예요.

첫째는 내 노트북에서 프로세스가 아직 살아있는 경우예요. 터미널을 닫았다고 생각했지만 백그라운드에 남아있거나, 터미널에서 Ctrl+C(프로세스 종료) 대신 Ctrl+Z(일시 중단 후 백그라운드 유지)를 눌러서 내 컴퓨터의 파이썬 프로세스가 여전히 텔레그램 신호를 낚아채고 있는 거죠.

둘째는 서버가 재시작되는 순간의 자기 충돌이에요. 봇을 재배포하면 이전 프로세스가 꺼지고 새 프로세스가 뜨잖아요. 텔레그램 서버는 이전 롱폴링 연결을 30초에서 50초 정도 붙잡고 있는 경우가 있어서, 새 프로세스가 뜨자마자 이전 연결과 충돌을 일으키기도 해요. 이 경우는 1분 정도 기다리면 자연스럽게 해결됩니다.

셋째는 과거에 웹훅을 설정했던 잔재예요. 예전에 Replit이나 웹 서버 방식으로 배포하느라 웹훅을 등록해 둔 적이 있다면, 웹훅을 삭제하기 전까지 롱폴링 루프가 409 에러를 뿜습니다.

어떻게 해결할까요?

  1. 내 로컬 컴퓨터의 작업 관리자나 터미널에서 실행 중인 파이썬 프로세스를 완전히 강제 종료(kill)해요.
  2. 예전에 등록된 웹훅 잔재가 의심된다면, 브라우저 주소창에 다음 URL을 입력해 웹훅을 깔끔하게 지워줍니다.
https://api.telegram.org/bot<내봇토큰>/deleteWebhook

성공했다는 {"ok":true,"result":true,"description":"Webhook was deleted"} 응답이 나오면 다시 서버를 기동해 보세요.

4. Address already in use: 봇에 포트가 왜 필요할까요?

로컬에서 잘 돌던 봇인데 서버에 올리니 갑자기 포트가 이미 사용 중이라는 에러가 뜹니다.

OSError: [Errno 98] Address already in use

왜 이런 코드가 끼어들었을까요?

Cursor나 ChatGPT에게 "봇 코드 짜줘"라고 부탁하면, AI가 인터넷에 돌아다니는 Replit이나 Glitch 시절의 옛날 템플릿을 참고해서 코드 맨 밑에 슬그머니 웹 서버 코드를 끼워 넣는 경우가 많아요.

# AI가 흔히 끼워 넣는 불필요한 코드
from flask import Flask
app = Flask(__name__)
 
@app.route('/')
def home():
    return "Bot is alive!"
 
if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8080) # 여기서 포트 충돌 발생!

과거 무료 호스팅 서비스들의 15분 슬립을 피하려고 가짜 웹 서버를 띄워두던 꼼수 코드예요. 하지만 텔레그램이나 디스코드 봇은 외부에서 들어오는 웹 포트가 전혀 필요 없거든요.

오히려 포트를 열어두면 서버 재배포 과정에서 이전 프로세스가 포트를 놓아주지 않아 충돌이 나거나, 플랫폼의 헬스체크 정책과 충돌해 프로세스가 죽어버립니다.

어떻게 해결할까요?

과감하게 Flask, FastAPI, app.run() 관련 줄을 전부 지워버리세요. 순수한 봇 실행 루프만 남겨두면 됩니다.

# 해결: 웹 서버 없이 순수 롱폴링만 남기기
if __name__ == "__main__":
    bot.infinity_polling()

5. 아무 에러도 없이 Exit 0으로 꺼질 때: 대기 루프가 없어요

에러 로그는 빨간 글씨 하나 없이 깨끗한데, 배포하자마자 상태가 STOPPED나 EXITED로 바뀌며 꺼져버리는 허무한 상황이에요.

Bot initialized successfully.
Process exited with code 0.

왜 그럴까요?

Exit 0은 프로그램이 에러를 내지 않고 정상적으로 끝까지 실행을 마치고 종료되었다는 뜻이에요.

AI가 봇 초기화 코드만 작성하고, **프로세스가 종료되지 않고 계속 살아 숨 쉬게 만드는 대기 루프(이벤트 루프)**를 빠뜨린 경우입니다. 1회성 스크립트처럼 코드가 위에서 아래로 한 번 쭉 실행되고 나면 프로그램이 할 일이 없어서 정상 종료해 버리는 것이죠.

어떻게 해결할까요?

라이브러리에 맞는 상시 대기 루프 메서드를 코드 마지막에 넣어주어야 해요.

# python-telegram-bot
app.run_polling()
 
# pyTelegramBotAPI
bot.infinity_polling()
 
# discord.py
client.run(BOT_TOKEN)

이 메서드들이 프로세스를 붙잡아두면서 24시간 동안 메시지가 오기를 기다리게 만들어줍니다.

6. 메모리 부족과 OOM 에러를 예방하는 법

처음 배포했을 때는 잘 돌다가 며칠 지나면 서버가 뻗어버리는 경우가 있어요. 서버 콘솔에 OOMKilled나 Exit code 137이 찍힌다면 메모리 초과입니다.

챗봇이나 자동화 스크립트에서 메모리가 새는 원인은 대부분 정해져 있어요.

  1. 무한히 커지는 캐시 딕셔너리: 유저별 대화 기록이나 데이터를 파이썬 딕셔너리에 계속 쌓아두기만 하고 지우지 않는 경우.
  2. 로그 파일 비대화: bot.log 파일에 모든 대화를 텍스트로 무한정 기록해 파일 크기가 수백 메가바이트로 불어나는 경우.
  3. 브라우저 컨텍스트 미종료: 크롤러나 스크린샷 봇에서 Playwright/Selenium을 쓸 때 페이지를 close()하지 않아 좀비 브라우저 프로세스가 메모리를 잠식하는 경우.

메모리 누수를 막으려면 오래된 대화 기록은 SQLite DB에 저장하고, 로그는 파일 대신 표준 출력(print)으로 찍어 플랫폼의 실시간 콘솔로 확인하는 편이 훨씬 안전합니다.

7. 대시보드에서 에러를 확인하고 3초 만에 다시 올리기

서버 배포 중 문제가 생겼을 때 가장 중요한 건 **"로그의 마지막 줄"**을 확인하는 습관이에요.

  1. DashCloud 대시보드의 로그 콘솔 탭을 엽니다.
  2. 화면 맨 아래로 스크롤해 빨간색 Traceback의 마지막 줄 에러 이름을 확인해요.
  3. 누락된 패키지(requirements.txt)나 환경변수 오타를 고친 뒤, 수정한 폴더를 다시 업로드하고 재배포 버튼을 누릅니다.

DashCloud MCP 서버를 연동해 두었다면 터미널 창을 열 필요도 없어요. Cursor 채팅창에서 이렇게 말하기만 하면 됩니다.

"지금 서버 배포 에러 로그 확인해서 필요한 requirements.txt 수정하고 다시 배포해줘."

AI가 대시보드의 실시간 에러 로그를 직접 읽어서 누락된 패키지를 채워 넣고 원클릭으로 재배포까지 끝내주거든요.


배포 절차와 환경변수 등록법은 빠른 시작 가이드에서 확인할 수 있어요.

DashCloud는 오픈베타 기간 동안 신용카드 등록 없이 무료로 제공돼요. GitHub 또는 Discord 계정 로그인 후 휴대폰 인증 1회를 마치면 지금 바로 무료 샌드박스를 띄울 수 있어요.