-0.7 C
New York
수요일, 12월 31, 2025

Buy now

Home Blog Page 234

코로나로 부진의 끝을 보여준 20년 2분기 스타벅스 실적

조금 시간이 지났지만 2020년 7월 28일 스타벅스 2분기 실적이 발표되었길래 간략히 정리, 메모해 봅니다.

  • 매출: 42.21억 달러(약 5조 631억원)
    전년 동기 비 -38.1% 역성장
  • 영업이익: 7.39억 달러(약 8,864억원)
    전년 동기 비 -162.8% 역성장
  • 주당순손실: 46센트, 전년 동기 비 -159%

코로나로 극히 부진했지만 점차 극복 중

아래 그래프에서 보는 것처럼 이번 20년 2분기 스타벅스 매출은 42억 달러로 전년 동기 비 -38.1% 감소했습니다.

코로나가 발발한 1분기에 -5 감소에 그쳤지만 코로나 팬데믹이 본격화된 2분기에는 가택대기력(Stay At Home)에 따라 오프라인 매장 매출이 극히 저조했던 것이 그 원인입니다.

스타벅스 분기별 매출 및 전년 동기 비 성장률 추이, Starbucks net Income Trend, Graph by Happist
스타벅스 분기별 매출 및 전년 동기 비 성장률 추이, Starbucks net Income Trend, Graph by Happist

그러나 이렇게 극히 부진한 실적을 냈지만 스타벅스 경영진은 이번 2분기 실적은 코로나 팬데믹으로 인한 일시적인 매출 감소로 점차 회복하고 있다고 밝혔습니다.

기업 실적 공개 시 CEO의 언급은 그동안 별 관심을 가지지 않았는데요. 요즘 실적 발표시 주주들과 시장에 전하는 CEO 메세지가 상당히 그 회사 전망을 확인하는데 도움이 된다는 생각을 합니다.

이번 스타벅스 실적 발표에서 케빈 존슨(Kevin Johnson) 스타벅스 사장 겸 최고경영자(CEO)는 아래와 같이 스타벅스 상황을 설명했습니다.

