본문 바로가기
Web

[Web] CORS(Cross-Origin Resource Sharing)

by clolee 2025. 5. 8.

✅ CORS 완전 정복

CORS(Cross-Origin Resource Sharing)는 웹 보안 정책과 클라이언트-서버 통신의 실제 구현이 맞닿는 지점으로,

실무에서 API 개발·프론트엔드 연동·보안 설정에서 매우 중요하게 다뤄집니다.

1. 📌 CORS란?

🔒 Same-Origin Policy (SOP)란?

  • 브라우저 보안 정책의 일환으로, 출처(origin)가 다른 리소스에 대한 접근을 기본적으로 제한함.
  • 출처는 다음 3가지 조합으로 구성됨:
  • protocol + domain + port ex) https://api.example.com:443

🧭 CORS란?

  • SOP의 예외를 만들기 위한 HTTP 기반 보안 메커니즘
  • 서버가 명시적으로 허용한 도메인에만 리소스 접근을 허용하는 방식

즉, 클라이언트가 다른 출처로 요청을 보냈을 때, 서버가 허용하는 경우에만 응답을 받을 수 있도록 함.


2. 💬 CORS 동작 흐름 요약

[Client] 브라우저 → [Server] API 요청
   |
   ├─ CORS 요청 헤더 포함 (Origin, etc)
   ↓
[Server] 응답 헤더에 CORS 허용 여부 명시
   └─ Access-Control-Allow-Origin: https://myapp.com

🙋 CORS 요청의 종류

요청 타입 설명 예시
Simple Request GET, POST (with safe headers) 등 제한된 요청 일반적인 GET, POST
Preflight Request CORS 조건이 복잡할 경우 사전 OPTIONS 요청 Content-Type: application/json, PUT, DELETE 등
Credentialed Request 쿠키, 인증정보 포함 요청 withCredentials: true 사용 시

3. 🧪 CORS 요청 조건 예시

✅ Simple Request 조건 (예: 브라우저가 사전 검사 없이 바로 요청 가능)

  • 메서드: GET, POST, HEAD
  • Header:
    • Content-Typeapplication/x-www-form-urlencoded, multipart/form-data, text/plain 중 하나
  • withCredentials를 사용하지 않음

❌ Preflight이 필요한 경우

  • 메서드가 PUT, DELETE, PATCH일 때
  • Authorization커스텀 헤더 사용 시
  • application/json 등의 Content-Type

4. 🛠️ 서버에서 CORS 설정 방법 (언어별 실무 예시)

Node.js (Express)

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

app.use(cors({
  origin: 'https://frontend.example.com',
  credentials: true,  // 쿠키/세션 허용
}));

Spring Boot

@CrossOrigin(origins = "https://frontend.example.com", allowCredentials = "true")
@RestController
public class ApiController {
    @GetMapping("/data")
    public ResponseEntity<?> getData() {
        return ResponseEntity.ok(...);
    }
}

Nginx (프록시 CORS 허용 설정)

location /api/ {
    add_header 'Access-Control-Allow-Origin' 'https://frontend.example.com';
    add_header 'Access-Control-Allow-Credentials' 'true';
    ...
}

5. 🧩 주요 CORS 응답 헤더 설명

헤더 의미
Access-Control-Allow-Origin 허용할 출처 도메인 (예: https://example.com 또는 *)
Access-Control-Allow-Methods 허용할 HTTP 메서드들 (예: GET, POST, PUT)
Access-Control-Allow-Headers 허용할 요청 헤더 (예: Authorization, Content-Type)
Access-Control-Allow-Credentials 쿠키 및 인증 포함 여부 (true)
Access-Control-Max-Age Preflight 응답을 브라우저가 캐시할 시간 (초 단위)

 


6. ⚠️ 실무에서 자주 발생하는 문제 및 해결 전략

문제 원인 해결법
CORS policy error: No 'Access-Control-Allow-Origin' 서버가 요청 도메인을 허용하지 않음 서버에서 Access-Control-Allow-Origin 설정
Preflight response not successful OPTIONS 요청에 대한 응답 없음 서버에 OPTIONS 메서드 처리 추가
쿠키가 전송되지 않음 서버 또는 클라이언트에서 credentials 설정 누락 withCredentials: true + Access-Control-Allow-Credentials: true
'*' 와 credentials 동시 사용 보안 제한 'Access-Control-Allow-Origin'에 명시적인 도메인 사용 필요

7. 💡 실무 팁

  • API 서버와 프론트엔드가 분리된 구조(e.g., React + Express, Vue + Spring)에서는 반드시 CORS 설정 필요
  • OAuth2 토큰 발급, 로그인 세션 기반 API의 경우 credentials 설정 필수
  • 사내망 API, BFF(Backend for Frontend) 구조에서는 Nginx에서 CORS 처리하는 것도 성능상 유리
  • CORS 문제가 발생하면 브라우저의 네트워크 탭에서 OPTIONS 요청과 응답 헤더를 반드시 확인

8. 🔐 CORS와 보안

  • CORS는 보안 기능이 아니라 브라우저의 보호 메커니즘입니다.
  • 서버는 Access-Control-Allow-Origin을 통해 어떤 도메인에 데이터를 공개할지 선택함
  • 중요한 API의 경우 API Gateway 또는 인증 토큰으로 추가적인 인증/인가 처리를 반드시 병행해야 함

✅ 요약

항목 내용
CORS 목적 브라우저에서 다른 출처의 리소스 접근 제한 완화
주요 요소 Origin, Allow-Origin, Credentials, Preflight
적용 시기 API 서버와 프론트엔드 도메인이 다를 때
설정 방법 서버 (Express, Spring), 프록시 (Nginx 등)
보안 주의 * 사용 제한, 토큰/세션 기반 인증 병행 필요

'Web' 카테고리의 다른 글

[Javascript] AJAX (Asynchronous JavaScript and XML) 완전 정리  (0) 2025.05.08
[Web] URL Encoding  (0) 2025.04.23
[Web] Query String  (0) 2025.04.23
[HTTP] HTTP 상태 코드  (0) 2025.04.14
[Web] API와 EndPoint  (3) 2022.10.20

댓글