Image Optimizer를 통해 이미지 렌더링을 최적화 해보자

정민·2022년 12월 9일
0

우리 서비스에서 가장 많이 발생 될 것이라 예상되는 이미지 I/O 비용… 해결하고 싶다… 😥

XOXO 는 이미지 위주의 SNS 서비스이기 때문에, 이미지를 최적화하는 것에 있어서 많은 신경을 써야만 했습니다.

또한 각 피드와 포스팅에 대한 썸네일 리스트를 보여주는 화면이 존재했는데, 해당 썸네일의 원본 이미지를 보여주는 것은 비효율 적이라 생각하였기 때문에, 각 피드와 포스팅의 썸네일을 따로 Object Storage 에 저장해야 하는 상황을 마주치게 되었습니다.

→ 그러던 중 CDN에 대한 것을 찾아보라는 멘토님의 조언이 있었고, 이후 CDN과 Image Optimizer에 대해 학습할 수 있었습니다.

배경 지식

Image CDN? 그냥 CDN과 다른 걸까?

  • CDN Content Delivery Network 서버와 사용자 사이의 물리적 거리를 줄여 콘텐츠 로딩에 소요되는 시간을 최소화 시킨다.
    • CDN이 필요한 경우 인터넷을 통해 비즈니스를 운영하거나 웹 사이트에서 그래픽 이미지, 동영상 파일 등의 콘텐츠를 제공한다면 CDN 서비스를 이용할 필요가 있습니다. CDN은 동영상 스트리밍이나 온라인 게임, 대용량 파일 전송, 그리고 해상도가 높아 용량이 큰 이미지를 다루는 쇼핑몰, 포털 사이트 등에서 안정적인 서비스 제공을 위해 활용되고 있습니다. 하지만 특정 국가나 지역만을 타깃으로 하는 웹 서비스를 운영한다면 CDN 서비스를 활용할 필요가 없습니다. 이 경우 CDN을 이용하면 오히려 불필요한 연결 지점이 늘어나 웹 사이트의 성능 저하를 불러올 수 있기 때문입니다.
  • Image CDN 이미지에 특화된 CDN 이미지를 사용자에게 보내기 전에 특정 형태로 가공하거나 혹은 사이즈를 줄인다거나 이미지 포멧을 바꾼다거나 하는 등의 처리과정을 거쳐 사용자에게 이미지를 전달해주는 것 일반적인 이미지 CDN에서 제공하는 주소는 다음과 같이 이루어져 있다. 🔗http://cdn.image.com?src={**image_src**}&width=240&height=240 이와 같이, 이미지 CDN 서버 주소에 쿼리스트링으로 가져올 이미지의 주소, 그리고 필요에 따라 변경하고자 하는 형태를 명시해 줌으로써, 내가 명시한 이미지를 변환된 상태로 받아올 수 있다.

기술 소개

Image Optimizer가 그래서 뭐지?

Naver Cloud Platform 에서 제공하는 Image CDN 서비스이다!

  • Client
    • 쿼리를 통해 CDN에게 이미지 변환 요청
  • CDN
    • Image Optimizer에게 이미지 변환 요청을 전달
    • Image Optimizer에서 변환된 이미지를 받아 Client에게 전달
  • Image Optimizer
    • 이미지 변환
  • Object Storage
    • 원본 이미지를 저장

클라이언트에서 이미지 업로드 하기 위한 Object Storage 연결

1️⃣ 버킷 생성

2️⃣ API 연결

https://api.ncloud-docs.com/docs/common-objectstorageapi-objectstorageapi

이제 진짜 Image Optimizer 생성 해보자!

1️⃣ 생성

  • Project 생성 클릭

  • 기존에 생성해놨던 (Image Optimizer와 연결할) Object Storage 를 선택한다.

  • 서비스 프로토콜 / 서비스 도메인 / 캐시 만료 / Custom Header 설정
  • Log 수집 설정

2️⃣ 설정

  • 변환룰 설정

우리가 이미지를 변환하고 싶은 룰을 생성한다. 
  • util/imageQuery.ts
    ...
    const getThumbSize = (type: string, windowWidth: number) => {
      const level = Math.floor(windowWidth / 100)
      switch (type) {
        case 'postingLQ' :
          if (level >= 5) return 50
          if (level >= 4) return 40
          return 30
        case 'posting' :
          if (level >= 5) return 500
          if (level >= 4) return 400
          return 300
        case 'feed' :
          if (level >= 4) return 240
          if (level >= 3) return 180
          return 120
        case 'feeds' :
          if (level >= 4) return 120
          if (level >= 3) return 90
          return 40
        default :
          return 300
      }
    }
    ...
    각 사용자의 window.innerWidth 에 따라 다른 사이즈의 크기를 반환할 수 있도록 util 을 구현한다. 이후에 해당 사이즈를 CDN주소/ObjectStorage파일경로/쿼리 로 요청하면 된다!
    const getQueryString = (type: string) => {
      const windowWidth = window.innerWidth
      const size = getThumbSize(type, windowWidth)
      return `?type=m&w=${size}&h=${size}`
    }
    
    const getPostingThumbUrl = (url: string) => {
      return `${process.env.REACT_APP_CDN_URI as string}/` + url + `${getQueryString('posting')}`
    }
    
    위의 getThumbSize 를 통해 받아온 이미지의 사이즈를 쿼리스트링으로 만든 뒤, 우리가 사용하고 있는 CDN 주소와 붙여 사용하면 정상적으로 변환된 이미지들을 실시간으로 불러올 수 있다.

성과

Image Optimizer 적용 전

화면 크기와 상관없이, 원본 이미지(약 478kb)를 받아온다.

Image Optimizer 적용 후

화면 크기에 알맞게 리사이징된 이미지(약 7kb)를 받아온다.

적용 전


적용 후

비용 절감 : 478kb → 7kb (약 60배 개선)

다운로드 속도 개선 : 64.23ms → 2.45ms (약 30배 개선)

profile
괴발개발~

0개의 댓글