프로토콜 + 호스트 + 포트 조합이 다르면 교차 출처로 간주됨.withCredentials: true + 서버의 allowCredentials(true) + 명시적 allowedOrigins 조합 필요.withCredentials: true 로 세션/쿠키 기반 인증 유지 가능.
// [1] 기본 GET (세션/쿠키 사용 안 함)
const r1 = await axios.get("http://localhost:8080/axios");
console.log(r1.data);
// [2] 로그인 (세션/쿠키 사용함)
const obj = { id: "admin", pwd: "qwer1234" };
const r2 = await axios.post("http://localhost:8080/axios", obj, { withCredentials: true });
console.log(r2.data);
// [3] 내 정보 조회 (세션/쿠키 유지)
const r3 = await axios.get("http://localhost:8080/axios/info", { withCredentials: true });
console.log(r3.data);
// 폼 DOM을 전송하려면 URLSearchParams로 인코딩
const form = formRef.current;
const params = new URLSearchParams(new FormData(form));
const r = await axios.post("http://localhost:8080/axios/form", params, {
headers: { "Content-Type": "application/x-www-form-urlencoded" },
withCredentials: true, // 쿠키 필요 시
});
console.log(r.data);
const form = formRef.current;
const formData = new FormData(form);
const r = await axios.post("http://localhost:8080/axios/formdata", formData, {
headers: { "Content-Type": "multipart/form-data" },
withCredentials: true,
});
console.log(r.data);
✅ TIP:
withCredentials를 쓰면 서버 CORS에서allowCredentials(true)필수.
또한allowedOrigins("*")와 동시에allowCredentials(true)를 사용할 수 없음 → 명시적 Origin 지정 필요.
WebMvcConfigurer 사용. 보통 보안 없이 간단한 API만 있을 때.
// CorsConfig.java
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:3000", "http://localhost:5173") // React dev 서버
.allowedMethods("GET","POST","PUT","PATCH","DELETE","OPTIONS") // 허용HTTP METHOD
.allowedHeaders("*")
.exposedHeaders("Location") // 필요시 노출 헤더
.allowCredentials(true) // 쿠키 허용
.maxAge(3600);
}
}
SecurityFilterChain에서 http.cors() 활성화 + CorsConfigurationSource 빈 제공.
// SecurityConfig.java
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.cors(cors -> cors.configurationSource(corsConfigurationSource()))
.csrf(csrf -> csrf.disable()); // 세션/쿠키 기반이면 CSRF 전략 별도 고려
return http.build();
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration cfg = new CorsConfiguration();
cfg.setAllowedOrigins(List.of("http://localhost:3000","http://localhost:5173"));
cfg.setAllowedMethods(List.of("GET","POST","PUT","PATCH","DELETE","OPTIONS"));
cfg.setAllowedHeaders(List.of("*"));
cfg.setAllowCredentials(true);
cfg.setExposedHeaders(List.of("Location"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", cfg);
return source;
}
}
✅ TIP: Spring Security를 사용한다면 WebMvcConfigurer만으로는 부족할 수 있음. 반드시
http.cors()와CorsConfigurationSource로 일치되는 정책을 등록.
allowedOriginPatterns (와일드카드) 사용운영에서 여러 서브도메인을 허용해야 하는 경우.
cfg.setAllowedOriginPatterns(List.of("https://*.example.com"));
cfg.setAllowCredentials(true); // 패턴 사용 시에도 크리덴셜은 명시적 허용 필요
withCredentials: trueallowCredentials(true) + 명시적 출처 지정 SameSite=None; Secure 설정 필요(HTTPS 권장)예) Spring에서 응답 쿠키 생성 시
ResponseCookie cookie = ResponseCookie.from("SESSIONID", sessionId)
.httpOnly(true)
.secure(true) // HTTPS에서만
.sameSite("None") // 크로스 사이트 전송 허용
.path("/")
.build();
response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString());
@RestController
@RequestMapping("/axios")
public class AxiosController {
@PostMapping
public ResponseEntity<String> login(@RequestBody Map<String,String> body, HttpSession session) {
// 검증 로직...
session.setAttribute("login", body.get("id"));
return ResponseEntity.ok("ok");
}
@GetMapping("/info")
public ResponseEntity<?> myInfo(HttpSession session) {
Object login = session.getAttribute("login");
if (login == null) return ResponseEntity.status(401).body("unauthorized");
return ResponseEntity.ok(Map.of("user", login));
}
}
프런트 개발 서버에서 프록시 설정을 두면 브라우저는 같은 Origin으로 인식 → CORS 회피.
vite.config.ts)export default defineConfig({
server: {
proxy: {
"/api": {
target: "http://localhost:8080",
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ""),
},
},
},
});
프런트 요청은 /api/... 로, 서버는 /... 로 받도록 매핑.
오류: CORS policy: No 'Access-Control-Allow-Origin' header
→ 서버 CORS 미설정 또는 Origin 불일치. allowedOrigins 확인.
오류: 쿠키가 안 붙음
→ 프런트 withCredentials:true + 서버 allowCredentials(true) + 명시적 Origin 필요. SameSite=None; Secure도 확인.
오류: Preflight 403/404
→ 서버가 OPTIONS 허용하지 않음. allowedMethods/필터 체인 확인.
오류: application/x-www-form-urlencoded 전송 실패
→ URLSearchParams(new FormData(form)) 로 인코딩, 헤더 정확히 지정.
withCredentials 및 알맞은 Content-Type 설정. SameSite=None; Secure 고려. GET/POST 기본 요청, withCredentials 사용 → CORS의 allowCredentials(true) 및 명시적 allowedOrigins 필요. application/x-www-form-urlencoded (정확).