“지난 1월 코로나10가 시작된 이래 위기를 전망하고 우리 임무에 충실하기 위해 가장 원칙적인 접근 방식을 취했습니다.
모든 단계에서 스타벅스 이해 관계자들의 요청 사항을 중시하고 해결해 왔습니다. 특히 우리의 파트너들이 고객을 보다 안전하고 친숙하면서도 편리한 경험을 제공할 수 있도록 업계 최고의 투자를 했다는 점을 자랑스럽게 생각합니다.
우리 파트너들은 이러한 위기속에서 맹활약을 하면서 고객에게 스타벅스만의 경험((Starbucks Experience)을 제공하면서 판매를 회복하고 있습니다.”

“현재 전 세계 스타벅스 매장들이 재개방했으며, 글로벌 비지니스가 꾸준히 희복하고 있습니다. 이는 스타벅스 브랜드 관련성과 고객의 신뢰를 보여주고 있습니다. 우리는 비지니스를 회복시킴과 동시에 고객 및 파트너 경험을 높이고 장기적인 성장을 이끌 수 있는 방향으로 비지니스 변화를 가속화할 것입니다. 우리는 코로나 팬데믹 이전의 긍정적인 비지니스 모멤텀을 회복하고 있다고 확신합니다.”

2분기 스타벅스 실적 주요 내용

미국뿐만이 아니라 중국을 비롯한 대부분 지역에서 트래픽이 감소해 비교매장매출(comparable store sales)이 크게 감소했습니다.

  • 글로벌 비교매장매출(comparable store sales)은 트래픽이 -51% 감소 및 평균 티켓 판매가 23% 증가하면서 전년 비 40% 감소
  • 미국을 포함한 북미 비교매장매출(comparable store sales)은 트래픽이 -53% 감소 및 티켓 판매 27% 증가에 따라 전년 비 -41% 감소
  • 글로벌 비교매장매출(comparable store sales)은 트래픽 -44% 감소 및 티켓 판매 13%로 -37% 감소
  • 중국은 비교매장매출(comparable store sales)은 트래픽 -27% 감소 및 티켓 판매 10% 증가에 따라 전년 비 -19% 감소

그러나 코로나 팬데믹에도 불구하고 스타벅스 매장은 오히려 늘었습니다.

  • 코로나 와중 글로벌로 130개 매장을 새롭게 열었습니다.
    따라 2020년 2분기말 기준으로 스타벅스 32,180개 매장을 보유하게 되었습니다.
  • 이중 회사 직영점은 51%를 차지하고 49%는 라이센스 매장입니다.
  • 스타벅스에서 미국과 중국의 비중은 절대적으로 높아 20년 2분기 기준으로 스타벅스 포트폴리오의 61%를 차지하고 있습니다.
    미국 매장 수 15,243개와 중국 매장 수 4,447개

순이익률 -16%로 악화

코로나 팬데믹으로 판매 손실이 커지면서 순이익은 42억 달러로 전년 비 -38% 감소했습니다.

더우기 순이익률도 전분기 5%에서 -16%로 크게 악화했습니다.

스타벅스 분기별 순이익 및 순이익률 추이, Starbucks net Income Trend, Graph by Happist
스타벅스 분기별 순이익 및 순이익률 추이, Starbucks net Income Trend, Graph by Happist

20년 2분기 스타벅스 실적 발표 자료

코로나로 최고 매출 및 두배 이익을 낸 20년 2분기 아마존 실적

코로나 팬데믹 대응으로 40억 달러 이상을 투입했야했지만 이를 상쇄하고 남을 정도로 판매가 증가하면서 20년 2분기 아마존 실적은 사상 최고 매출과 이익을 낸 최고의 분기가 되었습니다.

이는 온라인 판매 48% 증가, 글로벌 판매 40% 증가 등 전 부문에서 고른 성장의 결과이기도 했습니다.

  • 아마존 전체 매출 889억 달러, 전년 비 40.2% 성장
    영업이익 58억 달러, 영업이익률 6.6%
    순이익 52억 달러, 순이익률 5.9%
  • 온라인 매출 459억 달러, 전년 비 48% 성장
    북미 매출 554억 달러, 전년 비 43.4% 성장
    글로벌 매출 227억 달러, 전년 비 40% 성장
  • 아마존 웹 서비스(AWS) 매출 108억 달러, 전년 비 29% 성장
    영업이익 34억 달러, 영업이익률 31.1%로 최고치 기록
  • 광고가 포함된 기타 부문 매출 42억 달러, 전년 비 41% 성장
  • 아마존 프라임 멤버쉽과 같은 서브스크립션 서비스 매출 60억 달러로 전년 비 28.7% 성장

코로나 팬데믹으로 매출 및 이익 증가

코로나 팬데믹 수혜를 크게 입은 아마존은 20년 2분기에 매출 889억 달러를 기록해 전년 동기 비 40.2% 성장했고, 영업이익 58억 달러 영업이익률 6.6%를 기록해 매출과 손익 부분에서 커다란 성장을 이루었습니다.

  • 매출 889억 달러로 전년 동기 비 40.2% 성장
  • 비수기임에도 불구하고 코로내 팬데믹 덕분에 성수기 매출 수줄을 능가해 분기당 최고 매출을 달성
    (2019년 4분기 매출 874억 달러)
아마존 분기별 매출 및 전년 비 성장율(2014년 1분기 ~ 2020년 2분기) Amazo revenue & y2y growth rate by quarter, Graph by Happist
아마존 분기별 매출 및 전년 비 성장율(2014년 1분기 ~ 2020년 2분기) Amazo revenue & y2y growth rate by quarter, Graph by Happist

코로나 팬데믹 대응 40억 달러이상 투자에도 이익 증가

아마존은 이번 코로나 팬데믹 대응을 위해 40억 달러 이상을 투자했다고 밝혔습니다. 여기에는 직원 건강 보호 및 아마존 직원 및 파트너에게 주급 인상 등 보상 프로그램 제공등이 포함됩니다.

그럼에도 불구하고 20년 2분기 아마존 영업이익 및 순익은 큰 폭으로 증가했습니다.

  • 2분기 영업이익 55억 달러, 영업이익률 6.6% 기록
  • 2분기 순이익 52억 달러, 순이익률 5.9%
아마존 분기별 순이익 및 순이익율 추이(2014년 1분기 ~ 2020년 2분기) Amazo Net Imcome & Net Income Margin by quarter, Graph by Happist
아마존 분기별 순이익 및 순이익율 추이(2014년 1분기 ~ 2020년 2분기) Amazo Net Imcome & Net Income Margin by quarter, Graph by Happist

온라인 판매 급증 – 전년 비 48% 성장

이러한 아마존 매출 증가는 전년비 48% 성장한 온라인 판매에서 왔습니다.

익히 알려졌지만 코로나 팬데믹은 아마존과 같은 이커머스 기업에게는 날개를 달아준 절호의 기회였습니다.

아마존 온라인 판매는 평소 전년 비 10%대 성장률을 보였지만 코로나 팬데믹이 시작된 1분기엔 24% 성장으로 높아지더니 코로나 팬데믹이 본격화된 2분기엔 전년 비 무려 48% 성장했습니다.

20년 2분기 아마존 온라인 판매는 459억 달러를 기록해 최대 성수기인 연말 판매와 비슷한 수준으로 증가했습니다.

얼핏 보기에는 코로나 팬데믹으로 연말을 훨씬 더 뛰어넘는 판매를 올릴 것으로 생각되지만 실상은 지난 연말 성수기와 비슷한 수준의 판매를 보였습니다. 아마존 온라인 판매에 대해서는 생각보다는 대단하지는 않다는 생각입니다.

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

오프라인 매장 판매 감소- 전년 比 -12.8%

그렇지만 밝은 면이 있으면 어두운 면도 있겠죠.

아마존이 최근 몇년간 야심차게 밀어부친 오프라인 판매는 상대적으로 저조했습니다. 오프라인 매출은 38억 달러로 전년 동기 비 -13% 역성장에 그친 것이죠.

코로나 팬데믹에 따른 매장 폐쇄가 중요한 판매 감소 원인이라고는 하나, 월마트와 같은 기존 유통들의 오프라인 판매가 줄지 않았다는 보도를 감안하면 아마존 오프라인 판매 감소는 아마존 경쟁력에 대해서 주의깊게 볼 필요는 있다는 생각입니다.

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

이러한 절대적으로 높은 비중을 차지하는 온라인 판매 급증에 따라 아마존 북미 지역 매출도 554억 달러를 기록해 전년 비 43.4% 증가해 예년 아마존 전성기 모습을 보여주었습니다.

  • 북미 매출 554억 달러, 전년 동기 비 43.4% 성장
  • 북미 영업이익 21억 달러로 영업이익률 3.9%(이는 예전 수준보다는 다소 낮은 수준)

글로벌 매출 40% 성장 및 5년만에 흑자 전환

또한 이번 20년 2분기 아마존 시적에서 눈길을 사로잡는 것 중의 하나는 북미를 제외한 글로벌 실적이었습니다.

아마존 글로벌 진출은 일정 지역에 성과를 내고 있음에도 불구하고 북미에서처럼 압도적인 경쟁력을 보여주지 못하고 있었습니다.

아마존 전체에서 차지하는 비중이 점점 감소하고 투자가 급증하면서 이익을 낼 가망이 적어 보였습니다.

그러나 이번 코로나 팬데믹으로 아마존 글로벌 판매는 전년 비 40% 성장하면서 북미 판매 증가률(43.4%) 못지않은 성과를 냈으며 정말 오랜만에 영업이익이 흑자로 전환되었습니다.

  • 20년 2분기 아마존 글로벌 매출은 227억 달러로 전년 동기 비 40% 성장
    아마존 글로벌 매출 성장률은 최근 5년 내 가장 높은 수준
  • 이에 따라 아마존 글로벌 판매 비중은 25.5%로 소폭 상승
  • 아마존 글로벌 영업이익 3억 달러, 영업이익률 1.5%로 최근5년 내 처음으로 흑자 전환 함
    (2014년 4분기 영업이익 1억 달로로 흑자 전환 후 계속 적지 시현)
아마존 분기별 글로벌 부문 매출 및 전년 비 성장율(2014년 1분기 ~ 2020년 2분기) Amazo International revenue & y2y growth rate by quarter, Graph by Happist
아마존 분기별 글로벌 부문 매출 및 전년 비 성장율(2014년 1분기 ~ 2020년 2분기) Amazo International revenue & y2y growth rate by quarter, Graph by Happist

성장했지만 아쉬운 AWS 실적

이번 코로나 팬데믹은 언텍트 비지니스가 크게 흥하면서 이러한 언택트 비지니스를 지원하는 클라우드 성장을 이구동성으로 지적했습니다.

그런 의미에서 클라우드 시장을 장악하고 있는 아마존 웹 서비스(AWS) 매출 증가에 대한 관심이 높았습니다.

그러나 시장의 높은 기대와 달리 아마존 웹 서비스(AWS) 매출은 108억 달러를 기록해 지금까지 최고 매출 성적을 갱신하기는 했지만 전년 동기 비 성장률은 29%로 사상 최저 수준에 머물렀습니다.

아마존 웹 서비스 매출 규모가 100억 달러를 넘으면서 성장이 쉽지 않고, 29% 성장도 어마어마한 성장률이라는 것은 분명하지만 지금까지 아마존 매출 성장률 둔화 추세를 이번 코로나 팬데믹에도 극복하지는 못했다는 점에서 아쉬움이 있습니다.

그렇지만 아마존 웹 서비스 영업이익은 34억 달러, 영업이익률 31.1%로 사상 최고치를 기록했습니다.

애플이나 마이크로소프트 이익률이 30%가 넘는데 아마존 웹 서비스(AWS) 이익률은 이런 수익성 극강 회사들과 비슷한 수준으로 높은 이익을 낳고 있습니다.

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

코로나 팬데믹 경기 침체에도 광고 부문 성장

또 하나 아마존 실적에서 도드라지는 부문은 아마존 광고 부분입니다.

아시다시피 아마존은 광고 실적을 별도로 발표하지는 않기 때문에 기타 부문 매출로 광고 매출 추이를 추정합니다. 이 기타 부문 매출 대부분은 광고 매출이라고 하네요.

20년 2분기 아마존 광고 매출은 42억 달러로 전년 비 40.6 성장으로 코로나 팬데믹으로 고아고 시장이 극심한 위축을 보인 가운데 예전에 못지않은 성장세를 보였습니다.

이는 코로나 팬데믹으로 경기 침체가 심해지면서 구글이나 페이스북 광고 성장률이 둔화되는 것에 비해서 훨씬 더 긍정적인 모습이라고 할 수 있습니다.

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

아마존 실적 발표 자료

20년 2분기 마이크로소프트 실적, 코로나에도 놀라운 매출(13%)과 순이익률 30% 실현

코로나 팬데믹이 미국을 비롯한 글로벌 전역에서 여전히 기숭을 부렸지만 20년 2분기 마이크로소프트 실적은 시장 기대를 넘는 13% 매출 성장과 30% 손익률을 기록하면서 코로나 팬데믹에도 굳건한 모습을 보였습니다.

여기 간단히 마이크로소프트 20년 2분기 실적을 정리해 봅니다. 매출은 13% 증가하고 손익률도 30%가까이 유지하면서 시장 기대를 상회하는 좋은 실적을 냈습니다.

  • 2분기 매출 380억 달러, 전년 동기 비 13% 증가
  • 2분기 영업이익 134.2억 달러, 영업이익률 35.3%
  • 2분기 순이익 112억 달러, 순이익률 29.5%
  • 주당 이익 1.46달러

월가 애널리스트들의 마이크로소프트 투자의견 및 마이크로소프트 주가 전망

분기별 마이크로소프트 실적 분석 및 월가 애널리스트들의 마이크로소프트 투자의견 및 마이크로소프 목표 주가 등 마이크로소프트 투자에 도움이 될만한 정보를 더 원하면 아래 글을 참조하세요.

마이크로소프트 2분기 매출 – 13% 성장

20년 2분기 마이크로소프트 매출은 380억 달러로 전년 동기 비 12.8% 성장했습니다.

최근 마이크로소프트 분기별 성장률은 12~14%선을 유지하고 있었기 때문에 이번 20년 2분기 매출 성장률 13%는 예전 수준을 유지한 수준이라고 볼 수 있습니다.

마이크로소프트 분기별 매출 및 매출증가율 추이( ~ 2020년 2분기), Graph by Happist
마이크로소프트 분기별 매출 및 매출증가율 추이( ~ 2020년 2분기), Graph by Happist

마이크로소프트 2분기 순익 112억 달러, 순익률 29.5%

마이크로소프트 20년 2분기 순익은 112억 달러로 순이익율은 29.5%로 예전보다 약간 낮은 수준이지만 코로나 팬데믹을 감안하면 매우 훌륭한 성과라고 할 수 있습니다.

2019년 2분기이래 4분기 연속 순이익률이 30%를 넘었지만 이번에는 코로나 팬데믹 대응으로 손익이 약간 떨어졌다는 점에서 아쉬운 일이지만, 코로나 팬데믹이라는 점과 경쟁사 순익 수준으로 고려하면 여전히 압도적인 경쟁ㄹ겨을 가지고 있습니다.

마이크로소프트 분기별 순이익 및 순이익률 추이( ~ 2020년 2분기), Graph by Happist
마이크로소프트 분기별 순이익 및 순이익률 추이( ~ 2020년 2분기), Graph by Happist

마이크로소프트 비지니스 영역별 매출

마이크로소프트 비지니스 영역은 생산성(productivity), 클라우즈 그리고 퍼스널 제품군으로 나눕니다.

이 세개의 영역 중에서 퍼스널 제품군은 5%이하로 저성장 중이고, 생산성(productivity) 부문은 10% 중반대 성장하며, 클라우드 부문은 최근 20% 후반대 성장을 지속하고 있었습니다.

생산성 부문 6.4% 성장에 그침

그러나 이번 코로나 팬데믹의 영향으로 20년 2분기 마이크로소프트 생산성 부문은 118억 달러 매출을 올려 전년 비 6.4% 성장에 그쳤습니다. 전 분기엔 전년 비 15% 성장한 것에 비하면 상당한 수준으로 성장률이 둔화된 것입니다.

퍼스널 제품군 14.5% 고성장

반면 평소에 5%이하 저상장중이던 퍼스널 제품군은 129억 달러 매출을 올려 전년 동기 비 14.5% 성장하면서 평소 세배에 달하는 상장률을 보였습니다.

이는 코로나 팬데믹으로 온라인 교육이 증가하고 학교 교육도 온라인으로 대체되면서 관련 기기들 판매가 증가했기 때문으로 풀이됩니다.

클라우드 제품군 17.4%로 성장률 둔화

클라우드 제품군은 134억 달러 매출을 올려 전년 동기 비 17.4% 성장했습니다.

이 성장 수치로만보면 높은 수준이지만 마이크로소프트 평소 클라우드 부문 매출 성장률이 20% 후반대에 이르렀다는 점을 고려하면 상당히 성장률은 눈화된 것입니다.

마이크로소프트 분기별 비지니스 영역별 매출 추이( ~ 2020년 2분기), Graph by Happist
마이크로소프트 분기별 비지니스 영역별 매출 추이( ~ 2020년 2분기), Graph by Happist

마이크로소프트 클라우드 제품군중에서 아마존 웹 서비스와 경쟁하고 있는 마이크로소프트 애저(Azure)는 전년 비 47% 성장을 이어갔습니다. 마이크로소프트는 애저 자체 매출은 공개하지 않고 있습니다.

이러한 애저 성장률 47%는 여전히 굉장히 높은 수준이지만 근래 60%이상 성장률을 구가해왔다는 점에서 처음으로 50%이하로 성장률이 하락했습니다.

이러한 성장률 둔화는 지금까지 꾸준히 이어온 트렌즈의 연장선에 있지만 지속적으로 매출 성장률이 낮아질지 아니면 어느 정도 높은 수준으로 계속 유지할 수 있을지는 두고 봐야 할 것 같습니다.

마이크로소프트 애저(Azure) 분기별 매출 성장률 추이( ~ 2020년 2분기), Graph by Happist
마이크로소프트 애저(Azure) 분기별 매출 성장률 추이( ~ 2020년 2분기), Graph by Happist

한편 마이크로소프트가 매출 실적은 공개하지 않지만 전년 비 매출 성장률은 공개한 요소중의 하나인 링크드인(Linkdin)은 전년 비 10% 성장했습니다.

이 링크드인(Linkdin)은 평소에 25%이상 성장했기 때문에 코로나 팬데믹의 영향으로 링크드인(Linkdin)의 광고 등의 성과가 높지는 않았던 것으로 보입니다.

마이크로소프트 20년 2분기 실적 발표 자료

마이크로소프트가 이번에 발표한 20년 1분기 실적 발표 자료입니다. 참고로 보시기 바랍니다.

참고

마이크로소프트가 애플을 위협하는 최고 기업으로 성장한 이유

클라우드와 인공지능(AI)으로 부활하는 마이크로소프트 이야기

마이크로소프트 부활을 이끈 나델라의 5가지 전략

마이크로소프트 인터넷 익스플로러(IE) 몰락 이유 세가지

마이크로소프트 틱톡 인수로 본 마이크로소프트 인수합병 역사

20년만의 최고 순이익을 낸 3분기 마이크로소프트 실적과 향후 전망

20년 2분기 마이크로소프트 실적, 코로나에도 놀라운 매출(13%)과 순이익률 30% 실현

20년 1분기 마이크로소프트 실적을 이끈 놀라운 클라우드 실적

[실적 차트] 연도별 아마존 웹 서비스(AWS),마이크로소프트 및 구글 클라우드 매출(2010 ~ 2019)

우분투 20.04에서 MariaDB 업그레이드 방법(10.4 → 10.5)

2

근래 MariaDB가 10.5로 업그레이드 되었길래 기존 10.4 버젼에서 10.5로 업그레이드를 했습니다. 이 과정에서 정리했던 내용을 기반으로 우분투 20.04에서 MariaDB 업그레이드 방법(10.4 → 10.5)을 남겨 봅니다.

지난 2020년 5월 우분투 20.04 서버를 세팅할 때만해도 마리아디비(MariaDB) 안정 버젼은 10.4였습니다. 그때 곧 마리아디비(MariaDB) 업그레이드되지 않을까하는 생각을 했었는데요. 아니나다를까 2달이 채 지나지 않아서 10.5로 업그레이드 되었습니다.

요즘 성능 개션에 관심이 많아 틀립없이 마리아디비(MariaDB) 10.5는 이전버젼보다는 성능 측면에서 뛰어날 것이라는 기대하에 업그레이드를 했습니다.

솔직히 속도가 어느 정도 개선되었는지 인지할 정도는 아니라는 생각이긴 합니다. 아무튼 최신 버젼이 뭔가 나으리라는 생각을 하며..

성능은 어쩐지 모르겠지만 아직 안정성은 떨어진다는 생각을 했습니다. 그동안 한번도 말썽이 없었던 마리아디비(MariaDB)가 10.5로 업그레이드 후 깨지는 사태가 발생했기 때문이죠.

아무튼 이는 주제에서 벗어나서 마리아디비(MariaDB) 10.5 업그레이드에 대해서 간략 정리합니다.

기존 마리아디비(MariaDB) 삭제

가장 먼저 일은 기존 마리아디비(MariaDB)를 삭제하는 것입니다.

마리아디비(MariaDB) 삭제에는 마리아디비(MariaDB) 자체만 삭제하는 방법과 마리아디비(MariaDB)와 관련된 제반 파일들까지 깨끗히 삭제하는 방법이 있습니다.

이미 MariaDB 이전 버젼으로 서버를 운영하고 있는 상황이므로 MariaDB 관련 데이타베이스를 비롯한 제반 파일들을 전부 삭제해버리면 사이트 운영이 제대로 될 수 없겠죠.

그렇기에 여기선 MariaDB 자체만 삭제하도록 합니다.

MariaDB 이전 버젼용 저장소 삭제

먼저 마리아디비(MariaDB) 이전 버젼용 저장소를 삭제합니다. 이는 –remove 옵션을 사용합니다.

sudo add-apt-repository --remove 'deb [arch=arm64,amd64,ppc64el] http://mirror.yongbok.net/mariadb/repo/10.4/ubuntu focal main/debug'Code language: PHP (php)

MariaDB 신규 버젼용 저장소 등록

그리고 MariaDB 10.5 저장소를 등록합니다.

아래는 MariaDB 재단에서 제공하는 Ubuntu 20.04에서 MariaDB용 저장소와 키를 등록하는 명령어입니다. 이는 MariaDB Downloads Setting up MariaDB Repositories 페이지에서 확인할 수 있는데요.

한국의 경우는 Yongbok.net을 선택합니다.

sudo apt-get install software-properties-common
sudo apt-key adv --fetch-keys 'https://mariadb.org/mariadb_release_signing_key.asc'
sudo add-apt-repository 'deb [arch=amd64,arm64,ppc64el] https://mirror.yongbok.net/mariadb/repo/10.5/ubuntu focal main'Code language: PHP (php)

그 다음에서 업데이트 명령을 적용합니다.

sudo apt-get update
sudo apt-get upgrade -yCode language: PHP (php)

MariDB 중단

현재 작동하고 있는 우분투 Nginx 웹서버에서 MariaDB를 삭제하려면 mysql이 활동을 멈추어야 합니다. mysql을 멈춥니다.

sudo service mysql stopCode language: PHP (php)

MariaDB 구버젼 삭제 및 신규 버젼 설치

구버젼을 삭제하고 이어 본격적으로 MariaDB 신규 버젼을 설치합니다. 아래 명령을 참조하세요.

sudo apt-get remove mariadb-server
sudo apt-get update 
sudo apt-get -y install mariadb-server  
sudo service mysql restart

sudo service mysql statusCode language: PHP (php)

뭐 생각보다 간단합니다.

MariaDB와 관련파일 전부 삭제 후 재설치

이번에는 MariaDB 전체를 삭제하고 다시 설치하는 방법입니다. 서버 세팅 초기에 MariaDB를 완전히 지우고 다시 설치 시 사용할 수 있을 듯 합니다.

먼저 관련 내용을 완전히 지웁니다.

apt-get autoremove 
apt-get remove --purge mysql*  
apt-get autoclean  
deluser mysql  
rm -rf /var/log/mysql  
rm -rf /var/lib/mysql 
rm -rf /etc/mysqlCode language: PHP (php)

MariaDB를 다시 설치합니다. 기존 알고 있는 방법으로 설치하면 됩니다.

sudo apt-get update 
sudo apt-get -y install mariadb-server  
sudo service mysql statusCode language: PHP (php)

서버 구동 이슈, 80포트 사용으로 nginx 구동 불가 nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)

