완전히 죽어버린 백엔드 서버를 다시 살리기
NestJS + EC2 + RDS + Nginx + OAuth + Session + HTTPS
코끼리 사이트 너무 아깝다.
진짜 이쁘고, 진짜 열심이 만들었는데, 이대로 사라지게 둘 수는 없었다.
다시 살려 보자! 라는 마음에서 시작했다.
근데 백엔드 서버가 완전히 죽었다는 것을 알게 됐다.
완전히 죽었다는 뜻은, 프리티어 기간이 끝나서 EC2 서버가 통째로 사라졌다는 것.
RDS 주소도, 도메인도, 아무것도 남아있지 않았다.
처음부터 다시 시작해야 했다.
빌드만 거의 100번은 했다.
기존에는 프론트 코드만 다뤘고, 배포는 쉽게만 했었는데,
이번엔 서버 인프라 전체를 직접 구성했다.
항목 | 내용 |
---|---|
백엔드 프레임워크 | NestJS |
배포 대상 | AWS EC2 (Ubuntu 22.04) |
DB | MySQL (AWS RDS) |
세션 저장소 | Redis |
인증 | OAuth (Google, GitHub, Kakao) |
웹서버 | Nginx + HTTPS (Certbot) |
배포 자동화 | PM2 |
프론트 호스팅 | Netlify (dev.co-kkiri-api.com) |
도메인 | AWS Route 53에서 구매, 서브도메인 사용 (be.co-kkiri-api.com) |
EC2 인스턴스 생성 (Ubuntu 22.04)
SSH 접속
chmod 400 co-kkiri.pem
ssh -i "co-kkiri.pem" ubuntu@<EC2 퍼블릭 IP>
필수 패키지 설치
sudo apt update
sudo apt install -y nodejs npm git nginx
sudo apt install -y mysql-client
git clone https://github.com/내레포/BE_co-KKIRI.git
cd BE_co-KKIRI
npm install
touch .env
vim .env
.env 파일에는 아래와 같은 설정을 추가함:
DB_HOST=<rds-endpoint>
DB_PORT=3306
DB_USERNAME=admin
DB_PASSWORD=***
DB_NAME=cokkiri
COOKIE_NAME=***
COOKIE_SECRET=***
SESSION_COOKIE_DOMAIN=co-kkiri-api.com
REDIS_HOST=<redis-host>
REDIS_PORT=6379
REDIS_PASSWORD=***
npm run build # NestJS 프로젝트를 TypeScript → JavaScript로 컴파일하여 dist/ 폴더에 저장
pm2 start dist/main.js --name main
# PM2로 빌드된 서버(main.js)를 실행함
# --name main: 프로세스 이름을 'main'으로 지정 (관리하기 쉬움)
pm2 save
# 현재 실행 중인 PM2 프로세스 목록을 저장함 (재부팅 시 복구용)
pm2 startup
# EC2 재부팅 시 PM2가 자동으로 실행되도록 시스템에 등록함
# 출력되는 명령어 (sudo ... update...)를 복사해서 실행해야 적용됨
Type | Port | Source |
---|---|---|
MySQL/Aurora | 3306 | EC2 보안 그룹 |
접속 테스트
mysql -h <rds-endpoint> -u admin -p
TypeORM 설정 예시
TypeOrmModule.forRootAsync({
useFactory: () => ({
type: 'mysql',
host: process.env.DB_HOST,
port: 3306,
username: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
synchronize: true,
autoLoadEntities: true,
}),
});
⚠️ synchronize: true는 테스트 때만!
배포 시에는 반드시 false로 변경할 것.
sudo apt install redis-server
redis-cli ping
.env 설정 추가
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=
NestJS main.ts에서 Redis 연결
const redisClient = createClient({
socket: {
host: configService.get('REDIS_HOST'),
port: configService.get('REDIS_PORT'),
},
});
이 부분에서 가장 많은 삽질을 했다.
문제
해결
app.enableCors({
origin: ['https://co-kkiri-api.com'],
credentials: true,
});
cookie: {
maxAge: 1000 * 60 * 60 * 24,
domain: '.co-kkiri-api.com',
httpOnly: true,
sameSite: 'lax',
}
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d be.co-kkiri-api.com
/etc/nginx/sites-available/be.co-kkiri-api.com
server {
listen 80;
server_name be.co-kkiri-api.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name be.co-kkiri-api.com;
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
ssl_certificate /etc/letsencrypt/live/be.co-kkiri-api.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/be.co-kkiri-api.com/privkey.pem;
}
항목 | 했던 일 |
---|---|
EC2 | Ubuntu 설치 + 서버 실행 |
PM2 | 백엔드 프로세스 관리 |
Nginx | 리버스 프록시 + HTTPS |
Route53 | A레코드로 도메인 연결 |
Certbot | Let’s Encrypt 인증서 발급 |
RDS | MySQL 생성 + 보안 그룹 설정 |
Redis | 세션 저장소 |
OAuth | 3종 연동 + 세션 기반 로그인 |
CORS | 쿠키 포함 설정 |
Session | redis + cookie 기반 인증 |