일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
- QueryDSL
- 스택
- BFS
- 유니티
- 해시
- 스파르타내일배움캠프
- 이분탐색
- C++
- Inventory
- 프로그래머스
- FSM
- 언리얼엔진
- unityui
- Unity3d
- Unity2D
- 유클리드호제법
- Photon
- c#
- UE4
- Firebase
- 포톤
- UnrealEngine
- 내일배움캠프
- 순열
- 스파르타내일배움캠프TIL
- Unity
- 워크플로
- 문자열
- 구현
- 알고리즘
- Today
- Total
개발 낙서장
[TIL] 내일배움캠프 82일차 - WebSocket Connection Failed 본문
오늘의 학습 키워드📚
Connection Failed
진짜 환장할 오류가 발생했었다.
잘 되던 웹소켓이 배포 환경에서 HTTPS 프로토콜로 바꾸니 웹소켓 연결이 되지 않는 것이다.
로컬에서도 잘 되고 HTTP 프로토콜에서도 잘 동작하는데 배포 환경의 HTTPS 프로토콜에서만 동작하지 않았다.
오류 체크를 위해 레포지토리를 Fork 해서 로컬에서 HTTPS 세팅을 하고 실행했는데 연결이 잘 돼서 더 당황했다.
useEffect(() => {
if (currentRoom !== null && stompClient === null) {
const client = new StompJs.Client({
brokerURL: `ws://${window.location.hostname}:8080/gs-guide-websocket`,
onConnect: async message => {
console.log(message);
client.subscribe(
`/topic/chat-rooms/${currentRoom.chatRoomId}`,
onMessageReceived);
try {
const response = await getRoomMessages(
currentRoom.chatRoomId);
setRoomMessages(response.data.data);
setState(chattingAppState.채팅방입장);
} catch (error) {
alert("채팅방 정보 로드에 실패했습니다.");
}
},
onWebSocketError: error => {
alert('웹 소켓 에러');
setCurrentRoom(null);
},
onStompError: frame => {
alert('웹 소켓 에러');
setCurrentRoom(-1);
},
});
client.activate();
setStompClient(client);
} else if (currentRoom === null && stompClient) {
stompClient.deactivate();
setStompClient(null);
}
}, [currentRoom]);
기존 연결 코드인데 StompJS 모듈을 사용해 Endpoint URL로 연결을 시도하고 처리하는 로직이다.
하지만 HTTPS에서는 wss 프로토콜로 연결을 시도해야 된다고 해서 코드를 수정했다.
const protocol = window.location.protocol === "https:"
? "wss:"
: "ws:";
const domainUrl = window.location.port === ""
? window.location.hostname
: `${window.location.hostname}:${window.location.port}`;
현재 프로토콜과 도메인, 포트 번호를 동적으로 확인하여 URL을 생성했다.
하지만 계속해서 connection failed 오류가 발생했고 어떠한 오류 메세지도 발생하지 않아 계속해서 헤매고 있었다.
시도한 방법은 총 3가지이다.
1. 환경 변수 설정(실패)
https://github.com/facebook/create-react-app/issues/11897
페이스북 리액트 깃허브에 있는 이슈인데 여기서도 동일하게 HTTP에서는 동작하다가 HTTPS로 바꾸니 웹소켓 연결이 되지 않는다는 문제였다.
댓글들을 살펴보던 중 환경 변수에 해당 값을 추가하라는 댓글이 있었다.
WDS_SOCKET_PORT=0
웹소켓 포트를 설정해주는 것인데 클라이언트에서 windows.location.port를 웹소켓 포트로 설정해주어 연결이 가능하다고 한다.
실제로 이슈 댓글들을 살펴보면 이 방법으로 다 해결했다고 한다.
하지만 .env 파일에 추가하여 실행해봤는데 변한 것은 없었다...
2. 프록시 설정(실패)
프론트에서 프록시를 설정해주는 이유는 프론트에서 동작하는 포트와 백에서 동작하는 포트가 다르기 때문이다.
따라서 CORS 문제가 발생할 수 있기에 프록시를 설정하여 프론트와 백의 통신이 가능하도록 해주는 것이다.
HTTPS랑 프록시랑 무슨 관련인데? 싶었지만 어느 깃허브를 탐방하던 중 프록시로 wss 연결을 허용?해주는 설정을 볼 수 있었고 바로 적용했다.
const {proxy} = require('http-proxy-middleware');
module.exports = function(app) {
app.use(
proxy('/gs-guide-websocket', {
target: 'wss://www.wuzuzu.shop/gs-guide-websocket',
ws: true,
changeOrigin: true,
secure: false,
pathRewrite: {
'^/gs-guide-websocket': '',
},
}),
);
};
웹소켓 엔드포인트로 들어온 요청을 wss로 넘겨주는? 역할을 하는 것 같다.
하지만 이 역시 실패했다.
3. 모듈 바꿔주기(성공!!!)
에러 메세지도 안 뜨고 사람들이 해결했던 방법으로도 안 되고 도저히 갈피를 잡지 못하고 있었다.
그러던 중 처음 웹소켓 연결을 시도했던 때가 생각나서 모듈 문제인가? 싶어 연결 부분을 갈아엎었다.
기존에는 위에 있듯이 StompJS 모듈만을 사용하여 클라이언트를 생성하고 있었다.
이 방법으로도 많이 연결을 하지만 SockJS와 같이 사용해 연결하는 방법도 있었다.
https://stomp-js.github.io/guide/stompjs/rx-stomp/using-stomp-with-sockjs.html
SockJS 공식 문서를 바탕으로 세팅해주고 코드를 수정했다.
(의존성 추가, JS 라이브러리 세팅, npm 모듈을 설치해주어야 한다)
WebSocketConfig.java
// STOMP 엔드포인트 등록
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/gs-guide-websocket")
.setAllowedOriginPatterns("*")
.withSockJS(); // 핸드셰이크 엔드포인트 설정
}
주의해야 할 점은 setAllowedOrigins("*")를 사용하면 에러가 발생한다.
ChattingApp.js
useEffect(() => {
if (currentRoom !== null && stompClient === null) {
const socket = new SockJS(`/gs-guide-websocket`);
const client = StompJs.over(socket);
client.connect({}, async (frame) => {
console.log(frame);
client.subscribe(
`/topic/chat-rooms/${currentRoom.chatRoomId}`,
onMessageReceived
);
try {
const response = await getRoomMessages(
currentRoom.chatRoomId
);
setRoomMessages(response.data.data);
setState(chattingAppState.채팅방입장);
} catch (error) {
alert("채팅방 정보 로드에 실패했습니다.");
}
}, (error) => {
alert('웹 소켓 에러');
setCurrentRoom(null);
});
setStompClient(client);
} else if (currentRoom === null && stompClient) {
stompClient.disconnect(() => {
setStompClient(null);
});
}
}, [currentRoom]);
엔드포인트로 소켓을 생성하고 해당 소켓으로 Stomp 클라이언트를 생성해 연결해주었다.
연결이 돼서 콘솔에 잘 찍혔다.
아직도 왜 에러가 발생했었는지 원인은 잘 모르겠지만 아마 StompJS 모듈에서 HTTPS 관련 설정이 따로 필요한 것으로 보인다. 배포 환경과 로컬은 다르므로 AWS 인증서 문제인지 뭔지 자세히는 모르겠다.
참고
오늘의 회고💬
며칠 동안 해결이 안 되고 방법도 전혀 모르겠어서 너무 답답했었는데 마지막에 극적으로 해결돼서 너무 다행이고 속 시원하다.
내일의 계획📜
화면 부분 마지막으로 정리하고 발표 준비를 할 것 같다.
'Java > Sparta' 카테고리의 다른 글
[TIL] 내일배움캠프 81일차 - 대규모 트래픽 처리 (0) | 2024.04.24 |
---|---|
[TIL] 내일배움캠프 80일차 - 기술 면접 대비 (0) | 2024.04.23 |
[TIL] 내일배움캠프 79일차 - SSE (0) | 2024.04.19 |
[TIL] 내일배움캠프 78일차 - SQS 동시성 테스트 (0) | 2024.04.18 |
[TIL] 내일배움캠프 77일차 - AWS SQS FIFO (0) | 2024.04.17 |