프로젝트/당일

[FastAPI] AWS S3를 활용한 이미지 저장

cks._.hong 2024. 6. 1. 10:15

AWS S3를 활용한 이미지 저장 왜 궁금했을까❓

당일 서비스의 경우 사용자가 입력한 일기를 대표하는 이미지를 생성하여 선택할 수 있게 한다. 이미지를 생성한다면 서버에 보관을 했다가 사용자가 필요할 때 사용할 수 있도록 해야한다. 그래서 이미지를 저장하기 위해 AWS S3를 사용하기로 결정했다.

 

AWS S3를 사용해야 하는 이유?

  • S3는 데이터 저장 공간이 무제한이라는 점에서 확장성이 매우 우수
  • S3는 여러 Region에 데이터를 저장하고 있기 때문에 데이터 손실이 일어날 확률이 거의 제로
  • 사용하는 만큼 비용을 지불하기 때문에 프로젝트성이 강한 당일 서비스에 적합
  • S3에서 다양한 데이터 암호화 방식을 제공
위 이유 외에도 다양한 장점이 많아서 AWS S3를 당일 서비스에 적용시켜 보려고 한다.

 

FastAPI와 AWS S3 이미지 저장

1. 버킷 만들기

2. 버킷 엑세스 권한 설정

  • S3에 있는 이미지를 사용해야 하기 때문에 외부에 공개해야 하므로 체크 해제
  • 이후, 버킷 만들기 클릭

3. 퍼블릭 정책 생성

  • 버킷 클릭 후, 권한 탭 클릭
  • 버킷 정책 편집
  • 정책 생성기를 통해서 프로젝트에 맞는 정책 설정
{
	"Version": "2012-10-17",
	"Id": "Policy1714090463840",
	"Statement": [
		{
			"Sid": "Stmt1714090460253",
			"Effect": "Allow",
			"Principal": "*",
			"Action": "s3:GetObject",
			"Resource": "arn:aws:s3:::ssafy-today/*"
		}
	]
}

 

4. IAM 설정

  • IAM 검색 후, 사용자 생성 (엑세스 키는 추후 FastAPI에서 사용해야 하므로 따로 저장)
  • 사용자 클릭 후, 권한 추가
  • 직접 정책 연결 선택 후, S3 Full Access 선택

 

5. FastAPI 연결

  • python에서 AWS S3를 사용하기 위해서는 boto3라는 aws sdk를 사용
pip install boto3
  • 우선, boto3를 설치한다.
def connect_s3():
    print("=================== S3 connect start ===================")
    s3 = boto3.client(
        "s3",
        aws_access_key_id=os.getenv("AWS_S3_ACCESS_KEY"),
        aws_secret_access_key=os.getenv("AWS_S3_PRIVATE_KEY")
    )
    app.utils.global_vars.s3 = s3
    print("=================== S3 connect start ===================")
  • 4번 과정에서 저장해놨던 access_key와 private_key를 활용하여 S3 클라이언트와 연결
# 이미지 저장
for image in images:
    # 경로 및 파일명 지정
    file_name = f"{str(uuid.uuid4())}.jpg"
    s3_key = f"temp/{file_name}"

    # Convert PIL Image to JPG
    img_byte_arr = io.BytesIO()
    image.save(img_byte_arr, format='JPEG')
    img_byte_arr.seek(0)
        
    # S3 Image Upload
    try:
        s3.upload_fileobj(img_byte_arr, os.getenv("AWS_S3_BUCKET"), s3_key)
        images_url.append(os.getenv("AWS_S3_URL") + s3_key)
    except Exception as e:
        raise HTTPException(status_code = 500, detail=f"S3 upload failed: {str(e)}")
    return images_url
  • SDXL을 통해서 생성한 4가지 화풍의 이미지에 UID를 부여하고 SDXL을 통해서 추출한 이미지는 PIL 파일이므로 JPG로 변환 과정이 필요하다.
  • upload_fileobj(이미지 파일, 버킷 이름, s3 키 값)을 이용해서 S3에 저장한다.
  • 이후, images_url에 저장된 S3 경로를 추가하고 최종적으로 해당 값을 반환하면 사용자는 이미지를 보고 선택할 수 있게 된다.