AWS - S3

김기훈·2026년 3월 8일

AWS

목록 보기
3/5

Django

  • Django에서 S3로 이미지를 올리려면 두가지 "라이브러리" 필요
    • pip install boto3 django-storages pillow
    • poetry add boto3 django-storages pillow

boto3

  • 역할
    • 파이썬(Python) 프로그램이
    • AWS 서비스(S3, EC2 등)와 대화할 수 있게 해주는 AWS 공식 파이썬용 번역기(SDK)
  • 필요한 이유
    • 파이썬은 기본적으로 AWS가 어떻게 생겼는지 모름
    • boto3가 있어야 파이썬 코드로 "S3야, 이 파일 좀 받아줘"라는 명령을 내릴 수 있음

django-storages

  • 역할
    • Django의 내장 파일 저장 시스템을 가로채서 S3로 연결해 주는 어댑터(연결 젠더)
  • 필요한 이유
    • Django의 ImageField는 기본적으로
      • 내 컴퓨터(서버)의 하드디스크에 파일을 저장하도록 설계되어 있음
    • 이 라이브러리가 없으면 Django의 파일 저장 코드를 밑바닥부터 뜯어고쳐야 함
    • 하지만 이 라이브러리를 쓰면 코드 수정 없이
      • settings.py 설정 몇 줄만으로 저장 위치를 S3로 바꿔줌

Pillow

  • poetry add pillow
    • Django에서 이미지를 다루려면(즉, ImageField를 사용하려면)
      • 파이썬 이미지 처리 라이브러리인 Pillow가 반드시 필요
    • Django가 이미지를 인식하고 처리할 수 있게 해주는 필수 라이브러리

AWS 인프라 준비

AWS S3 버킷 생성하기 (이미지 저장소 만들기)

  • S3는 쉽게 말해 "무한대로 늘어나는 클라우드 USB 드라이브"

    • 이 USB 드라이브 하나를 '버킷(Bucket)'이라고 부름
  • 과정

    • AWS 콘솔 로그인: AWS 웹사이트에 로그인
    • S3 서비스 이동: 화면 맨 위 검색창에 S3를 검색해서 클릭
      • 버킷 만들기: 주황색 [버킷 만들기] 버튼을 클릭
    • 일반 구성 설정
      • 버킷 이름
        • 전 세계 AWS 사용자 중 나만 쓰는 고유한 이름이어야 함
        • 예: my-django-blog-images-1234 처럼 숫자 섞으면 좋음
      • AWS 리전
        • 아시아 태평양 (서울) ap-northeast-2를 선택
          • 한국 유저들이 가장 빠르게 이미지를 볼 수 있음
    • 객체 소유권 (중요)
      • 기본값인 'ACL 비활성화' 대신 [ACL 됨(ACLs enabled)]을 선택
      • 이유
        • django-storages가 파일을 올릴 때
        • "이 파일은 누구나 볼 수 있게 해줘"라는 권한(ACL)을 부여하기 위해서 필요
    • 이 버킷에 대한 퍼블릭 액세스 차단 설정 (매우 중요)
      • [모든 퍼블릭 액세스 차단]의 체크를 해제
      • "현재 설정으로 인해 이 버킷과 그 안에 있는 객체가 퍼블릭 상태가 될 수 있음을 알고 있습니다."라는 경고창에 체크
      • 이유
        • 블로그 방문자들이 내 썸네일과 이미지를 보려면 이 '차단'을 풀어주어야 함
    • 버킷 만들기
      • 화면 맨 아래 주황색 [버킷 만들기] 버튼을 누르면 완성
  • 과정 이미지

    • S3 서비스 이동 / AWS 리전 선택(ap-northeast-2)
    • 버킷 만들기 / 일반 구성 설정
    • 객체 소유권 / 퍼블릭 액세스 차단 설정
  • 결과


