ECMAScript | TypeScript

썸네일과 썸네일 서버 로직에 대해

partner_jun 2022. 4. 3. 14:34

FE 개발자가 자주 사용하지만 직접 구현해보는 사람은 많지 않은 썸네일 서버 로직에 대해 정리한 글이다.

회사에서 팀 내에 공유한 문서였는데 쓰는 글이 없어 허전하길래 다시 정리해서 업로드한다.


 

Thumbnail 썸네일이란?

위키백과의 설명 중 하이라이팅 한 저 부분이 중요하다

  • 트래픽 문제 → 용량의 문제 → 비용의 문제
  • 사용자 경험 (UX) 증대도 있지만 클라우드 비용 감소에 있어 아주 큰 영향을 차지한다.
    • 결국 사용자/제공자 모두에게 있어 비용 감소가 주요 목표라고 할 수 있음
  • 최근 IOS에서도 webp가 지원되어 (webm은 아직) 많은 사이트에서 썸네일을 webp로 제공하는 추세
    • webp/webm: 구글에서 공개한 이미지 코덱(포맷)으로 webp는 정적, webm은 동적(gif) 이미지에 사용됨
    • 대부분의 경우 용량을 아주 큰 폭으로 줄일 수 있지만 지원되지 않는 브라우저가 있어 폴백이 필요할 수 있음

 

썸네일 활용

  • 이미지 미리보기, 상품 리스트 등 이미지를 추상적으로 확인할 때 주로 적용
    사용자나 브라우저의 확대 및 축소, 그리고 인터렉션 등을 위해 보여지는 이미지의 x2 ~ x3 정도 크기로 사용하는 경우가 많음
    • ex) 60x60 이미지 → 120x120 썸네일 이미지 로드
  • 비디오의 특정 장면 (하이라이트)를 썸네일로 만들어 PV 증대를 유도하는 방안으로도 사용
    • 최근 기술의 향상 및 비디오 컨텐츠가 많아짐에 따라 gif, webm을 이용한 '움직이는' 썸네일이 늘어나고 있음
    • 트래픽 감소보다는 PV 증대에 집중된 것으로 보임
    • 흔히 말하는 '썸네일'과는 차이가 있지만 업계 동향으로 보는 것이 좋을 듯

 

실제 사례

 

구현 방법

  • 썸네일 클라우드 서비스
    • AWS
      • 기본적으로는 지원하지 않지만 Lambda를 이용하는 예제가 있음 (구림)
        • 람다 트리거를 이용하여 개발하는 경우
          • 파일 업로드 -> 트리거링(람다 실행) -> 썸네일 재업로드
          • 람다가 썸네일 파일 생성-업로드중 이미지를 로드하지 못하는 문제가 있음
        • 람다 자체를 썸네일 서버로 사용하는 경우
          • 뒤에서도 설명할 서버 부하, 비디오 썸네일 처리 불가등의 문제가 있을 수 있음
    • Alibaba Cloud
      • Video를 포함한 썸네일 제공
    • Google Cloud
      • Image API를 이용하여 제공

 

직접 구현 (JS 예시)

  • 썸네일 서버 처리 Flow
    • 1. 특정 크기에 대한 썸네일 요청 (위 줌 인터넷의 썸네일 URL에서의 100x100)
    • 2. 썸네일 처리할 이미지 원본 다운로드
    • 3. 썸네일 처리 (파일 생성)
      • a. 이미지 / 비디오에 따라 구분 처리
    • 4. 썸네일 이미지 반환 (Byte)
      • a. 반환된 이미지는 CDN에 캐싱
    • 5. 썸네일 이미지 삭제
      • 파일 다운로드 및 삭제 처리
        • 이미지/비디오 데이터를 하드에, 메모리에 직접 올려야 한다는 점을 주의깊게 살필 것

 

  • 이미지
    • 파일의 픽셀 처리를 위해 라이브러리를 주로 사용함 Sharp.js를 가장 많이 사용 (간단함)
    • 구글에서 공개한 라이브러리 및 코드를 이용, webp, webm으로 생성하기도 함
      • Node.js 진영에도 webp 제작 라이브러리가 굉장히 많음
    • webp 특성상 원본보다 용량이 커지는 경우도 있어 확인 필요
    • 생성시 소모되는 리소스가 jpeg/png등에 비해 상대적으로 크기 때문에 서버 관리에 어려움이 있음