0

오늘은 근래 종종 발행하는 Nginx 웹서버 구동 실패 원인, 98: Address already in use을 살펴보고 Nginx 웹서버에서의 서버 이슈 해결 방법에 대해서 살펴보도록 하겠습니다.

근래들어 nginx 웹서버 시작 시 에러가 나면서 구동에 실패하는 경우가 많아졌습니다. 대부분 원인은 nginx 웹서버가 사용하려는 80포트가 이미 사용중이기 때문이라고 합니다.

더 정확한 에러 메세지는 nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)인데요.

여기에서는 왜 이런 상황이 발생하면서 nginx 작동 시작을 실패하는지 살펴보면서 문제 해결 방법엔 무엇이 있는지 살펴보도록 하겠습니다.

Nginx 웹서버 작동 실패 메세지

아래는 오늘 제 서버가 작동이 되지 않아 systemctl status nginx.service 명령으로 확인하니 아래와 같은 메세지가 뜹니다.

:~# systemctl status nginx.service
● nginx.service - nginx - high performance web server
Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
Active:<strong> failed</strong> (Result: exit-code) since Mon 2020-07-27 18:58:53 KST; 11s ago
Docs: http://nginx.org/en/docs/
Process: 34135 ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf (code=exited, status=1/FAILURE)

Jul 27 18:58:51 happist.com systemd[1]: Starting nginx - high performance web server…
Jul 27 18:58:51 happist.com nginx[34135]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
Jul 27 18:58:51 happist.com nginx[34135]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
Jul 27 18:58:52 happist.com nginx[34135]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
Jul 27 18:58:52 happist.com nginx[34135]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
Jul 27 18:58:53 happist.com nginx[34135]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
Jul 27 18:58:53 happist.com nginx[34135]: nginx: [emerg] still could not bind()
Jul 27 18:58:53 happist.com systemd[1]: nginx.service: Control process exited, code=exited, status=1/FAILURE
Jul 27 18:58:53 happist.com systemd[1]: <strong><span style="color: #fcb900;" class="ugb-highlight">nginx.service: Failed with result 'exit-code'.</span></strong>
Jul 27 18:58:53 happist.com systemd[1]: <strong><span style="color: #cf2e2e;" class="ugb-highlight">Failed to start nginx - high performance web server.</span></strong>Code language: PHP (php)

이러한 현상은 주로 서버를 다시 부팅 시키는 경우 종종 나타납니다. 한번 구동에 성공한 경우엔 service nginx restart와 같이 nginx를 다시 구동시키는 경우 아직 문제를 발견하지는 못했습니다.

이러한 현상은 예전 우분투 18.04를 사용하던 시절에는 거의 나타나지 않았지만 우분투 20.04로 업그레이드 한후에 종종 나타나는 현상인 것을 보니 우부투 20.04의 일시적인 현상으로 추정합니다.

단기 해결 방안

이렇게 서버를 재구동시킬시 80 포트르 다른 어플리케이션이 선점하는 문제는 아래와 같은 apache2 사용 중지시킴으로써 대부분 해결 가능했습니다.

즉 아래와 같은 명령을 활용합니다.

sudo /etc/init.d/apache2 stop 

sudo service nginx restartCode language: PHP (php)

이렇게 apache2 stop 명령으로 대부분 문제는 해결됩니다.

장기적이고 근원적인 문제

이렇게 서버가 새롭게 부팅 문제가 발생 확률이 높아지면 서버 운영 시 위험도가 크게 높아집니다.

서버 운영 시 서버를 자동으로 리부팅 시키는 경우가 있을 수 밖에 없습니다. 예를들어 중요한 보안 업그레이드가 발생 시 보안 업데이트가 적용되기 위해서는 서버 리부팅이 필수적입니다.

그런데 서버 리부팅 시 웹서버를 구동시킬 수 없는 문제가 발생한다면 서버 운영에 큰 지장을 받을 수 있고 안정적인 서버 운영에 어려워집니다.

그러면 왜 이런 문제가 발생하는 것일까요?

구글링을 통해서 왜 이런 문제가 발생하는지 그 원을 찾아 보았지만 뚜렸한 답을 찾을 수는 없었습니다. 다만 아래와 같은 몇가지 요인을 추정할 수는 있습니다.

  • 80 포트를 다른 어플리케이션이 선점하는 문제는 apache2와 연관이 깊다.
    이렇게 판단하는 이유는 apsche2 stop 명령어로 대부분 문제가 해결되기 때문이다.
  • 예전엔 이런 문제가 많지 않았지만 근래 Certbot이 업그레이드되면서 이런 문제 발생이 증가했다고 이야기 있다.
    Certbot 설치하면서 알게 모르게 apache2를 구동시키는 경우가 있는 게 아닐까하는 합리적인 의심을 가져 본다.

결국 Nginx 웹서버를 사용하고는 있지만 기본적으로 apache2를 설치되어 있고, 어떤 연유에서인지 모르지만 apache2가 먼저 구동되면서 80포트를 차지하는 것이 아닐까 싶습니다.

그러면 이 apache2를 어떻게 해야할까요? 여기에는 2가지 방법이 있다고 보여집니다.

apache2 포트를 80이 아닌 다른 것으로 변경

첫번째 방법으로 apache2가 사용하는 port를 80아 아닌 다른 포트로 변경하는 것입니다.

어째피 Nginx 웹서버에서는 apache2를 사용할 일이 거의 없고 apache2와 nginx가 포트를 공유할 수 없도록 apache2 포트를 변경해주면 될 듯 합니다.

apache2 포트 설정은 /etc/apache2 폴더에 있는 ports.conf 파일에서 정의하고 있습니다.

# If you just change the port or add more ports here, you will likely also
# have to change the VirtualHost statement in
# /etc/apache2/sites-enabled/000-default.conf

Listen 70  # 80에서 70으로 변경

<IfModule ssl_module>
	Listen 443
</IfModule>

<IfModule mod_gnutls.c>
	Listen 443
</IfModule>

# vim: syntax=apache ts=4 sw=4 sts=4 sr noetCode language: PHP (php)

apache2를 삭제, 온전히 nginx만으로 운영

아니면 nginx 웹서버에서 apache2는 거의 사용하지 않기 때문에 이를 삭제하는 것입니다.

이는 아래와 같은 명령어를 사용합니다.

sudo apt-get --purge autoremove apache2Code language: PHP (php)

그러면 아래와 같이 apache2와 관련된 패키지들이 삭제되며 73메가 정도 용량을 확보할 수 있다는 메세지를 내면서 계속할지 질문을 합니다.

~# sudo apt-get --purge autoremove apache2
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following packages will be REMOVED:
  apache2* apache2-data* apache2-utils* libllvm9* lockfile-progs* sendmail-base* sendmail-cf* sensible-mda*
0 upgraded, 0 newly installed, 8 to remove and 1 not upgraded.
After this operation, 73.0 MB disk space will be freed.
Do you want to continue? [Y/n]Code language: PHP (php)

계속한다는 의미에서 Y를 누르면 삭제 작업이 진행됩니다.

(Reading database ... 145477 files and directories currently installed.)
Removing apache2 (2.4.41-4ubuntu3) ...
Removing apache2-data (2.4.41-4ubuntu3) ...
Removing apache2-utils (2.4.41-4ubuntu3) ...
Removing libllvm9:amd64 (1:9.0.1-12) ...
Removing sendmail-base (8.15.2-18) ...
Cleaning up the queues...done.
Removing lockfile-progs (0.1.18) ...
Removing sendmail-cf (8.15.2-18) ...
Removing sensible-mda (8.15.2-18) ...
Processing triggers for man-db (2.9.1-1) ...
Processing triggers for libc-bin (2.31-0ubuntu9) ...
(Reading database ... 144728 files and directories currently installed.)
Purging configuration files for sendmail-cf (8.15.2-18) ...
Purging configuration files for apache2 (2.4.41-4ubuntu3) ...
Purging configuration files for sendmail-base (8.15.2-18) ...
Processing triggers for systemd (245.4-4ubuntu3.2) ...
Code language: PHP (php)

이렇게 apache2가 모두 삭제되면 nginx를 다시 구동합니다.

sudo service nginx restartCode language: PHP (php)

마치며

그러나 이렇게 apache2를 삭제하고도 이런 문제가 몇번 더 발생했기 때문에 위에서 제시한 apache2 삭제는 해결책은 아닌 것으로 판단하고 있습니다.

또한 아래와 같이 apache2 실행을 중단 시키는 것도 먹히지 않는 경우를 만났기 때문에 완전한 해결책도 아닌 것으로 판단 합니다.

sudo /etc/init.d/apache2 stop 

sudo service nginx restartCode language: PHP (php)

그래서 최종적으로는 fuser 명령어로 80포트 사용된 메모리를 전부 죽여버리고 다시 nginx를 실행하는 방법을 사용하기로 했습니다.

fuser -k 80/tcp
/etc/init.d/nginx start Code language: PHP (php)

워드프레스 자동 실행 최소화로 워드프레스 속도 개선 방법

워드프레스를 오랫동안 운영하다보면 워드프레스 데이타베이스에 불필요한 자동 실행 데이타(wp-options Table)들이 증가해 워드프레스 속도를 지연시키게 됩니다. 그렇게 때문에 워드프레스 데이타베이스에서 이런 자동 실행 옵션(wp-options Table)들을 최적화해 워드프레스 속도 개선이 가능합니다.

이렇게 워드프레스 속도를 느리게 하는 것 중의 하나가 워드프레스 테마와 플러그인을 설치하면 자동 실행되도록 만드는 Autoloaded Data들입니다.

