드디어! 오랜 문제를 해결했습니다. 절대로 해결하지 못할 것 같던 문제를 해결하고 공유하게 되어서 기쁘네요 ㅎㅎ
어쩌다 이런일이?
도커환경에서 nginx를 사용하여 여러 서버들을 운용하고 있었는데, Vue 또한 그랬었죠. 도커의 Node 버전을 올림에 따라 Vue의 버전도 2.5.x에서 2.6.x 버전으로 그에 맞추어 업그레이드 해야만했습니다. 그리고 문제를 만나버렸습니다. 다른 것들은 괜찮았는데 HMR(Hot Module Replacement)가 제대로 동작하지 않았고 브라우저 콘솔에는 "WebSocket Connection to 'ws://some_ip/ws' failed~" 에러메시지만 나타났을 뿐이였습니다.
개발환경과 설정
- Mac OS
- Docker and Nginx
- Vue 2.6.x (using Webpack5)
Vue.congfig.js에 'http://localhost:3000'에 앱을 띄우도록 설정했었습니다.
const { defineConfig } = require('@vue/cli-service');
module.exports = defineConfig({
devServer: {
port: 3000,
allowedHosts: "all",
client: {
logging: 'log', // Set to see a log about devServer.
overlay: true,
},
}
});
그리고 nginx의 설정은 다음과 같았습니다.And nginx configurations for reverse proxy are here.
upstream backend {
server backend:5000;
}
upstream frontend {
server frontend:3000;
}
server {
listen 80;
client_max_body_size 50M;
location / {
proxy_pass http://frontend;
}
location /api {
proxy_pass http://backend;
}
location /sockjs-node {
proxy_pass http://frontend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
}
Docker-compose는 다음과 같았습니다.
version: "3"
services:
frontend:
build:
dockerfile: Dockerfile.dev
context: ./frontend
volumes:
- /app/node_modules
- ./frontend:/app
stdin_open: true
environment:
- CHOKIDAR_USEPOLLING=true
nginx:
restart: always
container_name: nginx
build:
dockerfile: Dockerfile
context: ./nginx
ports:
- "4000:80"
로컬환경으로 돌리면 전혀 문제가 없었지만, 도커컨테이너 위에서는 알 수 없는 에러만 나올 뿐이였죠.
증상
터미널에서는 정상적으로 빌드가 되었다고 표시만 되고 있었습니다.
하지만 브라우저 콘솔에는 WebSocket connection 에러와 함께 HMR, Live Reload 기능이 먹통이 되어버렸습니다. 개발의 변경사항을 확인하려면 매번 새로고침을 해야되버린 것...
원인은 무엇인가?
원인을 정확히 알아내는데에는 3개월 정도의 시간이 흘렀는데, 결국 메시지가 나타내는 말이 큰 힌트였었습니다. "야 나 너가 설정한 IP로 연결을 못하겠다니깐??" 그렇습니다. 아무것도 없는곳에 webpackd-dev-server가 있다고 착각하고 왜 연결이 안되냐 헤매고 있었던 것 입니다. 근데 왜 갑자기 잘되던게 에러를 뱉으며 작동하지 않았을까요?
Vue 버전이 2.6.x로 업그레이드 되면서 Webpack5를 사용하게 되었기 때문입니다. (2.6.x 이전 버전은 Webpack4를 사용) Webpack-dev-server의 프로토콜 변화가 있었기 때문에 해당 변화에 따라 nginx에 추가 설정이 필요하게 되었습니다.
해결방법
제가 겪은 고통에 비하면 해결책은 어어어엄청 단순했는데요. 단지 niginx 설정에 'location /ws' 블록을 추가하고 아래와 같이 작성하면 그만입니다.
server {
listen 80;
client_max_body_size 50M;
location /api {
proxy_pass http://backend;
}
location / {
proxy_pass http://frontend;
}
location /sockjs-node {
proxy_pass http://frontend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
location /ws {
proxy_pass http://frontend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
}
맨 위에서 설명드렸던 도커환경설정에 따르면 frontend 서버는 4000번 포트로 접근이 가능하게 되기 때문에 Webpack-dev-server도 "localhost:4000/ws"에 올라가게 될 것입니다.
아래와 같이 client의 설정란을 변경하여 그곳에 webpack-dev-server가 있음을 알려줍시다.
const { defineConfig } = require('@vue/cli-service');
module.exports = defineConfig({
devServer: {
port: 3000,
allowedHosts: "all",
client: {
logging: 'log',
overlay: true,
webSocketURL: 'auto://localhost:4000/ws' // Add this
},
}
});
이젠 브라우저 콘솔에 에러도 없고 새로고침을 하지 않아도 변경사항 바로바로 볼 수 있는 아름다운 세상이 되었습니다 :)
+) Vue뿐 아니라 Vite, Webpack 등의 툴을 사용하고 있는 프로젝트라면 Docker와 nginx의 reverse proxy에서 동일한 설정으로 위와 같은 문제를 해결 할 수 있을 것입니다. (Nextjs 쓰면서 적용바로 때려봤음 ㅅㄱ)
'JS, TS' 카테고리의 다른 글
아이콘은 어떤 확장자로 써야할까? (SVG, PNG, JPEG, GIF, WebP) (0) | 2023.09.20 |
---|---|
자바스크립트 비트연산자 시프트 활용하기 (Hex to RGB 컬러변환) (0) | 2023.09.08 |
Flutter, Nextjs 하이브리드앱 환경에서의 세션처리와 효율적인 HTTP 통신방법 (Axios 활용) (0) | 2023.07.13 |
Disk Cache를 이해하고 다루는 법 (0) | 2023.06.02 |
JSON file write and upload to S3 with Nodejs (0) | 2023.02.21 |