1. CORS란?
- CORS(Cross-Origin Resource Sharing)는 웹 브라우저 보안 정책으로, 특정 도메인에서 다른 도메인 리소스에 대한 요청을 제어합니다.
- 브라우저는 기본적으로 Same-Origin Policy(동일 출처 정책)를 따르며, 다른 도메인의 리소스 요청을 차단합니다.
- 동일 출처 정책: 요청의 프로토콜, 도메인, 포트가 동일해야 함.
- CORS는 이러한 제한을 완화할 수 있도록 서버에서 적절한 헤더를 설정하여 특정 출처(origin)에 대해 리소스 접근 권한을 부여합니다.
2. CORS의 동작 흐름
2.1 기본 요청 흐름
- 클라이언트:
- 브라우저가 XMLHttpRequest, Fetch API, <img> 등의 방식으로 리소스를 요청.
- 브라우저:
- 요청이 다른 도메인(origin)으로 향할 경우 CORS 정책을 적용.
- 서버:
- 요청 헤더에 포함된 출처(origin)를 확인하고, 허용된 출처인 경우 응답 헤더에 CORS 허용 헤더를 추가.
- 브라우저:
- 응답의 CORS 허용 헤더를 확인하여, 요청의 성공 여부를 결정.
3. CORS 구성 요소
3.1 요청 헤더
클라이언트 요청에는 Origin 헤더가 포함되어 출처 정보를 브라우저가 서버로 전달.
- 예시:
GET /data HTTP/1.1
Host: api.example.com
Origin: http://frontend.example.com
3.2 응답 헤더
서버는 클라이언트가 요청을 허용할지 응답 헤더로 전달.
헤더 이름 | 설명 |
Access-Control-Allow-Origin | 허용된 출처. 특정 도메인, 또는 *(모두 허용). |
Access-Control-Allow-Methods | 허용된 HTTP 메서드 목록 (예: GET, POST, PUT). |
Access-Control-Allow-Headers | 허용된 요청 헤더 목록 (예: Content-Type, Authorization). |
Access-Control-Allow-Credentials | 인증 정보를 포함한 요청(쿠키 등)을 허용할지 여부. |
Access-Control-Expose-Headers | 클라이언트가 접근 가능한 응답 헤더. |
Access-Control-Max-Age | 사전 요청(preflight)의 결과를 캐시하는 시간(초 단위). |
4. CORS 요청의 종류
4.1 단순 요청 (Simple Request)
- 브라우저가 CORS 요청을 바로 전송하며 사전 요청(preflight)이 필요하지 않음.
- 조건:
- HTTP 메서드는 GET, POST, HEAD 중 하나.
- 요청 헤더는 단순 헤더(Content-Type, Accept, Origin 등).
- 예시:
GET /data HTTP/1.1
Origin: http://frontend.example.com
4.2 사전 요청 (Preflight Request)
- 복잡한 요청(예: PUT, DELETE)은 서버에 사전 요청을 전송하여 허용 여부를 확인.
- 사전 요청은 OPTIONS 메서드로 전송됨.
- 예시 (사전 요청):
OPTIONS /data HTTP/1.1
Origin: http://frontend.example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type
- 예시 (응답):
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: http://frontend.example.com
Access-Control-Allow-Methods: POST, GET
Access-Control-Allow-Headers: Content-Type
5. Spring Boot에서 CORS 설정
5.1 컨트롤러 레벨 설정
- 특정 컨트롤러 메서드에 CORS 설정 적용.
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ApiController {
@CrossOrigin(origins = "<http://frontend.example.com>")
@GetMapping("/data")
public String getData() {
return "CORS 설정된 데이터";
}
}
5.2 글로벌 설정
- 전체 API에 대해 CORS를 설정.
방법 1: WebMvcConfigurer 사용
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // 모든 엔드포인트에 대해 CORS 허용
.allowedOrigins("<http://frontend.example.com>") // 허용된 출처
.allowedMethods("GET", "POST", "PUT", "DELETE") // 허용된 메서드
.allowedHeaders("*") // 모든 요청 헤더 허용
.allowCredentials(true) // 쿠키 전송 허용
.maxAge(3600); // 1시간 동안 캐시
}
}
방법 2: application.properties 설정
# 스프링 부트 2.4 이상에서 글로벌 CORS 설정 지원
spring.web.cors.allowed-origins=http://frontend.example.com
spring.web.cors.allowed-methods=GET,POST,PUT,DELETE
spring.web.cors.allowed-headers=*
spring.web.cors.allow-credentials=true
6. CORS 문제 해결 방법
- 서버 설정 확인:
- 서버가 적절한 Access-Control-Allow-Origin 헤더를 반환하도록 설정.
- 클라이언트 요청 확인:
- 클라이언트의 요청 헤더(Origin, Access-Control-Request-Headers)를 점검.
- 개발 중 해결 방법:
- 개발 환경에서는 프록시 설정을 사용하여 동일 출처처럼 동작하게 만들 수 있음.
- React 예시 (package.json):
"proxy": "http://localhost:8080"
4. 서버에서 `` 대신 특정 도메인 허용:
- 보안 문제를 방지하기 위해 Access-Control-Allow-Origin: * 대신 필요한 도메인만 허용.
'Spring' 카테고리의 다른 글
MariaDB 엔진 - InnoDB vs MyISAM (0) | 2025.01.10 |
---|---|
Swagger (REST API 문서화) (0) | 2025.01.10 |
AJAX(Asynchronous JavaScript and XML) (0) | 2025.01.10 |
REST API - @RestController (0) | 2025.01.05 |
REST API - XML과 JSON (0) | 2025.01.05 |