CORS와 프록시 — CorsConfig / SecurityConfig / Proxy (작성중)

DEV/Spring

CORS와 프록시 — CorsConfig / SecurityConfig / Proxy (작성중)

BI3A 2026. 3. 22. 03:30

반응형

 

Spring & Spring Boot

 

CORS란

브라우저는 출처(Origin) 가 다른 서버로의 요청을 기본적으로 차단한다.

Origin = 프로토콜 + 도메인 + 포트

http://localhost:5173http://localhost:8080 → 다른 Origin

프론트(5173)에서 백엔드(8080)로 요청하면 브라우저가 이를 감지하고, 실제 요청 전에 preflight 요청(OPTIONS 메서드) 을 먼저 보내 서버가 허용하는지 물어본다.

브라우저 → OPTIONS /api/projects (preflight)
백엔드   → 200 OK + Access-Control-Allow-Origin: http://localhost:5173
브라우저 → 허용 확인 후 실제 GET /api/projects 전송

서버가 허용 응답을 주지 않으면 브라우저가 실제 요청 자체를 차단한다.
차단은 서버가 하는 게 아니라 브라우저가 한다.


CorsConfig — "무엇을 허용할 것인가" 정의

@Configuration
public class CorsConfig {

    @Value("${cadence.cors.allowed-origins}")
    private String[] allowedOrigins;

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowedOriginPatterns(List.of(allowedOrigins)); // 허용 출처
        config.setAllowedMethods(List.of("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"));
        config.setAllowedHeaders(List.of("*"));
        config.setAllowCredentials(true); // Authorization 헤더 허용
        ...
    }
}

역할: CORS 규칙 자체를 정의하는 곳.
허용할 출처, 메서드, 헤더를 명시하고 CorsConfigurationSource 빈으로 등록한다.
Spring MVC 레벨(Controller에 도달하기 직전)에서 작동한다.

setAllowedOrigins vs setAllowedOriginPatterns

메서드 특징
setAllowedOrigins 정확한 문자열 일치. *setAllowCredentials(true) 동시 사용 불가
setAllowedOriginPatterns 와일드카드 패턴 허용. setAllowCredentials(true)와 함께 사용 가능

SecurityConfig — "누가 이 규칙을 쓸 것인가" 연결

.cors(cors -> cors.configurationSource(corsConfigurationSource))

역할: CorsConfig가 정의한 규칙을 Spring Security 필터 체인에 연결한다.

Spring Security 필터는 Spring MVC보다 먼저 실행된다.
SecurityConfig에 CORS를 연결하지 않으면 preflight(OPTIONS) 요청이 Security 필터에서 먼저 막혀버린다.

HTTP 요청
  → [Spring Security 필터]  ← SecurityConfig가 corsConfigurationSource 참조
      → [Spring MVC]         ← CorsConfig 빈이 작동하는 레이어
          → Controller

두 파일의 관계 요약

  CorsConfig SecurityConfig
역할 CORS 규칙 정의 (what) Security 필터에 규칙 연결 (who uses it)
설정 위치 Spring MVC 레벨 Security 필터 레벨 (더 앞)
단독 동작 Security 없이도 작동 규칙 자체를 정의하지 않음

CorsConfig만 있고 SecurityConfig에 연결 안 하면?
→ preflight가 Security에서 401/403으로 차단되어 모든 API 호출 실패.

SecurityConfig에만 인라인으로 정의하면?
→ 동작은 하지만 허용 출처가 하드코딩되어 환경별 관리가 어렵고, 설정이 두 곳에 분산된다.


Vite Server Proxy — 개발 환경 전용 우회

// vite.config.ts
server: {
  proxy: {
    '/api': {
      target: 'http://localhost:8080',
      changeOrigin: true,
    },
  },
},

역할: 로컬 개발 시 CORS를 서버 설정 없이 우회한다.

브라우저는 같은 5173 서버에 요청한다고 인식하고, Vite 개발서버가 백엔드로 포워딩한다.

브라우저(5173) --/api/projects--> Vite 개발서버(5173) ---> 백엔드(8080)
               ↑ 같은 Origin (CORS 없음)               ↑ 서버 간 통신 (CORS 없음)

changeOrigin: true
포워딩 시 요청의 Host 헤더를 localhost:8080으로 바꾼다.
없으면 백엔드가 localhost:5173으로 된 Host를 받아 거부할 수 있다.


세 가지의 관계 정리

  CorsConfig SecurityConfig Vite Proxy
동작 환경 로컬 + 운영 로컬 + 운영 로컬 개발만
처리 주체 Spring 서버 Spring 서버 Vite 개발서버
목적 CORS 허용 규칙 정의 Security 필터에 CORS 연결 브라우저 CORS 자체를 우회

로컬 개발 흐름

브라우저 → Vite proxy → 백엔드
         (CORS 우회)   (CorsConfig + SecurityConfig은 동작하나 실질적으로 무관)

운영 배포 흐름

브라우저 → CDN/프론트 서버 → 백엔드
          (Vite proxy 없음)  (CorsConfig + SecurityConfig이 실제로 작동)

운영에서는 Vite proxy가 없으므로 CorsConfigallowedOrigins에 실제 프론트 도메인이 정확히 등록되어 있어야 한다.


6. CORS 흐름

application-local.properties
cors.allowed-origins=http://localhost:5173
          ↓ @Value 주입
CorsConfig.corsConfigurationSource()
          ↓ 빈 주입
SecurityConfig.cors(...)

허용 출처를 변경할 때는 application-local.propertiescadence.cors.allowed-origins 값 하나만 수정하면 전체에 반영된다.

반응형