presigned URL 업로드 중 403 에러 해결 (ACL 헤더, 버킷 정책 및 CORS 설정)

2025. 7. 11. 21:13·Jungle

presigned URL 업로드 중 403 에러 해결

문제 원인 정리

1. ACL 헤더 불일치

  • presigned URL에 x-amz-acl 서명 포함
  • 실제 PUT 요청에서 ACL 헤더 누락
    • presigned URL이 x-amz-acl 헤더를 서명에 포함했다면, 실제 PUT 요청에서도 동일한 헤더를 보내야 함

2. 버킷 정책 부재

  • 처음에 tio-image-storage-jungle8th 버킷에 정책이 없었음
  • NoSuchBucketPolicy 에러 발생했었죠

3. CORS 설정 부재

  • 브라우저에서 presigned URL로 PUT 요청 시 CORS 필요
  • 설정 없으면 브라우저가 요청 자체를 차단

해결된 과정

단계별 해결:

  1. 버킷 정책 생성 → 기본 권한 설정
  2. CORS 설정 추가 → 브라우저 요청 허용
  3. ACL 헤더 문제 → Java 코드 수정 또는 헤더 추가
    1. 프론트엔드에서 ACL 헤더 추가 또는

      const response = await fetch(presignedUrl, {
        method: 'PUT',
        body: file,
        headers: {
          'Content-Type': file.type,
          'x-amz-acl': 'public-read'  // 이 헤더가 필요!
        }
      });
      
    2. 백엔드에서 presigned URL 생성 시 ACL 제거

      // 예시 코드 - ACL 제거
      GeneratePresignedUrlRequest generatePresignedUrlRequest =
          new GeneratePresignedUrlRequest("tio-image-storage-jungle8th", key)
              .withMethod(HttpMethod.PUT)
              .withExpiration(expiration);
              // .withCannedAcl() 제거!
      
      URL presignedUrl = s3Client.generatePresignedUrl(generatePresignedUrlRequest);
      

최종 설정 상태:

json
// 버킷 정책
{
"AllowImageUpload": "계정 내 업로드 권한",
"AllowPublicRead": "퍼블릭 읽기 권한"
}
// CORS 설정
{
"AllowedOrigins": ["localhost:3000", "localhost:8080", "[tio-style.com](http://tio-style.com/)"],
"AllowedMethods": ["PUT", "POST", "GET"]
}

ACL 헤더 문제 해결위한 백엔드 코드 수정

이런 코드가 있다면 제거
.withCannedAcl(...)
.setCannedAcl(...)
.acl(...)

수정 전 presigned URL:

X-Amz-SignedHeaders=host%3Bx-amz-acl // ACL 헤더 포함

수정 후 presigned URL:

X-Amz-SignedHeaders=host // ACL 헤더 없음

🔍 각 문제의 증상

버킷 정책 없을 때:

  • 403 Forbidden (권한 자체가 없음)

CORS 설정 없을 때:

  • 브라우저 콘솔에 CORS 에러
  • 네트워크 탭에서 preflight 요청 실패

ACL 헤더 불일치:

  • 403 Forbidden (서명 불일치)
  • presigned URL은 생성되지만 실제 업로드 실패

결론

세 가지 문제가 모두 해결되어야 정상 작동하는 상황이었음

  • ✅ 버킷 정책: 업로드 권한 부여
  • ✅ CORS 설정: 브라우저 요청 허용
  • ✅ ACL 처리: 서명 일치
728x90

'Jungle' 카테고리의 다른 글

Spring 서버 AWS 인프라 트러블슈팅: Secrets Manager 연동 및 보안 그룹 최적화  (0) 2025.07.12
FrontEnd 마이그레이션(CDN → SSR, Amplify 시도 but 결국 EC2)  (0) 2025.07.11
DB 이미지 마이그레이션 (외부 url → S3 저장 + URL 갱신)  (0) 2025.07.11
RDS 인스턴스 업그레이드(DB Connection Error)  (0) 2025.07.11
S3 / CloudFront AccessDenied 문제 해결 (URL 리라이팅, CloudFront function)  (0) 2025.07.11
'Jungle' 카테고리의 다른 글
  • Spring 서버 AWS 인프라 트러블슈팅: Secrets Manager 연동 및 보안 그룹 최적화
  • FrontEnd 마이그레이션(CDN → SSR, Amplify 시도 but 결국 EC2)
  • DB 이미지 마이그레이션 (외부 url → S3 저장 + URL 갱신)
  • RDS 인스턴스 업그레이드(DB Connection Error)
ahpicl64
ahpicl64
in the clouds
  • ahpicl64
    구름
    ahpicl64
  • 전체
    오늘
    어제
    • 분류 전체보기 (95)
      • WIL (4)
      • Jungle (36)
      • AWS (2)
      • SQL (2)
      • CS:APP (17)
      • Algorithm (10)
      • K8s (7)
      • 자료 구조 (10)
      • Spring (4)
      • React (0)
      • 운영체제 (1)
      • 기타등등 (2)
      • 이야기 (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • github
  • 공지사항

  • 인기 글

  • 태그

    Spring boot
    어셈블리
    queue
    python
    EC2
    알고리즘
    IAM
    CSAPP
    Spring
    부하테스트
    DevOps
    CloudFront
    트러블슈팅
    AWS
    자료구조
    github actions
    DB
    컴퓨터시스템
    k8s
    S3
  • 02-21 08:19
  • hELLO· Designed By정상우.v4.10.3
ahpicl64
presigned URL 업로드 중 403 에러 해결 (ACL 헤더, 버킷 정책 및 CORS 설정)
상단으로

티스토리툴바