CORS 에러

Olivia·약 22시간 전

[Trouble Shooting👾]

목록 보기
8/8

처음 백엔드 코드를 AWS 클러스터에 배포하고 S3에 배포한 프론트랑 연결하다가 마주친 CSP 에러!
반갑당

프론트 이미지 빌드할때 API_BASE_URL을 같이 빌드하니 BE로 요청은 가는데 CSP 에러 때문에 에러 발생.


S3 배포 환경에서 백엔드 API 호출 실패

요약

항목내용
문제S3에 배포된 프론트엔드에서 백엔드 API 호출이 완전히 차단됨
근본 원인Content Security Policy(CSP)에 백엔드 도메인이 허용되지 않음
상태✅ 해결됨
심각도High (서비스 불가)

1. 문제 정의

1.1 증상

  • 로컬 환경: 백엔드 API 호출 정상 작동 (npm run dev)
  • S3 배포 환경: 브라우저 Network 탭에 API 요청 자체가 나타나지 않음
  • 증상 특징: CORS 에러도 표시되지 않고, 요청이 아예 발생하지 않음

1.2 재현 조건

  1. 프론트엔드를 S3에 배포
  2. 브라우저에서 S3 URL로 접속
  3. 백엔드 API를 호출하는 기능 실행
  4. Network 탭 확인 → 요청 없음

1.3 환경 차이

항목로컬 개발 환경S3 배포 환경
프론트엔드 URLlocalhost:4180s3-bucket-url/AAA
백엔드 호출 방식Vite 프록시 (/api → 백엔드)직접 호출 (https://api-AAA.com)
CSP 적용개발 모드 (느슨함)빌드된 HTML의 엄격한 CSP

1.4 영향 범위

  • 영향받는 기능: 백엔드 API를 사용하는 모든 기능
  • 사용자 영향: S3 배포 환경에서 서비스 완전 불가
  • 데이터 영향: 없음 (요청이 발생하지 않음)

2. 타임라인

단계활동 내용
문제 보고"로컬에서는 되는데 S3에서는 백엔드 호출이 안 됨"
초기 가설CORS 에러로 추정 → 하지만 Network 탭에 요청 자체가 없음 확인
환경 분석.env.development.env.production 확인 → 환경 변수명 불일치 발견
빌드 검증빌드 명령어 확인: VITE_API_BASE_URL=... 환경 변수로 빌드 → API URL은 정상 주입됨
dist 분석dist/assets/*.js 파일에서 https://api-AAA 확인 → API URL 정상
CSP 발견index.html의 CSP 메타 태그 확인 → connect-src에 백엔드 도메인 누락 발견
해결 적용CSP의 connect-srchttps://*.AAA 추가
검증재빌드 및 재배포 필요 (사용자 측에서 확인 예정)

3. 근본 원인 분석

3.1 5 Whys 분석

#질문답변
1왜 S3에서 백엔드 호출이 안 되는가?브라우저가 요청을 차단함
2왜 브라우저가 요청을 차단하는가?Content Security Policy 위반
3왜 CSP 위반이 발생하는가?connect-src에 백엔드 도메인이 없음
4왜 백엔드 도메인이 없는가?CSP 설정 시 백엔드 도메인을 고려하지 않음
5왜 로컬에서는 작동했는가?Vite 개발 서버의 프록시가 CSP를 우회함

🎯 근본 원인:
index.html의 Content Security Policy에서 connect-src 지시어가 'self' https://*.paddle.com만 허용하도록 설정되어 있었고, 백엔드 API 도메인(https://*.AAA)이 포함되지 않아 브라우저가 요청을 원천 차단했음.

3.2 기술적 세부 사항

CSP (Content Security Policy) 동작 원리

<meta http-equiv="Content-Security-Policy"
  content="connect-src 'self' https://*.paddle.com;" />
  • connect-src: XMLHttpRequest, Fetch API, WebSocket 등 네트워크 요청을 제어
  • 'self': 현재 origin(S3 도메인)만 허용
  • https://*.paddle.com: Paddle 결제 도메인만 허용
  • 문제: api-dev.skuberplus.com은 허용되지 않음

로컬 환경이 정상 작동한 이유

// vite.config.ts
server: {
  proxy: {
    '/api': {
      target: 'https://api-AAA',
      changeOrigin: true,
    },
  },
}
  • 로컬에서는 Vite 프록시가 /api 요청을 백엔드로 전달
  • 브라우저 입장에서는 같은 origin(localhost:4180)으로 요청
  • CSP의 'self'에 해당하여 허용됨

S3 배포 환경의 차이

// src/api/client.ts
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL;
// → "https://api-dev.AAA"

export const apiClient = axios.create({
  baseURL: API_BASE_URL, // 직접 호출
});
  • S3에는 프록시 서버가 없음
  • 브라우저가 직접 `api-dev.AAA으로 요청
  • CSP에 해당 도메인이 없어 차단됨

profile
👩🏻‍💻

0개의 댓글