IAM 사용자 및 액세스 키 생성 (S3 출입증 발급하기)

  • Django 서버가 방금 만든 S3 버킷에 파일을 올릴 수 있도록

    • 전용 출입증(Access Key)을 만들어야 함
  • 내 최고 관리자(Root) 계정을 그대로 쓰면 해킹 시 큰일 나기 때문에

    • "S3만 만질 수 있는 알바생"을 하나 고용한다고 생각하면 됨
  • 과정

    • IAM 서비스 이동

      • 화면 맨 위 검색창에 IAM을 검색해서 클릭
    • 사용자 메뉴 이동

      • 왼쪽 메뉴에서 [사용자]를 클릭하고, 오른쪽 위의 주황색 [사용자 생성] 버튼을 누름
    • 사용자 세부 정보 지정

      • 사용자 이름
        • 알아보기 쉽게 적음 (예: django-s3-uploader) → [다음] 클릭
    • 권한 설정 (알바생에게 권한 부여)

      • [직접 정책 연결]이라는 네모 박스를 클릭

      • 아래 검색창에 AmazonS3FullAccess를 검색

      • 검색 결과로 나온 AmazonS3FullAccess 옆의 체크박스를 체크 → [다음] 클릭

      • 고민

        • 실무에서는 딱 내 버킷만 접근하는 권한을 직접 짜주는 것이 가장 안전
        • 하지만 처음 연습시에는 이 설정이 오류 없이 동작하는 가장 확실한 방법
        • 나중에 익숙해지면 권한을 축소하는 것이 좋음
    • 검토 및 생성

      • 내용 확인 후 [사용자 생성] 버튼을 클릭
    • 액세스 키 발급 (출입증 받기 - 아주 중요)

      • 방금 만든 사용자(django-s3-uploader)의 이름을 클릭

      • [보안 자격 증명] 탭을 클릭하고, 아래로 살짝 내려서 [액세스 키 만들기] 버튼을 누름

      • 사용 사례에서 [AWS 외부에서 실행되는 애플리케이션] (또는 기타)을 선택하고 [다음] 클릭

      • 설명 태그는 비워두고 [액세스 키 만들기] 클릭

    • 키 복사 및 보관

      • 화면에 액세스 키(Access Key)비밀 액세스 키(Secret Access Key)가 나타남

      • 경고 🚨

        • 이 창을 닫으면 '비밀 액세스 키'는 두 번 다시 볼 수 없음
        • 바로 이 두 개의 키를 메모장이나 안전한 곳에 복사해 두기
          • 절대 Github 같은 공개된 곳에 올리면 안됨, 요금 폭탄을 맞을 수 있음

코드 도입

settings

import os

INSTALLED_APPS += [
    'storages',  # S3 연동을 위해 설치한 패키지를 활성화합니다.
]

# AWS S3 기본 설정
# .env 파일에서 'AWS_ACCESS_KEY_ID' 값을 엄격하게 가져옵니다. 값이 누락되면 서버 실행 시 즉시 에러를 띄워줍니다.
AWS_ACCESS_KEY_ID = env("AWS_ACCESS_KEY_ID")  

# S3 접근을 위한 '비밀 액세스 키'를 가져옵니다. 외부에 절대 노출되면 안 되는 값이므로 확실하게 검증합니다.
AWS_SECRET_ACCESS_KEY = env("AWS_SECRET_ACCESS_KEY")  

# 이미지가 저장될 실제 '버킷 이름'을 가져옵니다.
AWS_STORAGE_BUCKET_NAME = env("AWS_STORAGE_BUCKET_NAME")  

# 버킷이 위치한 '리전 코드'를 가져옵니다. 
# default 값을 설정해두면 .env에 값이 없을 때 기본값(서울 리전)으로 동작하게 하여 안정성을 높일 수 있음
AWS_S3_REGION_NAME = env("AWS_REGION", default="ap-northeast-2")  

# 추가 옵션 설정
AWS_DEFAULT_ACL = 'public-read' # S3에 업로드된 파일에 접근할 수 있는 기본 권한을 '누구나 읽기 가능'으로 설정(블로그 썸네일이기 때문)
AWS_S3_FILE_OVERWRITE = False # 동일한 이름의 파일이 올라오면, 기존 파일을 덮어쓰지 않고 파일명 뒤에 랜덤한 문자를 붙여서 저장 (안전성 확보)
# S3 주소 체계를 설정 (boto3가 이 형식에 맞춰 이미지 URL을 만들어줌)
AWS_S3_CUSTOM_DOMAIN = f'{AWS_STORAGE_BUCKET_NAME}.s3.{AWS_S3_REGION_NAME}.amazonaws.com'

# Django 미디어 파일 저장소 변경
# 원래는 서버 하드디스크(FileSystemStorage)에 저장하던 것을, 이제부터 S3(S3Boto3Storage)에 저장하라고 장고에게 명령
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'

view

  • swagger에서 이미지 등록 가능하게 하기

from rest_framework.parsers import MultiPartParser, FormParser, JSONParser

class ~ APIView(APIView):

    permission_classes = []
    pagination_class = 
    parser_classes = [JSONParser, MultiPartParser, FormParser]
profile
안녕하세요.

0개의 댓글