내가 만든 웹 앱 서버에 올리기 (Node.js·Python)
내 PC에서 만든 Express·Next.js(Node.js)나 Flask·FastAPI(Python) 앱을 서버에서 24시간 돌리고, 도메인으로 접속할 수 있게 하는 전체 흐름입니다. Ubuntu 기준입니다.
전체 흐름
- 코드를 서버로 가져오기 (GitHub)
- 비밀값을
.env에 넣기 - 앱을 상시 실행하기 (Node.js는 pm2, Python은 systemd)
- Nginx로 도메인 연결하고 HTTPS 적용하기
1. 코드 가져오기
GitHub 저장소가 공개라면 바로 받습니다.
git clone https://github.com/내아이디/내앱.git
cd 내앱
비공개 저장소라면 (배포 키)
서버 전용 키를 만들어 저장소에 "읽기 전용"으로 등록하면, 내 GitHub 비밀번호를 서버에 두지 않아도 됩니다.
ssh-keygen -t ed25519 -f ~/.ssh/deploy_key -N ""
cat ~/.ssh/deploy_key.pub
출력된 한 줄을 복사해 GitHub 저장소 → Settings → Deploy keys → Add deploy key에 붙여 넣습니다. ("Allow write access"는 체크하지 않습니다) 그다음 서버가 이 키를 쓰도록 설정하고 받습니다.
printf 'Host github.com\n IdentityFile ~/.ssh/deploy_key\n' >> ~/.ssh/config
git clone [email protected]:내아이디/내앱.git
2. 비밀값은 .env에
DB 비밀번호, API 키 같은 값은 코드에 직접 쓰지 말고 서버의 .env 파일에 넣습니다.
nano .env
🔒
.env는.gitignore에 넣어 GitHub에 올라가지 않게 하세요.
3-1. Node.js 앱 (pm2)
Node.js 설치는 디스코드 봇 24시간 호스팅하기 (discord.js·discord.py)의 "Node.js 설치"와 같습니다.
npm ci # package-lock.json 기준으로 설치
npm run build # 빌드 단계가 있는 앱만 (Next.js 등)
sudo npm install -g pm2
pm2 start npm --name my-app -- start # package.json의 start 스크립트로 실행
pm2 save
pm2 startup # 출력된 명령어를 한 번 더 복사해서 실행
3-2. Python 앱 (systemd)
sudo apt install -y python3-venv
python3 -m venv venv
./venv/bin/pip install -r requirements.txt
./venv/bin/pip install uvicorn # FastAPI라면
./venv/bin/pip install gunicorn # Flask라면
서비스 파일을 만듭니다.
sudo nano /etc/systemd/system/my-app.service
경로의 계정명, 내앱은 실제 값으로 바꾸고, ExecStart는 둘 중 내 앱에 맞는 줄 하나만 남깁니다. (main:app은 main.py 안의 app, app:app은 app.py 안의 app이라는 뜻입니다)
[Unit]
Description=My Web App
After=network-online.target
[Service]
User=계정명
WorkingDirectory=/home/계정명/내앱
EnvironmentFile=/home/계정명/내앱/.env
# FastAPI
ExecStart=/home/계정명/내앱/venv/bin/uvicorn main:app --host 127.0.0.1 --port 8000
# Flask
# ExecStart=/home/계정명/내앱/venv/bin/gunicorn -w 2 -b 127.0.0.1:8000 app:app
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now my-app
sudo systemctl status my-app # active (running)이면 성공
4. 도메인 연결과 HTTPS
웹사이트 띄우기를 따라 Nginx와 도메인, 인증서를 설정하고, "Node.js·Python 앱을 연결하고 싶다면" 부분의 proxy_pass 포트를 내 앱 포트(Node.js는 보통 3000, 위 Python 예시는 8000)로 맞춥니다.
앱 포트(3000, 8000)는 방화벽에서 열 필요가 없습니다. 외부에는 Nginx의 80·443만 열고, 앱은 Nginx를 통해서만 접속되게 하는 것이 안전합니다.
5. 코드를 고친 뒤 업데이트하기
cd ~/내앱
git pull
# Node.js
npm ci && npm run build && pm2 restart my-app
# Python
./venv/bin/pip install -r requirements.txt && sudo systemctl restart my-app
잘 안 될 때
- 로그부터 확인하세요 —
pm2 logs my-app또는journalctl -u my-app -f - 502 Bad Gateway — 앱이 꺼져 있거나, Nginx의
proxy_pass포트와 앱 포트가 다릅니다. - EADDRINUSE / Address already in use — 그 포트를 이미 다른 프로그램이 쓰고 있습니다.
sudo ss -ltnp | grep 3000으로 무엇이 쓰는지 확인하세요. - 메모리 부족으로 빌드가 멈춰요 —
npm run build중에 서버가 멈춘다면 스왑을 추가해보세요.