이들 Autoloaded Data들은 워드프레스 옵션 테이블((wp-options Table)에 저장되어 테마나 플러그인이 삭제되어도 없어지지 않고 계속 자동 실행되기 때문에 일정 시간이 지나면 워드프레스 속도에 큰 영향을 미치게 됩니다.

보통 테마나 플러그인을 삭제했다만 이것으로 모든 것이 해결된 것으로 알고 안심하지만 실상은 여전히 워드프레스 데이타베이스에 남아 자동 실행되면서 성능에 영향을 미칩니다.

오늘은 워드프레스 데이타베이스 중 옵션 테이블 항목을 살펴보고 여기에서 자동으로 실행되는 Autoloaded Data를 최적화하는 방법에 대해서 알아보도록 하겠습니다.

워드프레스 옵션 테이블(wp-options Table)과 문제점?

워드프레스 옵션 테이블(wp-options Table)은 워드프레스 데이타베이스 중에서 사이트 주소(Site URL), 홈 주소(Home URL), 관리자 이메일, 기본 카테고리, 시간 설정 기준 등의 정보를 저장하고 있는 테이블입니다.

그리고 여기에는 플러그인과 테마에 대한 정보도 모두 들어 있습니다.

  • 사이트 주소(Site URL)
  • 홈 주소(Home URL)
  • 관리자 이메일
  • 기본 카테고리
  • 시간 설정 기준
워드프레스 데이타베이스 테이블 리스트 그리고 옵션 테이블(option table)
워드프레스 데이타베이스 테이블 리스트 그리고 옵션 테이블(option table)

이 워드프레스 옵션 테이블(wp-options Table)에는 아래와 같은 4가지 필드가 있습니다. 이 필드 중 autoload는 워드프레스 사이트가 구동되면 자동으로 실행 시킬 것인지를 정합니다.

  • option_id
  • option_name
  • option_value
  • autoload
워드프레스 데이타베이스 중 옵션 테이블 필드 일부

이러한 워드프레스 데이타베이스의 옵션 테이블은 아래와 같은 이유로 과도하게 데이타가 실행되는데 실상 많은 데이타 처리용으로 설계되지 않았기 때문에 효율이 떨어집니다.

  • 옵션 테이블의 autoload 설정을 살펴보면 알겠지만 100% 전부 autoload하겠다고 설정되어 있습니다.
  • 시간이 지날수록 워드프레스는 더 많은 양의 데이타를 자동으로 실행 합니다.
  • 왜냐하면 현재 사용중인 테마나 플러그인을 자동실행하지 말도록 조정해도 자동으로 실행시켜버립니다.
  • 더우기 과거에 사용하다 지워버린 테마나 플러그인에서 설정한 옵션도 자동 실행됩니다.
  • 테마나 플러그인 개발자들은 플러그인이나 테마를 위한 별도 테이블생성대신 워드프레스 옵션 테이블에 데이타를 저장하는 것을 선호합니다.
    그러다보니 옵션 테이블에서 처리하는 데이들이 많아졌습니다.
  • 그러나 워드프레스 데이타베이스 중 옵션 테이블은 원래 테마나 플러그의 그렇게 많은 세부 데이타를 처리할 수 있을 정도로 효율적으로 설계되지는 않았습니다.

위와 같은 이유로 워드프레스 데이타베이스 내의 옵션 테이블은 적절하게 최적화해야 더 빠른 워드프레스 사이트를 만들 수 있습니다.

옵션 테이블에서 자동 실행되는 내용 파악하기

우선 어느 정도 자동 실행되는 데이타가 있는지 확인해 보시죠. 사이트 운영에서 기본은 발생되는 데이타를 최소화시켜 물리적으로 속도를 빠르게 만드는 것입니다.

옵션 테이블에서 자동실행 데이타 총량 확인

워드프레스 사이트에서 자동 실행되는 데이타가 어느 정도인지 확인은 phpMyAdmin에서 아래와 같은 명령을 사용해 알 수 있습니다.

SELECT SUM(LENGTH(option_value)) as autoload_size FROM wp_options WHERE autoload='yes';Code language: PHP (php)
  1. 데이타베이스 이름 클릭
  2. 상단 메뉴 중 SQL 메뉴 크릭
  3. 쿼리문 입력란에 위 명령어 입력
  4. 실행
워드프레스 데이타베이스 옵션테이블 최적화, phpMyAdmin에서 자동 실행 데이타 확인

저의 경우 자동 실행되는 데이타 양이 470397바이트가 나왔네요. 이 정도는 다른 사이트들보다 훨씬 더 많은 데이타가 실행된다고 평가할 수 있습니다.

제가 플러그인 10개이상 설치한 워드프레스 사이트의 초기 자동 실행 데이타를 살펴보니 기껏해야 10만 바이트가 넘는 정도이니 40만이 넘는 저의 경우는 굉장히 많은 데이타가 자동으로 실행되고 있다는 것을 알 수 있습니다.

자동 실행되는 데이타 총량 확인

어떤 데이타들이 자동 실행될까?

그러면 자동 실행되는 데이타들이 무엇일까요? 자동 실행되는 데이타를 줄이려면 무엇을 조정해야 할까요?

이를위해서 자동 실행되는 데이타양을 기준으로 상위 30개를 추출해 보면서 무엇을 빼야하는 지 살펴보죠. 자동 실행 데이타 Top30을 보여주는 명령어는 아래와 같습니다.

SELECT option_name, length(option_value) AS option_value_length FROM wp_options WHERE autoload='yes' ORDER BY option_value_length DESC LIMIT 30;Code language: PHP (php)

이 명령어를 기반으로 아래 이미지와 같은 결과를 얻었습니다. 이 데이타들을 살펴보면서 아래와 같은 문제점을 찾았습니다.

  • 3위에 랭크된 redux_builder_amp는 amp 플러그인 관련된 내용으로 거의 1년전에 amp 플러그인을 삭제했는데 여전히 자동 실행되고 있습니다.
  • 4위에 랭크된 td_011은 사용하지 않는 뉴스페이퍼 테마관련 내용으로 이도 거의 1년전부터 사용하지 않고 있는 테마입니다.
  • 5위에 랭크된 lyte_cache_index은 유튜브 로딩 속도를 개선해주는 플러그인으로 이도 오래전부터 사용하지 않는 플러그인입니다.
  • 9위에 랭크된 theme_mods_marni도 오래전부터 사용하지 않았던 marni 테마 관련 내용입니다.

따라서 적어도 amp 플러그인, 뉴스페이퍼 테마, 유튜브 속도 개선 플로그인 그리고 marni 테마 관련 내용을 지워버릴 필요가 있습니다.

워드프레스 데이타베이스 옵션 테이블에서 자동 실행되는 데이타 Top 30 리스트

옵션 테이블에서 상세 내용 삭제 방법

위에서처럼 워드프레스 데이타베이스 옵션테이블을 분석해보니 사용하지 않는 테마나 플러그인을 위해서 자동 실행되는 데이타들이 많다는 것을 알 수 있습니다.

phpMyAdmin에서 이들을 효과적으로 찾아 삭제하는 방법은 아래 명령을 사용해 찾을 수 있습니다. 아래는 amp 관련 내용을 모두 찾겠다는 명령입니다.

SELECT * 
FROM `wp_options` 
WHERE `autoload` = 'yes'
AND `option_name` LIKE '%amp%'Code language: PHP (php)

그러면 아래와 같이 amp 관련 항목을 전부 보여줍니다. 이를 모두 선택해 지우면 되겠죠.

워드프레스 데이타베이스 최적화, phpMyAdmin에서 amp관련 항목을 찾기

위와 같은 방법으로 해당 테마 또는 플러그인 해당 내용을 찾아 삭제하면 됩니다.

워드프레스 속도 개선을 위한 오브젝트 캐시 적용법

오늘은 워드프레스 속도 개선을 위한 방안의 하나로 오브젝트 캐시를 살펴보고 워드프레스 사이트에 오브젝트 캐시 적용 방법을 살펴보도록 하겠습니다.

간단히 워드프레스 캐시 종류를 알아보고 이중에서 조금 생소한 개념이 오브젝트 캐시를 이해하고 이 오브젝트 캐시 성능을 높여 워드프레스 속도 개선하는 방법을 알아봅니다.

워드프레스 캐시 종류

워드프레스 사이트 이용자가 요청하는 정보가 처리되는 과정을 이해하기 위해서 데이타가 흐르는 플로우를 간단히 그린 다이어그램을 보시죠.

  • 사용자 측면에서는 크롬과 같은 브라우저에서 처리할 수 있는 브라우저 캐시가 있습니다.
    이 브라우캐시는 한번 사이트를 방문 후 방문 페이지의 데이타를 브라우저 캐시에 저장해 놓음으로써 추가 방문 시 빠른 속도로 접속할 수 있습니다.
  • 웹 서버에서는 사용자가 요구했던 페이지 구성 정보를 저장해 놓아 도 다른 사용자가 그 페이지를 요청하면 추가 작업할 필요없이 바로보여줄 수 있게 만든 페이지 캐시로 반응 속도를 크게 높일 수 있습니다.
  • 페이지 구성을 위해 PHP에서 데이타베이스에 접속해 필요 정보를 받아온 결과를 저장해 놓은 것이 오브젝트 캐시입니다.
웹사이트 데이타 흐름 및 단계별 캐시 플로우, 브라우저 캐시, 페이지 캐시, 오브젝트 캐시, Brower Cache, Page Cache, Object Cache, Image from SinupWP
웹사이트 데이타 흐름 및 단계별 캐시 플로우, Brower Cache, Page Cache, Object Cache, Image from SinupWP

이중에서 브라우저 캐시는 사용자 측면에 일어나는 것이고, 페이지 캐시와 오브젝트 캐시는 서버 측면에서 일어나는 일입니다.

페이지 캐시 – FastCgi 캐시

페이지 캐시는 서버측면에서는 일반적으로는 Nginx에서 제공하는 FastCgi 캐시를 사용합니다.

서버를 직접 제어할 수 없는 호스팅을 사용해 워드프레스 사이트를 운영한다면 워드프레스 캐스 플러그인을 사용할 수 있습니다. WP Rocket과 같은 플러그인이 그것이죠.

일반적으로 우리가 알고있는 워드프레스 캐시 플러그인보다는 FastCgi 캐시와 같은 서버 측면의 캐시가 훨씬 더 효율적이라고 알려져 있습니다.

오브젝트 캐시

PHP와 Mysql 데이타베이스간 이루어지는 데이타에 대해서는 이미 PHP 자체에서 제공하는 Opcache와 워드프레스 자체에서 제공하는 오브젝트 캐시가 각기 작동합니다.

그러나 이러한 캐시 프로그램들은 웹서버 + Mysql + 워드프레스 CMS간 이루어지는 다양한 데이트 요청을 충분하게 캐시하지 못합니다. 특히 우커머스와 같은 데이타 요청이 많은 경우 성공율이 크게 낮아집니다.

이렇게 웹서버 + Mysql + 워드프레스 CMS간 데이타 요청 결과를 저장하는 오브젝트 캐시 효율을 높이기 위해서 Redis와 같은 특별한 캐시 프로그램을 사용해 효율을 높입니다.

오브젝트 캐시, Redis 설치 및 사용법

위에서 이야기한대 오브젝트 캐시 효율을 높이기 위한 Redis 사용법에 대해서 살펴봅니다.

이 캐시는 PHP와 Mysql간 데이타를 제어하는 것이니 크게 워드프레스 운영자가 크게 신경쓸 여지가 적습니다.

서버단에서 Redis를 사용할 수 있도록 패키지를 설치해주고, 관련 워드프레스 플러그인을 설치, Redis를 사용토록 설정하기만 하면 됩니다. 나머지는 알아서 하겠죠.

워드프레스 오브젝트 캐시, Redis Object cache, redis-wordpress-ubuntu
워드프레스 오브젝트 캐시, Redis Object cache, redis-wordpress-ubuntu

우분투 서버에서 Redis 패키지 설치

우분투 서버에서 Redis를 사용할 수 있도록 Redis 패키지 설치 후 php7.4-fpm을 다시 가동시킵니다. 이는 아래 명령을 사용합니다.

sudo apt install redis-server
sudo service php7.4-fpm restartCode language: PHP (php)

Redis 지원 워드프레스 플러그인 설치

앞에서 서버에 설치한 Redis가 워드프레스 데이타를 효율적으로 캐시할 수 있도옥 워드프레스 명령들을 Redis와 연계시켜주는 워드프렛 플러그인을 설치합니ㅏㄷ.

이러한 워드프레스 플러그인은  WP RedisRedis Object Cache가 있는데요. 오브젝트 캐시를 소개하는 전문가들은 이 두 플러그인중에서 Redis Object Cache를 추천하고 있습니다.

워드프레스 오브젝트 캐시 플러그인, wordpress object cache Redis, WP Redis
워드프레스 오브젝트 캐시 플러그인, wordpress object cache Redis, WP Redis

Redis 플러그인 설정

Redis Object Cache 사용법은 아주 단순합니다. 설정에서 Enable Object cache 버튼을 눌러 활성화 시켜 주기만 하면 됩니다.

워드프레스 오브젝트 캐시 플러그인 Redis Object cache 설정
워드프레스 오브젝트 캐시 플러그인 Redis Object cache 설정

유료 커뮤니티 모델로 성공한 LWN 사례에서 보는 고품질 콘텐츠 확보 중요성

리눅스와 자유 소프프퉤어(Free Software) 전문 뉴스 사이트인 LWN은 오래전부터 유료 구독 모델을 적용해 성공적으로 성장하면서 눈여겨 볼만한 미디어 사례를 만들고 있는데요.

오늘은 LWN이 어떻게 오랫동안 유료 구독 모델을 성공적으로 운영할 수 있었는지 정리해 보도록 하겠습니다. 이 사례는 GreekNews에 올라온 글을 기반으로 추가 보완한 것입니다.

리눅스 관련 가장 좋은 뉴스들이 올라오는 LWN의 글 작성 가이드

리눅스와 자유 소프트웨어(Free Software) 전문 매체, LWN 메인 페이지
리눅스와 자유 소프트웨어(Free Software) 전문 매체, LWN 메인 페이지

LWN의 비지니스 모델

뉴스나 정보를 제공하는 사이트들은 대개 유료 구독 모델, 광고 모델 그리고 기부 모델로 나누어 볼 수 있습니다.
이 세가지 비지니스 모델은 독자적으로만 존재하는 것이 아니라 특성을 적절하게 섞어서 비지니스 모델 성과를 높이고 있습니다.

예를들어 유료 구독 모델이지만 부분적으로 광고를 실기도 하고, 광고를 주로 하면서 일정 부분만 유료 구독 모델로 운영하기도 합니다.

그냥 개인의 돈을 들여 운영하는 사이트도 있지만 어느 정도 규모를 가지고 목적에 맞추어 커스터마이제이션해 운영하려면 정기적인 비용이 적지않게 듭니다.

사이트를 운영하는 비용도 당연히 들겠지만 콘텐츠를 생산하고 유지하는데 드는 비용은 경우에 따라서는 어마어마한 비용이 드는 것이 사실입니다.

인터넷 시대에 콘텐츠는 무료라는 인식이 강하지만 점점 읽을만한 콘텐츠는 점점 유료화되고 있습니다.

왜냐하면 콘텐츠는 그냥 자연적으로 만들어지는 것이 아니라 누군가의 땀과 노력으로 만들어지기 때문이고, 이러한 품질 좋은 콘텐츠를 지속적으로 제공하려면 콘텐츠 제작자들에게 충분한 보상이 주어져야 장기적으로 안정적으로 품질좋은 콘텐츠를 제공할 수 있는 것이죠.

우리나라는 아직 덜하지만 점점 외국의 경우 어지간한 언론사들은 유료 구독모델로 변경된지 오래입니다.

광고, 구독, 기부가 적절히 활용된 4가지 구독 옵션을 제공

이러한 트렌드들보다도 먼저 유료 구독 모델을 운영한 곳이 LWN이라고 할 수 있는데요. LWN은 아래와 같이 광고와 유료 구독 그리고 기부 모델을 적절하게 사용하고 있습니다.

  • 가장 비용이 낮은 starving hacker에게는 광고 모델과 구독 모델을 혼용해 사용하고 있으며.
  • 가장 많은 돈을 내는 maniacal supporter은 구독 모델과 기부 모델을 적절해 활용한 구독 타입
구독 타입월 구독료광고 여부접근 가능 콘텐츠
starving hacker3.5$O모든 콘텐츠 접근 가능
정기 결제 불가
(비용 문제) 
professional hacker$7X모든 콘텐츠 접근 가능
정기 결제 가능
작성자별 댓글 필터링
댓글 답변 이메일 수신
professional hacker$14X모든 댓글 이메일 통보
새 댓글 하일라이트 기능
maniacal supporter$50X댓글에 서포터 표시
컨퍼런스에서 맥주/음료 제공

이렇게 광고와 구독 그리고 기부가 적절한 게 활용된 LWN이 비지니스 모델에서 광고가 차지하는 비중은 전체 수익의 10% 선이라고 밝히고 있습니다.

활발한 커뮤니티 이벤트

LWN은 Linux Weekly News라는 이름으로 거의 뉴스 사이트로 시작했지만 점점 성격은 정보 + 커뮤니티 성격이 가미되면서 이제는 오픈 소스를 비롯한 자유 소프트웨어(Free software) 커뮤니티를 지향하고 있습니다.

이러한 커뮤니티는 콘텐츠에 대한 활발한 논의(그렇기에 LWN의 구독 옵션에는 댓글에 대한 옵션을 매우 중시하고 있습니다.)와 더불어 오프라인 또는 온라인이벤트를 통한 활발한 교류를 통해서 커뮤니티를 발전시키고 있습니다.

2020년 7월 LWN 커뮤니티 캘린더(The LWN.net Community Calendar)
2020년 7월 LWN 커뮤니티 캘린더(The LWN.net Community Calendar)

그렇기에 이러한 활발한 커뮤니티 이벤트를 통한 수익도 LWN의 중요한 비지니스 모델이라고 할 수 있습니다. 이 비중이 어느 정도 되는지는 확인할 수 없었습니다.

부분 유료 커뮤니티를 지향한 LWN에서 읽는 시사점

위에서도 언급했지만 LWN은 Linux Weekly News에서 출발해 오픈 소스를 비롯한 자유 소프트웨어(Free software) 커뮤니티를 지향하는 가운데 커뮤니티를 활성화하는 강력한 도구로서 고품질의 콘텐츠 확보에 주력했습니다.

그것은 콘텐츠 품질에 대한 강력한 관리를 통해 일정 수준을 넘는 고품질 콘텐츠만 제공하고, 다양하면서도 고품질 콘텐츠 확보를 위해 콘텐츠 제공에 문호를 개발하되 충분한 비용을 지불하면서 콘텐츠 제공이 활성화 할 수 있도록 했습니다.

고품질 콘텐츠를 위한 면밀한 관리

뉴욕타임즈등과 같은 유력 언론은 서면 인터뷰를 진행하는 경우 수십번에 걸친 메일 커뮤니케이션을 통해서 언론사에서 원하는 충분한 고품질 콘텐츠가 나오도록 만듭니다.

유력 언론사들이 그만큼 충분히 검증하고 리뷰하면서 충분한 콘텐츠를 완성해가는 것처럼, LAW도 글을 제안하고 작성 그리고 리뷰를 통해 실제로 발표되는데까지 많은 시간과 엄청난 커뮤니케이션을 통해서 충분히 검증하고 논리를 보강하면서 완성도를 높인다고 합니다.

앞서 언급된 글에서 소개된 사례에서도 LAW에 주제를 제안해 발표하는데 2주일 이상 걸렸고 무려 30통이 넘는 이메일을 주고 받으며 글을 편집하면서 완성도를 높였다고 합니다.

I’ve written a couple of articles for LWN (I waived the fee)[1][2]. It’s quite an involved process going through many rounds of editing. You have to stick to the house style and use the house markup. The results are excellent because of this consistent attention to detail, but I wouldn’t recommend it as a way to make a quick buck 🙂 The whole process for these two articles took two weeks from proposal to publication and involved 30 emails as well as many edits in their CMS.

콘텐츠 제공자에 대한 보상 시스템

콘텐츠를 제공하는 회사들은 좋은 글을 확보하기 위한 많은 노력을 기울입니다.

제가 관심을 가지고 살펴보고 있는 VPS 업체인 Vultr이나 Lenode와 같은 업체들은 품질 좋은 콘텐츠가 비지니스에 도움을 주기 때문에 서버 운영, 운영체제 활용등에 대한 글을 제공하는 경우 글당 $300 정도의 비용을 지불합니다.

LAW도 업계 평균 수준이상의 고료를 제공합니다. 다만 계속 좋은 글을 기고하게 되면 고려가 상당한 수준으로 올라간다고 합니다.

그것은 지속적으로 좋은 글을 올리면 그의 글을 신뢰하고 지속적으로 방문해 트래픽과 구독자가 증가하기 때문에 당연하게도 가치가 올라가기 때문이겠죠.

  • 새로운 저자는 글 한 편당 $300 고료 지급
    난이도가 높은 커널 관련 글은 $350 고료 지급
  • 좋은 글을 지속적으로 기고하는 경우 고려가 상당한 수준으로 올라감

활성 커뮤니티를 통한 고품질 콘텐츠 생성 선순환

콘텐츠 제공자들이 글을 작성해 LAW에 기고하는 이유는 일정 정도 고료를 얻을 수 있다는 경제적인 동인도 있겠지만 자가기 알고 있는 내용을 알리고 그러는 가운데 인정을 받고 싶은 욕구가 있겠죠.

그것이 LAW와 같은 일정 권위를 인정받은 커뮤니티에서 인정을 받는다면 더욱 그러할 것입니다.

이는 활성화된 커뮤니티를 통해서 상당히 힘든 과정임에도 불구하고 LAW에 기고하도록 만들고 그 과정에서 LAW의 품질 관리 과정을 통해서 보다 고품질 콘텐츠를 만들 가능성을 높여주면서 좋은 콘텐츠가 늘어나는 선순환이 일어나는 것으로 보입니다.

The LSFMM 2019 group photo, Photo by LWN
The LSFMM 2019 group photo, Photo by LWN

프리미엄 모델

LAW는 오픈 소스와 자유 소프트웨어(Free Software)를 다루고 있기 때문에 영리적인 접근은 상당히 조심스러울 수 있습니다.

그러나 LAW는 유료 콘텐츠를 무한정 유료로 제한하는 것이 아니라 일정 시간이 지나면 누구나 자유롭게 열람할 수 있도록 만들면서 접근성을 높이면서도 유료화를 통한 지속 성장 가능성을 높였습니다.

  • LAW에 게재되는 글은 2주정도 LAW에 독점 게재 권리를 가짐
  • 따라 LAW 유료 구독자들은 이런 모든 글을 대기 시간없이 바로 볼 수 있음
  • 일반 사용자는 일정 시간 경과 후에야 볼 수 있음

멀웨어 스캔을 위한 리눅스 백신 Maldet 사용법

0

오늘은 LMD(Linux Malware Detect)로 알려진 리눅스 서버 멀웨어 감염 여부를 체크해주는 리눅스 멀웨어 스캐너인 Maldet를 사용해 정기 멀웨어 스캔 및 스캔 결과를 이메일로 받아보는 방법에 대해서 알아보도록 하겠습니다.

이전 글에서도 여러 번 말씀드렸지만 우분투를 비롯한 리눅스를 사용한 운영체제에서도 윈도우즈만큼은 아니지만 바이러스나 멀웨어를 퍼트리는 해커들이 활발하게 활동하고 있습니다.

따라서 정기적으로 바이러스나 멀웨어 감염 여부를 점검해 보는 것이 좋습니다.

이를 위해 ClamAV가 많이 사용되지만 멀웨어 스캔을 위해서 Maldet도 많이 사용됩니다. 그래서 저는 테스트삼아 두가지를 모두 사용해 정기적으로 스캔토록 만들었습니다.

여기에서는 Maldet를 할용해 정기적으로 리눅스 서버 멀웨어 스캔 및 스캔 결과를 이메일로 받아보는 방법에 대해서 살펴보겠습니다.

Maldet 설치 및 사용

우서 Maldet를 설치하는 방법을 살펴봅니다. 이하는 모두 우분투하에서 진행되는 방법입니다.

어선 /opt 폴더로 이동합니다.

cd /opt/Code language: PHP (php)

Maldet 공식 사이트인 rfxn.com에서 Maldet 최신 버젼을 다운받습니다. 이는 아래 명령어를 사용합니다.

wget http://www.rfxn.com/downloads/maldetect-current.tar.gzCode language: PHP (php)

최신 버전은 다운받았지만 이는 압축 파일이므로 압축을 풀어 줍니다.

tar xfz maldetect-current.tar.gzCode language: PHP (php)

압축을 풀고 ls -l 명령어로 어떤 파일 및 폴더가 생겼는지 확인해보면 maldetect-1.6.4와 같은 폴더가 생긴 것을 볼 수 있습니다.

트Maldet 설치 폴더 파일 리스트 maldetect-1.6.4

이제 이 폴더로 이동합니다. Maldet 버젼에 따라 폴더 이름이 달라지므로 확인 후 폴더 이동하는 것이 좋습니다.

cd maldetect-1.6.4Code language: PHP (php)

이 설치 폴더로 이동한 다음 Maldet 설치 스크립트 파일, install.sh을 만날 수 있는데요. 이를 실행해 줍니다.

./install.shCode language: PHP (php)

이제 설치스크립트가 실행되면서 설치를 시작합니다.

리눅스 백신 Maldet 설치 화면

Maldet 설정

이제 Maldet 설치가 끝났으면 설정으로 들어갑니다.

설정 파일은 /usr/local/maldetect/conf.maldet인데요. 이를 편집기로 수정합니다.

nano /usr/local/maldetect/conf.maldetCode language: PHP (php)

이 설정 파일에서는 주로 아래와 같은 내용을 변경해 줍니다. 뭐 사용자 목적에 따라서 적절한 옵션을 변경할 수 있습니다.

스캔 후 이메일 통보 관련

먼저 스캔 결과를 이메일로 통보 여부, 값이 0이면 통보하지 않고, 1인 경우 메일 통보

email_alert=1Code language: PHP (php)

실제 편집 파일에 해당 건에는 아래와 같은 주석이 달려 있습니다.

# Enable or disable e-mail alerts, this includes application version
# alerts as well as automated/manual scan reports. On-demand reports
# can still be sent using '--report SCANID user@domain.com'.
# [0 = disabled, 1 = enabled]
email_alert="1"Code language: PHP (php)

다음으로는 메일 주소를 설정합니다. 여러 메일 주소로 스캔 결과를 받아야 한다면 컴마(,)를 이용해 추가합니다.

email_addr=”user@yourdomain.com, user2@yourdomain.com”Code language: PHP (php)

실제 편집 파일에 해당 건에는 아래와 같은 주석이 달려 있습니다.

# The destination e-mail addresses for automated/manual scan reports
# and application version alerts.
# [ multiple addresses comma (,) spaced ]
email_addr=”user@yourdomain.com, user2@yourdomain.com”Code language: PHP (php)

다음으로는 Maldet가 멀웨러를 감지하고 깨끗하게 치료했다면 굳이 메일 경고하지 않는다는 옵션 선택할지를 결정합니다. 1값은 멀웨어가 치료되었다면 굳이 메일 경고를 하지 않습니다.

email_ignore_clean="0"
Code language: PHP (php)

실제 편집 파일에 해당 건에는 아래와 같은 주석이 달려 있습니다.

# Enable or disable slack alerts, this will upload the scan report as a file
# into one or more slack channels
# [0 = disabled, 1 = enabled]
slack_alert="0"Code language: PHP (php)

멀웨어 감염 파일 처리

다음에는 스캔 도중 멀웨어를 감지했다면 어떻게 할지에 대한 옵션인데요. 멀웨어에 걸린 파일을 특정 장소로 이동할지 그대로 둘지를 결정합니다.

값이 0이라면 감염되었다는 경고만 하고 파일은 그대로 유지합니다. 1 값을 주면 특정 장소로 이동 조치하고 경고해 줍니다.

quarantine_hits=1Code language: PHP (php)

실제 편집 파일에 해당 건에는 아래와 같은 주석이 달려 있습니다.

# The default quarantine action for malware hits
# [0 = alert only, 1 = move to quarantine & alert]
quarantine_hits="1"Code language: PHP (php)

그 다음에는 감염된 멀웨어를 치료할지 여부를 선택합니다. 치료한다면 1값을 입력하고 그대로 두려면 0값을 유지합니다.

quarantine_clean=1Code language: PHP (php)

실제 편집 파일에 해당 건에는 아래와 같은 주석이 달려 있습니다.

# Try to clean string based malware injections
# [NOTE: quarantine_hits=1 required]
# [0 = disabled, 1 = clean]
quarantine_clean="1"Code language: PHP (php)

이번에는 조금 더 강력한 조치를 할 것인지를 선택하는데요. 멀웨어에 감염된 사용자는 서버에서 활동을 중지시키는 조치인데요 .

0값을 입력 시 멀웨어에 감염되었다고 판명되어도 그 사용자는 그대로 작동하며, 만약 1값을 입력시 멀웨어가 팀지되면 그 사용자는 사용이 중지됩니다.

1인 사용자 서버는 서비스사 멈추는 것이므로 신중하게 선택할 필요가 있습니다. 아무래도 서비스 중단까지는 부담스러우니 0값을 사용합니다.

quarantine_suspend_user=0Code language: PHP (php)

여기에는 아래와 같은 주석과 설명이 달려 있습니다.

# The default suspend action for users wih hits
# Cpanel suspend or set shell /bin/false on non-Cpanel
# [NOTE: quarantine_hits=1 required]
# [0 = disabled, 1 = suspend account]
quarantine_suspend_user="0"Code language: PHP (php)

Maldet 실행

Maldet 설정이 끝났으면 Maldet를 실행해 봅니다. 우선 Maldet의 주요 실행 옵션을 살펴볼까요?

  • -u, –update-sigs [–force]
    데이타베이스 업데이트
  • -a, –scan-all PATH
    모든 파일을 스캔
    예) maldet -a /home/username
  • -e, –report SCANID email
    메일 보내기
    예) maldet –report SCANID user@domain.com

