5 C
New York
금요일, 12월 26, 2025

Buy now

Home Blog Page 261

[2020 슈퍼볼 광고] 아마존과 구글이 스마트 스피커를 접근하는 방법

0

이번 주말부터 미국 슈퍼볼 시즌이 본격적으로 시작되었죠. 슈퍼볼과 함께 항상 관심을 모았던 것이 슈퍼볼 광고인데요.

미디어 지형이 상당히 바뀌었지만 TV 중심의 슈퍼볼 광고는 아직도 건재합니다.

최근 트렌드라면 아마존이나 애플과 같은 IT 회사들이 적극적으로 슈퍼볼 광고에 뛰어들었다는 점입니다.

이번 슈퍼볼 광고에 스마트 스피커를 주제로 한 아마존과 구글이 광고를 공개했는데요. 그들은 접근 방법이 매우 다릅니다.

누가 더 슈퍼볼 광고로서 성과를 낼까요?

아마존, Before Alex

아마존은 스마트 스피커 사용 시나리오를 보여주면서도 이를 예전 역사속에서 과거 사람들이면 어떻게 했을까라는 상황 설정으로 상당한 유머와 재미를 통해서 스마트 스피커의 장점을 잘 보여줍니다.

Ellen DeGeneres와 Portia de Rossi는 외출하려고 하고 있습니다.

DeGeneres는 집을 떠나기 전 Echo Dot에게 집안 온도를 낮추라고 이야기 합니다.

그리고 나서 DeGeneres는 알렉사가 나오기전에 과거 사람들을 어떻게 했을까 의문을 품습니다.

그리고 과거 몇가지 사례가 등장하면 웃음을 줍니다.

벽난로가 피워져 있는 과거에서 온도를 낮추기 위해 하인은 벽나로에서 타고 있던 장작을 꺼내 밖으로 던져 버립니다.

여왕은 신하에게 재미있는 농담을 들려달라고 합니다. 신하가 시덥잖은 농담을 늘어 놓자 여황은 “Next”..라고 다른 농담을 주문합니다.

마차를 타고가면서 옆사람에게 내가 제일 좋아하는 노래를 시킴니다….

과거에는 이런 일들을 하려면 하인들, 신하들을 시켜야 했습니다. 그리고 그리 (콘텐츠가) 마음에 들지도 앟았죠..

이제 알렉사만 있으면 이 모든 것을 편하게 할 수 있다고 이야기하는 것일까요? 알렉사를 통한 고품격 삶이 우리 생활 곳곳에서 일부가 되어 있다는 것을 과거로의 여행을 통해서 잘 보여주고 있는 것이 아닐까요?

알렉사와 함께 과거로의 여행은 즐거웠습니다.

https://youtu.be/RF9t2rFmTVE

구글, Loretta

구글에게 스마트 스피커는 단순한 조력자가 아님니다. 단순 디바이스가 아니라 마음을 읽고 위로를 전해고 가장 적절한 대안을 이야기해 줄 삶의 동반자입니다.

이번 구글의 슈퍼볼 광고는 감정에 직접 호소합니다.

처음에는 굉장히 논리적으로 보였지만 죽은 아내 Loretta에 대한 추억을 소환하면서 슬픔을 주면서 스마트 스피커가 주는 능력에 소름끼쳐 할 수 있습니다.

https://youtu.be/6xSxXiHwMrg

구글의 광고는 “로레타(Loretta)”라는 제목으로 공개되었습니다.

나이든 노인은 구글 어시스턴트에게 오래 전에 사망한 미만인에 대한 추억을 요청합니다.

구글 어시스턴트는 두사람의 결혼 생활동안의 일련의 커플 사진들을 보여줍니다. 그러면서 아내가 알래스카를 사랑했고, 남편의 콧수염을 싫어했다는 것도 상기시켜줍니다.

여기에는 구글이 잘 할 수 있는 정보 검색과 인터넷의 정보 분류를 통해서 미처 개인이 깨닫지 못하는 미묘한 또는 명확한 사실조차 기억해 냅니다.

나보다 나와 내 아내를 더 잘아는 굉장한 존재가 나타난 것입니다. 인터넷 감시가 일상화된 요즘 구글의 광고는 슬프면서도 두려움을 느끼게 하는 이유가 여기에 있습니다.

이 광고는 구글 직원의 조부모 이야기를 바탕으로 광고로 제작한 것이라고 합니다.

참고, 애플의 스마트 스피커 광고, 홈팟

조금 오래되었지만 2018년 칸 광고제 그랑프리를 수상했던 애플 홈팟 광고 Welcome Home을 다시 소환해 봅니다.

아마존이나 구글이나 여기에 비하면…

[실적 차트] 테슬라 연도별 실적 트렌드 – 매출, 이익, 전기차 판매 등

0

요즘 주식 시장에서 테슬라가 아주 잘 나가죠.

테슬라 시가총액이 미국 내 주요 플레이어인 GM이나 포드를 제친 것을 물론 포드나 GM을 합한 것보다 더 많은 시총을 가진 업체가 되었나 싶더니만 이제는 도요타에 이어 세계 2대 자동차 업체가 되었습니다. (시가총액 기준)

그래서 테슬라가 이렇게 주식 시장에서 잘 나가는 이유를 살펴보기 위해서 테슬라의 주요 실적을 살펴 보았습니다.

Executive Summary

테슬라 연도별 실적을 검초한 결과를 아래와 같이 정리할 수 있었습니다.

  • 테슬라는 2019년 246억 달러 매출을 올려, 전년 비 15% 성장에 그쳤습니다.
    예전 7~80% 성장에 비해서는 초라한 수치입니다.
  • 2019년 테슬라는 36.8만대를 판매했고, 이는 전년 비 50% 증가한 것이고 테슬라가 목표로 삼았던 31.5만대보다 훨씬 높은 수치입니다.
  • 그러나 테슬라 매출과 손익을 견인했던 모델 S와 X 판매는 연간 10대 수준에서 6.7만대 수준으로 크게 감소하고 Mass 시장을 겨냥했던 모델 3 판매는 30만대 수준으로 급증했습니다.
    결국 평균 판매 단가를 떨어뜨려 판매가 크게 증가했으나 매출은 15% 증가에 그치는 이유가 되었습니다.
  • 테슬라는 여전히 적자에 허덕이고 있습니다. 2019년 8.6억 달러 적자
    그러나 2018년과 2019년 일부 분기에서는 오랜 적자를 깨고 흑자를 실현했고, 2019년 처음으로 연간으로 총이익(Gross Profit)은 흑자 전환하는 등 유의미한 결과들이 나오고 있습니다.
  • 테슬라 흑자 전환 가능성은 생산량이 급증하면서 규모의 경제와 생산 능력과 생산 기술이 안정화되면서 생산비가 줄어들고 있기 때문입니다.
  • 주식 시장에서 테슬라 주가가 급증하는 것은 2020년이후 중국 상하이 공장이 안정화되고 독일 베를린 공장과 북미 신공장이 본격 가동되면서 충분한 공급 능력이 확보되고, 기대하던 모델 Y가 본격 생산되는 등 라인업이 강화되어 시장 지배력이 더욱 강화될 것으로 보기 때문으로 추정합니다.

1. 매출 및 매출 성장율 추이

테슬라 매출을 연도별로 살펴보면 흥미로운 현상을 방견할 수 있습니다. 그것은 2019년 매출 성장율이 거의 정체 수준인데요.

이는 테슬라에 대해서 들었던 엄청난 이야기에 비해서 실망스러운 결과라는 것이 처음 받은 느낌 이었습니다.

뭐 곰곰히 생각해보면 다르게 생각할 수 있는 부문도 있겠지만 매출 자체 그리고 성장율만 본다면 고개가 갸우뚱 해집니다.

2019년 테슬라는 246억 달러 매출을 올렸고, 이는 전년 비 15% 성장에 그쳤습니다.

2019년 매출 성장율 15% 성장이 어떻냐고 반론할 수 도 있습니다.
그러나 최근 3년간 7~80%대 성장을 구가해온 테슬라로서는 쉽게 이해가지 않는 것도 사실
이죠. 아마도 다른 데이타를 더 살펴바야 할듯 합니다.

테슬라 연도별 매출액 추이( ~ 2021년), Tesla yearly Revenue,, Graph by Happist
테슬라 연도별 매출액 추이( ~ 2021년), Tesla yearly Revenue,, Graph by Happist

2. 테슬라 전기차 판매 추이

그러면 테슬라의 전기차 판매는 어떻까요? 테슬라 전기차 판매야말로 테슬라 비지니스 모델의 전부라고도 할 수 있으니 매우 중요한 지표임에 틀림이 없습니다.

다행이 테슬라 전지차 판매는 시장의 기대를 충족하고 있고, 테슬라가 목표했던 목표를 충분히 달성하고 있습니다.

2019년 테슬라는 36.8만대를 판매(Delivery 기준)했습니다. 이는 전년 비 50% 증가한 것이고 테슬라가 목표로 삼았던 31.5만대보다 훨씬 높은 수치입니다.

테슬라 연도별 전기차 판매( 딜리버리 기준) 추이, Tesla yearly Deliveries, Graph by Happist
테슬라 연도별 전기차 판매( 딜리버리 기준) 추이, Tesla yearly Deliveries, Graph by Happist

비록 증가율 측면에서 모델 3가 본격적으로 생산되기 시작한 2018년의 138% 성장보다는 둔화되었지만 여전히 높은 수준입니다.

더우기 2020년에는 모델 Y가 본격 생산을 시작하고, 상하이 공장과 독일 공장이 본격적으로 가동학 시작하면 테슬라 공급 능력은 시장의 기대를 훨씬 더 뛰어 넘을 것으로 보입니다.

테슬라 생산 공장 및 생산 모델 현황 및 계획, table by Tesla
테슬라 생산 공장 및 생산 모델 현황 및 계획, table by Tesla

3. 테슬라 모델별 판매 추이

조금 더 자세하게 살펴보기 위해 테슬라 모델 판매 추이를 살펴보았습니다.

그동안 테슬라 손익을 지탱했고, 테슬라 브랜드를 견인해왔던 모델 S와 X 판매는 연간 10대 수준에서 6.7만대 수준으로 크게 감소하고 Mass 시장을 겨냥했던 모델 3 판매는 30만대 수준으로 급증했습니다.

이는 대당 단가가 크게 떨어지는 역효과를 냈고, 그 덕분에 테슬라 전기차 판매는 50% 증가했지만 매출은 15% 증가 그치는 현상으로 나타났다는 생각입니다.

테슬라 연도별 프리미엄 모델(모델 S+X)과 모델 3와 모델 Y 딜리버리 추이, Tesla yearly Deliveries, Graph by Happist
테슬라 연도별 프리미엄 모델(모델 S+X)과 모델 3와 모델 Y 딜리버리 추이, Tesla yearly Deliveries, Graph by Happist

4.테슬라 손익 추이

테슬라는 회사 설립 후 한번도 이익을 내지 못한 것으로도 유명합니다. 드렇기 때문이 테슬라 주가는 비이성적으로 높다는 비판이 많았죠.

연도별로 테슬라 손익을 살펴보면 이런 지적은 타당합니다.
그러나 2018년과 2019년에 걸쳐 유의미한 결과가 나타나기 시작했다는 점이 흥미롭습니다.

아래는 분기별 순이익 추이를 그려본 것인데요. 2018년과 2019년 일부 분기에서는 오랜 적자를 깨고 흑자를 실현하고 있습니다.

테슬라 연도별 순이익 추이 ~ 2021년), Tesla Yearly Net Income, Grapg by Happist
테슬라 연도별 순이익 추이 ~ 2021년), Tesla Yearly Net Income, Grapg by Happist

그런 관점에서 테슬라의 연도별 총이익을 살펴보면 2019년 처음으로 0.65억 달러 흑자를 기록했다는 것을 알 수 있습니다. 크지는 않지만 연간 기준으로 총이익이지만 적자를 면했다는 점은 긍정적으로 볼 수 있죠.

테슬라 연도별 매출총이익 및 매출초이익률 추이( ~ 2021년), Tesla yearly Gross Profit & Gross profit Margin, Grapg by Happist
테슬라 연도별 매출총이익 및 매출초이익률 추이( ~ 2021년), Tesla yearly Gross Profit & Gross profit Margin, Grapg by Happist

이에 따라 연간 순이익도 적자가 줄고 순이익율도 -4%로 개선(?)되었습니다.

테슬라 연도별 순이익 및 순이익률 추이( ~ 2021년), Tesla yearly Net Income & Net Margin, Graph by Happist
테슬라 연도별 순이익 및 순이익률 추이( ~ 2021년), Tesla yearly Net Income & Net Margin, Graph by Happist