Sharp.js를 이용하여 이미지 버퍼를 리사이징하는 예시 코드

 

  • 비디오
    • 비디오 파일의 특정 시간을 스크린샷 촬영, 썸네일로 제작
    • ffmpeg를 이용하여 썸네일 제작
      • ffmpeg는 OS를 타게팅하여 빌드해 사용하는 '프로그램'
        • 비디오의 특정 시간을 지정하여 스크린샷을 찍어 저장, 해당 이미지 파일을 다시 가공하는 방식
        • 스크린샷을 이용하여 썸네일 후처리를 하는 경우, 그에 맞춰 비동기적으로 파일을 삭제하는 로직이 필요
      • 따라서 Node.js에서 사용하기 위해 child process로 실행시켜야 함 (spawn)
        • 직접 ffmpeg 프로세스를 관리하기는 매우 어려우기에 fluent-ffmpeg 와 같은 라이브러리를 주로 사용
        • ffmpeg 스폰-플래그 명령어를 래핑한 라이브러리로 메소드 체이닝을 이용해 간단하게 프로그램 사용 가능
          하지만 스마트한 라이브러리는 아니기에 ffmpeg 경로 환경 변수 설정 등 처리가 필요함
      • OS별로 빌드된 ffmpeg를 사용하여야 하므로 프로젝트에 OS별 ffmpeg를 추가하여야 함
        • M1 맥북과 같이 CPU, OS가 특별한 경우 다른 환경 세팅이 필요해짐
    • 이미지 썸네일과 차원이 다른 리소스 소모
      • 비디오를 실제 메모리에 올리게 되므로 메모리 누수 및 초과 사용에 항상 주의가 필요함

실행 환경별로 ffmpeg를 로드하는 예시 (production일 때 리눅스용 ffmpeg 로드)
00:00에 해당하는 비디오 스크린샷을 저장하는 예시 코드

 

썸네일 서버 관리 주의점

  • 직접 CPU 연산, File IO를 이용하기 때문에 서버 리소스 소모가 매우 심각함
  • t3.small급에서 보통 30~50ms 소요됨, webp의 경우 100ms 이상 소요
    • 특히 메모리 누수까지 발생할 수 있음 (Next/image 에서도 주기적으로 이슈업됨)
    • Node.js의 event loop의 특성과 맞지 않아 TPS 급락의 원인
    • AWS와 같은 클라우드 서비스에서는 순간적인 리소스 peek에 따라 서버를 다운시켜버리는 문제가 있음
      • 자세한 내용은 AWS의 토큰(번호표) 제도 등에 확인

 

결론

  • 구현 및 관리가 어렵다
  • 직접 구현하면 CPU 사용량, 메모리 누수, 다수 CDN 서버의 동시요청 등 고려할 요소가 많음
  • Node.js의 event loop와 성능을 제한하는 클라우드 특성상 어플리케이션이 죽어버릴 확률이 높음
  • 카카오, 네이버 등 서비스 기업 모두에서 발생하는 문제
    • 주말에 뉴스나 판에서 이미지가 노출되지 않는 이유는 십중팔구 썸네일 문제임
  • 하지만 너무나도 유용하기에 필요하다
    • 회사에서 누군가는 짊어져야 할 어플리케이션

 

참고

  • 업 스케일링(역 썸네일)
    • 특정 분야(2d)에 관심있는 사람은 이미 잘 알고 있는 waifu2x 등을 이용하여 업스케일링
    • 언어별로 라이브러리 개발되어 제공중 (Node.js 버전)
    • 엄청나게, 엄청나게 심각한 리소스 소모로 실 서비스 적용은 불가능에 가까움