CORS (교차 출처 리소스 공유, Cross-Origin Resource Sharing)는 브라우저 보안 정책(Same-Origin Policy, SOP)으로 인해 다른 출처(Origin)에서 온 요청을 제한하는 문제를 해결하기 위한 메커니즘입니다.
웹 브라우저는 보안상의 이유로 다른 출처에서 온 리소스를 기본적으로 차단합니다.
여기서 출처(Origin)란 아래 세 가지 요소로 결정됩니다.
http://
vs https://
example.com
vs api.example.com
:80
, :443
, :3000
등예를 들어, https://example.com
에서 실행 중인 웹 애플리케이션이 https://api.example.com
에 데이터를 요청하면 SOP 정책에 의해 차단됩니다.
CORS는 서버가 특정 출처에서 온 요청을 허용할 수 있도록 HTTP 헤더를 이용해 접근 권한을 부여하는 방법입니다.
브라우저는 보안이 중요한 요청(예: PUT
, DELETE
, Content-Type: application/json
포함 요청 등)에 대해 실제 요청 전에 OPTIONS 메서드를 사용한 사전 요청(Preflight Request)을 보냅니다.
요청 예시:
OPTIONS /data HTTP/1.1
Origin: https://example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type
서버 응답 예시:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type
서버가 CORS를 허용하면 응답 헤더에 Access-Control-Allow-Origin
값을 추가해야 합니다.
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Origin: *
쿠키나 인증 정보를 포함한 요청을 허용하려면 credentials: true
설정이 필요하며, Access-Control-Allow-Origin
을 특정 도메인으로 지정해야 합니다.
fetch("https://api.example.com/data", {
method: "GET",
credentials: "include" // 쿠키 전송 허용
});
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Credentials: true
@CrossOrigin
어노테이션 사용 (컨트롤러 레벨)@RestController
@RequestMapping("/api")
@CrossOrigin(origins = "https://example.com")
public class SampleController {
@GetMapping("/data")
public String getData() {
return "Hello, CORS!";
}
}
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("https://example.com")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*")
.allowCredentials(true);
}
}
Spring Security를 사용하면 기본적으로 모든 CORS 요청이 차단됩니다. 이를 허용하려면 다음 설정을 추가해야 합니다.
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.cors(withDefaults()) // CORS 설정 활성화
.csrf(AbstractHttpConfigurer::disable) // CSRF 비활성화
.authorizeHttpRequests(auth -> auth.anyRequest().permitAll());
return http.build();
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(List.of("https://example.com"));
configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE"));
configuration.setAllowedHeaders(List.of("*"));
configuration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
Next.js에서 백엔드 API 호출 시 CORS 문제가 발생할 수 있습니다. 이를 해결하려면 Next.js API Route에서 CORS를 허용해야 합니다.
import type { NextApiRequest, NextApiResponse } from 'next';
import Cors from 'cors';
const cors = Cors({
origin: 'https://example.com',
methods: ['GET', 'POST', 'PUT', 'DELETE'],
credentials: true,
});
export default function handler(req: NextApiRequest, res: NextApiResponse) {
res.setHeader('Access-Control-Allow-Origin', 'https://example.com');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
res.setHeader('Access-Control-Allow-Credentials', 'true');
res.status(200).json({ message: 'CORS 설정 완료' });
}
Access-Control-Allow-Origin
설정 확인cors()
설정 추가credentials: true
+ Access-Control-Allow-Credentials: true
적용OPTIONS
요청 처리Access-Control-Allow-Origin
등의 설정을 통해 허용할 수 있음.