이번 포스팅에서는 Docker를 활용하여 NestJS API 서버와 WebSocket 서버를 배포하는 과정에서 겪었던 문제와 그 해결 방법을 공유하고자 합니다. 특히, 배포 환경에서 WebSocket 서버가 작동하지 않는 문제를 어떻게 해결했는지에 대해 자세히 다뤄보겠습니다.
이번 프로젝트는 NestJS API 서버와 WebSocket 서버를 각각 Docker 컨테이너로 배포하고, Nginx를 통해 리버스 프록시를 설정하여 HTTPS를 적용한 환경에서 동작하도록 구성했습니다. 프론트엔드와 백엔드 모두 EC2 서버에 배포되어 있으며, 이를 Docker로 컨테이너화해 관리합니다.
Docker를 사용하여 API 서버와 WebSocket 서버를 배포했습니다. API 서버는 8080번 포트, WebSocket 서버는 4006번 포트를 사용하도록 설정했습니다.
docker run -p 8080:8080 -p 4006:4006 imagename
이 명령어를 통해 API 서버와 WebSocket 서버를 각각 8080번 포트와 4006번 포트로 노출시켰습니다.
Docker Compose 설정
version: '3'
services:
app:
build: .
ports:
- "8080:8080" # API 서버 포트
- "4006:4006" # WebSocket 서버 포트
배포 후 API 서버는 정상적으로 동작했지만, WebSocket 서버가 정상적으로 연결되지 않았습니다. 특히, WebSocket connection failed와 같은 에러가 발생했습니다. 여러 원인을 고려했지만, 주된 문제는 다음과 같았습니다.
Docker 컨테이너에서 WebSocket 서버 포트를 노출하지 않았기 때문에 외부에서 접속할 수 없었습니다.
해결 방법은 간단했습니다. Docker 명령어 또는 Docker Compose 파일에서 4006번 포트를 호스트와 연결해줌으로써 해결했습니다.
docker run -p 8080:8080 -p 4006:4006 <your_image>
WebSocket이 제대로 동작하지 않는 또 다른 원인은 Nginx 리버스 프록시 설정의 부재였습니다. WebSocket을 사용하기 위해서는 HTTP Upgrade 설정이 필요합니다.
다음과 같이 Nginx 설정 파일을 수정하여 WebSocket 연결을 허용하도록 했습니다.
server {
listen 443 ssl;
server_name yourdomain.com;
location /chat/ {
proxy_pass http://localhost:4006; # WebSocket 서버
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
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;
}
}
WebSocket 서버에서 CORS 설정을 올바르게 하지 않으면 배포 환경에서 문제가 발생할 수 있습니다. 이를 위해 NestJS의 @WebSocketGateway 데코레이터에서 CORS 설정을 추가했습니다.
@WebSocketGateway(4006, {
namespace: 'chat',
cors: { origin: 'https://your-frontend-domain.com' }, // 특정 도메인 허용
})
export class EventsGateway {
// WebSocket 로직
}
개발 환경에서는 모든 도메인을 허용했지만, 배포 환경에서는 프론트엔드 도메인만 허용하는 방식으로 수정했습니다.
이번 글에서는 Docker로 API 서버와 WebSocket 서버를 배포하고 Nginx와 CORS 문제를 해결하는 과정을 다뤘습니다. 특히, WebSocket 연결 문제는 포트 매핑과 Nginx 설정에서 주로 발생할 수 있다는 것을 알게 되었고, 이를 해결함으로써 배포 환경에서도 정상적으로 WebSocket을 사용할 수 있게 되었습니다.
혹시 비슷한 문제를 겪고 계신다면, 이번 포스팅이 도움이 되었기를 바랍니다!