TIL-20210117(이미지리사이징)

이미지 리사이징

이미지 리사이징을 하는 여러가지 이유 중 한 가지는 용량 때문이라고 생각합니다.

그럼 왜 용량을 줄이느냐?

보통 유저가 업로드 하는 사진들은 AWS S3와 같은 스토리지에 저장을 하게 되는데

request 요청 수와 용량에 따라 과금이 되기 때문입니다.

리사이징을 하기 위해 생각을 해보면

유저가 사진을 업로드하면 그 사진을 리사이징 하는 것입니다.

하지만 생각해보면 유저가 업로드하는 모든 사진을 리사이징 할 필요는 없습니다.

왜냐하면 유저가 작은 사이즈의 이미지를 올렸을 경우 그 사진은 라사이징 되어 더 작아지기 때문입니다.

그 다음 생각 할 수 있는 것은

일정 넓이 기준으로 이 크기가 넘어가면 리사이징을 진행하는 것입니다.

이렇게 했을 경우의 문제는

가로가 아주 긴 사진, 높이만 긴 사진같은 경우 리사이징을 했을 경우 비율 문제가 생기게 됩니다.

그럼 리사이징을 어떻게 해야할까?

리사이징 유무의 기준이 되는 용량을 정한 뒤 해당 용량 이상일때 리사이징을 진행합니다.

코드로 살펴보면

def resizing_image(image_file):
    image = image_file
    im = Image.open(image)
    output = BytesIO()

    width, height = im.size
    image_size = image.size
    base_size = 1024000  # 리사이징 작업 유무 기준 사이즈 1M
    comp_size = 102400  # 리사이징 작업 결과물 사이즈, 50~200KB 수준으로 압축됨 (50~200KB)
    ratio = math.ceil(math.sqrt((image_size / comp_size)))  # 리사이징 비율
    re_width = math.ceil(width / ratio)  # 리사이징 할 넓이 반올림
    re_height = math.ceil(height / ratio)  # 리사이징 할 높이 반올림

    # 이미지 리사이징
    if image_size > base_size:
        im = im.resize((re_width, re_height))

    if im.mode in ("RGBA", "P"):
        im = im.convert("RGB")  # jpg는 투명도를 표시할 수 없는 파일인데 alpha 값을 저장하려고 할 때
    im.save(output, format='JPEG', quality=75)
    output.seek(0)

    return output

파일이름을 유니크하게 생성을 해줍니다.

왜냐하면 A유저와 B유저가 같은 파일명의 파일을 S3에 업로드 한다고 가정해보면

A유저가 sample.jpg 를 먼저 업로드하고 B유저가 sample.jpg라는 이미지를 업로드 합니다

다른 이미지 파일이지만 파일명이 같아서 b유저가 사진을 보면 A가 올린 이미지가 보여지게 됩니다.

따라서 저는 uuid를 통해 파일명을 유니크하게 생성하여 S3에 업로드 하였습니다.

if request.FILES:
  image = request.FILES['image']
  image_name = str(image.name.split(".")[0])
  image_format = str(image.name.split(".")[-1])
  image.name = f'{image_name}-{uuid.uuid4().hex}.{image_format}'

이미지를 S3와 같은 저장소에 저장할 때 연/월/일로 구분하여 업로드 해주었습니다.

이렇게 해주는 이유는 한 디렉토리 안에 모든 이미지 파일을 넣는 것 보다

디렉토리를 구분하여 저장함으로써 파일 검색을 조금 더 효율적으로 할 수 있기 때문입니다.

object_name = f’images/{year}/{month}/{day}/{image.name}’

참고: post.flow.team/developer/img-resizing-2/

S3의 용량을 줄여보자

  1. 기존 방식 사진업로드 -> Django -> S3 -> 사용자

  2. 구현하고자 한 것 사진업로드 -> Django -> 사진 리사이징 -> S3 -> 사용자

문제점?

사진 크기가 크면 Error..

생각한 원인

  1. 웹서버에서 받을 수 있는 용량 초과

아파치에서 LimitRequestBody 설정으로 최대 용량을 설정할 수 있다.

  1. 응답 지연으로 인한 Error (time out per request)

mod_reqtimeout 에서 설정

  1. 결국.. 사진업로드 -> Django -> 사진 리사이징 -> S3 -> 사용자

업로드 크기제한(6MB)

문제점: 매번 리사이징마다 지연(UX 측면에서 안좋음) -> SKIA 통해 리사이징 시간 단축 시킬 수 있지만..연동 어려움

  1. 더 좋은 방법? 1.원본을 s3에 업로드 유저에게 리사이징 이미지를 줘야하는 경우 resizing server를 따로 둠

  2. webp로 변환 -> 용량 줄어듦

=> ux + 용량 개선

  1. s3용량은 3번이 가장 적음 그러나 UX 측면에서 안좋음

  2. UX, s3 용량은 줄일 수 있지만 3번보다는 s3 용량이 큼

파일을 업로드 할 때 같은 파일이름이 s3에 이미 저장되어 있을 때 s3에 이미 저장되어 있는 이미지를 가져옴

-> 파일 이름뒤에 uuid붙여서 해결

태그:

카테고리:

업데이트:

댓글남기기