2 minute read

2022.12.08

💡 CORS와 SOP

새로 배우는 개념인 CORS와 SOP

프론트에서도 기본적인 서버 관련 공부를 꼭 해야한다는 건 이제 누구나 아는 사실이다.

콘솔창에서 다음과 같은 에러를 종종 보고는 한다. 이 에러가 바로 CORS에러로 CORS가 필요하게 된 배경인 SOP에 대해 알아둘 필요가 있다.

스크린샷 2022-12-08 20 14 01

📌 SOP

SOP은 Same-Origin Policy의 줄임말로, 동일 출처 정책을 뜻한다.

같은 출처의 리소스만 공유가 가능하다라는 뜻인데 여기서 말하는 출처는 다음과 같다.

스크린샷 2022-12-08 20 15 57

출처는 프로토콜, 호스트, 포트의 조합으로 되어있습니다. 이 중 하나라도 다르면 동일한 출처로 보지 않는다.

예시를 들자면

  • https://www.codestates.com vs http://www.codestates.com ⇒ 두 URI는 프로토콜이 다르기 때문에 동일 출처 ❌ ( https / http )

  • https://urclass.codestates.com vs https://codestates.com ⇒ 두 URI는 호스트가 다르기 때문에 동일 출처 ❌ ( urclass.codestates.com / codestates.com )

  • ` http://codestates.com:81 **vs** http://codestates.com`

    http 프로토콜의 기본 포트는 80이다. 따라서 http://codestates.comhttp://codestates.com:80 과 동일. ⇒ 두 URI는 포트가 다르기 때문에 동일 출처 ❌ ( :81 / :80 )

  • https://codestates.com:443 vs https://codestates.com

    https 프로토콜의 기본 포트는 443이다. 따라서 https://codestates.comhttps://codestates.com:443 과 동일하다. ⇒ 두 URI는 프로토콜, 호스트, 포트가 모두 같은 동일 출처🙆‍♂️

🧐 그렇다면 왜? SOP은 생겨난걸까?

동일 출처 정책은 잠재적으로 해로울 수 있는 문서를 분리함으로써 공격받을 수 있는 경로를 줄여준다.

다른 사이트와의 리소스 공유를 제한하기 때문에 로그인 정보와 같이 민감한 정보가 타사이트의 코드에 의하여 새어나가는 것을 방지할 수 있다.

하지만 현실에서는 다른 출처의 리소스를 사용해야 할 일이 굉장히 많다. 그렇다면 어떻게 다른 출처의 리소스를 받아올 수 있는 걸까? 그 답은 바로 아래에 있다.

📌 CORS

CORS는 Cross-Origin Resource Sharing의 줄임말로 교차 출처 리소스 공유를 뜻한다.

브라우저는 SOP에 의해 기본적으로 다른 출처의 리소스 공유를 막지만, CORS를 사용하면 접근 권한을 얻을 수 있게 되는 것이다.

Request 요청 - GET, POST, PUT, PATCH, DELETE, OPTIONS, URL( /upper, /lower )… && 헤더 바디

GET은 서버의 리소스에서 데이터를 요청할 때, POST는 서버의 리소스를 새로 생성할 때, PUT & PATCH는 업데이트할 때

Response - 200 400 … && 헤더 바디

👨🏻‍💻 CORS의 동작 방식

CORS의 동작 방식은 크게 3가지가 있는데

  • 프리플라이트 요청 ( Preflight Request )

실제 요청을 보내기 전 OPTIONS 메서드로 사전요청을 보내서 접근 권한이 있는지 확인하는 방법이다. => 처음부터 통째로 요청을 보내는 것보다 효율적

스크린샷 2022-12-08 20 25 59

스크린샷 2022-12-08 20 26 53

  • 단순 요청 ( Simple Request )

특정 조건만 만족되면 프리플라이트 요청을 생략하고 요청을 바로 보내는 것

스크린샷 2022-12-08 20 27 37

  • 인증 정보를 포함한 요청

요청 헤더에 인증 정보를 담아 보내는 요청, 출처가 다를 경우에는 별도의 설정을 하지 않으면 쿠키를 보낼 수 없다( 민감한 정보이기 때문 ) 이 경우에는 프론트, 서버 양측 모두 CORS 설정이 필요

  • 프론트 측에서는 요청 헤더에 withCredentials : true
  • 서버 측에서는 응답 헤더에 Access-Control-Allow-Credentials : true 를 넣어줘야 한다.
  • 서버 측에서 Access-Control-Allow-Origin 을 설정할 때, 모든 출처를 허용한다는 뜻의 와일드카드(*)로 설정하면 에러가 발생한다. 인증 정보를 다루는 만큼 출처를 정확하게 설정해주어야 한다.
👨🏻‍💻 CORS의 설정 방법
  • Node.js 서버

    Node.js로 간단한 HTTP 서버를 만들 경우 다음과 같이 응답 헤더를 설정해 줄 수 있다.

    const http = require('http');
      
    const server = http.createServer((request, response) => {
    // 모든 도메인
      response.setHeader("Access-Control-Allow-Origin", "*");
      
    // 특정 도메인
      response.setHeader("Access-Control-Allow-Origin", "https://codestates.com");
      
    // 인증 정보를 포함한 요청을 받을 경우
      response.setHeader("Access-Control-Allow-Credentials", "true");
    })
    
  • Express 서버

    Express 프레임워크를 사용해서 서버를 만드는 경우 CORS 미들웨어를 사용해서 보다 간단하게 CORS 설정을 해줄 수 있다.

    const cors = require("cors");
    const app = express();
      
    //모든 도메인
    app.use(cors());
      
    //특정 도메인
    const options = {
      origin: "https://codestates.com", // 접근 권한을 부여하는 도메인
      credentials: true, // 응답 헤더에 Access-Control-Allow-Credentials 추가
      optionsSuccessStatus: 200, // 응답 상태 200으로 설정
    };
      
    app.use(cors(options));
      
    //특정 요청
    app.get("/example/:id", cors(), function (req, res, next) {
      res.json({ msg: "example" });
    });
    

Comments