개발로 사고하기

😤 CORS? 403? API 호출 대참사 해결기

tues 2025. 9. 11. 17:58

 

 

"로컬에서는 되는데 EC2에서는 왜 안 되지?"


🧩 사건 개요

클라우드에 React + Spring Boot 서비스를 배포하고 나서,
프론트에서 API를 호출하자마자 403 Forbidden 오류가 발생했다.

  • EC2 보안 그룹? 열려 있음
  • 백엔드 포트? 정상적으로 열려 있음
  • API 주소? 맞게 입력함
    그런데도 계속 에러가 난다...

❓ 왜 이런 문제가 발생했을까?

📌 CORS란?

CORS(Cross-Origin Resource Sharing)는 브라우저 보안 정책 중 하나로,
출처(origin)가 다른 도메인 간 요청을 제한하는 기능이다.

  • 로컬에서는 localhost:3000 → localhost:8080으로 요청하니 괜찮음
  • EC2에 배포 후에는 브라우저: http://<IP> → API: http://<IP>:8081로 다른 포트 간 통신

🔐 브라우저는 이를 보안 위반으로 판단 → 요청 자체를 막아버린다


🧪 에러 상황 정리

// 프론트에서 fetch 요청
fetch('http://<EC2-IP>:8081/api/rewards/summary?userId=u-123')
  .then(res => res.json())
  .then(data => console.log(data));

 

❌ 콘솔 에러

 

Access to fetch at 'http://<EC2-IP>:8081/...' from origin 'http://<EC2-IP>' 
has been blocked by CORS policy: 
Response to preflight request doesn't pass access control check: 
No 'Access-Control-Allow-Origin' header is present...

 

🔧 해결 방법 (Spring Boot)

✅ WebMvcConfigurer를 통한 CORS 설정 추가

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**") // 전체 API 경로 허용
                .allowedOrigins("*") // 모든 출처 허용 (*은 개발 환경에서만!)
                .allowedMethods("GET", "POST", "PUT", "DELETE") // 허용 메서드
                .allowedHeaders("*");
    }
}

 

📌 주의:

  • allowedOrigins("*")는 개발환경에서만 사용
  • 운영 환경에서는 http://yourdomain.com과 같이 정확한 도메인 지정이 필수

🧠 디버깅 중 알게 된 사실들

💡 프론트 요청 흐름 정리

  1. 브라우저가 Preflight 요청(OPTIONS) 전송
  2. 백엔드가 CORS 설정이 없으면 → 403 Forbidden
  3. 프론트는 본 요청(GET, POST)을 보내지 못하고 실패함

✅ 해결 이후 결과

  • API 요청 정상 응답 👏
  • 실제로 브라우저 콘솔에서 CORS 관련 에러 사라짐
  • 프론트에서 리워드 정보 조회 및 리더보드 정상 렌더링

🧠 배운 점

 

CORS 단순 서버 문제 아님. 브라우저 보안 정책에 의한 차단
Spring 설정 WebMvcConfigurer를 통해 제어 가능
로컬 vs 운영 로컬에서는 안 생기던 문제가 배포 후 발생할 수 있음

👉 결국 로컬 개발 환경과 실제 브라우저 환경은 다르다는 걸 절실히 느꼈다.
배포 이후 브라우저에서 실제 요청 흐름을 추적하는 게 중요하다.