5. 테슬라 영업이익률 추이

테슬라 연도별 영업이익 및 영업이익률 추이( ~ 2021년), Tesla yearly Operating Income & Operating Margin, Graph by Happist
테슬라 연도별 영업이익 및 영업이익률 추이( ~ 2021년), Tesla yearly Operating Income & Operating Margin, Graph by Happist

참고

천하의 아마존도 오프라인에서 고전하다 – 2019년 4분기 실적을 읽는 7가지 시사점

0

오랜만에 아마존 실적을 정리해 보고, 아마존 실적에서 읽을 수 있는 몇가지 시사점을 정리해 봅니다.

2019년 아마존의 주가는 MS나 구글에 비해서 제대로 평가받지 못했죠. 그리고 이번 2019년 4분기 실적 발표 후 주가가 폭등해 시가총액 1조달러를 넘었습니다. 뭐 바로 다시 밀렸지만요.

Amazon.com Announces Fourth Quarter Sales up 21% to $87.4 Billion

Executive Summary

2019년 아마존 실적에 대해서 저는 이렇게 평가합니다.

  • 아마존 전체 매출 성장율이 둔화되었습니다.
    (4분기 아마존 매출 874억 달러로 전년 비 21% 성장, 33억 달러의 순익을 달성래 순이익율 3.7%로 양호한 손익 추세를 이어 갔음)
  • 아마존이 그동안 심혈을 기울였던 오프라인 공략이 여의치 않습니다. 오프라인 매출은 오히려 감소하고 있습니다.
    (4분기 매출 43.6억 달러로 전년비 -1% 감소)
  • 반면 온라인 성장세는 여전하고 오히려 성장세가 더 커졌습니다.
    ( 2019년 4분기 전년 비 14.7% 성장, 전분기 20.6%보다는 다속 하락했지만 아직 상승 추세 유지)
  • 아마존의 차세대 비지니스라고 주목 받고 있는 서브스크립션 서비스 부분은 여전히 성장하나 성장율은 둔화되었습니다.
    2019년 4분기 아마존 프라임 회원수가 1.5억명이 넘었습니다.
    (4분기 매출 52억 달러로 전년 동기 비 32.2% 증가, 예전의 60%대 성장에는 다소 미치지 못하지만 2019년 3~40%대 꾸준히 성장하고 있음)
  • 광고 비지니스 등은 여전히 높은 성장을 유지했지만 성장율은 다소 누그러짐
    (광고 부문이 포함된 기타 부문 매출 48억 달러로 전년 비 41% 성장,
    이전에 100% 넘던 시기에 비해서 둔화된 것이지만 여전히 40%대 성장율을 유지하면서 고성장 동력을 이어가고 있음)
  • 아마존의 화수분이라 할 수 있는 아마존 웹 서비스 부문도 지속 성장하면서도 높은 영업이익율을 유지하고 있습니다.
    (4분기 매출 100억 달러로 전년비 34% 성장, 영업이익 26억 달러로 영업이익율 26% 기록)
  • 아마존은 미국 내에서는 엄청난 성과를 내고 있지만, 글로벌 비지니스는 각 지역의 로컬 업체와의 경쟁하면서 좀처럼 튼 성과를 내지 못하고 있습니다.
    (4분기 매출 238억 달러로 전년 비 14.3% 성장에 그쳤고 여전히 6억 달러의 적자)

아마존의 전반적 트렌드는 2018년 4분기 실적 분석 시 언급했던 내용과 크게 다르지 않습니다. 그래서 이번 2019년 4분기 실적도 비슷한 논조가 유지될 것입니다.

1. 천하의 아마존도 오프라인에서는 고전하다.

아마존은 온라인을 석권하고 오래전부터 오프라인 공략에 심혈을 기울려 왔죠.

그러나 홀푸드를 인수한 이후 아마존은 유의미한 여러 전략들이 수행되었음에도 오프라인에서의 성과는 매우 미흡합니다.

2019년 4분기 아마존 오프라인 실적은 43.6억 달러로 전년 동기 비 -1% 역성장했습니다.

연도별 4분기 매출을 비교해 보죠. 처음 제대로된 오프라인 매출을 발표했던 2017년 4분기 45.2억 달러에서 2018년 4.4억 달러 그리고 2019년 43.6억 달러로 매년 조금씩 조금씩 매출이 하락하고 있습니다.

계절적인 요인을 살펴보기 위해 다른 분기의 매출을 비교해 보아도 전년 동기 비 나이지는 경향이 없습니다.

홀푸드를 확장하고, 새로운 소매점을 확장하고 있지만 아직 외형적으로 ㅅㅇ과를 못내고 있습니다. 이익의 문제가 아닌 매출 규모의 문제이기 때문에 걱정스러운 부분입니다.

아마존 분기별 오프라인 실적 추이(2017년 3분기 ~ 2019년 4분기), Physical Stores Sales, Graph by Happist
아마존 분기별 오프라인 실적 추이(2017년 3분기 ~ 2019년 4분기), Physical Stores Sales, Graph by Happist

2. 온라인 성장세를 이어가다

고전을 면지 못하고 있는 오프라인과는 달리 아마존의 온라인 성적은 좋아지는 경향을 보였습니다.

아마존 온라인 부문 성장율은 2017년 3분기 22.2% 성장을 정점으로 지속하락해 2018년 3분기 10%, 2019년 1분기 9.5%까지 떨어졌으나, 이후 회복세를 보였습니다.

2019년 4분기 전년 비 14.7% 성장해 전분기 20.6%보다는 다속 하락했지만 아직 상승 추세에서 벗어났다고 단정하기는 어렵습니다.

2019년 아마존 온라인 부문은 생각외로 선방했다는 생각입니다.

아마존 분기별 온라인 스토어 매출 및 전년 비 증가율 추이,(2016년 1분기 ~ 2019년 4분기), Amazon Online stores sales, Graph by Happist
아마존 분기별 온라인 스토어 매출 및 전년 비 증가율 추이,(2016년 1분기 ~ 2019년 4분기), Amazon Online stores sales, Graph by Happist

3. 꾸준히 성장하는 서브스크립션 서비스

이번 2019년 4분기 실적 발표중 아마존은 2019년 4분기에 아마존 프라임 회원수가 1.5억명을 넘었다고 밝혔죠. 제프 베조스 아마존 회장은 지난 2018년 4분기에 1억명을 넘었다고 밝혀 화제가 되기도 했죠.

이렇게 아마존 프라임 회원이 1년 사이 50%가까이 증가하면서 아마존의 서브스크립션 서비스는 꾸준히 성과를 내고 있습니다.

여기에는 아마존 프라인 회원비, 아마존 비디오, 아마존 뮤직 등등 다양한 스크립션 서비스가 있고 그러한 서비스들이 나름 자리를 잡아가고 있다는 것을 의미합니다.

2019년 4분기 아마존 서브스크립션 서비스 부문 매물은 52억 달러로 전년 동기 비 32.2% 증가했는데요.
예전의 60%대 성장에는 다소 미치지 못하지만 2019년 3~40%대 꾸준히 성장하고 있는 점은 긍정적입니다.

아마존 분기별 서브스크립션 서비스 부문 매출 및 전년 비 성장율(2016년 1분기 ~ 2019년 4분기) Amazo Retail Subscription services revenue & y2y growth rate by quarter, Graph by Happist
아마존 분기별 서브스크립션 서비스 부문 매출 및 전년 비 성장율(2016년 1분기 ~ 2019년 4분기) Amazo Retail Subscription services revenue & y2y growth rate by quarter, Graph by Happist

아마존의 서브스크립션 서비스에 대해서는 아래 글을 참조해 보세요.

4. 아마존 광고 비지니스는 여전히 성장하다

서브스크립션 서비스와 더불어 아마존 차세대 비즈 모델로 기대를 모으고 있는 광고 비즈니스도 여전히 성장하고 있습니다. 물론 성장율은 다소 둔화되기는 했습니다.

아마존은 아직 광고 비지니스 부분을 별도 사업부로 분리하지 않았고 실적오 별도로 집계, 공개하지는 않습니다. 다만 기타 부문의 매출 대부분이 광고 매출이라서 이 데이타로 유추합니다.

이에 따르면 광고 부문이 포함된 기타 부문 매출은 2019년 4분기 48억 달러로 전년 비 41% 성장했습니다.
이는 마찬가지로 100% 넘던 시기에 비해서 둔화된 것이지만 2019년 대부분 40%대 성장율을 유지하면서 고성장 동력을 이어가고 있다고 판단됩니다.

아마존 디지탈 광고가 주를 이루는 기타 부문 분기별 매출 추이(2016년 1분기 ~ 2019년 4분기) Amazon  digital ads, Graph by Happist
아마존 디지탈 광고가 주를 이루는 기타 부문 분기별 매출 추이(2016년 1분기 ~ 2019년 4분기) Amazon digital ads, Graph by Happist

5. 아마존 웹 서비스(AWS)는 여전히 화수분이지만 둔화되고 있다

마이크로소프트 애저와 구글의 맹렬한 추격을 받고 있는 클라우드 비지니스를 담당하고 있는 아마존 웹 서비스(AWS)는 여전히 아마존 이익을 만들어 내고 있는 화수분이지만 성장율은 다소 둔화되고 있습니다.

2019년 4분기 AWS는 처음으로 분기 100억 달러를 달성했습니다. 전년비 34% 성장을 이어갔습니다. 이는 엄청난 기록이라 할 수 있죠.
그리고 영업이익도 26억 달러를 기록해 영업이익율 26%로 양호한 기록을 남겼습니다.

다만 전년 비 성장율은 40%대에서 2019년에는 30%대로 하락하면서 경쟁이 치열해짐에 따라 둔화되는 모습을 보였습니다.

아마존 분기별 AWS 부문 매출 및 전년 비 성장율(2014년 1분기 ~ 2019년 4분기) Amazo AWS International revenue & y2y growth rate by quarter, Graph by Happist
아마존 분기별 AWS 부문 매출 및 전년 비 성장율(2014년 1분기 ~ 2019년 4분기) Amazo AWS International revenue & y2y growth rate by quarter, Graph by Happist

6. 아마존 글로벌 비지니스는 여전히 고전중이다.

아마존은 여러 분야에서 좋은 성과를 내고 있지만 몇가지 부문에서는 고전을 면치 못하고 있습니다. 대표적인 것이 글로벌 부문이나 오프라인 부문이죠.

아마존은 미국 내에서는 엄청난 성과를 내고 있지만, 글로벌 비지니스는 각 지역의 로컬 업체와의 경쟁하면서 좀처럼 튼 성과를 내지 못하고 있습니다.

2019년 4분기 글로벌 부문 매출은 238억 달러로 전년 비 14.3% 성장에 그쳤고 여전히 6억 달러의 적자를 냈습니다.

아마존 북미 지역 매출 증가나 아마존 웹서비스와 같은 다른 부문의 매출 성장이 워낙 가파르기 때문에 글로벌 부문의 비중도 한때 40%에 육박했다가 이제는 27% 수중으로 하락했습니다.

아마존 분기별 글로벌 부문 매출 및 전년 비 성장율(2014년 1분기 ~ 2019년 4분기) Amazo International revenue & y2y growth rate by quarter, Graph by Happist
아마존 분기별 글로벌 부문 매출 및 전년 비 성장율(2014년 1분기 ~ 2019년 4분기) Amazo International revenue & y2y growth rate by quarter, Graph by Happist

아마존의 북미 지역과 글로벌 비지니스의 성과는 미국에서 고전하고 글로벌에서 날고 있는 넷플릭스와는 완전 반대의 모습을 보여주고 있습니다.

7. 아마존 매출 성장의 둔화

2019년들어 아마존 전체 매출 성장은 확실히 둔화되었습니다.

아마존 매출은 분기당 2~30%대 성장이 기본이었고 특히 2017년하반기 ~ 2018년 상반기엔 3~40%대의 대단히 높은 성장율을 보이면서 애플과 함께 시총 1조달러 클럽 경쟁을 벌이기도 했습니다.

그러나 2019년에는 매출 성장율은 10%로 둔화되면서 실망을 안겨주었죠. 덕분에 아마존 주가도 부진을 면치 못했습니다.

2019년 4분기 아마존은 874억 달러 매출을 올려 전년 동기 비 21% 성장했고(20%대 성장에 따라 월가가 환호 한듯..), 33억 달러의 순익을 달성, 순이익율 3.7%를 기록해 전반적으로 양호한 손익 추세를 이어 갔습니다.