특정 폴더를 전부 스캔 시 아래와 같은 명령어 사용

maldet -a /home/usernameCode language: PHP (php)

그러면 아래와 같은 메세지를 내면서 스캔을 시작한 후 그 결과를 표시해 줍니다.

Linux Malware Detect v1.6.4
            (C) 2002-2019, R-fx Networks <proj@rfxn.com>
            (C) 2019, Ryan MacDonald <ryan@rfxn.com>
This program may be freely redistributed under the terms of the GNU GPL v2

maldet(46026): {scan} signatures loaded: 17041 (14221 MD5 | 2035 HEX | 785 YARA | 0 USER)
maldet(46026): {scan} building file list for /home/happist, this might take awhile...
maldet(46026): {scan} setting nice scheduler priorities for all operations: cpunice 19 , ionice 6
maldet(46026): {scan} file list completed in 2s, found 85826 files...
maldet(46026): {scan} found clamav binary at /usr/bin/clamdscan, using clamav scanner engine...
maldet(46026): {scan} scan of /home/happist (85826 files) in progress...
maldet(46026): {scan} clamscan returned an error, check /usr/local/maldetect/logs/clamscan_log for details!

maldet(46026): {scan} scan completed on /home/happist: files 85826, malware hits 0, cleaned hits 0, time 491s
maldet(46026): {scan} scan report saved, to view run: maldet --report 200707-2004.46026
Code language: PHP (php)

