티스토리 뷰
개인적으로 Spring boot websocket을 이용하여 채팅방 구현을 하던 중 서버 쪽을 완성하고 apic을 이용해 테스트도 완료를 했지만 프론트 연결 중 오류를 하나 만났다.
var sockJs = new SockJS("/ws");
//1. SockJS를 내부에 들고있는 stomp를 내어줌
var stomp = Stomp.over(sockJs);
stomp.connect({}, function(frame) {
// 연결이 되지 않는 오류
});
SockJs를 선언 후 구독을 위해 연결을 하려고 하면 websocket.js:6 WebSocket connection to 'ws://localhost:8000/ws/241/ml45xvou/websocket' failed:
이라는 오류와 함께 커넥션이 멈춰 버리는 현상이 지속되었다.
서버쪽에도 따로 오류가 뜨지 않아 며칠을 고생하던 중 참고한 예제와 비교하기 위하여 채팅 부분만 따로 떼어내서 다시 구현을 해보았다.
원래는 위의 사진처럼 CONNECTED 응답이 있어야 했지만, 새롭게 구현한 채팅방에서는 비슷한 오류가 나타났다. 하지만 기존과는 다르게 연결이 강제 종료되고 서버쪽 오류도 잡혔다.
웹 소켓이 종료가 됨과 동시에 서버쪽에 오류가 떴다!
java.lang.IllegalArgumentException: When allowCredentials is true, allowedOrigins cannot contain the special value "*" since that cannot be set on the "Access-Control-Allow-Origin" response header. To allow credentials to a set of origins, list them explicitly or consider using "allowedOriginPatterns" instead.
찾아보니 addcorsmappings관련 에러로 스프링부트에서 CORS설정시, .allowCredentials(true)와 .allowedOrigins("*")를 동시에 사용할 수 없도록 업데이트 되었다고 한다.
해결책은 로그에서 .allowedOrigins("*")를 setAllowedOriginPatterns(*)로 변경을 권고 하고있다.
문제점을 알았으니 해결법은 간단했다.
@Configuration
@EnableWebSocketMessageBroker // STOMP 정의
public class WebSocketConfiguration implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/sub");
registry.setApplicationDestinationPrefixes("/pub");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws")
.setAllowedOrigins("*")
.withSockJS();
}
}
WebSocketConfiguration에서 .setAllowedOrigins("*')대신 setAllowedOriginPatterns(*)을 사용하는 방법과 직접 허용 주소를 넣어주는 방법으로 해결하였다.
@Configuration
@EnableWebSocketMessageBroker // STOMP 정의
public class WebSocketConfiguration implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/sub");
registry.setApplicationDestinationPrefixes("/pub");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws")
.setAllowedOrigins("http://localhost:8000", "http://localhost:3000")
.withSockJS();
}
}
예전 팀 프로젝트를 할 때도 리엑트와 스프링연결을 힘들게 했었던 CORS는 왜 일어나는 오류일까? 궁금해서 조금더 찾아 보았다.
결과적으로 CORS는 다른 출처의 자원에 대한 보호 정책이고 이렇게 출처를 비교하는 로직이 서버에 구현된 스펙이 아니라 브라우저에 구현되어 있는 스펙이라는 것이다.
따라서 서버단에서 체크를 했을 때는 이상이 없어도 프론트를 구현하면서 만나게 된것이다.
또한 , CORS는 브라우저의 구현 스펙에 포함되는 정책이기 때문에, 브라우저를 통하지 않고 서버 간 통신을 할 때는 이 정책이 적용되지 않는다. 그리고 CORS 정책을 위반하는 리소스 요청 때문에 에러가 발생했다고 해도 서버 쪽 로그에는 정상적으로 응답을 했다는 로그만 남기 때문에, CORS가 돌아가는 방식을 정확히 모르면 에러 트레이싱에 난항을 겪을 수도 있다.
CORS 참고 자료 : https://evan-moon.github.io/2020/05/21/about-cors/
'개발일지 > error' 카테고리의 다른 글
Uncaught ReferenceError: global is not defined at node_modules/buffer/index.js (0) | 2024.11.22 |
---|---|
npm error errno -4058 실행 경로 오류 (0) | 2024.11.15 |
React에서 두 번 랜더링 (0) | 2024.08.14 |