아마존 분기별 매출 및 전년 비 성장율(2014년 1분기 ~ 2019년 4분기) Amazo revenue & y2y growth rate by quarter, Graph by Happist
아마존 분기별 매출 및 전년 비 성장율(2014년 1분기 ~ 2019년 4분기) Amazo revenue & y2y growth rate by quarter, Graph by Happist
아마존 분기별 순이익 및 순이익율 추이(2014년 1분기 ~ 2019년 4분기) Amazo Net Imcome & Net Income Margin by quarter, Graph by Happist
아마존 분기별 순이익 및 순이익율 추이(2014년 1분기 ~ 2019년 4분기) Amazo Net Imcome & Net Income Margin by quarter, Graph by Happist

[플러그인 소개] 최신 기술로 무장해 부드러운 레이지 로딩 가능한 Lazy Loader 플러그인

이미지나 동영상 레이지 로딩은 새로운 기술은 아니지만 빠른 웹 페이지 로딩을 위해서는 꼭 필요한 기술이라 할 수 있죠.

레이지 로딩(Lazy loading)이란

혹 모르는 분을 위해 레이지 로딩(Lazy loading)을 간단히 설명해 보죠.

일반 브라우저는 웹 페이지를 불러올때 웹 페이지 전체에 포함되어 있는 모든 이미지 및 동영상 관련 사항을 내려받습니다.

그렇기 때문에 불필요한 트래픽이 생길 수도 있습니다.
이용자가 앞부분만 보고 다른 페이지로 이동할 가능성이 있지만, 이용자가 페이지 전체를 볼 것이라는 전제하에 모든 관련 콘텐츠를 다운받습니다. 어찌보면 트래픽이 낭비된다고 할 수 있겠죠.

또한 특히 동영상마다 자바스크립트를 내려 받아야하는 유튜브 영상이 많으면 다 내려받을 때가지 사이트가 멈춘 채 대기해야 합니다.

반면 레이지 로딩(Lazy Loading)은 웹 페이지 초기에 보이는 영역(Brower ViewPort)에 해당하는 이미지 또는 동영상 재생에 필요한 자바스크립트 등만 관련 내용만을 먼저 내려 받습니다.

이후 페이지가 스크롤되어 내려가면 이미지를 내려받아 보여주는 방식을 사용합니다.

아래는 Medium에서 볼 수 있는 블러드 이미지를 먼저 보여주고 이어서 명확한 이미지를 보여주는 방식의 레이지 로딩 예입니다.

레이지 로딩 샘플 이미지. Lazy-loading-example, Image from Google
레이지 로딩 샘플 이미지. Lazy-loading-example, Image from Google

이렇게 레이지 로딩(Lazy Loading)을 적용하면 불필요한 트래픽을 줄일 수 있고, 서버 성능, 메모리, 배터리 절감, 사용성 등 많은 부분에서 유리한 점이 많습니다.

그렇기때문에 레이지 로딩(Lazy Loading)은 많은 사람들에게 광범위하게 사용되는 기능이 되었습니다.

레이지 로딩의 문제점

그러나 이 레이지 로딩(Lazy Loading)도 여러가지 문제를 내포하고 있는데요.

그 중 하나는 웹 페이지를 스크롤해 내려갈 시 이미지가 툭툭 튀어나오듯이 보여지는데요. 조금 전문 용어로 콘텐츠 점핑(Contents jumping)이라고 부르네요.

이는 스크롤되어 이미지가 보여줄 시점에서 다운받아 보여주기 때문에 역간의 딜레이가 발생하고 다운 받자마자 급하게 이미지를 보여주는 것이라 부자연스럽게 이미지가 등장하므로 굉장히 좋지 않은 사용 경험을 줍니다.

이러한 현상은 인터넷 속도가 느릴수록 더 심합니다. 당연하게도..

네이티브 레이지 로딩

기존 레이지 로딩 기능은 자바스크립트로 직접 구현하거나 라이브러리를 사용한다고 해요.

그런데 구글은 2019년 새롭게 네이티브 레이지 로딩이란 개념을 제안했습니다. 이는 이미지를 내려받는 시점을 브라우저 내부에서 결정하는 방식으로 이전 방식보다는 더 많은 내부 정를 활용해 결정을 내리므로 보다 자연스로운 스크롤이 가능하다는 주장입니다.

구글은 크롬 75 버젼부터 iframe 및 img의 레이지 로딩을 네이티브로 지원하고 있습니다.

최신 기술이 적용된 레이지 로딩 플러그인, Lazy Loader

앞에서 레이지 로딩에 대해서 불필요할 정도로 다소 길게 적었는데요.

오늘 소개하는 Lazy Loader라는 플러그인은 위에서 이야기하는 문제점을 해결하고 있고, 최신 기술도 적용하고 있는 플러그인입니다.

  • 이미지
  • 썸네일
  • 인라인 백그라운드 이미지
  • markup으로 구현된 이미지와 여타 미디어
  • iframe으로 구현된 동영상 등 미디어
  • Video요소로 구현된 미디어
  • Audio 요소

Lazy loader 장점

개인적으로 이 Lazy loader플러그인의 장점은 아래와 같이 생각합니다.

  • 가볍다. 대부분의 lazy loading 플러그인이 그리 무겁지는 않지만 이 플러그인도 가볍습니다.
  • 상대적으로 스크롤해 내려갈 시 이미지가 툭툭 튀어나오듯이 보여지는 콘텐츠 점핑(Contents jumping)이 현상이 상대적으로 적습니다.
  • 위에서 소개한 네이티브 레이지 로딩 등 최신 기술을 적용해사용성이 뛰어납니다.
  • 이미지, 동영상, 사운드 등 다양한 포맷에 대한 레이지 로딩을 지원합니다.

아파치에서 inotify-tools을 사용한 WebP 이미지 적용 및 관리 방법

이미 우분투 서버의 크론탭 기능을 활용한 이미지 최적화 시스템 구축 방안에 대해 정리했고, 이를 기반으로 운영중입니다.

그런데 조금 더 자료를 검색하다보니 inotify-tools을 사용해 조금 더 효과적으로 Webp 이미지를 적용하고 관리할 수 있는 방법이 있어 소개해 봅니다.

이는 VPS업체인 디지탈오션(digitalocean) 튜터리얼에서 소개하는 방법인데요. 도움이 될 것 같아서 번역 겸해서 소개해 봅니다.

이 글에서는 우분투 16.04와 CentOS 7를 설치하고 웹서버로는 아파치를 사용자를 대상으로 설명하고 있습니다.

How To Create and Serve WebP Images to Speed Up Your Website

필요 조건

이 방법은 우분투 16.04와 CentOS 7에 아파치 사용자를 대상으로 설명된 것입니다. 저는 NGINX를 사용하므로 소개만 하기로 합니다.

  • 사용자는 non-root sudo user여야 함
  • 웹서버는 아파치
  • mod_rewrite가 설치 되어 있어야 함

1. cwebp 설치 및 이미지 폴더 준비

여기에서는 webp 이미지를 만들 수 있는 webp를 설치해 webp를 사용할 수 있게 만들고 webp이미지를 저장할 수 있는 폴더를 만드는 방법에 대해서 알아봅니다.

1.1. webp 설치

sudo apt-get update
sudo apt-get install webp Code language: PHP (php)

만약 CentOS 7 사용자라면 아래 명령어를 사용합니다

sudo yum install libwebp-toolsCode language: PHP (php)

1.2. 이미지 폴더 생성

webp라는 이미지 저장 폴더를 만듭니다. 이는 아파치 웹 루트( /var/www/html )에 만듭니다.

sudo mkdir /var/www/html/webpCode language: PHP (php)

이 폴더의 소유권을 변경합니다.

sudo chown sammy: /var/www/html/webpCode language: PHP (php)

새로 만든 이미지 폴더로 이동합니다.

cd /var/www/html/webpCode language: PHP (php)

이 단계에서 아파치 서버에서 mod_rewrite와 cwebp이 설치되어 있고 이미지 폴더가 만들어 졌다면 준비가 완료된 것입니다.

2. cwebp를 이용 이미지 압축

이용자들에게 webp 이미지를 보여주려면 webp 이미지가 만들어져야 합니다. 너무 당연한 소리..

이를 위한 일반적인 명령어는 아래와 같은 형식을 띱니다. 여기서 -o 옵션은 WebP 파일의 경로를 지정합니다.

cwebp image.jpg -o image.webpCode language: PHP (php)

3. JPEG와 PNG 이미지를 변환합니다.

이제 본격적으로 JPEG와 PNG 이미지를 변환을 위한 스크립트 파일 webp-convert.sh를 만들어 봅니다.

nano ~/webp-convert.shCode language: PHP (php)

여기에는 아래와 같은 내용으로 구성됩니다.

#!/bin/bash

# converting JPEG images
find $1 -type f -and \( -iname "*.jpg" -o -iname "*.jpeg" \) \
-exec bash -c '
webp_path=$(sed 's/\.[^.]*$/.webp/' <<< "$0");
if [ ! -f "$webp_path" ]; then 
  cwebp -quiet -q 90 "$0" -o "$webp_path";
fi;' {} \;

# converting PNG images
find $1 -type f -and -iname "*.png" \
-exec bash -c '
webp_path=$(sed 's/\.[^.]*$/.webp/' <<< "$0");
if [ ! -f "$webp_path" ]; then 
  cwebp -quiet -lossless "$0" -o "$webp_path";
fi;' {} \;
Save the fileCode language: PHP (php)
  • find : 지정된 디렉토리 내에서 파일을 검색합니다.
  • $1 :이 위치 매개 변수는 명령 행에서 가져온 이미지 디렉토리의 경로를 지정합니다.
  • -type f : 일반 파일 만 찾도록 합니다.
  • -iname : 지정된 패턴과 파일 이름을 일치시킵니다.
    -iname은 대소 문자를 구분하지 않으며, jpg 또는 .jpeg 파일 이름을 찾도록 합니다.
  • -o : find 명령을 사용하여 첫 번째 -iname 테스트(“*.jpg”) 또는 두 번째 테스트(iname “*.jpg”)와 일치하는 파일을 나열합니다.
  • () : -and 연산자와 함께이 테스트를 괄호로 묶으면 첫 번째 테스트 (예 : -type f)가 항상 실행됩니다.
  • bash: webp 이미지 파일을 만드는 스크립트를 실행합니다.
    이 스크립트는 -c 옵션 덕분에 문자열로 bash로 전달됩니다.
  • ‘commands’ : 이 자리 표시자는 webp 이미지를 만드는 스크립트입니다.
  • webp_path : 이 변수는 위치 매개변수 $0로 표시된 bash 명령에서 sed 및 일치하는 파일 이름을 사용하여 생성됩니다.
    여기서 문자열(<<))은 이 이름을 sed로 전달합니다.
  • if [ ! -f “$webp_path” ] : 이 테스트는 “$webp_path”라는 이름의 파일이 이미 존재하는지(!) 논리 비 연산자를 사용하여 확인합니다.
  • cwebp : webp 파일이 존재하지 않는 경우 -q 옵션(상태를 출력하지 않음)으로 webp 이미지 파일을 만듭니다.

이 스트립트 실행 가능하도록 권한을 변경합니다.

chmod a+x ~/webp-convert.shCode language: PHP (php)

이 스크립트 파일은 이미지 폴더에서 실행합니다.

./webp-convert.sh /var/www/html/webpCode language: PHP (php)

4. 이미지 폴더 변경 사항을 모니터링 하기

이 단계에서는 notify-tools을 이용해서 이미지 폴더에서 어떤 변경 사항이 발생하는지 모니터링하고 이에 따른 액션읗 취합니다.

4.1. inotify-tools 설치하기

우분투 18.04를 위한 inotify-tools 바이너리 패키지가 있기 때문에 apt-get 명령어로 inotify-tools를 설치할 수 있습니다.

sudo apt-get update -y
sudo apt-get install -y inotify-tools
Code language: PHP (php)

참고로 CentOS 7을 이용한다면 다음 명령어를 이용해서 설치할 수 있습니다.

sudo yum install epel-release
sudo yum install inotify-tools
Code language: PHP (php)

4.2. inotify-tools 이용한 모니터링 스크립트 작성

