목차


Frontend Issue

이슈 #1: S3 CORS 에러 (Presigned URL 업로드 실패)

1. 이슈 상황

항목 내용
발생 환경 프론트엔드에서 Presigned URL로 S3 직접 업로드 시
증상 “net::ERR_FAILED”, “TypeError: Failed to fetch” 에러 발생
영향 범위 공지사항 첨부파일, 교육자료 썸네일, 케어로그 사진/오디오 등 모든 파일 업로드

문제 상황:

PUT <https://soulbridge-tt.s3.ap-northeast-2.amazonaws.com/>...
net::ERR_FAILED

Console Error:
Access to fetch at '<https://soulbridge-tt.s3.amazonaws.com/>...'
from origin '<http://localhost:5173>' has been blocked by CORS policy:
No 'Access-Control-Allow-Origin' header is present on the requested resource.

2. 해결 방안 후보

방안 장점 단점
A. S3 버킷 CORS 설정 근본적 해결, 직접 업로드 가능 AWS 콘솔 접근 필요
B. 서버 프록시 버킷 설정 변경 없음 서버 부하 증가, Presigned URL 장점 상실
C. CloudFront 경유 CDN 캐싱 가능 추가 인프라 비용, 복잡성 증가

3. 선택한 해결법

선택: A안 (S3 버킷 CORS 설정)

AWS S3 CORS 설정:

[
  {
    "AllowedHeaders": ["*"],
    "AllowedMethods": ["GET", "PUT", "POST", "DELETE", "HEAD"],
    "AllowedOrigins": ["주소"],
    "ExposeHeaders": ["ETag", "Content-Length", "Content-Type"],
    "MaxAgeSeconds": 3600
  }
]

프론트엔드 업로드 코드 개선:

// Content-Type 헤더 정확히 전달
const uploadToS3 = async (presignedUrl: string, file: File) => {
  const response = await fetch(presignedUrl, {
    method: 'PUT',
    body: file,
    headers: {
      'Content-Type': file.type,  // 정확한 MIME 타입
    },
  });

  if (!response.ok) {
    throw new Error(`S3 upload failed: ${response.status}`);
  }
  return response;
};

4. 선택 이유

관점 이유
아키텍처 Presigned URL의 핵심 가치(서버 부하 감소)를 유지
성능 클라이언트-S3 직접 통신으로 최적의 업로드 속도
보안 와일드카드(*) 대신 명시적 Origin 지정으로 보안 유지
확장성 대용량 파일도 서버 트래픽 없이 처리 가능