[CORS] socket.io를 사용할 때 Access-Control-Allow-Origin 에러 with React

혜원·2025년 6월 18일

프로젝트 진행중 백엔드는 PM2로, 프론트엔드는 Vercel로 각각 배포하였다.
실행해보니 다음과 같은 에러가 발생하였다.

Access to XMLHttpRequest at 'https://서버도메인/socket.io/?EIO=4&transport=polling&t=8y24hbv2' 
from origin 'https://프론트도메인' has been blocked by CORS policy: 
No 'Access-Control-Allow-Origin' header is present on the requested resource.

GET https://서버도메인/socket.io/?EIO=4&transport=polling&t=8y24hbv2 net::ERR_FAILED 404 (Not Found)

찾아보니 CORS(Cross-Origin Resource Sharing) 정책과 관련된 문제였고, 프론트에서 요청을 보내는 도메인과 서버 도메인이 다르기 때문에, 서버에서 CORS 헤더를 설정하지 않으면 요청이 차단된다는것이었다.


CORS, Origin이란?

CORS(Cross-Origin Resource Sharing)는 브라우저의 보안 정책 중 하나이다.
Origin은 프로토콜(http/https) + 도메인 + 포트의 조합이다.

브라우저는 기본적으로 Same-Origin Policy를 따른다.
즉, 같은 Origin에서만 리소스를 요청할 수 있다는 것이다.

하지만 실제 개발에서는 프론트와 백엔드가 다른 도메인에 배포되는 경우가 많고, 이때 서버에서 특정 Origin에 대해 접근을 허용한다고 명시적으로 선언해야 하는데, 이것이 바로 CORS이다.

보통 NestJS에서는 main.ts에서 다음과 같이 CORS를 설정한다

// main.ts
app.enableCors({
  origin: [
    'http://localhost:5173',
    'https://프론트배포도메인',
  ],
  credentials: true,
});

하지만 나는 socket.io까지 사용하고 있었기 때문에 main.ts에서 CORS 설정을 하고 난 뒤로도 계속 에러가 났던 것이다.


Socket.io의 통신 방식

  1. HTTP Long Polling: 초기 연결은 HTTP 요청으로 시작
  2. WebSocket: 조건이 맞으면 WebSocket으로 업그레이드
  3. Fallback: WebSocket이 불가능하면 Long Polling 유지

즉, 초기에는 일반적인 HTTP 요청으로 시작되기 때문에,
Socket.io 자체적으로도 CORS 설정이 필요하다.

그래서 Socket.io Gateway에서 CORS 옵션을 추가로 설정해주었다!

const allowedOrigins = [
  'http://localhost:5173',           // 로컬 개발 환경
  'https://프론트배포도메인',          // Vercel 배포 환경
  'https://서버도메인',               // 직접 서버 접근 시
];

@WebSocketGateway({
  cors: {
    origin: allowedOrigins,
    credentials: true,
  },
})
export class 게임Gateway {
  //  로직
}

credentials: true란?

redentials: true는 쿠키, 인증 헤더 등의 자격 증명을 포함한 요청을 허용한다는 뜻이다. 로그인 상태 유지나 세션 기반 인증이 필요한 경우 필수로 설정해줘야 한다.


Socket.io를 사용하는 프로젝트를 배포할 때는 Gateway에서 추가적인 CORS 설정을 해주어야한다!!

0개의 댓글