inotifywait -q -m -r --format '%e %w%f' -e close_write -e moved_from -e moved_to -e delete $1 Code language: PHP (php)
  • inotifywait: 이 명령어는 특정 폴더의 변경 내용을 모니터링 합니다.
  • -q: 이 옵션은 inotifywait작동 시 불필요한 소리와 메세지를 내지말도록 합니다.
  • -m: 이 옵션은 inotifywait를 계속 실행하고, 어느 한 이벤트가 끝나도 종료하지 않습니다.
  • -r: 이 옵션은 지정된 폴더와 하위 폴더 모니터링을 반복적으로 실행합니다.
  • --format: 이 옵션은 inotifywait에게 이벤트 이름과 파일 경로를 이용하여 변경 사항을 모니터링하도록 합니다.
  • –format ‘%w%f’ : /complete/path/file.name과 같은 형식으로 파일을 인쇄(print out)
  • 모니터링하는 이벤트는 close_write(파일을 만들고 디스크에 기록을 완료할 때 발생), moved_from 및 moved_to (파일 이동 시) 및 delete (파일 삭제 시)입니다.
  • $1: 변경된 파일 경로를 가지고 있는 위치 매개 변수
| grep -i -E '\.(jpe?g|png)$' --line-bufferedCode language: PHP (php)
  • grep : 이 명령어를 사용해 변경된 파일이 JPEG나 PNG 파일인지 확인합니다.
  • -i : 이 옵션은 grep에게 대문자, 소문자를 무시하도록 합니다.
  • -E : 이 옵션은 grep이 확장 정규 표현식을 사용하도록 합니다.
  • –line-buffered : 이는 grep에게 일치하는 행을 while 루프에 전달하도록 지시합니다.
| while read operation path: do
  # commands
done;Code language: PHP (php)
  • 여기서는 read 명령으로 while 루프를 만듭
  • read는 inotifywait가 감지 한 이벤트를 처리하여 $ operation이라는 변수에 처리하고 파일 경로는 $ path라는 변수에 지정합니다.

while 루프가 이벤트를 확인하면, 그 결과에 따라 다음 명령을 수행합니다.

  • 새로운 이미지 파일을 생겼거나 대상 폴더로 이동해온 경우 이 이미지에 대한 WebP 파일을 만듭니다.
  • 관련 이미지 파일이 삭제되거나 대상 폴더에서 다른 곳으로 이동한 경우 WebP 파일을 삭제합니다.

루프 내부에는 세가지 주요 섹션이 있습니다. webp_path라고 불리우는 변수는 해당 이미지의 WebP에 대한 경로 정보를 가지고 있습니다.

webp_path="$(sed 's/\.[^.]*$/.webp/' <<< "$path")";Code language: PHP (php)
if [ $operation = "MOVED_FROM" ] || [ $operation = "DELETE" ]; then
  # commands to be executed if the file is moved or deleted
elif [ $operation = "CLOSE_WRITE,CLOSE" ] || [ $operation = "MOVED_TO" ]; then
  # commands to be executed if a new file is created
fi;Code language: PHP (php)
  • 만약 파일이 다른 곳으로 옴겨졌거나 지워졌으면 WebP 파일을 지웁니다.
if [ -f "$webp_path" ]; then
  $(rm -f "$webp_path");
fi;
if [ $(grep -i '\.png$' <<< "$path") ]; then
  $(cwebp -quiet -lossless "$path" -o "$webp_path");
else
  $(cwebp -quiet -q 90 "$path" -o "$webp_path");
fi;Code language: PHP (php)

만약 이미지가 새로 만들어졌다면 아래 조건에 따라 압축이 이루어집니다.

  • 만약 PNG 이미지라면 무손실 압축을 실시
  • PNG 이미지가 아니라면 손실 압축을 실시

이미지 폴더를 모니터링하고 변화에 따른 후속 조치를 취하는 전체 스크립트는 아래와 같습니다. 이 스크립트를 watchers.sh에서 반영합니다.

nano watchers.shCode language: PHP (php)

아래 스크립트를 watchers.sh에 포합시킵니다.

#!/bin/bash
echo "Setting up watches.";

# watch for any created, moved, or deleted image files
inotifywait -q -m -r --format '%e %w%f' -e close_write -e moved_from -e moved_to -e delete $1 \
| grep -i -E '\.(jpe?g|png)$' --line-buffered \
| while read operation path; do
  webp_path="$(sed 's/\.[^.]*$/.webp/' <<< "$path")";
  if [ $operation = "MOVED_FROM" ] || [ $operation = "DELETE" ]; then # if the file is moved or deleted
    if [ -f "$webp_path" ]; then
      $(rm -f "$webp_path");
    fi;
  elif [ $operation = "CLOSE_WRITE,CLOSE" ] || [ $operation = "MOVED_TO" ]; then  # if new file is created
     if [ $(grep -i '\.png$' <<< "$path") ]; then
       $(cwebp -quiet -lossless "$path" -o "$webp_path");
     else
       $(cwebp -quiet -q 90 "$path" -o "$webp_path");
     fi;
  fi;
done;Code language: PHP (php)

watchers.sh 파일을 실행가능토록 권한을 변경합니다.

chmod a+x ~/webp-watchers.shCode language: PHP (php)

이 배치 파일은 아래와 같은 형식으로 사용합니다.

./webp-watchers.sh /var/www/html/webp > output.log 2>&1 &Code language: PHP (php)

5. HTML에서 WebP 이미지 사용

여기에서는 아파치에서 WebP 이미지 파일을 활용할 수 있도록 만드는 방법을 설명합니다.

먼저 /var/www/html/webp 폴더에 .htaccess 파일을 만듭니다. /var/www/html/webp/.htaccess

nano /var/www/html/webp/.htaccessCode language: PHP (php)

아래 내용이 반영됩니다.

<ifModule mod_rewrite.c>
  RewriteEngine On 
  RewriteCond %{HTTP_ACCEPT} image/webp
  RewriteCond %{REQUEST_URI}  (?i)(.*)(\.jpe?g|\.png)$ 
  RewriteCond %{DOCUMENT_ROOT}%1.webp -f
  RewriteRule (?i)(.*)(\.jpe?g|\.png)$ %1\.webp [L,T=image/webp,R] 
</IfModule>

<IfModule mod_headers.c>
  Header append Vary Accept env=REDIRECT_accept
</IfModule>

AddType image/webp .webpCode language: PHP (php)

무료로 구축하는 이미지 최적화 자동화 시스템

이전부터 효율적인 이미지 최적화 방안에 대해 고민을 했습니다. 오늘은 그동안 고민했던 효율적인 이미지 최적화 방안에 대해서 살펴보겠습니다.

1. 이미지 최적화를 고민하는 이유

먼저 이 글을 시작하게 전에 이미지 최적화를 고민한 이유를 간단히 정리해 보았습니다.

1.1. 풍부한 소스를 지닌 콘텐츠로 경쟁력을 높여야

여기와 같은 블로그 사이트든, 쇼핑몰이든 경쟁력을 가지려는 그 사이트가 얼마나 콘텐츠 경쟁력을 가지고 있느냐가 매우 중요해지고 있습니다.

사이트 방문자에게 풍부한 콘텐츠 이용 경험을 주기 위해서는 다양한 정보 소스를 풍부하게 제공하고, 흥미를 끌 수 있도록 배치해 쉽고 편하게 콘텐츠를 이용하도록 만드는 것이 필요합니다.

이러려면 포스팅이든 새로운 콘텐츠이든 이미지나 동영상 등의 정소 원천을 과하다고 생각될 정도로 풍부하게 사용해야 합니다. 웹 페이지가 가질 수 있는 장점을 최대한 활용해야 어느 정도 경쟁력을 가질 수 있습니다.

이전에는 트래픽이나 로딩 속도를 고려해 이미지나 동영상 사용을 자제하거나 최소한으로 활용했다면 앞으로는 콘텐츠 경쟁력 자체에 중점을 둬야 합니다.

이제는 5G가 전면에 등장하는 등 어느 정도 속도와 트래픽을 보장할 수 있는 시대로 나아가고 있습니다.

1.2. 속도도 중요하지만 콘텐츠 질이 더 중요

이제는 트래픽이나 속도가 중요한 것이 아니라 얼마나 풍부하게 충실한 콘텐츠를 만들 수 있느냐가 점점 더 중요해지고 있습니다.

이는 예전부터 지당하게 여견운 일종의 언명이었지만 요즘과 같이 동영상을 비롯한 다양한 콘텐츠 포맷이 경쟁하면서 콘텐츠의 질과 풍부함은 더욱 더 중요해졌습니다.

기술의 발전과 콘텐츠 최적화 기술의 발전으로 이제는 최적화가 용이해져 풍부한 콘텐츠 소스를 적용하면서도 느리다는 느낌을 주지 않아 콘텐츠 질로서 승부할 수 있는 시기가 왔습니다.

1.3. 점차 중요해지는 이용자와 커뮤니케이션

이전에도 중요해졌지만 요즘 더 중요해지는 것이 기업과 이용자 또는 소비자간 커뮤니케이션이 매우 중요해졌습니다.

이는 이용자 리뷰나 Q&A와 같은 방식으로 이용자와 적극적으로 커뮤니케이션해야합니다. 이러다보면 글과 콘텐츠를 올리는 고객 및 이용자가 늘어야 합니다.

사이트에 글을 쓰는 사람이 단 관리자 한명이라면 애정을 가지고 최적화된 이미지를 사용하겠지만 불특정 다수가 글을 쓰는 경우 최적화된 이미지를 사용하는 확율은 그리 크지 않습니다.

더우기 모바일이 보편화된 시점에서 이미지 편집이 쉽지는 않기 때문에 대부분 그냥 활영한 사진을 그대로 올릴 가능성이 높죠.

스마트폰 사진 사양이 고급화되면서 이미지 크기도 커졌기때문에 대용량 파일을 올릴 가능성이 커지지죠.

그렇기때문에 정기적으로 이미지 크기와 품질을 최적화해서 적절한 사이즈로 만들어주는 것이 필요합니다.

2, 이미지 최적화 방법

그러면 어떻게 이미지를 최적활 수 있을까요? 이미지를 최적화해주는 다양항 솔류션이 있음에도 불구하고, 하나하나 점검해 보면 괜찮은 선택지는 별로 없습니다.

그래도 몇가지 고민하고 탐색해본 내용을 여기에 정리해 봅니다.

2.1. 플러그인 + 유료 서비스 이용

워드프레스에는 당연히 수많은 이미지 최적화를 도와주는 플러그인들이 있습니다. 이미지 압축 등 이미지 최적화에 대한 니즈가 많기 때문에 관련 플러그인도 괸장히 많습니다.

그러나 이들 플러그인들을 자세히 살펴보다보면 많은 한계점을 발견하게 됩니다.

쓸만한 플러그인은 유료가 많다

그러나 워드프레스용 플러그인들 상당수는 본격적으로 이미지 최적화를 하려면 일정 비용을 내야 합니다.

이미지 크기를 줄이고, 이미지 압축도를 변경하는 등의 작업은 서버 자체를 활용해야 하므로 워드프레스 내에서 자체적으로 해결하기엔 한계가 큽니다.

그렇기때문에 API 등을 활용해 별도 작업 서버에서 작업 후 보내주는 방식을 취하게 되죠.

그리고 이러한 방식은 무료로 운영하기 힘들기도하고 어느 정도 수요도 있기 때문에 자연스럽게 비지니스 모델로 이어지고 있다는 생각입니다.

이미지 최적화 플러그인을 잘 살펴보면 무료로 쓸만한 플러그인이 많지 않습니다. 쓸만하다싶어 본격적으로 사용하려면 비용을 내야 합니다.

저의 경우 이미지량이 어느 정도인지 봤더니 12GB쯤 되더군요. 워드프레스는 다양한 크기의 이미지를 만들기 때문에 용량이 더 많은 스토리지가 필요합니다.

앞으로도 계속 콘텐츠를 만들면 이미지 및 동영상이 계속 증가할텐데 이를 유료 서비스로 해결하기엔 감당이 되지 않습니다.

워드프레스 속도에 악영향을 끼치기도

그리고 이미지 최적화 플러그인들은 API를 이용하든 다양한 서비스를 제공하기 때문이든 워드프레스 자체 속도에 영향을 미치는 경우가 많습니다.

EWWW Image Optimizer, Smush Image Compression & Optimization, Imsantiy 등은 대표적인 이미지 관리 플러그인이지만 동시에 사이트 속도르 느리게 만드는 플러그인이기도 합니다.

2.2. CDN 활용 – 유료

일부 CDN을 사용하면 이미지 압축 및 WebP 파일 생성등 로딩 속도를 높이고, 트래픽을 절감해주는 기능을 통해서 최상의 이미지 최적화 효과를 누릴 수 있습니다.

