CORS Error 해결법

Jerry·2025년 8월 4일

CORS(Cross-Origin Resource Sharing) 에러는 프론트엔드와 백엔드가 다른 도메인/포트에서 실행될 때 자주 발생합니다.

상황 예시

  • Frontend: http://localhost:3000 (Next.js)
  • Backend: http://localhost:8080 (Spring Boot REST API)

오류:

Access to fetch at 'http://localhost:8080/api/data' from origin 'http://localhost:3000' has been blocked by CORS policy

CORS 에러 해결법 (Spring Boot 기준)

Spring Boot에서 CORS 문제를 해결하려면:

  • Global CORS 설정
  • Controller 레벨 @CrossOrigin 사용
  • Security 설정에 CORS 허용 추가 (Spring Security 사용 시)

Global CORS 설정 (모든 컨트롤러에 적용)

package com.example.demo.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.*;

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**") // 모든 API 경로 허용
                .allowedOrigins("http://localhost:3000") // Next.js origin
                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
                .allowedHeaders("*")
                .allowCredentials(true) // 인증 정보(쿠키 등) 허용
                .maxAge(3600);
    }
}

Controller 레벨에서 @CrossOrigin 사용

@RestController
@RequestMapping("/api")
@CrossOrigin(origins = "http://localhost:3000") // 이 컨트롤러에만 적용
public class ApiController {

    @GetMapping("/data")
    public ResponseEntity<String> getData() {
        return ResponseEntity.ok("Hello from backend");
    }
}

이 방법은 테스트/소규모 서비스에서는 간편하지만, 전역 적용이 필요할 땐 WebConfig를 추천합니다.

Spring Security 설정

Spring Security를 사용 중이라면, CORS 허용을 명시적으로 추가해야 합니다.
안 그러면 필터 레벨에서 먼저 막히게 됩니다.

package com.example.demo.config;

import org.springframework.context.annotation.*;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.web.cors.*;

@Configuration
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .cors().configurationSource(corsConfigurationSource()) // CORS 허용 추가
            .and()
            .csrf().disable()
            .authorizeHttpRequests()
            .requestMatchers("/**").permitAll();

        return http.build();
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedOrigin("http://localhost:3000");
        config.addAllowedMethod("*");
        config.addAllowedHeader("*");
        config.setAllowCredentials(true); // 쿠키/인증정보 전달 허용

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);
        return source;
    }
}

Next.js에서 API 호출 (fetch 예시)

// pages/index.tsx
import { useEffect } from 'react';

export default function Home() {
  useEffect(() => {
    fetch('http://localhost:8080/api/data', {
      credentials: 'include', // 쿠키 등 인증 정보 전달할 경우
    })
      .then(res => res.text())
      .then(data => console.log(data));
  }, []);

  return <div>Next.js + Spring Boot CORS 테스트</div>;
}

credentials: 'include' 를 설정한 경우, Spring 쪽에서도 allowCredentials(true) 반드시 필요

정리

구성설정 위치설명
Spring 전역 CORSWebConfig.java전체 API에 CORS 허용 적용
Spring SecuritySecurityConfig.java필터단에서 CORS 허용 (Security 사용 시 필수)
Controller 단위@CrossOrigin개별 엔드포인트 CORS 허용
Next.jsfetch(..., credentials)인증정보 보내는 경우 필요
profile
Backend engineer

0개의 댓글