FE 개발자가 자주 사용하지만 직접 구현해보는 사람은 많지 않은 썸네일 서버 로직에 대해 정리한 글이다.
회사에서 팀 내에 공유한 문서였는데 쓰는 글이 없어 허전하길래 다시 정리해서 업로드한다.
Thumbnail 썸네일이란?
- 트래픽 문제 → 용량의 문제 → 비용의 문제
- 사용자 경험 (UX) 증대도 있지만 클라우드 비용 감소에 있어 아주 큰 영향을 차지한다.
- 결국 사용자/제공자 모두에게 있어 비용 감소가 주요 목표라고 할 수 있음
- 최근 IOS에서도 webp가 지원되어 (webm은 아직) 많은 사이트에서 썸네일을 webp로 제공하는 추세
- webp/webm: 구글에서 공개한 이미지 코덱(포맷)으로 webp는 정적, webm은 동적(gif) 이미지에 사용됨
- 대부분의 경우 용량을 아주 큰 폭으로 줄일 수 있지만 지원되지 않는 브라우저가 있어 폴백이 필요할 수 있음
썸네일 활용
- 이미지 미리보기, 상품 리스트 등 이미지를 추상적으로 확인할 때 주로 적용
사용자나 브라우저의 확대 및 축소, 그리고 인터렉션 등을 위해 보여지는 이미지의 x2 ~ x3 정도 크기로 사용하는 경우가 많음- ex) 60x60 이미지 → 120x120 썸네일 이미지 로드
- 비디오의 특정 장면 (하이라이트)를 썸네일로 만들어 PV 증대를 유도하는 방안으로도 사용
- 최근 기술의 향상 및 비디오 컨텐츠가 많아짐에 따라 gif, webm을 이용한 '움직이는' 썸네일이 늘어나고 있음
- 트래픽 감소보다는 PV 증대에 집중된 것으로 보임
- 흔히 말하는 '썸네일'과는 차이가 있지만 업계 동향으로 보는 것이 좋을 듯
실제 사례
- 주로 특정 도메인을 할당한 썸네일 API 서버로 구성하여 사용
- URL에 크기를 요청하여 서버에서 썸네일을 찍어낸 후, CDN을 이용하여 캐싱하는 방식이 일반적
- 리전별 CDN 서버가 있을 때 같은 파일을 동시에 썸네일 제작 요청하는 고질적인 문제가 있음
- 예시) 줌 인터넷의 썸네일 서버
- 사랑하는 줌인터넷은 URL 하단에 썸네일의 크기와 주소를 입력하도록 아주 일반적인 방식으로 구현했다.
구현 방법
- 썸네일 클라우드 서비스
- AWS
- 기본적으로는 지원하지 않지만 Lambda를 이용하는 예제가 있음 (구림)
- 람다 트리거를 이용하여 개발하는 경우
- 파일 업로드 -> 트리거링(람다 실행) -> 썸네일 재업로드
- 람다가 썸네일 파일 생성-업로드중 이미지를 로드하지 못하는 문제가 있음
- 람다 자체를 썸네일 서버로 사용하는 경우
- 뒤에서도 설명할 서버 부하, 비디오 썸네일 처리 불가등의 문제가 있을 수 있음
- 람다 트리거를 이용하여 개발하는 경우
- 기본적으로는 지원하지 않지만 Lambda를 이용하는 예제가 있음 (구림)
- Alibaba Cloud
- Video를 포함한 썸네일 제공
- Google Cloud
- Image API를 이용하여 제공
- AWS
직접 구현 (JS 예시)
- 썸네일 서버 처리 Flow
- 1. 특정 크기에 대한 썸네일 요청 (위 줌 인터넷의 썸네일 URL에서의 100x100)
- 2. 썸네일 처리할 이미지 원본 다운로드
- 3. 썸네일 처리 (파일 생성)
- a. 이미지 / 비디오에 따라 구분 처리
- 4. 썸네일 이미지 반환 (Byte)
- a. 반환된 이미지는 CDN에 캐싱
- 5. 썸네일 이미지 삭제
- 파일 다운로드 및 삭제 처리
- 이미지/비디오 데이터를 하드에, 메모리에 직접 올려야 한다는 점을 주의깊게 살필 것
- 파일 다운로드 및 삭제 처리
- 이미지
- 파일의 픽셀 처리를 위해 라이브러리를 주로 사용함 Sharp.js를 가장 많이 사용 (간단함)
- 구글에서 공개한 라이브러리 및 코드를 이용, webp, webm으로 생성하기도 함
- Node.js 진영에도 webp 제작 라이브러리가 굉장히 많음
- webp 특성상 원본보다 용량이 커지는 경우도 있어 확인 필요
- 생성시 소모되는 리소스가 jpeg/png등에 비해 상대적으로 크기 때문에 서버 관리에 어려움이 있음
- 비디오
- 비디오 파일의 특정 시간을 스크린샷 촬영, 썸네일로 제작
- ffmpeg를 이용하여 썸네일 제작
- ffmpeg는 OS를 타게팅하여 빌드해 사용하는 '프로그램'
- 비디오의 특정 시간을 지정하여 스크린샷을 찍어 저장, 해당 이미지 파일을 다시 가공하는 방식
- 스크린샷을 이용하여 썸네일 후처리를 하는 경우, 그에 맞춰 비동기적으로 파일을 삭제하는 로직이 필요
- 따라서 Node.js에서 사용하기 위해 child process로 실행시켜야 함 (spawn)
- 직접 ffmpeg 프로세스를 관리하기는 매우 어려우기에 fluent-ffmpeg 와 같은 라이브러리를 주로 사용
- ffmpeg 스폰-플래그 명령어를 래핑한 라이브러리로 메소드 체이닝을 이용해 간단하게 프로그램 사용 가능
하지만 스마트한 라이브러리는 아니기에 ffmpeg 경로 환경 변수 설정 등 처리가 필요함
- OS별로 빌드된 ffmpeg를 사용하여야 하므로 프로젝트에 OS별 ffmpeg를 추가하여야 함
- M1 맥북과 같이 CPU, OS가 특별한 경우 다른 환경 세팅이 필요해짐
- ffmpeg는 OS를 타게팅하여 빌드해 사용하는 '프로그램'
- 이미지 썸네일과 차원이 다른 리소스 소모
- 비디오를 실제 메모리에 올리게 되므로 메모리 누수 및 초과 사용에 항상 주의가 필요함
썸네일 서버 관리 주의점
- 직접 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 버전)
- 엄청나게, 엄청나게 심각한 리소스 소모로 실 서비스 적용은 불가능에 가까움
'ECMAScript | TypeScript' 카테고리의 다른 글
인클루시브 디자인 패턴을 읽고 (0) | 2022.09.08 |
---|---|
Vue.js 2.x SSR시 computed 객체와 template 렌더링 문제 (0) | 2022.07.30 |
FE개발자로서 못해준 이야기 2 - 컴포넌트 (3) | 2022.01.18 |
FE개발자로서 못해준 이야기 1 - 프로젝트 (1) | 2022.01.13 |
Spring boot + Vue 프로젝트 생성하기 (0) | 2018.08.17 |