예를들어 Akamai은 이미지 품질을 유지하면서도 이미지 용량을 압축해주며, 모바일 및 데스크 탑 PC 등과 같은 이용자 디바이스별로 최적 크기의 이미지를 보여주어 속도를 개선하며, WebP(크롬, 엣지, 파이어폭스 등 지원)나 JPEG-XR/JPEG 2000과 같이 특정 브라우저에서 최고 효과를 내는 이미지 포맷으로 변환해 보여줍니다.

다만 이런 서비스는 비쌉니다. Akamai은 1TB 트래픽당 350$ 사용료를 받습니다.

무료 플랜이 있는 Cloudflare의 경우에도 자동으로 기기에 맞추어 압축해 주는 서비스는 유료(월 20$)인 프로부터 제공합니다.

2.3. 이미지 최적화 솔류션 – 유료

또한 이미지 최적화 서드파티 솔루션업체드링 많이 존재합니다.

Cloudinary, imgix, Fastly’s Image Optimizer, Instart Logic’s SmartVision, ImageOptim API등이 그것인데요. 이들 업체는 이미지 최적화를 자동으로 해주는 종합 솔류션들을 탑재하고 비지니스를 하고 있습니다.

당연히 이들은 제한적으로 무료 서비스도 제공하지만 제대로 사용하려면 유료로 서비스를 이용해야 합니다.

위 리스트중에서 맨 처음으로 언급된 Cloudinary는 Free/Plus/Advanced/Custom 서비스가 있는데요.

Free 플랜의 경우 월 트래픽을 25GB를 줍니다.. 저의 경우 최소 300GB가 나오기때문에 Free 플랜은 사용 불가하고 월 99$짜리 Plus 플랜을 사용해야 합니다.

2.4. 서버에서 자체적으로 관리 – 무료

비용 문제나 속도 저하 문제로 플러그인을 사용할 수 없다면 서버에서 자체적으로 이이미지 최적화를 할 수 밖에 없습니다.

다행히 우분투와 같은 서버에서 적용할 수 있는 다양한 이미지 최적화 패키지들이 존재하기 때문에 이를 잘 활용하면 완벽하지는 않지만 해결 가능할 것입니다.

물론 서버에서 작동하도록 만들어야하므로 상당한 서버 운용 능력이 필요하다는 어려움은 있습니다.

구체적인 방법은 다음 장에서 차분히 설명하기로 하죠.

3. 서버에서 이미지 관리 프로세스

그러면 이제부터 서버에서 이미지 관리하는 방안을 살펴보도록 하겠습니다.

참고로 저는 Vultr VPS를 이용하고 있으며, Ubuntu 18.04에 웹서버는 NGINX를 사용하고 있기 때문에 이를 기반으로 설명해 보고자 합니다.

  • 서버 업체 : Vultr(일본 동경)
  • 서버 상품 : High Frequency 4GB RAM, 2 CPU
  • 서버 타입 : Ubuntu 18.04
  • 웹서버 : NGINX

조금 더 구체적으로 어떤 솔류션을 상요해야 할까요? 무슨 작업이 필요할까요?

다양하고 훌륭한 방법이 많이 있겠지만 저는 아래와 같은 프로세스를 사용했습니다.

  • 이미지 최적화를 진행하기 전에 최적화 대상 이미지들을 백업받습니다.
  • 그 다음 업로드된 이미지 리사이즈 여부를 검토, 리사이즈 합니다. 이때 기준은 사이트 도구 – 미디어에서 정의하는 최대 이미지 사이즈에 맞추기로 합니다.
    저는 최대 이미지 폭을 1024로 정했기 때문에 폭이 1024를 넘으면 1024로 줄이도록 했고
    이미지 높이는 어쩔 수 없이 긴 이미지를 사용하는 경우가 많아서 이는 컨트롤하지 않기로 했습니다. 쇼핑몰의 경우 설명을 이미지로 대체해 아주 긴 이미지를 사용하는 경우가 많죠.
  • 다음으로는 JPEG와 PNG 이미지를 압축합니다.
  • 다음으로는 WebP나 JPEG-XR과 같은 특정 브라우저에서 효율적인 이미지 포맷을 생성합니다.
  • 이미지가 효과적으로 이용자들에게 노출될 수 있도록 Lazy Loading을 적용합니다.

이러한 이미지 최적화 프로세스는 서버에 새로운 이미지가 발생시마다 바로 바로 할 수도 있고 정기적으로 모아 한번에 처리하는 방법이 있습니다.

대부분 서비스는 이미지가 새로 생성되는 순간 관련 작업을 진행해 항상 최적의 상태로 이미지를 최적화합니다.

그러나 이러한 방식은 서버에 무리를 줄 수도 있기 때문에 일정 시간만다 일괄 처리(Batch) 하는 것도 나쁘지는 않을 듯 합니다.

여기에서는 더 적용하기가 쉽기 때문에 크론탭을 사용해 일정 시간마다 일괄 처리하는 방법을 채택해 설명드립니다. 저는 1시간마다 실행토록 만들었습니다.

4. 서버를 이용한 이미지 최적화 시스템

여기서터는 위에서 정의한 프로세스에 따라서 이미지 최적화 시스템(?)을 구축하는 구체적인 방법을 살펴봅니다.

4.1. 이미지 백업

이미지 최적화를 진행 전 백업을 진행합니다.

최적화 시스템 구축 방법에 따라 해당 이미지만을 백업 받을 수도 있고, 폴더를 통채로 백업받을 수도 있습니다.

저는 서버 공간도 남아돌고, CPU도 남아돌고 있기 때문에 폴더채 백업받는 방안을 선택했습니다. 그리고 이는 우선 서버 내에서 백업을 하는 것으로 했습니다.

4.1.1 백업 디텍토리 만들기

# mkdir /backup         # backup 디렉토리 만들기
# chmod +x  /backup  # 퍼미션 조정
Code language: PHP (php)

4.1.2. 백업 스크립트 만들기

이어서 백업 스크립트를 만듭니다. 이걸 실핼해도 되고, 뒤에서 설명하는 크론탭에서 자동 실행토록 하면 됩니다.

# 이미지 최적화 진행 전에 백업하기
tar -zcvf /backup/"happistimagebackup$(date +%y%m%d%H%M).tgz" /home/happist/wp-content/uploads/2020 1>/dev/null 2>/dev/nullCode language: PHP (php)

4.1.3. 오래된 백업 파일 삭제

백업을 계속하다보면 엄청난 백업 파일이 쌓이게 됩니다. 그러면 아무리 서버 용량이 많아도 곧 용량 부족 상태에 이르게 되겠죠.

그래서 일정 시간이 경과한 백업 파일은 삭제하도록 합니다. 여기서는 10일 지난 백업 파일은 삭제하도록 했습니다.

find /backup/ -type f -mtime +10 | sort | xargs rm -fCode language: PHP (php)

워드프레스 자동 백업 시스템에 대해서는 아래 글을 참조하세요.

4.2. 이미지 리사이즈

먼저 이미지가 새로 업로드되면 이미지가 지나치게 크지는 않은지를 검토합니다.

이 전 글에서도 언급했지만 사이트에 글을 쓰는 사람이 단 관리자 한명이라면 애정을 가지고 최적화된 이미지를 사용하겠지만 불특정 다수가 글을 쓰는 경우 최적화된 이미지를 사용하는 확율은 그리 크지 않습니다.

더우기 모바일에서 댓글 등의 글을 쓴다면 모바일에서 이미지 편집이 쉽지는 않고 그 귀찮은 일을 할 사람이 거의 없기 때문에 대부분 그냥 활영한 사진을 그대로 올립니다.

스마트폰 카메라 사양이 고급화되면서 이미지 크기도 커졌기때문에 대용량 파일을 그냥 올릴 가능성이 커졌습니다. 물론 댓글이나 상품 리뷰 시 이미지를 사용하지 않토록 만들었다면 별 문제는 없지만 대세는 적극적으로 이미지를 댓글과 상품 리뷰에 적용하고 있는 상황이기도 합니다.

그렇기때문에 정기적으로 이미지 크기와 품질을 최적화해서 적절한 사이즈로 만들어주는 것이 필요합니다.

저는 이러한 이미지 크기를 점검해 지나치게 크다면 사이즈를 줄이는 것을 Imagemagick를 이용해 구현했습니다.

기준으로 폭만 변경하려면 widthxheighr중에서 앞의 width만 적어주고, 높이를 맞추려면 xheight를 사용합니다. 아래 내용을 보시고 제가 사용한 명령어를 그 아래에 소개해 놓았습니다.

  • 폭만 변경하여면 width> 예를 들어 1024>
  • 높이만 변경하려면 xheight> 예를 들어 x1024>
# JPEG 이미지가 지나치게 크다면 폭을 1024px로 줄임
find /home/happist/wp-content/uploads/2020 -iname '*.jpg' -exec convert \{} -verbose -resize 1024\> \{} \;

# PNG 이미지가 지나치게 크다면 폭을 1024px로 줄임
find /home/happist/wp-content/uploads/2020 -iname '*.png' -exec convert \{} -verbose -resize 1024\> \{} \;
Code language: PHP (php)

ImageMagick를 이용한 이미지 리사이즈에 대해서는 아래 글을 참조해 보세요.

4.3. 이미지 압축

적절한 크기의 이미지로 사이즈 조정되었다면 각 이미지를 압축하는 단계로 진입니다. 이미지 압축 대상은 가장 많이 사용하는 JPEG와 PNG 이미지입니다.

JPEG 이미지 압축 방법

JPEG 이미지를 압축하는 방법은 여러가지가 소개되어 있습니다. 각기 자기 방법이 최고라고 주장하고 있죠.

그렇지만 전문가들의 평가를 보면 MozJPEGGuetzli를 가장 좋은 JPEG 이미지 압축 방법으로 소개하고 있습니다.

그렇지만 Guetzli는 가장 압축 효과가 뛰어난 대신 인코딩 시간이 많이 걸리고, Progressive를 지원하지 않는등 약점이 있습니다.

그래서 저는 MozJPEG를 사용하는 JPEG-recompress를 사용하기로 했습니다.

JPEG-recompress를 이용해 JPEG와 PNG 이미지를 압축하는 아래와 같은 명령을 사용했습니다.

# jpeg-recompress를 이용 JPEG 이미지 압축
find /home/happist/wp-content/uploads/2020 -type f -iname '*.jpg' -exec jpeg-recompress --quality medium --min 60 --method smallfry \{} \{} \;Code language: PHP (php)

JPEG 압축 방법에 대한 설명은 아래 글을 참조하세요

PNG 파일 압축 방법 – pngquant 사용

마찬가지로 PNG 이미지 압축 방법도 여러가지가 있지만 가장 효율이 좋은 압축 방법으로 pngquant가 추천되고 있기에 이를 사용하기로 했습니다.

pngquant를 이용한 PNG 이미지 파일 압축 명령을 아래와 같습니다.

# pngquant를 이용 PNG 이미지 압축
find /home/happist/wp-content/uploads/2020 -iname "*.png" -exec pngquant --force --quality=40-100 --skip-if-larger --strip --verbose \{} --output \{} \;Code language: PHP (php)

pngquant를 비롯한 PNG 이미지 파일 압축에 대한 내용은 하기 포스팅을 참조하세요

4.4. WebP 적용 및 WebP 이미지 생성

기존 JPEG이미지보자 20%이상 압축효과가 좋다는 WebP 이미지를 사용할 수 있도록 만들고 WebO 이미지를 생성하는 방법을 알아 봅니다.

여기서는 아주 간단히 정리해 설명하니 자세한 내용은 아래 링크하는 포스팅을 참조하시기 바랍니다.

WebP이미지를 사용 가능하게 만들자.

웹서버가 NGINX인 경우 WebP를 지원하는 브라우져가 WebP 이미지를 인식토록 하기위해 아래와 같은 과정을 거칩니다.

먼저 NGINX 웹서버 동작을 설정하는 http 블락안에 다음 코드를 추가합니다.

map $http_accept $webp_suffix {
  default   "";
  "~*webp"  ".webp";
}Code language: PHP (php)

다음으로는 server 블락안에 다음 코드를 추가합니다.

이는 브라우져가 WebP 이미지를 지원하는 경우, 모든 이미지(jpg, png)에 대한 WebP 이미지를 로딩하도록 합니다.

location ~* ^.+\.(jpe?g|png) {
  add_header Cache-Control "public, no-transform";
  add_header Vary "Accept-Encoding";
  try_files $uri$webp_suffix $uri =404;
  expires max;
}Code language: PHP (php)

WebP 이미지 생성

그 다음으로는 WebP 이미지를 만들기 위해 아래와 같은 명령을 사용합니다.

