on my way

CORS란? 필요성, 작동 방식 및 어노테이션 예제 본문

Computer Science/React

CORS란? 필요성, 작동 방식 및 어노테이션 예제

wingbeat 2024. 8. 6. 15:42
반응형

]

CORS(Cross-Origin Resource Sharing)는 웹 브라우저에서 다른 출처(도메인, 프로토콜, 포트)의 리소스에 접근할 수 있도록 허용하는 보안 기능입니다. 기본적으로 웹 브라우저는 보안상의 이유로 동일 출처 정책(Same-Origin Policy)을 따르며, 이 정책은 다른 출처에서 리소스를 요청하는 것을 제한합니다. CORS는 이러한 제한을 완화하여 특정 조건 하에 다른 출처의 리소스에 접근할 수 있도록 합니다.

CORS의 필요성

웹 애플리케이션은 종종 다른 도메인의 리소스에 접근해야 하는 경우가 있습니다. 예를 들어, example.com 도메인에서 실행되는 웹 애플리케이션이 api.example.com 도메인에 있는 API에 요청을 보내는 경우입니다. 동일 출처 정책에 따르면, 이러한 요청은 기본적으로 차단됩니다. CORS를 사용하면 서버가 특정 출처에서 오는 요청을 허용하도록 설정할 수 있습니다.

CORS의 작동 방식

CORS는 HTTP 헤더를 사용하여 작동합니다. 브라우저는 서버에 요청을 보낼 때 CORS 관련 헤더를 포함시킵니다. 서버는 해당 요청을 허용할지 여부를 결정하고, 응답 헤더를 통해 브라우저에 이를 알립니다.

주요 CORS 헤더

  1. Access-Control-Allow-Origin
    • 서버가 특정 출처에서의 요청을 허용할 때 사용합니다.
    • 예: Access-Control-Allow-Origin: https://example.com
    • 모든 출처를 허용하려면 *를 사용할 수 있습니다.
  2. Access-Control-Allow-Methods
    • 허용되는 HTTP 메소드를 지정합니다.
    • 예: Access-Control-Allow-Methods: GET, POST, PUT
  3. Access-Control-Allow-Headers
    • 허용되는 HTTP 헤더를 지정합니다.
    • 예: Access-Control-Allow-Headers: Content-Type, Authorization
  4. Access-Control-Allow-Credentials
    • 자격 증명을 포함한 요청을 허용할지 여부를 지정합니다.
    • 예: Access-Control-Allow-Credentials: true
  5. Access-Control-Max-Age
    • 프리플라이트(preflight) 요청의 결과를 캐시할 시간을 지정합니다.
    • 예: Access-Control-Max-Age: 3600

프리플라이트 요청

CORS는 단순 요청(Simple Request)과 프리플라이트 요청(Preflight Request)으로 나뉩니다. 프리플라이트 요청은 브라우저가 실제 요청을 보내기 전에 서버에 OPTIONS 메소드를 사용하여 안전성을 확인하는 요청입니다. 이 요청을 통해 서버는 실제 요청이 허용될지 여부를 결정합니다.

단순 요청(Simple Request)

  • GET, POST, HEAD 메소드 중 하나를 사용하고,
  • 커스텀 헤더를 포함하지 않으며,
  • Content-Type이 application/x-www-form-urlencoded, multipart/form-data, 또는 text/plain인 경우.

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

  • 단순 요청이 아닌 경우,
  • PUT, DELETE 등의 메소드를 사용하거나,
  • 커스텀 헤더를 포함하는 경우.

예제

서버에서 CORS를 설정하는 간단한 예제는 다음과 같습니다. 예를 들어, Express.js를 사용하는 Node.js 서버에서 CORS를 설정할 수 있습니다.

javascript

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

app.use(cors({
  origin: 'https://example.com', // 허용할 출처
  methods: ['GET', 'POST'],      // 허용할 메소드
  allowedHeaders: ['Content-Type'], // 허용할 헤더
  credentials: true              // 자격 증명 허용 여부
}));

app.get('/api/data', (req, res) => {
  res.json({ message: 'CORS 설정 완료' });
});

app.listen(3000, () => {
  console.log('서버가 3000번 포트에서 실행 중입니다.');
});

이 예제에서는 https://example.com 출처에서 오는 GET 및 POST 요청을 허용하며, Content-Type 헤더를 허용하고, 자격 증명을 포함한 요청을 허용하도록 설정합니다.

CORS는 웹 애플리케이션의 보안과 유연성을 동시에 고려한 중요한 기능입니다. 올바르게 설정하여 적절한 출처에서의 요청을 허용하면서도 보안을 유지하는 것이 중요합니다.


Spring Framework에서는 @CrossOrigin 애노테이션을 사용하여 CORS 설정을 쉽게 적용할 수 있습니다. 이 애노테이션은 컨트롤러 클래스나 메소드 수준에서 사용할 수 있으며, 특정 출처에서 오는 요청을 허용하는 데 사용됩니다.

@CrossOrigin 애노테이션 사용 방법

클래스 수준에서 사용

클래스 수준에서 @CrossOrigin 애노테이션을 사용하면 해당 컨트롤러의 모든 엔드포인트에 대해 CORS 설정이 적용됩니다.

java

import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@CrossOrigin(origins = "https://example.com")
public class MyController {

    @GetMapping("/api/data")
    public String getData() {
        return "CORS 설정 완료";
    }
}

메소드 수준에서 사용

메소드 수준에서 @CrossOrigin 애노테이션을 사용하면 해당 메소드에 대해서만 CORS 설정이 적용됩니다.

java

import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyController {

    @CrossOrigin(origins = "https://example.com")
    @GetMapping("/api/data")
    public String getData() {
        return "CORS 설정 완료";
    }
}

@CrossOrigin 애노테이션의 주요 속성

  1. origins: 허용할 출처(도메인)를 지정합니다. 기본값은 모든 출처(*)입니다.
  2. methods: 허용할 HTTP 메소드를 지정합니다. 기본값은 RequestMethod.GET입니다.
  3. allowedHeaders: 허용할 HTTP 헤더를 지정합니다. 기본값은 모든 헤더입니다.
  4. exposedHeaders: 클라이언트에 노출할 헤더를 지정합니다.
  5. allowCredentials: 자격 증명(쿠키, 인증 정보 등)을 포함한 요청을 허용할지 여부를 지정합니다. 기본값은 false입니다.
  6. maxAge: 프리플라이트 요청의 결과를 캐시할 시간(초)을 지정합니다.

예제

다양한 속성을 사용한 예제입니다.

java

import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyController {

    @CrossOrigin(
        origins = "https://example.com",
        methods = {RequestMethod.GET, RequestMethod.POST},
        allowedHeaders = {"Content-Type", "Authorization"},
        exposedHeaders = {"Custom-Header"},
        allowCredentials = "true",
        maxAge = 3600
    )
    @GetMapping("/api/data")
    public String getData() {
        return "CORS 설정 완료";
    }
}

이 예제에서는 https://example.com 출처에서 오는 GET 및 POST 요청을 허용하며, Content-Type과 Authorization 헤더를 허용합니다. 또한, Custom-Header를 클라이언트에 노출하고, 자격 증명을 포함한 요청을 허용합니다. 프리플라이트 요청의 결과는 3600초(1시간) 동안 캐시됩니다.

반응형