Network

CORS 에러란? 발생 원인과 해결 방안까지

Hannana. 2024. 6. 18. 00:37
반응형

 

프론트-백을 겸하여 개발하다보면

쉽게 만날 수 있는 CORS 에러.

특히나 서로 다른 도메인이나 포트에서 실행되는 마이크로서비스(MSA)들 간의 요청에서

CORS 문제가 발생할 수 있다.

■ CORS란?

CORS(Cross-Origin Resource Sharing)는 보안 기능 중 하나로, 웹 브라우저가 다른 출처(origin)의 리소스를 요청할 때 발생할 수 있는 문제를 해결하기 위해 존재한다. 예를 들어, 웹사이트 A에 접속해 있는데 이 웹사이트가 다른 도메인(B)에 있는 데이터를 요청하면, 브라우저는 보안상의 이유로 이를 막을 수 있다. 이때 CORS 정책이 작동한다.

 

쉽게 말해, 서버의 Origin이 다르면 접근을 제한하는 것이다.

 

 

■ CORS 정책이 없으면 발생할 수 있는 문제?

  1. 크로스 사이트 요청 위조(CSRF, Cross-Site Request Forgery):
    • 공격자가 피해자의 브라우저를 이용해 피해자의 권한으로 원하지 않는 행동을 수행하게 할 수 있음
    • 예를 들어, 사용자가 이미 은행 사이트에 로그인한 상태에서 공격자가 만든 악성 웹사이트를 방문하면, 그 웹사이트가 사용자의 은행 계좌에서 돈을 송금하는 요청을 보낼 수 있다. 브라우저는 사용자가 이미 로그인한 상태이기 때문에 이 요청을 정상적으로 처리

  2. 정보 탈취:
    • 다른 도메인에서 민감한 정보를 탈취할 수 있음
    • 예를 들어, 사용자가 어떤 웹사이트에 로그인한 상태에서 다른 웹사이트가 사용자의 세션 정보나 쿠키를 가져와서 악용할 수 있다. 브라우저는 다른 서버에서 온 해당 요청을 정상적인 요청으로 인식하고, 공격자에게 민감한 정보를 전달할 수 있음

  3. 보안 정책 우회:
    • 웹 애플리케이션의 보안 정책을 우회하여 데이터베이스에 접근하거나, 서버에서 의도하지 않은 데이터를 조회
    • 예를 들어, 악성 웹사이트가 다른 도메인의 API 서버에 악의적인 요청을 보내서 서버의 데이터베이스에서 민감한 정보를 추출

 

 

역시나 서버의 보안을 위해 기본적으로 필요하다고 볼 수 있다.

 

 

■ Origin의 개념 (CORS 판단 기준)

서버의 Origin이 다르면 접근을 제한한다고 했는데
그럼 제한 기준이 되는 Origin의 구성은 어떻게 될까? 

  1. 스킴 (Scheme): 프로토콜 (예: http, https)
  2. 호스트 (Host): 도메인 이름 또는 IP 주소 (예: example.com)
  3. 포트 (Port): 서버가 사용 중인 포트 번호 (예: 80, 443, 5173 등)

이 세 가지 요소가 모두 같아야 같은 "origin"이라고 할 수 있다.

 

http://example.com:80과 http://example.com:80은 같은 origin
http://example.com:80과 https://example.com:80은 다른 origin (스킴이 다름)
http://example.com:80과 http://example.com:8080은 다른 origin (포트가 다름)
http://example.com:80과 http://anotherdomain.com:80은 다른 origin (호스트가 다름)

 

 

위의 예시처럼, 겉보기에 같은 Origin같아도 3가지 조건이 모두 같지 않다면

다른 Origin으로 보고 CORS 정책을 적용하게 된다. 이 때는 서버의 허가 없이 요청을 차단할 수 있다.

 

 

 

 

■ CORS 문제 발생 시 해결 방법

1) 서버에서 CORS 헤더 설정
백엔드 서버에서 CORS 요청을 허용하도록 설정할 수 있다.
① Access-Control-Allow-Origin 헤더를 설정하여 특정 도메인에서의 요청을 허용하거나,

아예 ② cors 헤더에 접근 허용 도메인을 등록해두는 것이 방법이다.

예를 들어, Node.js의 Express 프레임워크를 사용하는 경우, cors 미들웨어를 추가한다.

const express = require('express');
const cors = require('cors');
const app = express();

app.use(cors({
  origin: 'http://localhost:5173', // 특정 도메인만 허용
  methods: ['GET', 'POST'], // 허용할 HTTP 메서드
}));

 

 

 

2) 프락시 서버 사용 

프론트 엔드에서 프락시 서버를 사용해 브라우저와 API 서버 사이에서 요청을 중계할 수 있다.
쉽게 말해, 개발 환경에서 프락시 설정을 통해 동일한 origin으로 요청을 보내는 것처럼 브라우저를 속여

CORS 문제를 피하는 방법이다. Proxy서버의 Proxy는 "대리자"의 역할을 한다.


Vue.js에서는 vue.config.js 파일을 사용해 설정할 수 있다.

module.exports = {
  devServer: {
    proxy: {
      '/api': {
        target: 'http://localhost:80',
        changeOrigin: true,
        pathRewrite: { '^/api': '' },
      },
    },
  },
};

 

 

이렇게 하면 프론트엔드 서버에서 /api로 시작하는 모든 요청이

프락시를 통해 백엔드 서버로 전달된다.

브라우저는 동일한 origin으로 요청을 보낸다고 인식하기 때문에 CORS 문제가 발생하지 않음.

 

 

 

 

 

 

 

 

 

 

 

반응형