물론 이 명령이 제대로 실행되면면 사전 서버에 webp 패키지를 설치해야 합니다.

apt-get install webpCode language: PHP (php)

JPEG 이미지나 PNGㅇ 이미지에 대한 WebP 이미지 생성은 아래와 같은 명령어를 사용합니다.

# JPEG와 PNG 이미지 파일을 WebP파일로 변환 
echo "===== Converting images into WebP .webp ====="
for x in `find /home/happist/wp-content/uploads/2020 -type f \( -iname \*.jpeg -o -iname \*.jpg -o -iname \*.JPG -o -iname \*.png \)`
  do cwebp -quiet -q 80 ${x} -o ${x}.webp;
  echo "Converted $x to ${x}.webp"
doneCode language: PHP (php)

위와 같이 WebP 이미지 이용에 대해서는 아래 포스팅을 참조해 보시기 바랍니다.

4.5. 이미지 Lazy Loading 적용

페이지 로딩 시 페이지 전체의 이미지를 한꺼번에 로딩하지 말고 이용자가 이미지를 볼 시점에 로딩시켜주자는 것이 lazy Loading인데요.

이 lazy loading의 효과나 사용자 경험 관련해서는 긍정과 부정이 섞여 있습니다. 심지어 lazy loading은 인터넷 속도가 느리던 시절의 유산이므로 요즘에는 전혀 신경쓸 필요가 없다는 주장도 있습니다.

사용자 경험 관점에서 마우스를 내리면 그제야 이미지가 로딩되는 경험은 그리 좋은 경험은 아닙니다.

그렇지만 유튜브의 경우 지나치게 많은 이미지와 자바스크립트 등을 로딩하면서 확실히 속도를 늦추고 있기 때문에 Lazy Loading 효과가 아주 극명합니다.

저는 Lazy Loading은 유튜브 동영상과 이미지 lazy loading을 지원하는 플러그인을 사용해 로딩 시간이 많이 걸리는 문제를 해결했습니다.

5. 이미지 최적화 크론탭 설정

위에서 설명한 일련의 이미지 최적화 과정을 하나씩 하나씩 실행하기는 쉽지 않으므로 우분투 서버의 크론탭 기능을 활용해 자동화 합니다.

저의 경우 매시 15분마다 살행되도록 성정했습니다.

실행 배치 파일 만들기

먼저 실행 배치 파일을 만듭니다. 여기서는 nano 편집기를 이용해 webp.sh 파일을 만듭니다.

nano webp.shCode language: PHP (php)

nano 편집기가 열리면 아래와 같은 실행 명령문을 입력하고 저장합니다.

# 이미지 최적화 진행 전에 백업하기
tar -zcvf /backup/"happistimagebackup$(date +%y%m%d%H%M).tgz" /home/happist/wp-content/uploads/2020 1>/dev/null 2>/dev/null

# 10일이 지난 백업 파일은 삭제합니다.
find /backup/ -type f -mtime +10 | sort | xargs rm -f

# JPEG 이미지가 지나치게 크다면 폭을 1024px로 줄임
find /home/happist/wp-content/uploads/2020 -iname '*.jpg' -exec convert \{} -verbose -resize 1024x10240\> \{} \;

# PNG 이미지가 지나치게 크다면 폭을 1024px로 줄임
find /home/happist/wp-content/uploads/2020 -iname '*.png' -exec convert \{} -verbose -resize 1024x10240\> \{} \;

# jpeg-recompress를 이용 JPEG 이미지 압축
find /home/happist/wp-content/uploads/2020 -type f -iname '*.jpg' -exec jpeg-recompress --quality medium --min 60 --method smallfry \{} \{} \;

# pngquant를 이용 PNG 이미지 압축
find /home/happist/wp-content/uploads/2020 -iname "*.png" -exec pngquant --force --quality=40-100 --skip-if-larger --strip --verbose \{} --output \{} \;

# JPEG와 PNG 이미지 파일을 WebP파일로 변환 
echo "===== Converting images into WebP .webp ====="
for x in `find /home/happist/wp-content/uploads/2020 -type f \( -iname \*.jpeg -o -iname \*.jpg -o -iname \*.JPG -o -iname \*.png \)`
  do cwebp -quiet -q 80 ${x} -o ${x}.webp;
  echo "Converted $x to ${x}.webp"
doneCode language: PHP (php)

이제 자동 실행되도록 크론탭을 설정합니다.

crontab -eCode language: PHP (php)

아래와 같이 15분마다 webp.sh 파일이 실행되도록 합니다.

15 * * * * webp.shCode language: PHP (php)

크론탭 설정을 마쳤으면 크론탭이 재시작할 수 있도록 합니다. 아래 명령어를 사용합니다.

service cron restartCode language: PHP (php)

크론탭 사용 방법에 대해서는 아래 포스팅을 참조하세요.

Imagemagick 이용, 이미지 사이즈 일괄 변경 방법

사이트에 글을 쓰는 사람이 단 관리자 한명이라면 애정을 가지고 최적화된 이미지를 사용하겠지만 불특정 다수가 글을 쓰는 경우 최적화된 이미지를 사용하는 확율은 그리 크지 않습니다.

더우기 모바일이 보편화된 시점에서 이미지 편집이 쉽지는 않기 때문에 대부분 그냥 활영한 사진을 그대로 올릴 가능성이 높죠.

스마트폰 사진 사양이 고급화되면서 이미지 크기도 커졌기때문에 대용량 파일을 올릴 가능성이 커지지죠.

그렇기때문에 정기적으로 이미지 크기와 품질을 최적화해서 적절한 사이즈로 만들어주는 것이 필요합니다.

여기에서는 Imagemagick을 이용해 쉽게 이런 작업을 할 수 있는 방법을 찾아 보았습니다.

Imagemagick 설치

먼저 Imagemagick을 설치합니다.

우분투용 Imagemagick 패키지가 있기때문에 설치는 매우 간단합니다.

apt-get update
apt-get install imagemagick -yCode language: PHP (php)

배치 실행 파일을 만듭니다.

편집기를 이용해 패치 실행 sh 파일을 만듭니다.

nano resizeimage.sh
Code language: PHP (php)

아래와 같은 내용을 추가 합니다.

# 이미지가 있는 절대 주소를 입력합니다(absolute path to image folder)
FOLDER="/var/www/happist.com/wp-content/uploads"

# 이미지 최대 폭을 설정합니다.max width
WIDTH=1024

# 이미지 최대 높이를 설정
# 쇼핑몰등은 설명 이미지를 길게 만드는 경우가 많아 높이 조정은 문제가 있어 가능한 큰 값을 지정
HEIGHT=102400


# PNG와 JPG의 폭이나 높이가 최대치를 넘어가면 이미지 폭이나 높이를 조정합니다. 
# 이때 imagemagick은 그 이미지의 폭과 높이 비율을 유지합니다. 
find ${FOLDER} -iname '*.jpg' -o -iname '*.png' -exec convert \{} -verbose -resize $WIDTHx$HEIGHT\> \{} \;

# PNG만 폭이나 높이가 최대치를 넘어가면 이미지 폭이나 높이를 조정합니다. 
# 이때 imagemagick은 그 이미지의 폭과 높이 비율을 유지합니다.
# find ${FOLDER} -iname '*.png' -exec convert \{} -verbose -resize $WIDTHx$HEIGHT\> \{} \;

# JPG만 폭이나 높이가 최대치를 넘어가면 이미지 폭이나 높이를 조정합니다. 
# 이때 imagemagick은 그 이미지의 폭과 높이 비율을 유지합니다.
# find ${FOLDER} -iname '*.jpg' -exec convert \{} -verbose -resize $WIDTHx$HEIGHT\> \{} \;

# 다른 대안 소개 폭과 높이를 일정 비율로 축소하는 방법
# mogrify -path ${FOLDER} -resize ${WIDTH}x${HEIGHT}% *.png -verboseCode language: PHP (php)

다음으로는 배치 파일 resizeimage.sh 파일이 실행 가능하도록 만듭니다.

chmod a+x resizeimage.shCode language: PHP (php)

배치 파일 실행

이제 준비가 다 끝났습니다. 아래와 같은 방식으로 배치 파일 resizeimage.sh를 실행시켜 이미지 사이즈를 조정하도록 합니다.

sh resizeimage.shCode language: PHP (php)

나중에 크론탭을 이용해 정기적으로 이를 실행하면 됩니다.

참고

서버에서 PNG 이미지 최적화로 사이트 속도 개선 방법

이미지 최적화 중 PNG 포맷의 이미지를 최적화하는 방법을 알아봅니다.

여기서는 PNG 이미지 포맷 최적화 방법을 설명하지맘 이미 이전에 우리가 가장 많이 사용하는 이미지 포맷인 JPEG 파일 최적화 방법에 대해 포스팅 한적이 있습니다. 이 내용은 아래 포스팅한 글을 참조하세요.

또한 이미지 최적화 방법 중 WebP 포맷을 이용해 사이트 로딩 속도를 높이고 트래픽을 줄이는 방법에 대해서는 아래 글을 참조하시기 바랍니다.

1. 왜 PNG 포맷을 사용할까?

일반적으로 알기에, 아니 사실 그대로 가장 효율이 좋은 이미지 포맷은 JPEG, JPG입니다. 그러면 이 JPEG만 사용하면 되는데 왜 PNG나 GIF를 사용할까요?

이는 이미지 포맷마다 특성이 조금씩 다르기에 이미지 효율을 높이려면 이미지 포맷마다의 특성을 살려, 별도로 적용할 필요가 있기 때문입니다.

PNG는 투명부분을 지원하고 무손실에 가깝기 때문에 하얀색이 많은 그래프나 도표와 문자 중심의 화면을 저장시 압축 효율과가독성이 뛰어납니다.

그래프를 JPG로 저장 후 압축하면 글자나 그래프의 선들이 뭉개지면서 가독성을 엄청 떨어뜨리는데요. PNG를 사용하면 그런 문제가 없어집니다.

아래는 넷플릭스 실적을 막대와 선 그래프로 그려 PNG로 저장한 것인데요. 폭 1024px로 비교적 큰 이미지이지만 용량은 34kb정도로 작습니다. 그러면서도 그래프 고유의 가독성을 유지하고 있습니다.

JPG로 이정도 용량이 나오도록 압축하면 글자나 선등이 많이 뭉게집니다. 특히 붉은 계열 컬러의 선과 글자는 뭉게져 보기 싫을 정도입니다.

넷플릭스 연도별 매출 및 성장율 추이, Graph by Happist
넷플릭스 연도별 매출 및 성장율 추이, Graph by Happist
GIF지원지원전체
PNG지원지원 안 함전체
JPEG지원 안 함지원 안 함전체
JPEG XR지원지원IE
WebP지원지원Chrome, Opera, Android

2. 가장 좋은 PNG 압축 유틸리티

PNG도 많이 사용하기 때문에 다양한 압축 유틸리티들이 존재합니다.

그들 PNG 이미지 압축 유틸리티 중 pngquant의 압축율이 가장 낫고 그러면서도 속도도 빠르다는 평가입니다.

저도 이미지 작업 시 데스크탑용 pngquant로 PNG 이미지를 압축하는데 확실히 압축율이 좋더군요. 그래서 PNG 압축운 pngquant를 사용하기로 했습니다. 알아보니 구글 전문가들도 이를 추천하고 있더군요.

3. pngquant 설치

우선 pngquant를 우분투 18.04 서버에 설치해 보죠. 아래는 설치 명령어입니다.

apt-get update
apt-get install pngquant -yCode language: PHP (php)

3.1. pngquant 버젼 업데이트

pngquant가 설치되었으면 버젼 체크를 해봅니다. 2015년 6월에 발표된 버젼 2.5.0이네요.

pngquant -V
2.5.0 (June 2015)Code language: PHP (php)

pngquant 사이트에 확인해보니 pngquant의 최신 버젼은 2.12.5네요. 업데이트할 필요가 있습니다.

업데이트는 아래와 같은 패키지를 설치한 후 진행합니다.

apt-get update
apt-get install build-essential liblcms2-dev libpng-dev git -yCode language: PHP (php)

Tmp 폴더에서 최신 pngquant를 다운받습니다.

cd /tmp
git clone https://github.com/pornel/pngquant/
cd pngquant*
./configure --prefix=/usrCode language: PHP (php)

컴파일을 합니다.

make
make installCode language: PHP (php)

다시 pngquant 버젼을 확인해 봅니다. 이제는 최신 버젼이 설치되었네요.

pngquant -V
2.12.6 (July 2019)Code language: PHP (php)

