MySQL 설치는 명령 하나면 끝납니다. 진짜 일은 그다음입니다. 앱용 사용자, 포트 3306을 인터넷에 내놓지 않고 내 컴퓨터에서 데이터베이스에 닿는 방법, 작은 서버에 맞는 메모리 설정, 그리고 손대지 않아도 돌아가는 백업이 필요합니다. 이 가이드는 Ubuntu 24.04에서 이 네 가지를 모두 다룹니다. 모든 단계를 저희 Ubuntu 24.04 이미지에서 실행했고, 아래 수치도 그 서버에서 나온 것입니다.
명령은 sudo 권한이 있는 사용자로 실행하세요. Ubuntu 설정 가이드에서 만들 수 있습니다.
1. 설치하기
sudo apt update
sudo apt install -y mysql-server
mysql --version
저희 서버에서 설치는 51초가 걸렸고 MySQL 8.0.46이 설치되었습니다. 바로 시작되고, 부팅할 때마다 다시 시작되며, 서버 자신에서만 대기합니다. 일반 연결은 127.0.0.1:3306, MySQL의 새 X 프로토콜은 127.0.0.1:33060입니다. 아직 밖에서는 아무것도 닿지 않습니다.
2. 데이터베이스와 사용자 만들기
Ubuntu에서 MySQL root 계정은 소켓 인증을 쓰므로 sudo mysql로 비밀번호 없이 로그인됩니다. 앱용 데이터베이스와 사용자를 만드세요.
sudo mysql
CREATE DATABASE app CHARACTER SET utf8mb4;
CREATE USER 'app'@'localhost' IDENTIFIED BY 'a-long-random-password';
GRANT ALL PRIVILEGES ON app.* TO 'app'@'localhost';
EXIT;
앱이 접속하는 방식 그대로 테스트하세요.
mysql -u app -p app -e "SELECT CURRENT_USER();"
app@localhost가 출력되어야 합니다. 비밀번호가 틀리면 ERROR 1045 (28000): Access denied for user 'app'@'localhost'가 나옵니다. 이 사용자는 app 안에서는 무엇이든 할 수 있고, 밖에서는 아무것도 할 수 없습니다.
3. 내 컴퓨터에서 접속하기: SSH 터널
DBeaver, MySQL Workbench, mysql 명령줄 같은 데스크톱 클라이언트를 내 컴퓨터에서 쓰려 해도 포트를 열지 마세요. SSH로 하나를 전달하세요.
ssh -L 3307:127.0.0.1:3306 deploy@YOUR.SERVER.IP
NAT 요금제라면 -p와 대시보드의 개인 SSH 포트를 붙이세요. 그 창이 열려 있는 동안 클라이언트를 호스트 127.0.0.1, 포트 3307, 사용자 app으로 지정합니다. 로컬 쪽을 3307로 한 것은 내 컴퓨터에서 돌고 있을지 모르는 MySQL과 겹치지 않게 하려는 것입니다. 테스트에서 서버는 터널로는 바로 응답했고, 서버 주소의 3306으로 직접 연결하면 거부되었습니다.
4. 다른 서버 한 대에 직접 접근 허용하기
앱이 두 번째 서버에서 돌아 데이터베이스에 직접 접속해야 할 때도 있습니다. 그러려면 데이터베이스 쪽에 전용 IPv4가 있는 요금제가 필요합니다. NAT 요금제는 SSH 포트만 전달하기 때문입니다. 변경은 세 가지이며, 모두 앱 서버 주소(여기서는 203.0.113.20)로 한정합니다.
sudo sed -i 's/^bind-address.*/bind-address = 0.0.0.0/' /etc/mysql/mysql.conf.d/mysqld.cnf
sudo systemctl restart mysql
sudo ufw allow from 203.0.113.20 to any port 3306 proto tcp
CREATE USER 'app'@'203.0.113.20' IDENTIFIED BY 'a-long-random-password';
GRANT ALL PRIVILEGES ON app.* TO 'app'@'203.0.113.20';
ufw가 아직 켜져 있지 않다면 먼저 SSH를 허용하고(sudo ufw allow OpenSSH) 그다음 sudo ufw enable을 실행하세요. 자세한 내용은 ufw 가이드에 있습니다.
두 자물쇠를 따로따로 확인했습니다. 방화벽 규칙은 있지만 맞는 MySQL 사용자가 없을 때 서버는 error 1130: Host '…' is not allowed to connect to this MySQL server로 거부했습니다. 사용자를 추가하자 연결이 되었습니다. 방화벽 규칙을 지우자 연결은 그냥 시간 초과가 났습니다. 인터넷의 다른 모든 주소도 똑같이 시간 초과를 받습니다.
5. RAM 아끼기
자체 데이터가 없는 유휴 상태에서 MySQL 8.0은 저희 서버에서 383 MB를 썼습니다. 대부분은 Performance Schema로, 메모리를 미리 잡아 두는 진단 기능입니다. 작은 VPS에서는 이것을 끄고 주 캐시 크기를 직접 정하세요.
sudo tee /etc/mysql/mysql.conf.d/zz-small-vps.cnf >/dev/null <<'EOF'
[mysqld]
performance_schema = OFF
innodb_buffer_pool_size = 256M
max_connections = 50
EOF
sudo systemctl restart mysql
ps -o rss= -C mysqld
재시작 후에는 165 MB를 썼습니다. buffer pool은 데이터와 인덱스를 캐시하며, 앱도 함께 도는 2 GB 서버에는 256 MB가 알맞습니다. 데이터베이스가 서버의 주된 용도이고 캐시보다 커졌다면 늘리세요. max_connections = 50은 커넥션 풀을 쓰는 앱 하나에 충분하고도 남습니다. performance_schema 통계는 잃게 되니, 느린 쿼리를 자세히 파고들어야 할 때 다시 켜세요.
6. 매일 밤 백업
mysqldump --single-transaction은 앱을 막지 않고 InnoDB 테이블의 일관된 사본을 만듭니다. 작은 스크립트에 넣으세요.
sudo tee /usr/local/bin/mysql-backup >/dev/null <<'EOF'
#!/bin/bash
set -euo pipefail
umask 077
mkdir -p /var/backups/mysql
mysqldump --single-transaction --routines --triggers app | gzip > /var/backups/mysql/app-$(date +%F).sql.gz
find /var/backups/mysql -name 'app-*.sql.gz' -mtime +14 -delete
EOF
sudo chmod 755 /usr/local/bin/mysql-backup
echo '0 3 * * * root /usr/local/bin/mysql-backup' | sudo tee /etc/cron.d/mysql-backup
sudo /usr/local/bin/mysql-backup && sudo ls -l /var/backups/mysql
각 줄에는 이유가 있습니다.
- **
umask 077**은 덤프를 root만 읽을 수 있게 합니다(-rw-------). 모든 데이터가 들어 있기 때문입니다. - **
pipefail**은mysqldump가 실패하면 스크립트 전체도 실패하게 합니다. 이것이 없으면gzip이 내용 없는 작은 압축 파일을 쓰고 성공했다고 보고합니다. 일부러 명령을 망가뜨려 봤더니 스크립트가 예상대로 코드 2로 끝났습니다. - **
find … -mtime +14 -delete**는 2주치 사본을 남깁니다. - 스크립트가 root로 돌기 때문에
mysqldump는 소켓으로 로그인하고, 비밀번호를 파일에 둘 필요가 없습니다.
한 번도 복원해 보지 않은 백업은 아직 백업이라 할 수 없습니다. 임시 데이터베이스에 복원하고 데이터를 확인하세요.
sudo mysql -e "CREATE DATABASE app_restore"
gunzip -c /var/backups/mysql/app-2026-10-25.sql.gz | sudo mysql app_restore
sudo mysql -e "SHOW TABLES FROM app_restore"
sudo mysql -e "DROP DATABASE app_restore"
테스트에서 복원한 테이블에는 원본과 같은 행이 들어 있었습니다. 같은 디스크에 있는 사본으로는 서버를 잃었을 때 지킬 수 없으니, 가끔 scp나 restic으로 다른 컴퓨터에 옮겨 두세요. Managed Backups를 쓰면 서버 전체의 일일 복원 지점이 추가됩니다.
어떤 요금제를 고를까
Micro(2 vCPU, 2 GB, 25 GB, 월 $5)면 위처럼 조정한 MySQL과 웹 앱을 함께 올릴 수 있습니다. 데이터베이스 자체가 몇 GB를 넘으면 4 GB, 35 GB에 월 $8인 Small로 buffer pool에 1 GB 이상을 줄 수 있습니다. 둘 다 NAT 요금제이고, 3단계의 SSH 터널은 그대로 작동합니다. 4단계에는 전용 IPv4가 필요하며 Micro-IP는 월 $10입니다.
PostgreSQL을 선호하시나요? PostgreSQL 가이드가 같은 흐름으로 설명합니다. 모든 요금제는 VPS에 있으며, 결제는 Base, Ethereum, Polygon 네트워크의 USDT, USDC, ETH로 합니다.
댓글
아직 댓글이 없습니다. 첫 번째가 되세요.