최신 Let’s Encrypt SSL 인증서 발급 방법 4가지 정리

여기에서는 우분투 20.04운영체제에서 웹서로로 NGINX를 사용 시 무료 SSL 인증서로 인기있는 Let’s Encrypt SSL 인증서 발급 방법 전반에 대해서 살펴보도록 하겠습니다.

이전에도 정리한 적이 있지만 시간이 흘러 발급 방법이 달라져 수정 정리할 필요가 생겼습니다.

Let’s Encrypt도 알고 보면 수많은 인증서 발급 기관,  CA(Certificate Authority) 업체 중이 하나입니다. 다만 SSL 인증서 가격이 비싸 보급이 느려지면서 인터넷 보안에 문제가 있다는 문제 의식하에 무료 보급을 통한 인터넷 보안을 강화하겠다는 비영리 단체라고 할 수 있습니다.

  1. 인증서 발급 기관, CA(Certificate Authority) 중 점유율이 가장 높은 곳은 IdenTrust로 2020년 12월 기준으로 42%가 넘습니다.(42.3%)
  2. IdenTrust 다음으로는 DigiCert Group(15.7%) > Sectigo(14.1%) > GoDaddy Group(5.4%) > GlobalSign(2.3%
  3. Let’s Encrypt 점유율은 생각보다 낮아서 0.1%에 불과
  4. 하지만 Let’s Encrypt 사용을 아래 그래프에서 보듯 매우 빠르게 증가
    (개인적인 생각으로는 무료이기 때문에 테스트로 중복 인증도 많다고 생각)
Let’s Encrypt SSL 인증서 사용 증가 추이, Graph by Let’s Encrypt
Let’s Encrypt SSL 인증서 사용 증가 추이, Graph by Let’s Encrypt

Let’s Encrypt SSL 인증서는 아래와 같은 장점들이 있어 사용이 확대되고 있습니다.

  1. 인증 절차가 단순(서버에서 필요한 프로그앰들이 설치되어 있다면) 단 한줄 명령어로 발급
  2. 발급 대기 시간 없이 바로 발급(이메일 입력 등을 포함해 1분 이내)
  3. Nginx나 아파치와 같은 웹서버에 맞추어 자동 옵션 설정되도록 설치 가능
  4. 인증 유효기간은 90일이지만 인증을 자동화 가능
  5. 무엇보다도 무료

근래 새롭게 사이트를 구축하하면서 Let’s Encrypt SSL 인증서 발급 과정에서 기존에 알고 있던 방법들이 대부분 작용하지 않는 것을 확인했습니다. 그것은

  • Let’s Encrypt SSL 인증서에서 여러가지 보안 이슈들이 발견되면서 발급 방법에 대한 보완이 진행되었고,
  • 발급에 필요한 패키지들도 업그레이드 되었고,
  • 예전에 알려졌던 기능들 일부는 지원이 중단(예를들어 자동 갱신 기능으로 많이 사용했던 Cert-Auto기능 지원 중단 등)되기도 했으며
  • 운영체제 업그레이드, DB 업그레이드에 따른 문제 발생 등

위와 같은 요인들로 인해서 기존에 알고 있던 방법들이 이를 제대로 반영하지 못하는 것으로 보입니다.

이제 Let’s Encrypt SSL 인증서 발급 방법에 대해서 알아 보시죠.

인증서 설치를 위한 Certbot tool 설치

Let’s Encrypt SSL 인증서 발급은 Certbot을 이용합니다. Certbot은 우분투 20.04를 설치 후 letsencrypt을 설치했다면 그 안에 포함되어 있기 때문에 별도 Certbot을 설치할 필요가 없습니다.

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

[참고] Nginx 또는 아파치용 인증서 프로그램 설치 이용

Let’s Encrypt SSL 인증서 발급은 매우 다양한 방법으로 이루어지는데요. 이 중에는 Nginx나 아파치와 같은 웨서버가 전적으로 인증서를 제어토록 하는 방법이 있습니다.

이 경우 인증서 관리는 웹서버가 세팅과 관리를 알아서 한다고 하는데요. 저는 몇번 테스트해보고 기존 방식을 사용하기로하고 사용을 그만 두었습니다.

이 방법을 사용하려면 웹서버에 맞는 Certbot을 추가 설치합니다.

우선 우분투에서 Nginf용 Certbot 설치는 아래 명령을 사용합니다. 여기서는 Nginx 웹서버용 파이썬3를 설치합니다.

sudo apt update 
sudo apt upgrade -y 
sudo apt install certbot python3-certbot-nginxCode language: PHP (php)

만약 Apache를 사용한다면 python3-certbot-nginx 명령은 아파치를 지원하도록 python3-certbot-apache 명령으로 대체되겠죠.

sudo apt install certbot python3-certbot-apacheCode language: PHP (php)

그리고 과거 자료들을 보면 python-certbot-nginx 명령을 사용하는데 파이썬3으로 업그레이드되면서 파이썬3를 사용하라는 권고를 받습니다.

Let’s Encrypt SSL 인증서 발급 방법 4가지

Let’s Encrypt SSL 인증서 발급 방법은 webroot와 Standalone, DNS의 3가지 방식이 있습니다. 인증서 발급은 사이트에서 인증기관인 Let’s Encrypt에 접속해 이 사이트의 유효성을 검증하는 과정을 거치며 이 과정을 아래 3가지 방법 중 하나를 선택해 진행할 수 있습니다.

  1. webroot : 사이트 디렉토리 내에 인증서 유효성을 확인할 수 있는 파일을 업로드하여 인증서를 발급하는 방법
    . 실제 작동하고 있는 웹서버의 특정 데렉토리의 특정 파일 쓰기 작업을 통해서 인증
    . 이 방식의 장점은 nginx를 중단시킬 필요가 없음.
    . 이 방법의 단점은 인증 명령에 하나의 도메인 인증서만 발급 가능
  2. 웹서버
    . Nginx나 아파치와 같은 웹서버에서 직접 SSL 인증을 실시하고 웹서버에 맞는 SSL세팅값을 부여
    . 발급이나 갱신을 위해 웹서버를 중단시킬 필요가 없음
    . 인증서 갱신 시 상황에 맞게 세팅을 자동으로 업데이트
    . 사용자가 세팅을 변경할 수 있지만 자동 업데이트 시 반영되지는 않음
  3. Standalone : 사이트 작동을 멈추고 이 사이트의 네크워킹을 이용해 사이트 유효성을 확인해 Let’s Encrypt SSL 인증서를 발급하는 방식
    . 80포트로 가상 staandalone 웹서버를 띄워 인증서를 발급
    . 이 방식은 동시에 여러 도메인을 발급 받을 수 있음
    . 그렇지만 인증서 발급 전에 Nginx를 중단하고 발급 완료 후 다시 Nginx를 시작해야 함
  4. DNS : 도메인을 쿼리해 확인되는 TXT 레코드로 사이트 유효성을 확인하는 방법
    . 와일드 카드 방식으로 인증서를 발급 가능
    . 이 방법은 당연하게도 서버 관리자가 도메인 DNS를 관리/수정할 수 있어야 하며
    . 인증서 갱신 시마다 DNS에서 TXT값을 변경해야 하므로
    외부에서 TXT 레코드를 입력할 수 있도록 DNS가 API를 제공하는 경우만 갱신 과정을 자동으로 처리(클라우두플레어 API가 대표적인 사례)

1. webroot으로 SSL 인증서 발급

이 방법에 대해서는 Let’s Encrypt 설치 및 SSL 인증서 발급, NGINX 설정 방법nginx 서버에 HTTPS사용을 위한 SSL 인증서 발급받기 (Let’s Encrypt)등을 참조했습니다.

솔직히 이 방법은 번거롭기도하고 나중에 설명하겠지만 한계도 있는 방법입니다. 한번 설치해 운영하다가 한 서버에서 여러 도메인을 운영하는 것이 쉽지 않고, 이 방식으로 인증 시 일부 회사 방화벽에서 거부당하는 사례를 발견해서 사용 중단했습니다.

well-known이 있는 곳을 지정

위에서 설명한 것처럼 이 방법은 사이트 디렉토리 내에 인증서 유효성을 확인할 수 있는 파일을 업로드하여 인증서를 발급하는 방법으로 서버 내에 .well-known이 있는 곳을 지정해 줍니다.

이는 엄청 번거롭지만 1) 특정 폴더를 만들고 2) 이 특정 폴더에서 letsencrypt.conf 파일을 만들고 3) 이를 Nginx 설정 파일에서 이 파일을 읽어오도록 합니다.