4. pngquant 이용 방법

  • –force : 원본 파일을 덮어쓰기, overwrite existing output files (synonym: -f)
  • –skip-if-larger : 원본 파일 사이즈보다 작은 경우만 저장, only save converted files if they’re smaller than original
  • –output file : destination file path to use instead of –ext (synonym: -o)
  • –ext new.png : set custom suffix/extension for output filenames
  • –quality min-max : don’t save below min, use fewer colors below max (0-100)
  • –speed N : speed/quality trade-off. 1=slow, 4=default, 11=fast & rough
  • –nofs : disable Floyd-Steinberg dithering
  • –posterize N : output lower-precision color (e.g. for ARGB4444 output)
  • –strip : remove optional metadata (default on Mac)
  • –verbose : print status messages (synonym: -v)

5. Batch PNG 최적화

특정 폴더의 PNG 이미지 전체를 한꺼번에 압축 최적화

find /***/******/wp-content/uploads -iname "*.png" -exec pngquant --force --quality=40-100 --skip-if-larger --strip --verbose \{} --output \{} \;Code language: PHP (php)

서버에서 JPEG 이미지 최적화로 사이트 속도 개선 방법

오늘은 사이트 속도 최적화 방법중에서 가장 귀찮고도 어려운 이미지 최적화 방안에 대해서 알아봅니다.

흔히 사용하는 이미지 포맷에는 JPEG와 PNG 그리고 드물게 GIF가 있는데요. 이 중에서 가장 많이 사용하는 JPEG파일 최적화에 대해서 먼저 살펴보죠,

그리고 PNG 파일 최적화 방법은 아래 글을 참조하시기 바랍니다.

또한 이미지 최적화 방법 중 WebP 포맷을 이용해 사이트 로딩 속도를 높이고 트래픽을 줄이는 방법에 대해서는 아래 글을 참조하시기 바랍니다.

1. JPEG 압축 모드에는 무엇이 있을까?

먼저 JPEG 압축에 대해서 본격적으로 살펴보기 전에 JPEG관련 배경 지식 몇가지를 살펴보죠.

1.1. JPEG 이미지 압축모드 세가지

먼저 JPEG 이미지 압축포맷 종류를 알아 보도록 합니다.

당연히 JPEG 가 널리 사용되고 역사도 오래되었기 때문에 끊임없이 새로운 기술이 등장했기에 상당히 많은 압축 모드가 있습니다.

이러한 압축모드 중 널리 사용되는 압축모드 세가지는 Baseline(순차적으로 보여주는 jpeg), Progressive(점진적으로 보여주는 jpeg), 그리고 Lossless(무손실)입니다.

  • Baseline JPEG는 인코딩과 디코딩이 위에서 아래로 진행되기 때문에 웹에서 이미지는 위에서부터 아래로 순서대로 보여줍니다.
    JPEG 이미지 최적화, Baseline모드 설명, Image from google
  • Progressive JPEG는 이미지를 여러번 나누어서 스캡합니다. 첫번째는 흐리게 나타나는 낮은 품질의 이미지이고 스캔 횟수가 늘어날수록 이미지가 뚜렸해지고 품질이 정상에 가까워집니다.
    JPEG 이미지 최적화, Progressive JPEG 설명, Image from google
  • Lossless JPEG는 말 그대로 이미지 품질 저하없이 EXIF 데이타만 제거하거나 이미지 허프만 테이블을 최적화는 정도로 이미지 품질 저하없이 압축하는 것입니다.

1.2. 웹에서 좋은 압축모드는?

그러면 웹에서는 무엇이 좋을까요?

일반적으로 인터넷 속도가 느려도 저품질 이미지를 먼저 보여주고 이미지가 로딩되면 완전한 이미지를 보여주면 사용자들은 사이트가 느리다는 인식을 받지 않는다고 합니다.

그런 의미에서 처음에는 흐린 이미지를 보여주다가 점점 또렸하게 보여주는 Progressive JPEG 방식이 더 낫습니다.

이미지rk 아닌 동영상관련 내용이지만, 넷플릭스의 성공 요인중의 하나로 이런 방식으로 영상 품질 또는 영상 접속에 대한 불만을 최소화한 점이 손꼽히고 있습니다.

즉 넷플릭스는 인터넷 망 상태에 따라 처음에는 저화질 영상을 보여주다가 데이타를 완전히 받으면 고화질 영상으로 전환해 보여주는 기술을 개발, 적용해 낮은 품질의 인터넷 환경하에서도 사용자들의 불만을 최소화하면서 스트리밍 서비스를 할 수 있었습니다.

또한 Progressive JPEG 이미지 용량이 10k 이상되는 경우 Baselinr 방식보다 대역폭이 2~10% 줄어들어 보다 높은 압축이 가능합니다.

다만 이러한 Progressive JPEG 이미지 압축은 인코딩 속도가 느립니다. 경우에 따라서 Baseline 방식보다 3배이상 걸릴 수 있습니다.

그러나 데스크탑 PC를 사용하거나 서버에서 한가한 시간을 이용해 압축한다면 이런 시간 소요는 감당할 수 있을 것입니다.

모바일과 같은 리소스가 제한적인 디바이스에서는 다소 무리가 따를 수 있습니다.

2. 어떤 압축 알고리즘(인코더)을 사용할 것인가?

JPEG 이미지 품질을 크게 낮추지 않으면서도 파일 크기를 획기적으로 줄일 수 있다면 정말 좋겠죠.

어떤 JPEG 인코더를 사용하느냐에 따라 압축률이 차이가 납니다.

이에 대한 답은 이 글에서 추천하는 내용을 그대로 가져오겠습니다.

  • 일반 웹 이미지 에셋: MozJPEG
  • 품질이 주요 고려 대상이고 인코딩 시간이 길어도 상관없다면: Guetzli를 사용

그리고 압축 알고리즘(인코더)의 옵션을 변경해 보다 풍부하고 효율적으로 압축하고 싶다면 아래 방법을 사용할 수 있습니다.

  • JPEGRecompress(내부적으로 MozJPEG을 사용)
  • JPEGMini : 유료 서비스
    Guetzli와 유사하게 자동으로 최상 품질로 인코딩 해줌.
    Guetzli처럼 정교하지는 않으나 속도가 더 빠름
  • ImageOptim API : 유료 서비스

결국 JPEG 압축시 여러 옵션을 주려면 자체적으로 구축 가능한 JPEGRecompress를 사용할 수 밖에 없다는 결론이네요. 비용이 많다면 다른 유료 서비스를 이용할 수 있겠지만요.

2.1. Guetzil에 대해서

Guetzil은 구글에서 만든 지각력을 갖춘 JPEG 인코더입니다.

즉 사람 눈으로는 차이를 느낄 수 없는 수준의 압축 상태를 자동으로 판별해 최상의 품질을 유지하면서 높은 압축율을 보여주는 새로운 기술입니다.

구글의 최신 기술이 잘 녹여든 이 Guetzli에 대한 칭찬도 많지만 이에 대한 비판도 많습니다.

장점이라면 압축율이 가장 좋다고 합니다.

그렇지만 일부 테스트 결과는 MozJPEG를 활용한 JPEGRecompress보다는 못하다는 테스트 결과도 있습니다. 압도적으로 압축율이 좋다고 말할 수 없죠

그렇지만 앞서 이야기한대로 자동으로 눈으로 확인 불가능한 수준까지 압축을 해주기 때문에 가장 효율적으로 이미지를 활용할 수 있습니다.

반면 단점도 많이 있죠. 아래와 같은 단점을 지적할 수 있을 것 같습니다.

  • 압축시간이 많이 걸려 CPU에 많은 부담을 줍니다.
    MozJPEG보다 800~1000배 더 시간이 걸린다고 하네요.
  • jpeg Progressive 옵션을 지원하지 않습니다.
  • 오직 sRGB만 지원합니다.
  • 정적인 콘텐츠에서만 사용 가능합니다.

구글에서는 Guetzli는 고품질 이미지에 사용하라고 제안합니다. (Butteraugli는 q=90+에 가장 적합)

2.2. MozJPEG는 뭐죠?

MozJPEG는 파이어폭스 브라우져를 개발한 곳으로 유명한 모질라는 인터넷 사용 경험 개선을 위한 여러가지 프로젝트를 진행해 왔는데요.

이 중 하나가 웹 트래픽을 줄이고, 로딩을 빠르게 만들어 인터넷 사용 경험을 개선하기 위한 획기적인 JPEG 파일 압축 방식을 2014년에 발표했습니다.

이 방식을 사용하면 JPEG 파일 용량을 약 10%이상 줄일 수 있다고 합니다.

일반적으로 MozJPEG는 압축 품질을 q=75 정도로 세팅하면 가장 좋다고 합니다.

2.3. 무엇을 사용할 것인가?

구글에서 야심차게 개발한 Guetzil은 압축은 뛰어나지만 너무 서버 자원을 많이 요구하고 몇가지 단점도 있습니다.

따라서 Guetzil 대안으로 MozJPEG를 적용한 JPEGRecompress를 사용하기로 했습니다.

3. 우분투에서 JPEGRecompress 적용 방법

우분투 18.04가 적용된 Vultr VPS 서버에서 테스트한 방법입니다.

3.1. 백업

뭐든 새로운 작업을 하려면 완벽한 백업을 한다음 해야죠.

지금 하려는 것은 워드프레스에서 사용하는 JPEG 이미지를 최적화하는 방법이므로 최소한 이미지들은 전부 백업해 놓은 것이 좋습니다.

우선은 이미지 폴더인 uploads 폴더 전체를 백업하기로 하죠.
아래와 같은 명령어를 사용하면 금방 전체 이미지를 압축해 줍니다.

# tar -cvzf imagebackup20200129.tgz /****/****/wp-content/uploadsCode language: PHP (php)

3.2. 먼저 MozJPEG 설치하자

jpeg-recompress는 기본 압축 알고리즘으로 MozJPEG를 사용하므로 이를 설치해 줍니다.

MozJPEG를 설치하기 전에 업데이트 및 MozJPEG 컴파일에 필요한 프로그램들을 설치합니다.

apt-get update
apt-get install build-essential autoconf pkg-config nasm libtool git gettext libjpeg-dev -y
Code language: PHP (php)

다음으로는 MozJPEG 최신 버젼이 무엇인지 확인합니다. MozJPEG 최신 버젼 확인은 여기 링크 주소에서 할 수 있습니다. 제가 확인 시 v3.3.1이 최신 버젼이네요.

MozJPEG 최신 버젼 3.3.1.을 wget을 사용해 다운받습니다.

cd /tmp
wget https://github.com/mozilla/mozjpeg/archive/v3.3.1.tar.gz -O mozjpeg.tar.gz
tar -xf mozjpeg.tar.gz
cd mozjpeg-3.3.1
autoreconf -fiv
./configure --with-jpeg8 --prefix=/usr
make
make installCode language: PHP (php)

3.3. jpeg-recompress 설치하기

아래 명령어를 사용해서 jpeg-recompress를 설치합니다.

다만 jpeg-archive는 2.2.0으로 업데이트되었지만 리눅스용으로 컴파일된 것을 찾지못해 2.1.1 버젼을 그대로 사용했습니다.

apt-get install bzip2
cd /tmp
wget https://github.com/danielgtaylor/jpeg-archive/releases/download/2.1.1/jpeg-archive-2.1.1-linux.tar.bz2 -O jpeg-archive.tar.bz2
tar -xf jpeg-archive.tar.bz2
cp jpeg-recompress /usr/bin/jpeg-recompress
chmod 755 /usr/bin/jpeg-recompressCode language: PHP (php)

여기까지 마쳤다면 필요한 모든 것은 설치된 셈입니다.

3.4. jpeg-recompress에서 사용가능한 이미지 매트릭스

jpeg-recompress에서는 아래 이미지 매트릭스가 사용 가능합니다. 디폴트는 SSIM입니다.

NameOptionDescription
MPE-m mpeMean pixel error (as used by imgmin)
SSIM-m ssimStructural similarity DEFAULT
MS-SSIM*-m ms-ssimMulti-scale structural similarity (slow!) (2008 paper)
SmallFry-m smallfryLinear-weighted BBCQ-like (original project2011 BBCQ paper)

이러한 매트릭스 및 옵션 명령어를 사용해 이미지를 압축합니다. 예를드면 아래와 같은 명령을 사용할 수 있습니다.

jpeg-recompress --quality medium --method ssim dog.jpg dogoutput.jpg
jpeg-recompress --quality high --method smallfry --min 60 dog.jpg dogsmallfry.jpg
jpeg-recompress --quality high --accurate --method smallfry --min 60 dog.jpg accurate.jpgCode language: PHP (php)

