?
사용자

CORS 오류 발생하는 이유와 해결 방법 완벽 가이드

웹 개발 중 자주 마주치는 CORS(Cross-Origin Resource Sharing) 오류의 근본적인 원인을 이해하고, 이를 해결하기 위한 실질적인 방법을 단계별로 안내합니다. 프론트엔드와 백엔드 개발자 모두에게 유용한 가이드입니다.

#cors#web development#security#api#cross-origin
recipe.sh
## CORS(Cross-Origin Resource Sharing)란?

CORS는 웹 브라우저의 SOP(Same-Origin Policy, 동일 출처 정책)에 의해 제한되는 웹 페이지의 제한된 리소스 공유를 허용하도록 해주는 추가적인 HTTP 헤더를 사용하여 서버가 특정 출처(origin)로부터의 요청을 허용하도록 하는 메커니즘입니다.

### 1. SOP(Same-Origin Policy) 이해

웹 브라우저는 보안상의 이유로 동일한 출처(origin)에서 로드된 스크립트만이 다른 출처의 리소스에 접근할 수 있도록 하는 SOP를 적용합니다. 여기서 '출처'는 프로토콜(http, https), 도메인(example.com), 포트(80, 443)가 모두 일치해야 합니다.

**동일 출처 예시:**
*   `http://example.com/page.html` 에서 `http://example.com/api.js` 접근

**다른 출처 예시:**
*   `http://example.com` 에서 `http://api.example.com` 접근 (서브도메인 다름)
*   `http://example.com` 에서 `https://example.com` 접근 (프로토콜 다름)
*   `http://example.com` 에서 `http://example.com:8080` 접근 (포트 다름)

### 2. CORS 오류가 발생하는 이유

동일 출처 정책 때문에, 다른 출처에 있는 API 서버로 JavaScript(예: `fetch` 또는 `XMLHttpRequest`)를 통해 요청을 보낼 때 브라우저가 기본적으로 차단합니다. 이로 인해 브라우저 콘솔에 CORS 오류 메시지가 나타납니다.

**주요 발생 시나리오:**
*   프론트엔드 애플리케이션(예: React, Vue)이 다른 도메인 또는 다른 포트에서 실행되는 백엔드 API 서버에 요청할 때.
*   서로 다른 서브도메인을 사용하는 경우.
*   HTTPS와 HTTP 프로토콜이 혼합되어 사용될 때.

### 3. CORS 해결 원리 및 방법

CORS 문제를 해결하려면, 요청을 받는 서버(API 서버)가 브라우저에게 "이 다른 출처의 요청을 허용해도 된다"고 알려주어야 합니다. 이는 HTTP 응답 헤더에 특정 CORS 관련 헤더를 포함시켜 구현합니다.

**핵심 HTTP 헤더:**

*   **`Access-Control-Allow-Origin`**: 가장 중요하며 필수적인 헤더입니다. 응답이 허용되는 출처를 지정합니다. `*`는 모든 출처를 허용하며, 특정 출처(예: `http://frontend.com`)를 명시할 수도 있습니다.
*   **`Access-Control-Allow-Methods`**: 허용되는 HTTP 메서드(GET, POST, PUT, DELETE 등)를 지정합니다.
*   **`Access-Control-Allow-Headers`**: 클라이언트가 요청 시 사용할 수 있는 HTTP 헤더를 지정합니다. (예: `Content-Type`, `Authorization`)
*   **`Access-Control-Allow-Credentials`**: 쿠키와 같은 인증 정보(credentials)를 포함한 요청을 허용할지 여부를 지정합니다. `true`로 설정하면 `Access-Control-Allow-Origin`에 `*`를 사용할 수 없습니다. 반드시 특정 출처가 명시되어야 합니다.
*   **`Access-Control-Expose-Headers`**: 클라이언트 측 JavaScript에서 접근할 수 있도록 서버가 응답 헤더 중 노출할 헤더를 지정합니다.

#### 해결 단계 (서버 측 설정)

**1. 브라우저의 사전 요청(Preflight Request) 이해:**

`POST`, `PUT`, `DELETE`와 같은 '안전하지 않은(unsafe)' HTTP 메서드를 사용하거나, `Content-Type` 헤더가 `application/json` 또는 `multipart/form-data`와 같이 기본값이 아닌 경우, 브라우저는 실제 요청을 보내기 전에 `OPTIONS` 메서드를 사용하여 서버에게 사전 요청(preflight request)을 보냅니다. 서버는 이 사전 요청에 대해 위 CORS 헤더들을 포함한 응답을 보내야 합니다. 만약 사전 요청에 대한 응답이 정상적이지 않으면, 실제 요청은 브라우저에 의해 차단됩니다.

**2. 서버 코드에서 CORS 헤더 설정:**

사용하는 백엔드 프레임워크에 따라 CORS 설정 방법이 다릅니다. 일반적으로 미들웨어(middleware)를 사용하여 구현합니다.

**예시 (Node.js - Express.js):
```javascript
const express = require('express');
const cors = require('cors'); // npm install cors
const app = express();

// 모든 출처 허용 (개발 환경에서 유용, 프로덕션에서는 특정 출처 명시 권장)
app.use(cors()); 

// 특정 출처만 허용하는 경우
// const corsOptions = {
//   origin: 'http://frontend.com', // 허용할 프론트엔드 주소
//   methods: 'GET,POST,PUT,DELETE',
//   allowedHeaders: 'Content-Type,Authorization',
//   credentials: true // 쿠키를 주고받기 위함
// };
// app.use(cors(corsOptions));

app.get('/api/data', (req, res) => {
  res.json({ message: 'Hello from API!' });
});

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

**예시 (Python - Flask):
```python
from flask import Flask, jsonify, request
from flask_cors import CORS

app = Flask(__name__)

# 모든 출처 허용
CORS(app)

# 특정 출처만 허용하는 경우
# CORS(app, resources={r"/api/*": {"origins": "http://frontend.com"}})

@app.route('/api/data')
def get_data():
    return jsonify({'message': 'Hello from API!'})

if __name__ == '__main__':
    app.run(port=5000)
```

**3. 클라이언트 측 설정 (필요한 경우):**

대부분의 경우 서버 측 설정만으로 충분합니다. 하지만 `credentials: true` 옵션을 서버에서 사용했다면, 클라이언트(브라우저)에서도 `XMLHttpRequest` 또는 `fetch` API 호출 시 `withCredentials: true` 옵션을 설정해야 합니다. (주의: `fetch` API에서 `credentials: 'include'` 옵션이 이를 담당합니다.)

*   **fetch API 예시:**
    ```javascript
    fetch('http://api.backend.com/data', {
      method: 'GET',
      headers: {
        'Content-Type': 'application/json'
      },
      mode: 'cors', // 기본값
      credentials: 'include' // 서버에서 credentials: true 설정 시 필요
    })
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(error => console.error('Error:', error));
    ```

### 4. 주의사항

*   **`Access-Control-Allow-Origin: *` 사용 
9
스크랩
10
좋아요
0
댓글
CORS 오류 발생하는 이유와 해결 방법 완벽 가이드