먼저 특정 폴더를 만들고 mkdir -p 명령 옵션을 사용해 존재하지 않는 폴더를 만들어 줍니다.

mkdir -p /var/www/letsencrypt/.well-known/acme-challengeCode language: PHP (php)

다음으로는 webroot 경로를 알려주는 letsencrypt.conf 파일을 만듭니다. 이 파일 위치는 일반적으로 /etc/nginx/snippets/에 만드네요. 뭐 nano 편집기를 이용해서 아래와 같이 새로 만들 파일을 엽니다.

nano /etc/nginx/snippets/letsencrypt.conf Code language: PHP (php)

이 파일에 아래와 같은 내용을 추가합니다.

location ^~ /.well-known/acme-challenge/ {
default_type "text/plain";
root /var/www/letsencrypt;
}Code language: PHP (php)

다음으로는 Nginx 설정 파일 중 server 영역에서 아래 파일을 참조하도록 합니다.

include /etc/nginx/snippets/letsencrypt.conf;Code language: PHP (php)

이렇게 설정이 끝나면 Nginx를 다시 시작해 주어야겠죠.

sudo service nginx restartCode language: PHP (php)

예를 들면 아래와 같습니다.

server {
    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;
    server_name happist.com www.happist.com;

    include /etc/nginx/ssl/letsencrypt.conf;

    location / {
        return 301 https://www.happist.com$request_uri;
        expires epoch;
        # return 301 아래에 expires epoch; 을 붙여주는 것은 301 리다이렉트가 캐싱되지 않도록 하기 위함
    }

}Code language: PHP (php)

SSL 인증서 발급

SSH command line에서 아래 명령을 입력합니다.

certbot certonly --webroot --webroot-path=/var/www/letsencrypt  -d 사이트명.com -d www.사이트명.com  Code language: PHP (php)

여기서 webroot-path는 사이트 루트를 말하는 것이 아니라 .well-known 폴더가 있는 곳을 말합니다.

2. 웹서버를 통한 Let’s Encrypt SSL 인증서 발급

앞에서 설명했듯이 SSL인증서를 일반적인 방식으로 발급할 수도 있도 Apache나 Nginx와 같은 웹서버 옵션을 이용해서 Let’s Encrypt SSL 인증서 발급받을 수도 있습니다.

웹서버를 통한 SSL 인증서 발급 방법의 좋은 점은 standalone 방식과 비슷한 방식이면서도 다르게 발급 받을 시 사이트 서비스를 중단하지 않아도 된다는 점이고, 웹서버가 알아서 적절한 SSL 옵션을 제안해 적용해 준다는 점입니다.

이 과정을 다시 자세하게 설명하면

Certot 설치

서버에서 SSL 인증서를 설치할 웹서버용 인증서 설치 툴인 Certbot을 설치합니다. 위에서 설명했듯이 nginx 웹서버용입니다. Certbot은 파이썬 2.7 또는 3.6버젼 이상을 지원한다고 하네요.

sudo apt install certbot python3-certbot-nginxCode language: PHP (php)

아파치라면 아래 명령어를 사용합니다.

sudo apt install certbot python3-certbot-apacheCode language: PHP (php)

Nginx 설정 확인

Nginx 설정에서 도메인이 제대로 설정되어 있는지 확인합니다. 다른 방식은 nginx 설정에서 도메인에 적용되어 있는지가 중요하지 않지만 웹서버를 이용하는 SSL 인증 방식 선택 시 Nginx 설정에서 도메일이 제대로 설정되어 있어야 합니다.

Nginx 설정 파일은 웹서버 설치 방식에 따라 달라지지만 Nginx 기본 설치 방식으로는 설치 시 /etc/nginx/conf.d/에 있고, 우분투에서 권장하는 방식으로 설치 시 /etc/nginx/sites-available/ 디렉토리에 있습니다.

저는 우분투 20.04를 사용하지만 Nginx 기본 설치 방식으로 설치해 /etc/nginx/conf.d/ 디렉토리 아래에 happist.com.conf라는 파일을 만들어 설정 내용을 넣엇습니다.

nano /etc/nginx/conf.d/happist.com.confCode language: PHP (php)

여기에서 다음과 같은 server_name이 등록되어 있는지만 확인하면 됩니다.

server_name example.com www.example.com;Code language: PHP (php)

도메인 등록이 되어 있는지 확인이 되었으면 편집기를 닫습니다. 없다면 도메인을 등록 , 저장 후 편집기를 빠져 나옵니다.

본격적으로 SSL 인증을 시작하기 전에 nginx가 제대로 작동하는지 확인합니다. 우선 테스트해 봅니다.

sudo nginx -tCode language: PHP (php)

아무 문제가 없다고 나오면 nginx를 다시 가동시킵니다.

sudo systemctl reload nginxCode language: PHP (php)

방화벽에서 HTTPS를 허용

아마 기본적으로 설정되어 있기는 하겠지만 80포트와 443포트를 허용해 주고 있는지 확인합니다.

우분투 20.04라면 기본 방화벽으로 ufw를 사용하고 있겠죠. 여기에서라면 ‘Nginx Full’ 옵션을 사용합니다.

sudo ufw allow ssh
sudo ufw allow 'Nginx Full'Code language: PHP (php)

그냥 iptables를 사용한다면 다음 명령으로 80포트와 443포트를 사용 가능하게 만들 수 있습니다.

sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPTCode language: PHP (php)

SSL 인증서 발급

이제 본격적으로 SSL 인증서를 발급해 보시죠. Nginx 웹서버의 경우 아래 명령어를 사용합니다.

sudo certbot --nginx -d 사이트명.com -d www.사이트명.com  Code language: PHP (php)

만약 아파치라면 다음과 같은 명령을 사용합니다.

sudo certbot --apache d 사이트명.com -d www.사이트명.com  Code language: PHP (php)

그러면 /etc/etsencrypt 폴더에 자동으로 SSL 적용 옵션을 제안해 줍니다. 사용자는 이 옵션을 그대로 사용할 수도 있고, 독자적인 옵션을 적용할 수도 있습니다.

그러나 별도 옵션을 적용하면 nginx가 제안하는 사항들이 제대로 업데이트가 안되기 때문에 매번 수작업으로 업데이트를 해주어야 합니다.

독자적인 옵션을 사용하지 않고 그냥 웹서버가 제안하는 옵션 그대로 사용한다면 나쁘지 않다는 생각입니다.

자동 갱신

자동 갱신은 크론에서 다음 명령어를 적용해 가능토록 만들 수 있습니다.

sudo certbot renew --dry-runCode language: PHP (php)

3. standalone 옵션 적용 SSL 인증서 발급

여기 소개하는 standalone 옵션은 사이트 서비스를 중단하고 사이트의 네트워킹을 이용해 인증서버와 접속하는 방식을 사용합니다. 처음에 가장 많이 소개된 방식이기도 합니다.

이러한 방식은 단점이면서도 장점을 가지는데요. 단점은 이 인증을 진행하는 동안 사이트 서비스를 중단해야 한다는 점이구요. 장점은 간편하고 빠르고 더우기 안정성도 높습니다.

사내 방화벽을 매우 까다롭게 관리하는 국내 일부 회사 중에서 SSL 인증 방식에 따라 접속을 허용하는 않는 경우도 있는데요. 우리나라에서 가장 큰 회사 중의 하나도 이 standalone 방식만 제대로 통과되는 것으로 확인하기도 했습니다.(2020년 5월 기준)

이런 저런 이유로 웹서버를 중단시키고 발급받는 불편함은 있지만 상대적으로 안정적인 방식이라고 생각합니다.

아래와 같은 명령어를 사용합니다. 혼란을 피하기 위해 처음부터 다시 설명해 봅니다.

우선 SSL 인증을 위한 Certbot tool을 설치합니다. 이전 단계에서 설치 했다면 Pass

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

다음으로는 웹서버를 중단시킵니다. 아무 디렉토리에서나 가능한 명령이지만 root로 이동해서 진행해 봅니다.

cd /root/
service nginx stopCode language: PHP (php)

이제 certbot 명령을 이용해 SSL 인증을 시작합니다. standalone 명령을 사용하고 도메인 이름만으로 인증이 진행되는 -d 옵션을 적용합니다.

certbot certonly --standalone -d 사이트명.com -d www.사이트명.comCode language: PHP (php)