3.5. Screen 설치

서버에 있는 수만개의 이미지를 압축한다면 screen을 설치해 사용하라고 합니다.

이 screen은 SSH 세션이 끊겨도 계속 작업을 진행하기 때문에 수만장의 이미지 압축처럼 장시간 작업이 필요한 경우 유용하다고 합니다.

apt-get install screenCode language: PHP (php)

screen 명령을 사용해 screen 세션으로 전환합니다.

screenCode language: PHP (php)

3.6. JPEG 파일의 Batch 최적화

특정 폴더, 워드프레스에서는 이미지가 있는 uploads 폴더에 있는 jpeg 파일 전체를 압축하려면 아래와 같은 명령을 사용합니다.

  • find 명령은 하위 폴더를 포함해 모든 이미지가 압축 처리되도록 검색합니다.
  • 목적에 맞도록 적절한 quality와 min 값을 매트릭스 및 압축 옵션을 적용해야 합니다.
find /***/******/wp-content/uploads -type f -iname '*.jpg' -exec jpeg-recompress --quality medium --min 60 --method smallfry \{} \{} \;Code language: PHP (php)

3.7. screen 해제

Batch 작업을 위해 작동했던 screen을 해제하기 위해는 Ctrl+A를 누른다음 D를 누릅니다.

screen을 다시 가동시키려면 아래 명령을 사용합니다.

screen -rCode language: PHP (php)

3.8. 이미지의 EXIF 정보를 일괄 삭제하기

exiftool를 이용하면 이미지의 EXIF 정보를 일괄 삭제 가능합니다.

먼저 exiftool를 설치합니다.

apt install exiftoolCode language: PHP (php)

일괄 삭제는 아래와 같은 명령을 사용합니다.

  • 디폴트로 이미지를 jpg_original 확장자를 붙여 백업하도록 되어 있음
  • 백업하지않고 압축파일만 사용하려면 -overwrite_image 옵션을 사용합니다.
find /***/******/wp-content/uploads -type f -iname "*.jpg" -exec exiftool -overwrite_original -all= \{} \;Code language: PHP (php)

NGINX에서 최고의 이미지 압축 포맷 WebP 적용 방법

오늘은 Nginx 웹서버에서 최고의 이미지 압축 포맷이라고 불리우는 Webp 적용 방법을 알아봅니다.

적용 방법에는 매우 다양한 방법이 있는데요, 오늘은 조금 단순하면서 적용하기 용이한 방법을 소개합니다.

참고로 WebP를 지원하는 브라우저에 대한 관심이 높을 수 밖에 없는데요. 아래 링크 페이지에서 WebP 지원 브라우저 현황을 볼 수 있습니다.

이에 따르면 WebP 포맷은 20년 11월 현재 전체 브라우저 79% 정도 87.7%를 커버하고 있네요(데스크탑 90%, 모바일 87%)

이 글을 작성한 지 1년이 채 지난지 않았는데 webp 포맷 커버리지 10%이상 올랐습니다. 아마도 아이폰에서 이 webp 포맷을 지원하면서 비율이 크게 올라간 것 같습니다.

WebP image format

2020년 11월 현재 webp 이미지 포맷 지원 브라우저

이 방법은 아래 글을 기반으로 정리, 수정 보완했습니다.

ADDING WEBP SUPPORT FOR NGINX

1. WebP 설치

먼저 우분투 NGINX 웹서버에서 WebP를 설치합니다. 우분투에서는 apt-get 명령어를 사용해 WebP를 설치하면 그것으로 끝입니다.

apt-get install webpCode language: PHP (php)

2. Webp 적용을 위한 NGINX 웹서버 세팅

이제는 NGINX 웹서버 세팅을 통해서 WebP 이미지를 브라우저가 지원하는지 학인 후 지원한다면 Webp 이미지가 기본으로 설정되도록 만듭니다

먼저 NGINX 웹서버 동작을 설정하는 http 블락안에 다음 코드를 추가합니다.

이는 브라우저가 WebP 이미지를 지원하는지 확인합니다. 만약 브라우저가 Webp 이미지를 지원한다면 WebP 이미지 파일이 웹 소스의 기본 이미지 파일로 설정됩니다.

인터넷 익스플러처럼 WebP 이미지를 지원하지 않는다면 WebP 이미지가 아닌 본래의 jpg나 png 파일을 웹 소스의 기본 이미지 파일로 설정합니다.

map $http_accept $webp_suffix {
  default   "";
  "~*webp"  ".webp";
}Code language: PHP (php)

다음으로는 server 블락안에 다음 코드를 추가합니다.

이는 브라우저가 WebP 이미지를 지원하는 경우, 모든 이미지(jpg, png)에 대한 WebP 이미지를 로딩하도록 합니다.

location ~* ^.+\.(jpe?g|png) {
  add_header Cache-Control "public, no-transform";
  add_header Vary "Accept-Encoding";
  try_files $uri$webp_suffix $uri =404;
  expires max;
}Code language: PHP (php)

Webp 적용위해 NGINX 웹서버에서 이미지 변환하기

글을 작성 시 jpg 파일과 함께 WebP 이미지 파일을 같이 올렸다면 상관이 없지만 대부분은 그렇지 않기 때문에 서버에 있는 jpg나 png 포맷 이미지에 WebP 포맷 이미지를 추가합니다.

즉 서버의 이미지 저장 폴더에는 확장자가 jpg 또는 png인 이미지 파일 하나와 WebP 확장자를 가진 이미지 파일의 2개의 이미지가 존재하게 됩니다.

웹서버는 WebP 이미지를 지원하는 브라우저에게는 WebP 이미지를 로딩해 주고, 지원하지 않는 브라우저에게는 원래의 jpg 또는 png 파일을 로딩합니다.

그렇기 때문에 WebP 이미지를 이용한다는 것은 기존 jpg 파일에 추가로 WebP 이미지를 추가로 가지고 있기 때문에 서버 용량을 더 많이 차지 합니다.

다만 WebP 이미지를 지원하는 대부분의 브라우져에서는 로딩 속도가 빠르고 트래픽 양이 줄어드는 긍정적인 효과가 있습니다.

아래 코드는 jpg나 png 파일 원본은 그대로 유지하면서 추가로 WebP 파일을 생성해주는 코드입니다.

여기에서는 쉽게 사용하기 위해 sh 파일 스크립트로 사용하도록 만들겠습니다.

먼저 webp.sh 파일을 만듭니다. 만드는 파일 위치는 적절히 관리 가능한 곳에 만듭니다.

여기서는 제가 주로 사용하는 편집기로 가장 쉽다는 nano를 사용했으니 여러분이 사용하는 편집기로 webp.sh 파일을 만들고 코드를 입력하면 됩니다.

nano webp.shCode language: PHP (php)

다음으로는 webp.sh 파일안에 WebP 파일 생성 코드를 추가합니다.

  • 아래 코드 중 echo가 있는 줄은 삭제해도 무방합니다.
  • 이미지 파일이 있는 폴더 위지는 서버의 풀 주소를 사용합니다.
    예를 들어 /home/mysite/wp-content/uploads
  • WebP 파일을 만드는 명령어인 cwebp의 옵션을 정합니다. 옵션은 아래와 같은 것들이 있습니다.
    -lossless : 무손실 WebP 이미지 파일을 만듭니다.
    -q : 압축율 지정 예를 들어 -q 80처럼
    -quiet : 아무것도 인쇄하지 말라는 옵션
    -resize width height : 이미지 크기를 조정, width나 height 중 하나가 0이라면 종횡비를 유지
  • Webp 적용을 위한 압축율을 조정할 수 있습니다.
    아래는 압축 옵션으로 -q 80를 적용하고 있는데요. 이 압축율 대신 다른 원하는 압축율로 변경합니다. 예를 들어 -q 90처럼 말입니다.
    중간 품질 -q 75가 WebP에선 기본값이라고 하네요.
    80~99는 고품질로 WebP의 잇점은 감소한다고 구글은 이야기합니다. WebP는 품질보다 속도가 중요한 경우 사용하라고 하네요.
echo "===== Converting images into WebP .webp ====="
for x in `find 이미지 파일이 있는 폴더 위치(예 /var/www/happist) -type f \( -iname \*.jpeg -o -iname \*.jpg -o -iname \*.JPG -o -iname \*.png \)`
  do cwebp -quiet -q 80 ${x} -o ${x}.webp;
  echo "Converted $x to ${x}.webp"
doneCode language: PHP (php)

다음으로는 webp.sh 파일을 실행 가능하도록 만들어야 합니다. 이는 chmod 명령어를 사용합니다.

chmod a+x webp.shCode language: PHP (php)

이제 준비가 다 끝났습니다. 아래와 같은 방식으로 webp.sh를 실행시켜 WebP 이미지를 생성하도록 합니다.

sh webp.shCode language: PHP (php)

Webp 적용을 위한 cwebp 옵션

Options:
  -h / -help ............. short help
  -H / -longhelp ......... long help
  -q <float> ............. quality factor (0:small..100:big), default=75
  -alpha_q <int> ......... transparency-compression quality (0..100),
                           default=100
  -preset <string> ....... preset setting, one of:
                            default, photo, picture,
                            drawing, icon, text
     -preset must come first, as it overwrites other parameters
  -z <int> ............... activates lossless preset with given
                           level in [0:fast, ..., 9:slowest]

  -m <int> ............... compression method (0=fast, 6=slowest), default=4
  -segments <int> ........ number of segments to use (1..4), default=4
  -size <int> ............ target size (in bytes)
  -psnr <float> .......... target PSNR (in dB. typically: 42)

  -s <int> <int> ......... input size (width x height) for YUV
  -sns <int> ............. spatial noise shaping (0:off, 100:max), default=50
  -f <int> ............... filter strength (0=off..100), default=60
  -sharpness <int> ....... filter sharpness (0:most .. 7:least sharp), default=0
  -strong ................ use strong filter instead of simple (default)
  -nostrong .............. use simple filter instead of strong
  -sharp_yuv ............. use sharper (and slower) RGB->YUV conversion
  -partition_limit <int> . limit quality to fit the 512k limit on
                           the first partition (0=no degradation ... 100=full)
  -pass <int> ............ analysis pass number (1..10)
  -crop <x> <y> <w> <h> .. crop picture with the given rectangle
  -resize <w> <h> ........ resize picture (after any cropping)
  -mt .................... use multi-threading if available
  -low_memory ............ reduce memory usage (slower encoding)
  -map <int> ............. print map of extra info
  -print_psnr ............ prints averaged PSNR distortion
  -print_ssim ............ prints averaged SSIM distortion
  -print_lsim ............ prints local-similarity distortion
  -d <file.pgm> .......... dump the compressed output (PGM file)
  -alpha_method <int> .... transparency-compression method (0..1), default=1
  -alpha_filter <string> . predictive filtering for alpha plane,
                           one of: none, fast (default) or best
  -exact ................. preserve RGB values in transparent area, default=off
  -blend_alpha <hex> ..... blend colors against background color
                           expressed as RGB values written in
                           hexadecimal, e.g. 0xc0e0d0 for red=0xc0
                           green=0xe0 and blue=0xd0
  -noalpha ............... discard any transparency information
  -lossless .............. encode image losslessly, default=off
  -near_lossless <int> ... use near-lossless image
                           preprocessing (0..100=off), default=100
  -hint <string> ......... specify image characteristics hint,
                           one of: photo, picture or graph

  -metadata <string> ..... comma separated list of metadata to
                           copy from the input to the output if present.
                           Valid values: all, none (default), exif, icc, xmp

  -short ................. condense printed message
  -quiet ................. don't print anything
  -version ............... print version number and exit
  -noasm ................. disable all assembly optimizations
  -v ..................... verbose, e.g. print encoding/decoding times
  -progress .............. report encoding progress

Experimental Options:
  -jpeg_like ............. roughly match expected JPEG size
  -af .................... auto-adjust filter strength
  -pre <int> ............. pre-processing filter
Code language: PHP (php)

참고

무료로 구축하는 이미지 최적화 자동화 시스템

아파치에서 inotify-tools을 사용한 WebP 이미지 적용 및 관리 방법

NGINX에서 최고의 이미지 압축 포맷 WebP 적용 방법

워드프레스 이미지 설정 최적화 방법

[워드프레스 최적화] 구글 페이지스피드 활용, 최고 이미지 포맷 WebP 이용 방법

Imagemagick 이용, 이미지 사이즈 일괄 변경 방법

서버에서 PNG 이미지 최적화로 사이트 속도 개선 방법

서버에서 JPEG 이미지 최적화로 사이트 속도 개선 방법