[Day96] 프로젝트 - CORS란?

Validator·2023년 11월 3일

CORS(Cross-Origin Resource Sharing, 크로스-오리진 리소스 쉐어링)는 웹 페이지가 다른 도메인의 리소스에 접근할 수 있도록 허용하는 보안 메커니즘이다. 웹은 기본적으로 같은 출처 정책(Same-Origin Policy)을 따른다. 이 정책은 웹 페이지가 다른 도메인의 리소스를 요청할 때 보안상의 이유로 제한을 두는 것을 말한다. 예를 들어, 도메인 A의 웹 페이지가 도메인 B의 서버에 AJAX 요청을 보낼 때, 도메인 B의 서버는 이 요청을 거부할 수 있다.

CORS는 HTTP 헤더를 사용해 서버가 어떤 출처의 웹 페이지가 자신의 리소스에 접근할 수 있는지를 브라우저에 알려준다. 만약 서버가 CORS를 지원하고, 올바른 Access-Control-Allow-Origin 헤더를 포함하여 응답하면, 브라우저는 리소스에 대한 접근을 허용한다.

CORS가 생긴 배경에는 웹 애플리케이션의 복잡성 증가와 다양한 웹 서비스 간의 상호 작용 필요성이 있다. 예를 들어, 소셜로그인(카톡, 구글 로그인같은 것들), 컨텐츠 배포 네트워크(CDN), REST API 등은 다른 출처의 리소스를 안전하게 사용할 수 있어야 한다.

CORS의 작동 원리

  1. 단순 요청(Simple Requests):

    • GET, HEAD, POST 중 하나의 메소드를 사용하고, 안전한 헤더 세트만을 포함하는 요청.
    • 브라우저는 자동으로 Origin 헤더를 요청에 추가한다.
    • 서버는 Access-Control-Allow-Origin 헤더를 포함한 응답을 반환한다.
  2. 사전 요청(Preflight Requests):

    • PUT, DELETE, CONNECT 등 다른 HTTP 메소드를 사용하거나, 사용자 정의 헤더를 포함하는 복잡한 요청.
    • 브라우저는 OPTIONS 메소드를 사용해 사전 요청을 보낸다.
    • 서버는 Access-Control-Allow-MethodsAccess-Control-Allow-Headers를 포함한 응답을 반환하여 허용하는 메소드와 헤더를 알려준다.

CORS를 구현하는 방법

아래는 Node.js와 Express를 사용하여 CORS를 구현한 예시다.

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

const app = express();

// 모든 도메인에 대해 CORS를 허용할 경우
app.use(cors());

// 특정 도메인에 대해 CORS를 허용할 경우
app.use(cors({
  origin: 'https://example.com' // 해당 도메인에서만 요청을 허용한다.
}));

// 동적으로 출처를 결정하는 경우
app.use(cors({
  origin: function (origin, callback) {
    if (whitelist.indexOf(origin) !== -1) {
      callback(null, true);
    } else {
      callback(new Error('Not allowed by CORS'));
    }
  }
}));

app.get('/data', (req, res) => {
  res.json({ message: 'This is CORS-enabled for all origins!' });
});

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

이 코드는 cors 미들웨어를 사용하여 CORS를 적용한다. 첫 번째 app.use(cors());는 모든 출처의 요청을 허용한다. 두 번째는 특정 도메인에서만 요청을

허용한다. 세 번째는 출처를 동적으로 결정하여 허용하는 복잡한 예시다.

CORS는 웹 개발의 중요한 부분이며, 보안과 상호 운용성을 위해 필수적이다. 위 코드와 설명은 CORS의 기본적인 이해를 돕기 위한 것이며, 실제 웹 애플리케이션에서는 더 복잡한 시나리오와 보안 요구 사항을 고려해야 할 수 있다.


CORS의 헤더와 응답 처리

CORS는 여러 HTTP 헤더를 사용하여 작동한다. 이 헤더들은 요청이나 응답에 따라 다르게 사용되며, 각각의 헤더는 특정 목적을 가지고 있다.

  1. 요청 헤더(Request Headers):

    • Origin: 요청을 보내는 페이지의 출처를 나타낸다.
    • Access-Control-Request-Method: 사전 요청에서 실제 요청에서 사용할 HTTP 메소드를 서버에 알린다.
    • Access-Control-Request-Headers: 실제 요청에서 사용할 커스텀 헤더를 서버에 알린다.
  2. 응답 헤더(Response Headers):

    • Access-Control-Allow-Origin: 어떤 출처의 리소스가 리소스에 접근할 수 있는지 나타낸다.
    • Access-Control-Allow-Methods: 실제 요청에서 허용되는 HTTP 메소드를 나타낸다.
    • Access-Control-Allow-Headers: 실제 요청에서 허용되는 헤더를 나타낸다.
    • Access-Control-Allow-Credentials: 요청에 사용자 인증 정보(쿠키, HTTP 인증 및 클라이언트 SSL 인증서 등)를 포함할 것인지를 나타낸다.
    • Access-Control-Max-Age: 사전 요청의 결과를 얼마나 오랫동안 캐시할 것인지를 나타낸다.

CORS 요청 처리 예시

웹 애플리케이션에서는 자바스크립트의 fetch API나 XMLHttpRequest 객체를 사용하여 CORS 요청을 처리할 수 있다. 아래는 fetch API를 사용한 예시다.

fetch('https://example.com/api/data', {
  method: 'GET', // HTTP 요청 메소드
  headers: {
    'Content-Type': 'application/json',
    // 필요한 경우 추가 헤더를 여기에 포함한다.
  },
  credentials: 'include' // 쿠키/인증 정보를 포함할 것인지 설정
})
.then(response => {
  if (response.ok) {
    return response.json(); // 응답을 JSON으로 파싱한다.
  }
  throw new Error('Network response was not ok.');
})
.then(data => {
  console.log(data); // 응답된 데이터를 처리한다.
})
.catch(error => {
  console.error('There has been a problem with your fetch operation:', error);
});

이 코드는 다른 도메인의 API로부터 데이터를 가져오는 간단한 GET 요청을 보내는 방법을 보여준다. credentials 옵션은 요청과 함께 쿠키나 인증 헤더를 보낼 것인지를 결정한다.

0개의 댓글