인증이 완료되면 웹서버를 다시 가동시킵니다.

service nginx restartCode language: PHP (php)

여러개 도메인을 한번에 인증받기

이 standalone 옵션은 또한 한꺼번에 여러 개의 사이트를 인증 받을 수 있는데요. 아래와 같은 명령을 사용할 수 있습니다. 이는 연속해서 사이트명을 나열해주면 가능합니다.

예를들면 아래와 같이요.

service nginx stop
certbot certonly –standalone -d happist.com -d http://www.happist.com -d sample1.com -d http://www.sample1.com -d sample2.kr -d http://www.sample2.kr -d sample3.co -d http://www.sample3.co -d sample4.net -d http://www.sample4.net
service nginx restart
Code language: PHP (php)

단 이렇게 여러개 사이트를 인증 받을 시 인증서 존재 위치가 맨앞 사이트명으로 통일되게 됩니다. 나중에 사이트를 없앨 때 난감할 수도 있습니다.

즉 위의 경우 맨 앞에 happist.com 이름을 딴 폴더가 만들어지고 이 폴더 아래에 4개의 .pem 파일이 만들어지고, 이 파일들이 5개 사이트에 대한 인증이 구성됩니다.

그럴 경우 나중에 어느 한 사이트를 없애는 경우 – 사이트가 커져서 그 사이트는 다른 서버에서 운영을 한다던지, 아예 사이트를 폐쇄해 버리든지 – 하는 경우 관리가 불편해 질 수 있습니다.

따라서 조금 귀찮드라로도 사이트 하나 하나 명령어를 따로 입력하는 것이 관리엔 더 좋습니다. 아래처럼

certbot certonly --standalone -d happist.com -d www.happist.com

certbot certonly --standalone -d sample1.com -d www.sample1.com

certbot certonly --standalone -d sample2.kr -d www.sample2.kr

certbot certonly --standalone -d sample3.co -d www.sample3.co

certbot certonly --standalone -d sample4.net -d www.sample4.netCode language: PHP (php)

이렇게 각각 명령을 사용해 인증하면 사이트마다 폴더가 생겨서 관리가 좀금 더 쉽워집니다. 아래처럼 각 사이트별 폴더가 형성됩니다. 그 폴더 아래에 그 사이트에 해당하는 각종 .pem 파일이 만들어지기 때문에요.

  • /etc/letsencrypt/live/happist.com
  • /etc/letsencrypt/live/sample1.com
  • /etc/letsencrypt/live/sample2.kr
  • /etc/letsencrypt/live/sample3.co
  • /etc/letsencrypt/live/sample4.net

4. DNS 이용해 발급 받기

도메인이 연결된 DNS의 TXT레코드를 이용해 인증받는 방식으로 많은 장점을 가진 방법이지만 갱신 시 마다 DNS 정보 중 TXT 레코드를 새로 생성해야 하므로 이를 지원하는 DNS API가 없는 경우 자동 갱신이 어렵다는 단점이 있습니다.

  • 와일드 카드 방식으로 인증서를 발급 가능
  • 당연하게도 서버 관리자가 도메인 DNS를 관리/수정할 수 있어야 하며
  • 인증서 갱신 시마다 DNS에서 TXT값을 변경해야 하므로
    외부에서 TXT 레코드를 입력할 수 있도록 DNS가 API를 제공하는 경우만 갱신 과정을 자동으로 처리

이 방법은 위에서 소개한 방법 중에서 가장 까다로운 방법으로 에러 가능성이 높아 여러번 시도하다보면 최대 허용 시도를 초과해 당분간(1주일 정도) 인증이 불가능해지는 불쌍사가 종종 발생하더군요.

그래서 저는 편리함에도 불구하고 사용하지 못하고 있습니다.

클라우드플레어(CloudFlare)의 경우

DNS를 클라우드플레어(CloudFlare)에 도메인 네임서버로 등록해 사용하는 경우 클라우드플레어(CloudFlare)가 제공하는 DNS API를 이용해서 와일드 카드 인증서 등록 및 갱신이 가능합니다.

클라우드플레어(CloudFlare) API 관리 폴더와 파일 생성

클라우드플레어(CloudFlare) API를 관리할 폴더와 파일을 생성합니다.

cd /root
mkdir .secret
nano /root/.secret/cloudflare_api.iniCode language: PHP (php)

cloudflare_api.ini 파일에는 아래 내용을 추가합니다.

여기서 이메일 주소는 클라우드플레어(CloudFlare) 계정에 등록된 이메일이고, Global API Key는 CloudFlare의 계정 관리에서 발급 받을 수 있습니다.

dns_cloudflare_email = "이메일 주소 입력"
dns_cloudflare_api_key = "Global API Key 입력"Code language: PHP (php)

생성한 폴더와 파일에 대한 권한을 변경합니다.

chmod 700 /root/.secret
chmod 400 /root/.secret/cloudflare_api.iniCode language: PHP (php)

Certbot tool과 클라우드플레어 DNS 인증 플러그인 설치

여기에서는 SSL 인증 진행에 필요한 Certbot tool인 letsencrypt과 클아우드플레어 인증 플러그인을 설치합니다.

먼저 인증 플러그인 설치를 위한 파이선 PIP를 설치합니다.

<em>apt install python-pip</em>Code language: PHP (php)
<em>pip install certbot-dns-cloudflare</em>Code language: PHP (php)

혹시SSL 인증을 위한 Certbot tool가 설치되지 않았다면 설치합니다. 이전 단계에서 설치 했다면 Pass

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

SSL 인증서 발급

SSL 인증서 발급 명령어입니다. example.com을 예를 든 것이고 자신의 도메일을 대체하면 됩니다.

/usr/local/bin/certbot certonly --dns-cloudflare --dns-cloudflare-credentials /root/.secret/cloudflare_api.ini -d example.com,*.example.com --preferred-challenges dns-01Code language: PHP (php)

이후 nginx라면 dhparam을 생성해 줍니다.

mkdir /etc/nginx/ssl  
cd /etc/nginx/ssl
openssl dhparam -out dhparams.pem 4096Code language: PHP (php)

이후 아래 명령을 추가합니다.

openssl rand 48 > 
session_ticket.key Code language: PHP (php)

인증서 자동 갱신

이렇게 발행된 인증서를 자동으로 갱신하기 위해서는 코론에 등록합니다.

crontab -eCode language: PHP (php)

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

30 4 * * 0 /usr/local/bin/certbot renew --quiet --post-hook "/usr/sbin/service nginx reload" > /dev/null 2>&1Code language: PHP (php)

아파치라면 아래 명령을 사용합니다.

30 4 * * 0 /usr/local/bin/certbot renew --quiet --post-hook "/usr/sbin/service apache2 restart" > /dev/null 2>&1Code language: PHP (php)

Vultr에서 DNS를 이용한 와일드카드 인증 방법

가상서버 호스팅인 Vultr를 이용하는 경우에도 DNS를 이용해 와일드카드 인증이 가능하다고 합니다.

이는 Install Wildcard Certificate from Let’s Encrypt (Ubuntu 20.04 + Nginx + Vultr)를 참조해 간단히 정리했습니다.

필요 사항

  • 우분투 20.04 설치된 서버
  • Vultr DNS에 도메인 네임 등록, 예를들어 example.com
  • A/AAAA 레코드 및 CNAME DNS 레코드 등록
  • Vultr API 사용 가능 상태로 변경
    . 이는 Account – API에서 Enanble API를 눌러서 활성화 함
    . 그러면 Personal Access Token 번호가 나오는데 이를 기록해 놓음
Vultr 가상 서버 API

필요 패키지 설치

이 작업에 필요한 필요 패키지를 설치합니다. 우선 파이썬이 없으면 파이선3를 설치합니다. 그렇지만 우분투 20.04를 설치하면 파이썬 3가 설치되어 있습니다.

<code>sudo apt install -y python3</code>Code language: PHP (php)

다음으로는 Lexicon tool을 설치하는데요. 이는 다양한 DNS 프로바이더로부터 DNS 기록을 관리할 수 있는 파이썬 도구라고 합니다.

<code>sudo apt install -y lexicon</code>Code language: PHP (php)

acme.sh 클라이언트 설치

이 클라이언트는 root 사용자만 설치 가능하므로 root 사용자로 전환합니다.

<code>sudo su - root</code>Code language: PHP (php)

scme.sh를 다운받아 설치합니다. 아래 your_email@example.com는 Vultr 계정에서 사용하는 이메일 주소입니다.

<code>git clone https://github.com/Neilpang/acme.sh.git </code>
<code>cd acme.sh </code>
<code>./acme.sh --install --accountemail "your_email@example.com" </code>
<code>source ~/.bashrc </code>
<code>cd</code>Code language: PHP (php)

와일드카드 SSL 인증

도메인에 대한 RSA와 ECC와일드카드 인증을 받습니다. 아래와 같은 명령을 사용합니다.

  • 아래 your_email@example.com는 Vultr 계정에서 사용하는 이메일 주소
  • XXXXXXXXXXXXXXX은 Personal Access Token 번호
Configure your API key and username
 export PROVIDER=vultr
 export LEXICON_VULTR_USERNAME="your_vultr_email@example.com"
 export LEXICON_VULTR_TOKEN="XXXXXXXXXXXXXXX"
 RSA 2048
 acme.sh --issue --dns dns_lexicon -d example.com -d '*.example.com' --keylength 2048
 ECC 256
 acme.sh --issue --dns dns_lexicon -d example.com -d '*.example.com' --keylength ec-256Code language: PHP (php)

이러한 작업 결과 RSA 및 ECC/ECDSA인증 및 키는 아래 폴더에 위치하게 됩니다.

RSA: <code>~/.acme.sh/example.com</code> directory.
ECC/ECDSA: <code>~/.acme.sh/example.com_ecc</code> directory.Code language: PHP (php)

이들 폴더를 이용할 수 없기 대문에 이들을 /etc/letsencrypt 폴더로 옮김니다. 먼더 폴더를 만들고..

<code>sudo mkdir -p /etc/letsencrypt/example.com </code>
<code>sudo mkdir -p /etc/letsencrypt/example.com_ecc</code>Code language: PHP (php)

아래 명령으로 인증 및 복사합니다.

RSA
 acme.sh --install-cert -d example.com \
         --cert-file /etc/letsencrypt/example.com/cert.pem \
         --key-file /etc/letsencrypt/example.com/private.key \
         --fullchain-file /etc/letsencrypt/example.com/fullchain.pem \
         --reloadcmd "sudo systemctl reload nginx.service"
 ECC/ECDSA
 acme.sh --install-cert -d example.com --ecc \
         --cert-file /etc/letsencrypt/example.com_ecc/cert.pem \
         --key-file /etc/letsencrypt/example.com_ecc/private.key \
         --fullchain-file /etc/letsencrypt/example.com_ecc/fullchain.pem \
         --reloadcmd "sudo systemctl reload nginx.service"Code language: PHP (php)

SSL 인증서 관련 참고

최신 Let’s Encrypt SSL 인증서 발급 방법 4가지 정리

Let’s Encrypt SSL 인증서 발급 및 자동 갱신 방법(업데이트)

최신 보안 트렌드를 반영한 Let’s Encrypt 인증서 세팅 방법

웹, 브라우저, 서버에서 SSL 인증서 정보 확인 방법, SSL 인증서 만료일 확인 등

서버 보안 관련

랜섬웨어 대응, 서버 및 워드프레스 필수 보안 설정 15가지

워드프레스 보안 강화 NGINX 설정 방법 8가지

리눅스 서버 보안을 위한 포트 사용 최적화

리눅스 서버 root 사용 중지로 리눅스 서버 보안 강화하기

우분투 서버 보안 자동 업데이트 및 업데이트 메일 통보 방법

워드프레스 보안 진단 WPScan 사용법 및 이메일로 결과 받아보기

DDoS 취약 기능 XMLRPC 사용 중지로 워드프레스 보안 강화하기

워드프레스 보안 강화를 위한 사용자명 변경 방법

워드프레스 멀웨어 경험에서 배운 워드프레스 보안 가이드

가상서버호스팅 서버 보안 설정 방법 – Nginx +Ubuntu의 경우