-3.8 C
New York
금요일, 1월 2, 2026

Buy now

Home Blog Page 212

코로나 중국 경제, 2028년 세계 1위 경제대국 등극 전망 by CEBR

0

코로나 대응에 따라 미국과 중국 경제 성장률 격차가 커지면서 경제대국 순위에서 중국이 기존 예상보다 5년이 빠른 2028년에 세계 1위 경제대국이 될 것이라는 CEBR 전망이 나왔습니다.

영국에 본부를 두고 있는 경제 예측 전문기관 CEBR(Center for Economic and Business Research)은 2020년 12월 26일 발표된 연례 보고서에서 다음과 같은 주요 내용을 발표했습니다

  1. 코로나 팬데믹과 이로 인한 경제 성장 후퇴는 확실히 중국에 유리한 상황을 만들었습니다.
  2. 중국은 엄격한 조기 봉쇄를 통한 “코로나 팬데믹 관리”에 성공하면서 상대적으로 높은 경제 성장이 가능하게 만들었으며, 반면 미국을 비롯한 서구는 코로나 팬데믹 관리에 실패하면서 장기적 성장 잠재력을 잃었습니다.
  3. 중국은 2021년~2025년에 연평균 5.7% 경제 성장이 예상되고, 2026년~2030년에는 연평균 4.5% 성장할 것으로 전망했습니다.
  4. 미국은 2021년 강한 반등을 보일 가능성이 있지만, 성장률은 2022년에서 2024년에는 1.9%로 둔화되고 2025년 이후에는 1.6%로 더욱 더 둔화할 것으로 전망했습니다.
  5. 따라 이전 예상보다 5년이나 빠른 2028년 중국은 미국을 추월해 세계 최대 경제대국이 될 것이라고 전망했습니다.

2020년 10대 경제대국에 한국 포함되다

코로나 팬데믹으로 2020년 10대 경제대국 순위는 크게 변동되지 않았지만. 코로나 팬데믹 대응이 비교적 성공한 한국이 10위권에 진입하는 등 일부 변동이 있었습니다.

  1. 미국, 중국, 일본, 독일의 최상위 4개국 순위에는 변동이 없음
  2. 2019년 영국을 제치고 5위로 올라섰던 인도는 코로나 팬데믹 영향을 크게 받으면서 6위로 떨어짐.
  3. 영국의 극심한 경제 침체에도 불구하고, 인도 경제성장 부진에다 인도 통화 루피의 약세에 힘입어 다시 5위로 복귀.
  4. 프랑스, 이탈리아는 순위를 유지
  5. 브라질은 코로나 팬데믹 악영향을 받아 극심한 역성장으로 2019년 9위에서 2020년에는 12위로 밀림
  6. 캐나다는 브라질을 대신해 9위로 올라섰습니다.
  7. 한국은 코로나 팬데믹 관리에 비교적 성공하면서 2019년 12위에서 10위권에 신규 진입
    코로나 팬데믹 관리에 실패한 브라질과 러시아를 제친 것

CEBR은 2020년 10대 경제대국 리스트를 아래와 같이 밝혔습니다.

  1. 미국
  2. 중국
  3. 일본
  4. 독일
  5. 영국
  6. 인도
  7. 프랑스
  8. 이탈리아
  9. 캐나다
  10. 한국 

참고로 IMF가 전망한 2020년 GDP 순위는 아래와 같습니다.

IMF전망, 2020년 GDP 순위, Graph by Happist
IMF 전망, 2020년 GDP 순위, Graph by Happist

주요 경제대국들의 경제 전망

CEBR은 세계 경제에 대해 코로나 팬데믹 영향은 느린 성장보다는 높은 인플레이션 형태로 나타날 것으로 전망했습니다.

2020년대 중반에 금리가 상승하는 경제 순환이 예상되면서 이는 코로나 팬데믹에 대응하기 위해 막대한 자금을 투입한 각국 정부들에게 도전이 될 것입니다.

하지만 2030년대까지 가속화되는 근본적인 추세는 보다 친환경적이고, 기술 기반 사회로 발전할 것입니다.

중국과 미국

CEBR은 코로나 팬데믹 초기부터 엄격한 조기 봉쇄를 통해 비교적 코로나 팬데믹을 성공적으로 관리하면서 미국과의 경제전쟁을 유리하게 이끌었다고 지적했습니다.

한동안 세계 경제의 가장 중요한 주제는 미국과 중국 간 경제 및 소프트 파워 투쟁이었습니다. “코로나 팬데믹”과 그에 따른 경제적 타격은 확실하게 이러한 경쟁을 중구에 유리하게 만들었습니다.

중국은 2021년~2025년에는 연평균 5.7% 경제 성장율이 예상되며, 2026년 ~ 30년에는 연평균 4.5%로 성장률이 둔화할 것으로 예상됩니다.

미국은 코로나 팬데믹 후 2021년 강한 경제 반등을 보일 가능성이 높습니다. 그렇지만 2022년 ~ 2024년에는 연평균 성장률이 1.9%로 둔화되고 2025년부터는 1.6%로 더욱 더 둔화할 것으로 전망됩니다.

이러한 중국과 미국 경제 전망에 따라 이전에 예상한 것보다 5년 이른 2028년에는 중국이 미국을 제치고 세계 1위 경제대국이 될 것이라고 전망했습니다.

2028년 중국, 세계 1위 경제대국 등극 예상,미중 무역전쟁 이미지, Image - Bloomberg
미중 무역전쟁 이미지, Image – Bloomberg

영국

코로나 팬데믹으로 영국은 지난 3월 단행된 국경 봉쇄 이후 경제가 악화되어 상반기에 -22.3% 역성장을 기록했습니다. 그러면 2020년 G7국가 중에서 가장 심한 경제 불황을 겪어 영국 내 경제 연구소 OBR(Office for Budget Responsibility)은 -3.4% 역성장을 예상하고 있습니다.

CEBR은 영국 경제가 코로아 팬데믹 이후 2024년까지 연평균 4% 성장할 것이며, 2026년 ~ 2030년까지는 연평균 1.8% 성장할 것으로 전망했습니다.

따라서 영국 GDP는 전통적인 경쟁국인 프랑스를 지속적으로 앞지를 것이며, 2035년 기준 프랑스보다 GDP측면에서 23% 더 높은 것으로 전망했습니다.

이는 브랙시트 협상이 긍정적으로 끝나면서 영국이 브랙시트로 인한 손실이 상대적으로 적으며, 영국의 디지탈 부문이 향허 영국 경제를 견인하면서 번창할 것으로 봤습니다.

영국의 실업률은 4.8% 수준으로 EU 평균 8.4%에 비해서 상당히 안정적인 수준으로 유지하고 있으며, 안정적인 브랙시트 협상 결과 유럽에서 성과가 높은 국가중의 하나가 되고 있다고 밝혔습니ㄷ.

유럽

유럽은 2020년 세계 10대 경제국가 중 생산량 19%를 차지하고 있지만 점점 그 지위이 떨어지면서 2035년에는 12% 수준으로 낮아질 것으로 전망했습니다.

더우기 영국과 EU간 심각한 분쟁이 격화되면 생산량 비중은 더욱 더 낮아질 것으로 보인다고 CEBR은 부정적으로 전망했습니다.

인도

인도는 코로나 팬데믹 대응에 실패하면서 2020년에는 어려움을 겪었습니다.

그렇지만 2021년이후에는 안정적인 백신 공급과 풍부한 농업부문 덕분에 안정적인 성장이 가능할 것으로 보입니다.

우선 코로나 팬데믹에서 빨리 탈출하기 위한 선결 조치인 백신 공급과 관련, 세계 대부분 백신 제조업체 공장이 인도에 있기 때문에 안정적인 백신 공급이 가능하기 때문에 다른 개발도상국보다는 유리한 위치에 있다고 CEBR은 밝혔습니다.

또한 2016년 단행된 민주화 개혁과 최근 논란이 되고 있지만 농업 부문 자유화 노력이 장기적인 경제적 이익을 가져다 줄 것으로 전망햇습니다.

이러한 근거에 따라 인도 경제는 2021년에는 9% 성장할 것이며, ㅇ어 2022년에도 7% 성장하면서 높은 성장을 이어갈 것으로 보입니다.

이후 경제 규모가 커지면서 자연스럽게 경제성장률은 둔화될 것이며 2035년에 5.8% 정도 성장할 것으로 예상했습니다.

참고

나이키 실적 분석과 월가의 나이키 주가 평가(23년 2분기 업뎃)

그동안 분기별 나이키 실적과 월가 증권사들의 나이키 주가 전망을 을 분석했지만, 당기 분석 뿐만이 아니라 이전 분기 분석도 같은 페이지에서 볼 수 있다면 좀더 효율적이라는 지적에 따라 , 이 페이지에서는 분기별 나이키 실적, 나이키 전망 그리고 월가 증권사들의 나이키 주식 추천지수를 비롯한 나이키 주가 목표 등을 같이 정리, 업데이트 하고자 합니다.

기본적으로 분기별 나이키 실적은 별도 포스팅하기로 하고 여기서는 그 분석 내용 중 핵심 내용 중심으로 분기마다 업데이트 하도록 하겠습니다. 그리고 나이키 주가와 관련된 평가 등을 수시로 업데이트 하고자 합니다.

월가의 나이키 주식 추천지수 및 니이키 주가 목표

여기서는 월가 증권사들이 제시하는 나이키 주식 추천지수 및 나이키 주가 목표에 대해서 살펴보도록 하죠. 한국과 마찬가지로 미국 주식에 대한 증권사 리포트들은 끊임없이 나오는데 이를 정리해주는 사이트 데이타를 기반으로 주기적으로 업데이트 합니다.

나이키 주가 추이

먼저 나이키 주가가 어떻게 움직여 왔는지 간단히 살펴보기 위해 나이키 주가 추이 그래프를 살펴보죠.

아래 그래프는 IE와 같은 레거시 브라우저에서는 제대로 보이지 않으니, 크롬과 같은 모던 브라우저를 사용하면 제대로 볼 수 있습니다. 아직 한국에서는 iE 브라우저 사용자가 어느 정도 되지만 해외에서는 거의 사라진 브라우저로 대부분 업체에서 지원을 중단하고 있습니다.

[stock_market_widget type=”chart” template=”basic” color=”#5679FF” assets=”NKE” range=”1mo” interval=”1d” axes=”true” cursor=”true” range_selector=”true” api=”yf”]

주목할만한 나이키 주가 전망 보고서

이번 21년 3분기 분기 나이키 실적, 특히 매출은 시장 기대에 미치지 못했고, 더 나아가 부정적인 향후 전마잉 제기되면서 나이키 주가는 하락하고 있습니다.

이에 따라 많은 증권사들이 나이키 주가에 부정적인 전망을 발표하고 있는데요. 월가 리서치 회사인 BTIG는 나이키 주식을 매수에서 중립으로 하향 조정했습니다. BTIG는 별도 나이키 주가 목표를 제시하지는 않았지만, 이전 보고서에서는 177달러를 제시했었습니다.

BTIG 분석가 Camilo Lyon은 소매업체 현황과 공급망 전반을 검토한 결과, 베트남에서 코로나 팬데믹 확산으로 인한 공장 폐쇄 결과 심각한 공급망 중단이 나타나고 있다는 점을 확인했으며, 이러한 상황은 나이키 2분기 실적 발표 이후 악화되었다고 분석했습니다.

이러한 공급망 문제로 나이키 등의 생산 주문 취소는 여름 휴가에서 시작해 내년 봄까지 지속될 가능성이 상당이 커졌으며, 나이키 공급의 51%를 차지하는 베트남에서 최소 2개월동안 생산량이 거의 없는 상황에 직면해 있다고 분석했습니다.

베트남은 나이키 공급에 있어 신발 30%, 의류의 30%를 담당하고 있어 당분가 나이키 전망이 상향 조정될 가능성이 낮다고 봤습니다.

월가 증권사들의 나이키 주가 평가(9월 업뎃)

2021년 9월 나이키 주식에 대해 의견을 제시한 37개 증권사들의 나이키 주식에 대한 의견을 살펴보면

  • 강력 매수 의견은 7개사로 지난 5월 10개사에 비해 다소 줄었습니다.
    매수 의견 12개사로 마찬가지로 5월 18개사에 비해 줄었습니다.
    반면 보유 의견을 제시한 증권사는 17곳으로 크게 늘었습니다.
  • 그러나 전체적으로 나이키 주식 추천율은 1.9로 매수를 추천하고 있습니다.
  • 또한 증권사 애널리스트들의 평균 목표 주가는 184.83달러로 이전의 161.87달러에 비해서 상승
    현재 주가 149.59달러에 비해서는 상승 여력이 있다는 평가
월가 증권사들의 나이키 주가 전망, 나이키 목표 주가, 2021년 9월 기준

나이키 주가와 경쟁사들 주가 비교

나이키 주가를 경쟁사들과 비교해보기 위해서 아디다스, 언더아머와 같은 스포츠 기업과 스포츠 의류에서 두각을 나타내고 있는 룰루레몬 주가를 비교해 보았습니다.

[stock_market_widget type=”comparison” template=”basic” color=”#5679FF” assets=”NKE,LULU,UA,ADDYY” fields=”name,change_abs,change_pct,volume,dividend_yield,eps,forward_eps,pe_ratio,forward_pe_ratio,gross_margin,operating_margin,quarter_earnings_growth,market_cap,chart,target_mean_price,target_high_price,target_low_price” api=”yf” chart_range=”1mo” chart_interval=”1d”]

지난 11월 30일로 끝나는 4분기 나이키 실적(회계년도 2021년 2분기) 실적이 발표되었습니다. 이번에 발표된 4분기 나이키 실적을 살펴보고 중권사들이 제시하는 나이키 전망 및 나이키 주가 목표 등을 살펴 봅니다.

23년 2분기 나이키 실적 분석

나이키 실적을 발표전에 월가에서는 먼저 나이키 북미 수요는 좋지 않다고 소문이 났엇습니다. 나이키 제품을 떼다가 판매하는 도매상들의 주문이 크게 줄엇다는 통게가 발표되기도 했습니다.

그래서 니이키기 믿을 곳은 팬데믹이 해제된 중국 수요가 어느 정도 나오느냐가 관건이라는 지적이 많았습니다.

다행히 이번 분기 나이키 중국 매출이 크게 늘어 다른 지역의 부진을 커버하고도 남았기 때문에 나이키 분기 매출은 전년비 5% 증가하며, 월가 예상치를 상회했습니다.

다만 경기침체 조짐 등으로 마진압박을 받으며 낙 및 나이키 주당 순익은 월가 예상치에 미치지 못햇습니다.

나이키 실적 요약

이번 분기 나이키 실적은 매출은 월가 예상치를 상회했지만 주당 순이익은 소폭 하회했습니다.
이러한 주당순이익

  • 주당순이익 66센트, 월가 예상치 67센트 하회
  • 매출 128.3억 달러, 월가 예상치 125.9억 달러 상회
    • 전년동기 매출 122.3억 달러비 5% 증가
  • 순이익 10.3억 달러로 전년동기 14.4억 달러(주당 90센트)에서 감소

나이키 매출이 월가 예상치를 상회하면서 성장을 지속한 이유는 중국의 팬데믹 개방 후 중구 매출이 크게 늘었기 때문으로 풀이

21년 3분기 나이키 실적 분석

2021년 8월 31일로 끝나는 3분기 나이키 실적(회계년도 2022년 1분기) 실적이 발표되었습니다. 시장에서 우려했던 공급망 혼란으로 시장 기대에 미치지 못한 매출 등으로 다시 실망스러웠던 3분기 나이키 실적을 살펴보고 중권사들이 제시하는 나이키 전망 및 나이키 주가 목표 등을 살펴 봅니다.

코로나 팬데믹으로 어려움을 겪었던 나이키는 경제아 오픈되면서 빠른 회복세를 보였지만 델타 변이가 확산되고, 특히 팬데믹 동안 안정적이었던 아시아의 델타 변이 확산은 공장 폐쇄 등 공급망 혼란을 불러왔고, 그러한 피해 직격탄을 받앗습니다.

결국 이익 등 지표는 시장 기대를 웃돌았지만 매출 지표는 시장 기대에 미치지 못했고, 향후 전망도 부정적입니다. 그러면서 나이키 주가도 빠지고 있습니다.

Executive summary

우선 나이키 실적을 시장 예측치와 발표 실적을 간단히 비교해 봤습니다. 주당 이익은 시장 기대를 넘었지만 매출은 시장 예상을 하회했습니다.

또한 글로벌 공급망이 혼란스러워짐에 따라 시장 예측을 하회했고, 베트남 운송시간 및 노동력 부족으로 인한 공급망 혼란의 타격이 점점 더 심화되면서 이후 실적 전망을 낮추었습니다.

항목결과실적/가이드시장 예측
조정 주당 이익
(Earnings Per Share)
시장 예측
상회
$1.16$1.11
매출($M) 시장 예측
하회
122.5억 달러124.6억 달러
연간 매출 전망시장 예측
하회
한자릿수 중반대
증가율
12% 증가
다음 분기 전망
매출($M)
시장 예측
하회
한자리수
증가율
12% 증가
  1. 3분기 나이키 매출 122.5억 달러로 전년비 15.6% 증가
    전분기 매출 123.4억 달러에 비해서는 0.8% 감소
    이는 월가 예측치 124.6억 달러에 미치지 못한 것
    . 나이키 브랜드 매출 116.4억 달러로 전년비 16% 증가
    . 캔버스 브랜드 매출 6.29달러로 전년비 12% 증가
  2. 전 지역에서 매출이 증가했지만 매출 증가율은 10~30%대로 이전 분기에 비해서 둔화
    . 북미 매출 48.8억 달러로 전년비 15.5% 증가
    . 유럽 매출 33.07억 달러로 전년비 13.6% 증가
    . 아시아/남미 매출 14.65억 달러로 33.3 증가
    . 중국 매출 19.8억 달러로 11.1% 증가
  3. 대부분 제품 판매가 크게 늘었는데, 성장률은 스포츠 장비, 의류, 신발순을 보임
    . 신발 매출 77.2억 달러로 전년비 14% 증가했지만 전분기 79.5억 달러 비 감소
    . 의류 매출 34.5억 달러로 전년비 20% 증가했지만 전분기 39.4억 달러 비 감소
    . 스포츠 장비 매출 4.7억 달러로 전년비 25.3% 증가했으며, 전분기 3.7억 달러 비 증가
  4. 나이키 소비자 직접 판매(D2C) 매출은 47억 달러로 전년비 28% 증가
    이는 전분기 45억 달러에 비해서도 소폭 증가
  5. 나이키 디지탈 판매는 전년비 25% 증가해 증가율은 크게 둔화됨
    . 이는 경제가 정상화되고 오프라인 매장 판매가 늘면서 디지탈 판매 증가율이 둔화했지만
    . 미국 온라인판매 증가율에 비해서 높은 수준
  6. 매출총이익은 56.96억 달러, 매출총이익율 46.5%로
    , 전년 동기 매출총이익율 43.1%에서 상승(3.4%p 상승)
  7. 영업이익 21.4억 달러, 영업이익율 17.3%로 전년비 20.3% 증가
    . 이번 분기 영업이익율은 전년동기 비나 전분기해 비해 모두 상승
  8. 순이익 18.74억 달러, 순이익율 15.3%를 기록
    . 이는 전년 동기 14.3%나 전분기 12.2%에 비해서도 상당히 개선된 것
  9. 주당 순이익(EPS)는 1.16달러로 시장 예측치 1.11달러를 상회

향후 다소 부정적인 전망 제시

  1. 나이키는 글로벌 공급망 혼란으로 비즈니스가 타격을 받고 있다고 밝히면서 회계년도 2022년 연간 전망치를 낮춤
    . 나이키 신발 50%와 의류 30%를 생산하고 있는 베트남에서는 팬데믹으로 공장 폐쇄가 진행중으로 생산 차질을 빛고 잇음
    . 생산 제품의 운송 시간지 증가하고 운송 가격이 상승하면서 타격을 주고 있음
    Friend에 따르면 북미로 운송 시간은 팬데믹 이전에 비해서 두배에 달하고 있으며
    아시아에서 북미로 이동 시간은 80일이 걸리고 있음
  2. 이에 따라 나이키는 연간 실적 전망을 한 자릿수 중반 증가율을 보일 것으로 전망해 시장 기대치 12%에 미치지 못했으며,
  3. 다음 분기 매출도 한자릿수 증가를 제시해 시장 기대치 12%에 미치지 못했음
  4. 이러한 공급 이슈에도 불구하고 신발과 운동복에 대한 수요는 여전히 강하다고 평가
    다만 공급 이슈로 단기 실적은 저조할 것으로 예상

매출 122.5억 달러로 전년비 16% 성장

모든 지역에서 매출 증가로 3분기 매출 122.5억 달러로 전년 비 15.6% 성장했습니다. 하지만 이는 월가 예측치 124.6억 달러에 다소 미치지 못한 결과로 시장에서 어닝 쇼크로 받아들이는 것 같습니다.

  1. 3분기 나이키 매출 122.5억 달러로 전년비 15.6% 증가
    전분기 매출 123.4억 달러에 비해서는 0.8% 감소
    이는 월가 예측치 124.6억 달러에 미치지 못한 것
  2. 나이키 브랜드 매출 116.4억 달러로 전년비 16% 증가
    캔버스 브랜드 매출 6.29달러로 전년비 12% 증가
  3. 대부분 제품 판매가 크게 늘었는데, 성장률은 스포츠 장비, 의류, 신발순을 보임
    . 신발 매출 77.2억 달러로 전년비 14% 증가했지만 전분기 79.5억 달러 비 감소
    . 의류 매출 34.5억 달러로 전년비 20% 증가했지만 전분기 39.4억 달러 비 감소
    . 스포츠 장비 매출 4.7억 달러로 전년비 25.3% 증가했으며, 전분기 3.7억 달러 비 증가

분기별 나이키 매출 및 매출 증가율 추이

북미와 유럽이 성장 견인

전 지역에서 매출이 증가했지만 매출 증가율은 10~30%대로 이전 분기에 비해서 매출증가율은 크게 둔화되었습니다.

그동안 팬데믹에서 먼저 벗어난 중국이 나이키 매출 성장을 견인했었지만 , 이번 분기에는 중매출 증가율은 가장 낮은 수준을 기록했습니다.

나이키 중국 매출은 11% 증가하면서 모든 지역 중에서 가장 낮은 증가율을 보였는데 이는 일찍부터 팬데믹 기저 효과가 끝났기 때문으로 볼 수 있습니다.

북미지역 매출은 15% 증가한 48.8억 달러를 기록했습니다. 이러한 북미 지역 매출은 월가에서 예측한 50.5억 달러에 미치지 못했습니다.

  1. 북미 매출 48.8억 달러로 전년비 15.5% 증가
  2. 유럽 매출 33.07억 달러로 전년비 13.6% 증가
  3. 아시아/남미 매출 14.65억 달러로 33.3 증가
  4. 중국 매출 19.8억 달러로 11.1% 증가

지역별 매출 증가율 추이

직접판매(D2C) 및 디지탈 판매 지속

그 동안 나이키는 직접판매(D2C)전략을 성공적으로 수행한 회사로 명성이 높았죠. 이러한 전략적 성과들이 이번 코로나 팬데믹 위기를 극복하는데 큰 도움을 주었다는 것은 주지의 사실입니다.

이번 21년 2분기 나이키 직접판매(D2C) 매출은 47억 달러를 기록해 전년비 28% 증가했습니다. 아래에서 언급하겠지만 나이키 디지탈 판내, 즉 이커머스판매 증그율이 둔화되면서 나이키 직접판매 증가율도 전분기 73%에서 크게 둔화되었습니다.

또한 경제 오픈에 따라 오프라인 매장 판매가 증가하면서 상대적으로 나이닠 디지탈 판매, 즉 이커머스 판매 증가율은 25%로 둔화되었습니다. 하지만 이는 전반적인 미국 이커머스 성장율 둔화와 맥을 같이하고 또 평균보다는 높은 수준입니다.

이러한 디지탈 판매에 대해 나이키는 점점 온라인쇼핑은 더 많은 사람들의 쇼핑 여정의 일부가 되고 있기 때문에 2025년까지 나이키 디지탈 매출 비중을 40%까지 늘리겠다는 나이키 목표 달성 가능성이 점점 높아지고 있다고 평가했습니다.

또한 이런 디지탈 판매 증가는 나이키 제품 수익성을 더욱 더 높이고 있는데요. 여기에는 할인 인센티브가 없기 때문입니다. 지속적으로 할인 가격을 판매의 중요한 동력으로 삼는 도매 판매 파트너 비중이 줄어들면서 이는 궁극적으로 나이키 손익 개선으로 이어지고 있습니다.

  1. 나이키 소비자 직접 판매(D2C) 매출은 47억 달러로 전년비 28% 증가
    이는 전분기 45억 달러에 비해서도 소폭 증가
  2. 나이키 디지탈 판매는 전년비 25% 증가해 증가율은 크게 둔화됨
    . 이는 경제가 정상화되고 오프라인 매장 판매가 늘면서 디지탈 판매 증가율이 둔화했지만
    . 미국 온라인판매 증가율에 비해서 높은 수준

분기별 나이키 디지탈 판매 증가율, 이커머스 증가율 추이

여전히 높은 영업이익 유지

이번 분기 나이키 매출은 시장 기대에 미치지 못했지만 손익 지표은 시장 기대를 웃돌았습니다.

  1. 매출총이익은 56.96억 달러, 매출총이익율 46.5%로
    , 전년 동기 매출총이익율 43.1%에서 상승(3.4%p 상승)
  2. 영업이익 21.4억 달러, 영업이익율 17.3%로 전년비 20.3% 증가
    . 이번 분기 영업이익율은 전년동기 비나 전분기해 비해 모두 상승
  3. 순이익 18.74억 달러, 순이익율 15.3%를 기록
    . 이는 전년 동기 14.3%나 전분기 12.2%에 비해서도 상당히 개선된 것
  4. 주당 순이익(EPS)는 1.16달러로 시장 예측치 1.11달러를 상회

분기별 나이키 매출총이익률 추이

분기별 나이키 영업이익 추이

분기별 나이키 순이익 추이

나이키 실적 전망, 실적 가이드는 향후 다소 부정적인 전망 제시

이번 분기 실적 발표에서 나이키는 공급망 혼란 등으로 향후 실적은 기대에 못 미칠것으로 보고 전망치를 낮추었습니다.

  1. 나이키는 글로벌 공급망 혼란으로 비즈니스가 타격을 받고 있다고 밝히면서 회계년도 2022년 연간 전망치를 낮춤
    . 나이키 신발 50%와 의류 30%를 생산하고 있는 베트남에서는 팬데믹으로 공장 폐쇄가 진행중으로 생산 차질을 빛고 잇음
    . 생산 제품의 운송 시간지 증가하고 운송 가격이 상승하면서 타격을 주고 있음
    Friend에 따르면 북미로 운송 시간은 팬데믹 이전에 비해서 두배에 달하고 있으며
    아시아에서 북미로 이동 시간은 80일이 걸리고 있음
  2. 이에 따라 나이키는 연간 실적 전망을 한 자릿수 중반 증가율을 보일 것으로 전망해 시장 기대치 12%에 미치지 못했으며,
  3. 다음 분기 매출도 한자릿수 증가를 제시해 시장 기대치 12%에 미치지 못했음
  4. 이러한 공급 이슈에도 불구하고 신발과 운동복에 대한 수요는 여전히 강하다고 평가
    다만 공급 이슈로 단기 실적은 저조할 것으로 예상

애널리스트와 투자자들은 글로벌 공급망 혼란 등으로 제조업이 타격을 입으면서 나이키를 비롯한 많은 기업들의 매출이 일시적으로 타격을 입을 것으로 전망하고 있습니다. 베트남 공장 폐쇄는 나이키 뿐만이 아니라 경쟁업체인 룰루레몬이나 고급 가구업체 RH 등 수많은 소애업체들에게 큰 영향을 미치고 있습니다.

21년 2분기 나이기 실적 분석

2021년 5월 31일로 끝나는 2분기 나이키 실적(회계년도 2021년 4분기) 실적이 발표되었습니다. 이번에 발표된 2분기 나이키 실적을 살펴보고 중권사들이 제시하는 나이키 전망 및 나이키 주가 목표 등을 살펴 봅니다.

코로나 팬데믹으로 어려움을 겪었던 나이키는 백신 접종이 증가하고 경제가 회복되면서 나이키 매출도 폭발적으로 증가하면서 월가 기대 이상의 실적을 냈고, 향후 회계년도 2025년까지 긍정적인 나이키 향후 전망을 발표하면서 주식 시장에서는 긍정적으로 반응하고있습니다.

나이키 모델 세레나 월리엄스, Serena Wwilliams, Image from NIKE
나이키 모델 세레나 월리엄스, Serena Wwilliams, Image from NIKE

Executive summary

  1. 2분기 매출 123.4억 달러로 전년비 96% 성장
    이는 월가 예측치 110억 달러를 크게 상회한 것
    . 나이키 브랜드 매출 118억 달러로 전년비 88% 증가
    . 캔버스 브랜즈 매출 5.96억 달러로 전년비 85% 증가(북미와 유럽 중심 수요 증가)
  2. 전 지역에서 성장했지만 특히 북미와 유럽에서는 전년비 100%이상 성장함
    . 북미 매출 54억 달러로 전년 비 141% 성장
    . 유럽 매출 29.8억 달러로 전년 비 124% 성장
    . 아시아/남미 매출 14.6억 달러로 82% 성장
    . 중국 매출 19.3억 달러로 17.4% 성장
  3. 중국 매출은 가장 낮은 매출 성장률을 기록했는데,
    이는 신장지구 강제 노동 이슈로 중국의 불매 운동의 영향을 받았음
    하지만 최근 매출은 다시 회복 추세를 보이고 있다고 밝힘
  4. 대부분 제품 판매가 크게 늘었는데, 성장률은 스포츠 장비, 의류, 신발순을 보임
    . 신발 매출 79.5억 달러로 전년 비 89% 성장
    . 의류 매출 39.4억 달러로 전년 비 109.7% 성장
    . 스포츠 장비 매출 3.7억 달러로 전년 비 123% 성장에 그침
  5. 나이키 소비자 직접 판매(D2C) 매출은 45억 달러로 전년비 73% 증가했고, 전분기 40억 달러에 비해서 크게 늘었음
  6. 디지탈 판매는 전년비 41% 성장,
    . 경제가 정상화되고 오프라인 매장 판매가 늘면서 디지탈 판매 증가율이 둔화했지만
    여전히 높은 수준을 유지
    . 특히 3억명 이상의 나이키 회원의 온라인 구매가 30억 달러로 최고 수준을 기록해
    나이키가 추진중인 맴버쉽 프로그램이 효과를 보고 있다고 밝힘
  7. 매출총이익은 56.6억 달러, 매출총이익율 45.8%로
    , 전년 동기 매출총이익율 37.6%에서 크게 상승(7.2%p 상승)
    . 이러한 매출총이익율 상승은 생산 비용의 감소, 재고 증가 준비금 감소, 공급망 및 고정 비용 하락 등의 영향을 받음
  8. 영업이익 19.1억 달러, 영업이익율 15.5%을 기록
    . 이는 전년동기 적자에서 흑자 전환한 것이며
    . 전분기 영업이익율 16.2%에서 다소 하락했지만 근래들어 높은 수준을 유지 중
  9. 순이익 15.09억 달러, 순이익율 12.2%를 기록
    . 이는 전년 동기 10.8%도 개선된 것이나 전 분기 14.3%에 비해서는 크게 하락한 것
  10. 주당 순이익(EPS)는 93센트로 시장 예측치 51센트를 크게 상회

긍정적인 향후 전망 제시

  1. 또한 나이키는 상반기 보다는 하반기에 빠르게 성장할 것으로 전망
    하지만 공급망 지연과 높은 물류 비용이 22년 회계년도 내내 지속될 것으로 전망
    현재도 콘테이너 부족과 트럭 운전사 부족으로 항구에서 창고로, 매장으로, 온라인쇼핑객 집으로 배달이 지연되고 있음
  2. 긍정적인 차년도 실적 제시
    . 회계년도 2022년 매출 500억 달러를 넘을 것으로 전망,
    이는 두자리수 성장을 지속할 것으로 예상한 것,
    . 이는 시장에서 예측한 485억 달러를 크게 웃도는 전망임
  3. 스포츠 시장에서 장시장 기 지배 공표 – 2025년 전망 제시
    . 또한 회계년도 2025년 매출 655억 달러를 제시, 향후 연간 10%이상 성장할 것으로 예상,
    이는 향후 스포츠 시장에서 나이키 주도를 분명히 제시한 것으로 평가
    . EBIT(이자 및 세금 전 수익) 마진을 2021년 15.5%에서 10%대 후반대로 개선될 것으로 전망
    . 영업이익은 2021년 69억 수준에서 118억 달러로 70% 증가 예상
    . 소비자 직접 판매(D2C)가 이러한 나이키 성장을 견인할 것으로
    2025년 소비자 직접 판매(D2C) 비중은 2021년 38.7%에서 60% 수준으로 상승할 것
    . 2025년 소비자 직접 판매(D2C)에서 디지탈 판매 비중은 50%까지 늘어날 것이고,
    전체 매출에서 디지탈 판매 비중은 40%에 이를 것으로 전망

매출 123.4억 달러로 전년비 96% 성장

모든 지역에서 매출 증가에 힘입어 2분기 매출 112.4억 달러로 전년 비 8.9% 성장했습니다. 이는 월가 예측치 110억 달러를 크게 웃도는 좋은 실적을 보였습니다.

  1. 2분기 매출 123.4억 달러로 전년비 96% 성장
    이는 월가 예측치 110억 달러를 크게 상회한 것
  2. 나이키 브랜드 매출 118억 달러로 전년비 88% 증가
  3. 캔버스 브랜즈 매출 5.96억 달러로 전년비 85% 증가(북미와 유럽 중심 수요 증가)
나이키 실적, 분기별 나이키 매출 및 전년 비 성장률( ~ 21년 3월~5월), Nike Revenue & YoY growth rate(%), Graph buy Happist
나이키 실적, 분기별 나이키 매출 및 전년 비 성장률( ~ 21년 3월~5월), Nike Revenue & YoY growth rate(%), Graph buy Happist

매출 증가 지속 예상

  • 나이키는 회계년도 2022년에는 매출 500억 달러를 넘을 것으로 전망, 두자리수 성장을 지속할 것으로 전망,
    이는 시장에서 예측한 485억 달러를 크게 웃도는 전망
  • 또한 나이키는 상반기 보다는 하반기에 빠르게 성장할 것으로 전망
  • 하지만 공급망 지연과 높은 물류 비용이 22년 회계년도 내내 지속될 것으로 전망
  • 현재도 콘테이너 부족과 트럭 운전사 부족으로 항구에서 창고로, 매장으로, 온라인쇼핑객 집으로 배달이 지연되고 있음

북미와 유럽이 성장 견인

그동안 팬데믹에서 먼저 벗어난 중국이 나이키 매출 성장을 견이했지만, 이번 분기에는 본격적으로 경기 회복이 시작된 북구와 유럽이 매출 성장을 견인했습니다.

이번 4분기 중국 매출 성장은 광군제 기간동안 기대를 넘는 실적에 기인한 것입니다. 광군제 기간동안 나이키는 Tmall에서 가장 매장 수요와 가장 많은 트래픽을 기록한 1위 스포츠 브랜드로 등극했습니다.

이번 분기 동안 중국 지역에서는 온라임 판매만 증가한 것이 아니라 나이키 직매장으로 소비자 트래픽도 크게 증가하면서 오프라인 매장 판매도 마찬가지로 크게 성장했습니다.

이 결과 나이키 중국 매출은 23억 달러로 처음으로 분기 매출 20억 달러를 돌파하는 대기록을 세우기도 했습니다.

  1. 전 지역에서 성장했지만 특히 북미와 유럽에서는 전년비 100%이상 성장함
  2. 북미 매출 54억 달러로 전년 비 141% 성장
    . 북미는 전분기 배송 지연으로 인한 분진이 이번 분기에 상쇄되었고,
    . 백신 접종율 상승 등으로 경기가 회복으로 수요가 회복되었기 때문
    . 북미 디지탈 매출은 전년비 54% 증가했는데 이는 19년에 비해서는 177% 증가한 것
  3. 유럽 매출 29.8억 달러로 전년 비 124% 성장
    아시아/남미 매출 14.6억 달러로 82% 성장
  4. 중국 매출 19.3억 달러로 17.4% 성장
    중국 매출은 가장 낮은 매출 성장률을 기록했는데,
    이는 신장지구 강제 노동 이슈로 중국의 불매 운동의 영향을 받았음
    하지만 최근 매출은 다시 회복 추세를 보이고 있다고 밝힘
  5. 대부분 제품 판매가 크게 늘었는데, 성장률은 스포츠 장비, 의류, 신발순을 보임
    . 신발 매출 79.5억 달러로 전년 비 89% 성장
    . 의류 매출 39.4억 달러로 전년 비 109.7% 성장
    . 스포츠 장비 매출 3.7억 달러로 전년 비 123% 성장에 그침
나이키 실적, 분기별 나이키 지역별 매출 추이( ~ 21년 2분기), Nike Regional Revenue & YoY growth rate(%), Graph by Happist
나이키 실적, 분기별 나이키 지역별 매출 추이( ~ 21년 2분기), Nike Regional Revenue & YoY growth rate(%), Graph by Happist

직접판매(D2C) 및 디지탈 판매 지속

그 동안 나이키는 직접판매(D2C)전략을 성공적으로 수행한 회사로 명성이 높았습니다. 이러한 전략적 성과들이 이번 코로나 팬데믹 위기를 극복하는데 큰 도움을 주었습니다.

이번 21년 2분기 나이키 직접판매(D2C) 매출은 45억 달러를 기록해 전년비 73% 증가헸습니다. 이러한 직접판매(D2C) 매출 증가는 전년 비 41% 증가한 디지탈 판매 증가 덕분이기도 합니다.

  1. 나이키 D2C 매출은 45억 달러로 전년비 73% 증가했고, 전분기 40억 달러에 비해서 크게 늘었음
    하지만 상대적으로 오프라인 매장 판매도 활성화되면서 나이키 도매 판매는 전년비 세자리수 증가를 보임
  2. 디지탈 판매는 전년비 41% 성장,
    . 경제가 정상화되고 오프라인 매장 판매가 늘면서 디지탈 판매 증가율이 둔화했지만
    여전히 높은 수준을 유지
  3. 특히 3억명 이상의 나이키 회원의 온라인 구매가 30억 달러로 최고 수준을 기록해
    나이키가 추진중인 맴버쉽 프로그램이 효과를 보고 있다고 밝힘
나이키 실적, 분기별 나이키 디지탈 매출 성장률( ~ 21년 2분기), Nike Ooline Sales increase rate(%), Graph buy Happist
나이키 실적, 분기별 나이키 디지탈 매출 성장률( ~ 21년 2분기), Nike Ooline Sales increase rate(%), Graph buy Happist

여전히 높은 영업이익 유지

이번 분기 나이기 이익 지표는 매출 증가, 수요 증가로 코로나 팬데믹 시 많이 발생했던 주문 취소 비용 감소, 재고 비용, 환율 효과 등으로 크게 개선되었습니다.

지난 해 코로나 팬데믹으로 대부분 이익 지표가 적자를 기록했지만 이번 분기에는 위에서 열거한 여러 요인들 덕분에 시장 예측을 뛰어넘는 높은 이익을 보고했습니다.

  1. 매출총이익은 56.6억 달러, 매출총이익율 45.8%로
    , 전년 동기 매출총이익율 37.6%에서 크게 상승(7.2%p 상승)
    . 이러한 매출총이익율 상승은 생산 비용의 감소, 재고 증가 준비금 감소, 공급망 및 고정 비용 하락 등의 영향을 받음
  2. 영업이익 19.1억 달러, 영업이익율 15.5%을 기록
    . 이는 전년동기 적자에서 흑자 전환한 것이며
    . 전분기 영업이익율 16.2%에서 다소 하락했지만 근래들어 높은 수준을 유지 중
  3. 순이익 15.09억 달러, 순이익율 12.2%를 기록
    . 이는 전년 동기 10.8%도 개선된 것이나 전 분기 14.3%에 비해서는 크게 하락한 것
  4. 주당 순이익(EPS)는 93센트로 시장 예측치 51센트를 크게 상회
    이는 전년 51센트 적자에서 흑자 전환 것

분기별 나이키 영업이익 추이

나이키 실적, 분기별 나이키 영업이익 및 영업이익률( ~ 21년 2분기), Nike querterly Operating Income & Operating income(%), Graph by Happist
나이키 실적, 분기별 나이키 영업이익 및 영업이익률( ~ 21년 2분기), Nike querterly Operating Income & Operating income(%), Graph by Happist

분기별 나이키 순이익 추이

나이키 실적, 분기별 나이키 순이익 및 순이익률( ~ 21년 2분기), Nike querterly Net Income & Net margin(%), Graph by Happist
나이키 실적, 분기별 나이키 순이익 및 순이익률( ~ 21년 2분기), Nike querterly Net Income & Net margin(%), Graph by Happist

20년 4분기 나이키 실적 분석

그동안 코로나 팬데믹 당시 어려움을 겪었던 나이키였지만 이번 4분기 나이키 실적은 시장 기대를 뛰어넘는 어닝 서프라이즈를 기록해 주식 시장에서 열렬한 반응을 이끌어 냈습니다.

코로나 팬데믹으로 엄청난 역성장을 거듭했음에도 코로나 이후에 대한 기대가 반영되면서 나이키 주가는 꾸준히 올랐고, 최근 실적 발표 전후로는 최고치에 이르기도 했습니다.

Executive summary

  1. 4분기 매출 112.43억 달러로 전년 비 8.9% 성장
    이는 지난 2분기 및 3분기에 코노란 팬데믹으로 역성장을 거듭하다 다시 플러스 성장으로 전환한 것
  2. 전 지역에서 모두 전년 비 성장했지만 특히 중국과 유럽에서 성장세가 두드러짐
    . 중국 매출 23억 달러로 전년 비 24.4% 성장
    . 유럽 매출 29.6억 달러로 전년 비 16.6% 성장
    . 북미와 아시아/남미는 1% 이하 성장
  3. 제품별로는 신발과 의류 판매가 크게 늘면서 성장을 견인
    . 신발 매출 68억 달러로 전년 비 9.6% 성장
    . 의류 매출 35.9억 달러로 전년 비 9.1% 성장
    . 스포츠 장비 매출 3.5억 달러로 전년 비 1.8% 성장에 그침
  4. 나이키 D2C 매출은 43억 달러로 전 분기 37억 달러에 비해서 크게 늘었고
    전년 동기에 비해서도 32% 증가
  5. 디지탈 판매는 전년 비 84% 성장하면서 나이키 매출 성장을 견인
    . 이번 디지탈 성장율은 나이키가 디지탈 판매 성장율 데이타를 공개한 이래 가장 높은 수준
    . 이러한 디지탈 판매 증가는 도매 판매 및 나이키 직매장 판매 감소를 상쇄
  6. 매출총이익은 48.5억 달러, 매출총이익율 43.1%로 전년 동기 매출총이익율 44% 및 전 분기 44.8%에 비해서 하락
    . 이러한 매출총익율 하락은 코로나 팬데믹으로 봄과 여름 판매 부진으로 재고 증가 문제를 해소하기 위한 가격 인하 영향
  7. 영업이익 15.8억 달러, 영업이익율 14.1%을 기록
    . 이는 전년 동기 11.8%에 비해 여전히 높은 수준을 기록
    . 참고로 전 분기 영업이익율 16.7%로 사상 최고를 기록
    . 이러한 영업이익 증가는 코로나 팬데믹 영향으로 마케팅 비용이 크게 줄었기 때문
  8. 이러한 영업이익 증거 덕분에 순이익 12.51억 달러, 순이익율 11.1%를 기록
    . 이는 전년 동기 10.8%도 개선된 것이나 전 분기 14.3%에 비해서는 크게 하락한 것
  9. 주당 순이익(EPS)는 0.78달러로 전년 비 11% 증가
  10. 재고는 전년 비 2% 감소해 예젼의 건전항 상태로 전환

매출 112.4억 달러로 8.9% 성장 전환

모든 지역에서 전년 비 매출 성장에 힘입어 4분기 매출 112.4억 달러로 전년 비 8.9% 성장했습니다.

이러한 성장은 지난 2분기 -38% 및 3분기 -0.6% 역성장에서 벗어나 코로나 팬데믹을 극복하고 본격적인 성장을 시작했다는 점에서 긍정적으로 평가되고 있습니다.

나이키 실적, 분기별 나이키 매출 및 전년 비 성장률( ~ 20년 4분기), Nike Revenue & YoY growth rate(%), Graph buy Happist
나이키 실적, 분기별 나이키 매출 및 전년 비 성장률( ~ 20년 4분기), Nike Revenue & YoY growth rate(%), Graph buy Happist

중국과 유럽이 성장 견인

지난 3분기와 마찬가지로 중국과 유럽 매출이 크게 신장되면서 이번 4분기 나이키 매출 성장의 견인차가 되었습니다.

이번 4분기 중국 매출 성장은 광군제 기간동안 기대를 넘는 실적에 기인한 것입니다. 광군제 기간동안 나이키는 Tmall에서 가장 매장 수요와 가장 많은 트래픽을 기록한 1위 스포츠 브랜드로 등극했습니다.

이번 분기 동안 중국 지역에서는 온라임 판매만 증가한 것이 아니라 나이키 직매장으로 소비자 트래픽도 크게 증가하면서 오프라인 매장 판매도 마찬가지로 크게 성장했습니다.

이 결과 나이키 중국 매출은 23억 달러로 처음으로 분기 매출 20억 달러를 돌파하는 대기록을 세우기도 했습니다.

나이키 실적, 분기별 나이키 중국 매출 및 전년 비 성장률( ~ 20년 4분기), Nike China Revenue & YoY growth rate(%), Graph buy Happist
나이키 실적, 분기별 나이키 중국 매출 및 전년 비 성장률( ~ 20년 4분기), Nike China Revenue & YoY growth rate(%), Graph buy Happist

나머지 지역도 큰 성장은 없었지만 전년 비 미세하게나마 성장을 기록하면서 전체 성장을 도왔습니다.

  1. 전 지역에서 모두 전년 비 성장했지만 특히 중국과 유럽에서 성장세가 두드러짐
  2. 중국 매출 23억 달러로 전년 비 24.4% 성장
    중국은 온라인 판매 뿐만이 아니라 오프라인 매장 판매도 크게 늘면서 온라인과 오프라인이 쌀끌이로 매출을 견인
  3. 유럽 매출 29.6억 달러로 전년 비 16.6% 성장
    . 이는 전 분기 4.9% 성장에서 성장율이 크게 높아 짐
  4. 북미와 아시아/남미는 1% 이하 성장
  5. 제품별로는 신발과 의류 판매가 크게 늘면서 성장을 견인
    . 신발 매출 68억 달러로 전년 비 9.6% 성장
    . 의류 매출 35.9억 달러로 전년 비 9.1% 성장
    . 스포츠 장비 매출 3.5억 달러로 전년 비 1.8% 성장에 그침
나이키 실적, 분기별 나이키 지역별 매출 성장률( ~ 20년 4분기), Nike Revenue & YoY growth rate(%), Graph buy Happist
나이키 실적, 분기별 나이키 지역별 매출 성장률( ~ 20년 4분기), Nike Revenue & YoY growth rate(%), Graph buy Happist

직접판매(D2C) 및 디지탈 판매 큰 성장

그 동안 나이키는 직접판매(D2C)전략을 성공적으로 수행한 회사로 명성이 높았습니다. 이러한 전략적 성과들이 이번 코로나 팬데믹 동안 위기를 극복하는데 큰 도움을 주었습니다.

이번 4분기 나이키는 직접판매(D2C) 매출은 43억 달러를 기록해 전년 비 32% 성장했습니다. 그 덕분에 도매판매 및 나이키 직매장 트래픽 감소로 인한 판매 감소를 상쇄할 수 있었습니다.

이러한 직접판매(D2C) 매출 증가는 전년 비 84% 증가한 디지탈 판매 증가 덕분이기도 합니다.

나이키는 실적 발표 당시매장 90%이상이 문을 열고 판매하고 있는 상황이지만, 코로나19 감염이 확산되면서 일시적인 폐쇄 지역이 늘고 있다고 밝혀 코로나 팬데믹 악영향을 여전히 진행중임을 밝혔습니다.

이 영향은 특히 북미 지역, 유럽지역 그리고 남미 지역에서 큰 영향을 받고 있지만 디지탈 판매 전환율이 높아지면서 상쇄되고 있다고 밝혔습니다.

  1. 나이키 D2C 매출은 43억 달러로 전 분기 37억 달러에 비해서 크게 늘었고
    전년 동기에 비해서도 32% 증가
  2. 디지탈 판매는 전년 비 84% 성장하면서 나이키 매출 성장을 견인
    . 이번 디지탈 성장율은 나이키가 디지탈 판매 성장율 데이타를 공개한 이래 가장 높은 수준
    . 이러한 디지탈 판매 증가는 도매 판매 및 나이키 직매장 판매 감소를 상쇄
나이키 실적, 분기별 나이키 온라인 매출 성장률( ~ 20년 4분기), Nike Ooline Sales increase rate(%), Graph buy Happist
나이키 실적, 분기별 나이키 온라인 매출 성장률( ~ 20년 4분기), Nike Ooline Sales increase rate(%), Graph buy Happist

여전히 높은 영업이익 유지

코로나 팬데믹은 오프라인 매장 폐쇄로 급격한 매출 감소를 불러왔지만 역설적으로 판매 증지을 위한 마테팅 투자 유인을 없애면서 오히려 영업이익이 크게 증가하는 효과를 가져왔습니다.

그 덕분에 지난 3분기 나이키 영업이익은 지난 5년 내 가장 높은 수준의 영업이익율을 기록하기도 했습니다.

이번 분기도 코로나 팬데믹 영향으로 마케팅 비용 축소 및 매출 증가에 힘입어 전 분기 못지않은 높은 영업이익율을 기록했습니다.

  1. 매출총이익은 48.5억 달러로 매출총이익율 43.1%로 전년 동기 44% 및 전 분기 44.8%에 비해서 하락
    . 이러한 매출총익율 하락은 코로나 팬데믹으로 봄과 여름 판매 부진으로 재고 증가 문제를 해소하기 위한 가격 인하 영향
  2. 영업이익 15.8억 달러, 영업이익율 14.1%을 기록
    . 이는 전년 동기 11.8%에 비해 여전히 높은 수준을 기록
    . 참고로 전 분기 영업이익율 16.7%로 사상 최고를 기록
    . 이러한 영업이익 증가는 코로나 팬데믹 영향으로 마케팅 비용이 크게 줄었기 때문
  3. 이러한 영업이익 증거 덕분에 순이익 12.51억 달러, 순이익율 11.1%를 기록
    . 이는 전년 동기 10.8%도 개선된 것이나 전 분기 14.3%에 비해서는 크게 하락한 것
  4. 주당 순이익(EPS)는 0.78달러로 전년 비 11% 증가

분기별 나이키 영업이익 추이

나이키 실적, 분기별 나이키 영업이익 및 영업이익률( ~ 20년 4분기), Nike querterly Operating Income & Operating income(%), Graph by Happist
나이키 실적, 분기별 나이키 영업이익 및 영업이익률( ~ 20년 4분기), Nike querterly Operating Income & Operating income(%), Graph by Happist

분기별 나이키 순이익 추이

나이키 실적, 분기별 나이키 순이익 및 순이익률( ~ 20년 4분기), Nike querterly Net Income & Net margin(%), Graph by Happist
나이키 실적, 분기별 나이키 순이익 및 순이익률( ~ 20년 4분기), Nike querterly Net Income & Net margin(%), Graph by Happist

참고

D2C 중심 아디다스 전략, 디지탈 기반 옴니채널 전략으로 D2C 비중 50% 목표

나이키는 왜 소비자 직접 판매를 강화할까 – 나이키 D2C 전략

나이키, 벤앤제리스, 버라이즌에서 배우는 인종차별 이슈 대응법

[트렌드 차트] 연도별 스니커즈 브랜드 매출, 나이키 지배는 계속된다

스포츠화 시장에서 위기를 극복하는 나이키 미래 전략 3가지

스포츠화의 신흥 강자 언더 아머(Under Armour)의 미래 – 리복의 길? 또는 나이키의 길?

나이키를 위협하는 스포츠웨어 신흥 강자, 언더아머(Under Armour)의 성공요인 세가지

나이키 광고 관련

나이키가 인종차별 저항을 이끈 캐퍼닉을 모델로 기용한 이유

나이키, 캐퍼닉 광고로밀레니얼과 Z세대를 사로 잡다 – 광고 효과조사 결과

나이키 광고, 재일 외국인으로 차별을 딛고 계속 움직인다. 미래를 기다리지 않는다

실적 관련

연도별 나이키 실적, 매출 및 이익에서 읽는 나이키 전망

[트렌드 차트] 연도별 아디다스 실적, 매출 및 이익에서 읽는 아디다스 전망

사상 최대 매출 및 영업이익의 2분기 나이키 실적, 향후 전망은 어떻까?

코로나를 딛고 가속 성장한 4분기 나이키 실적 및 향후 나이키 전망

코로나19 악몽에서 벗어난 3분기 나이키 실적, 중국 유럽이 회복을 견인

코로나 팬데믹 기간 나이키 실적, 예상 외 매출 감소 및 적자 전환

2021년 스트리밍 전쟁 전망, 진정한 승자는 디즈니플러스가 될 것 by eMarketer

0

2021년 스트리밍 전쟁 승자는 넷플릭스가 아닌 디즈니플러스가 될 것이라는 시장조사 업체 이마케터 전망이 나왔습니다. 간단히 요약해 보죠

2020년 코로나 팬데믹으로 넷플릭는 상당히 인상적인 사용자 증가를 기록했습니다. 그렇지만 디즈니플러스는 이보다도 더욱 더 빠르게 디니플러스 가입자가 증가하고 있다고 지난 2020년 12월 디즈니 기업 설명회에서 밝혔습니다.

이렇게 빠르게 성장하는 디즈니플러스와 디즈니플러스가 밝힌 미래 전망은 넷플릭스에게 위협이 되기에 충분하다는 생각입니다.

20년 12월, 디즈니플러스 가입자 8,680만명

20년 12월 10일 딪니 투자 설명회에서 밝힌 20년 12월 2일 기준 디즈니플러스 가입자는 8천 6백 8십만명으로 지난 3분기 실적 시 밝힌 7천 3백 7십만명에 비해서 약 1천 3백만명이나 늘었습니다.

디즈니플러스 가입자 추이, 디즈니플러스 구독자, Disney+ Subscribers(Millions), Graph by Happist
디즈니플러스 가입자 추이, 디즈니플러스 구독자, Disney+ Subscribers(Millions), Graph by Happist

디즈니플러스 가입자를 넷플릭스 가입자와 직접 비교해 보면 아직은 많은 차이가 있지만 빠르그 그 차이가 줄어들고 있음을 알 수 있습니다.

넷플릭스 가입자와 디즈니플러스 가입자 증가 추이 비교( ~ 20년 12월), Graph by Happist
넷플릭스 가입자와 디즈니플러스 가입자 증가 추이 비교( ~ 20년 12월), Graph by Happist

2021년 미국 디즈니플러스 시청자 8천 5백만명에 달할 듯

이마케터는 스트리밍 전쟁이 가열되고 있는 미국 시장에서 디즈니플러스 시청자는 2020년에는 7천 2백만명, 2021년에 8천 5백만명에 이를 것이며, 2024년에는 1.2억명으로 넷플릭스 1.8억명에 비해 69% 수준으로 늘어날 것으로 전망되었습니다.

반면 현재 2위를 달리고 있는 아마존 프라임 비디오 시청자 수는 2018년 9천 3백만명에서 2020년 1.3억명 그리고 2024년에는 1.54억 명으로 늘면서 넷플릭스 시청자 비 63%에 불과했지만 2024년에는 85% 수준으로 경쟁력이 강회될 것으로 보입니다.

2021년 스트리밍 전쟁 전망, 진정한 승자는 디즈니플러스가 될 것 by eMarketer 1

디즈니플러스 성장이 가장 가파르다

2020년 현재 미국 스트리밍 시장에서 디즈니플러스는 런칭 1년만에 4위 스트리밍 브랜드로 성장했고, 2024년에는 흘루(Hulu)를 제치고 3위 스트리밍 브랜드가 될 것으로 보입니다.

이는 같은 계열사 스트리밍 서비스인 흘루(Hulu) 시청자는 연간 5% 정도 증가해 2020년 9천 5백만명으로 넷플릭스 비 60%에서 2024년 63.4%로 3.5%p 증가에 그치지만, 디즈니플러스는 연간 10%대 빠르게 성장하면서 넷플릭스 비 2020년 46%에서 2024년 68%로 22%p나 폭증하기 때문입니다.

아마존 프라임 비디오 연간 5% 이하로 성장세가 둔화되고 어느 정도 포화 상태에 이르어 2020년 넷플릭스 비 82% 수준에서 2024년 85% 수준으로 3%p증가에 그칠 것으로 보이기 때문입니다.

디즈니플러스는 글로벌 전개에 따라 더욱 빠르게 성장할 듯

지난 12월 디즈니 플러스가 발표한 글로벌 디즈니플러스 가입자 수는 8천 7백만명에 이른다고 했으니 디즈니플러스 가입자 대부분은 미국에서 이루어지고 있는 것으로 보입니다.

디즈니플러스가 발표하는 가입자 정보와 이마케터가 발표한 시청자는 기준이 다르기 때문에 1:1로 비교할 수는 없지만 산출적으로 추정해보면 디즈니플러스 가입자 또는 시청자 80% 정도는 미국에 집중되어 있다고 봐야 합니다.

넷플릭스 가입자는 미국보다는 해외 가입자가 훨씬 더 많은 것에 비해서는 아직은 디즈니플러스가 미국 집중도가 높은 편이라 앞으로 디즈니 글로벌 진출이 가시화되면 더욱 더 디즈니플러스 경쟁력이 높아질 것으로 보입니다.

특히 2021년 하반기에는 디즈니플러스가 한국에도 진출해 이미 국건하게 자리를 잡은 넷플릭스와 어떻게 경쟁할지도 좋은 관전 포인트가 될 것 같습니다.

디즈니의 스트리밍 서비스 중심 조직 정비 및 공격 가속화

또한 디즈니는 그동안 테마파크와 영화 스튜디오 등 콘텐츠에 집중해 왔지만 2020년 코로나 팬데믹을 기화로 조직을 스트리밍 서비스 중심으로 변경하고 네플릭스 등 경쟁사를 빠르게 따라잡기 위한 전사 총력 체제를 갖추고 있습니다.

이러한 디즈니의 움직임은 테마파크나 영화 스튜디오와 같은 기존 비즈니스 모델과 상충될 수도 있지만 과감하게 스트리밍 중심 전략으로 전환하면서 죄고우면하지 않고 스트리밍 시장에서 승부를 보겠다는 전략으로 보입니다.

지금은 너무 빠르게 변화하고 있기 때문에 이러한 디즈니의 전략은 긍정적이고, 더 나이가 글로발 공략 속도도 더욱 빨라지면서 경쟁력이 강화될 수 있는 근거가 될 것으로 보입니다.

참고

디즈니가 밝힌 디즈니플러스 비젼과 디즈니 스트리밍 서비스 미래

콘텐츠 비즈니스에서 디즈니 비즈니스 모델과 뉴욕타임스 비즈니스 모델 비교

넷플릭스를 제압할 디즈니 전략, 디즈니플러스에서 디즈니2로 진화

미래 비디오 스트리밍 전쟁 예측 – 넷플릭스 vs 디즈니 플러스

누가 비디오 스트리밍 전쟁에서 승리할 것인가? 디즈니? 아마존?

디즈니의 폭스(Fox) 인수에서 읽어보는 디즈니 미래 전략

디즈니의 넷플릭스 배신 그리고 동영상 스트리밍 시장 진출 배경과 전망

디즈니 플러스가 생각보다 강력한 이유 그리고 넷플릭스가 고전하는 이유

디즈니 새로운 실험, 영화 뮬란 온라인 공개, 30$에 디즈니 플러스에서 시청 가능

디즈니와 픽사를 움직이는 힘 – 애드 캣멀의 창의성을 지휘하라를 읽고

컨텐츠 왕국 디즈니의 위기 극복 전략 – 과감한 M&A와 창의력 강화 프로그램

픽사와 디즈니에서 배울 수 있는 교훈(Lessons from Pixar and Disney Animation)

실적 관련 정리

디즈니플러스 구독자 7천 3백만명, 4년 목표를 단 10개월에 달성하며 넷플릭스를 맹렬 추격하

놀라운 디즈니플러스 구독자 증가가 실적 부진을 상쇄해 버린 3분기 디즈니 실적

20년 2분기 디즈니 실적, 코로나로 매출 -42% 역성장과 적자 -47억 달러

20년 1분기 디즈니 실적, 코로나 악영향 속 스트리밍 서비스에서 희망을 찾다

20년 3분기 넷플릭스 실적을 읽는 인사이트 5가지

[실적 차트] 디즈니 연도별 매출 및 손익 추이(1983 ~ 2019)

워드프레스 메모리 부족 문제 해결 방법 4가지

워드프레스에서 종종 볼 수 있는 메모리 부족 문제를 해결하기 위해 워드프레스 메모리 부족 문제 해결 방안을 주제를 살펴 보았습니다. 워드프레스 메모리 부족은 필연적으로 php 메로리 설정과 연계되기에이를 포함한 4가지 방법에 살펴 봤습니다.

우리나라에서 사용하는 CMS 중에서 워드프레스가 많은 메모리를 사용하는 것으로 악명(?)이 높죠. 그러다보니 가장 흔하게 접하는 에러 메세지 중의 하나는 허용 메모리 제한을 초과했다는 것입니다. Allowed memory size of 268435456 bytes exhausted와 같은…

이번에 서버를 우분투 20.04에 php 8을 적용하면서 어떤 문제가 있는지 살펴보고 있는데 아래와 같은 메모리 제한 이슈가 종종 발생하고 있었습니다. php에서 메모리 제한(memory_limit)는 128M인데요. 보통 256M 정도 설정해 사용하곤 합니다.

워드프레스 메모리 부족 문제 발생

그런데 이 설정하에서 메모리 제한 문제가 종종 발생합니다. 에러 로그들을 살펴보니 아래와 같은 문제가 있었다고 기록되어 있습니다.

FastCGI sent in stderr: "PHP message: PHP Fatal error:  Allowed memory size of 268435456 bytes exhausted (tried to allocate 61440 bytes) in /home/happist/wp-includes/wp-db.php on line 2056" while reading response header from upstream, client: 13.66.139.121, server: happist.com, request: "GET /post-sitemap1.xml HTTP/1.1", upstream: "fastcgi://unix:/var/run/php/php8.0-fpm.sock:", host: "happist.com"Code language: PHP (php)
FastCGI sent in stderr: "PHP message: PHP Fatal error:  Allowed memory size of 268435456 bytes exhausted (tried to allocate 20480 bytes) in /home/happist/wp-content/plugins/query-monitor/classes/Backtrace.php on line 97" while reading response header from upstream, client: 13.66.139.70, server: happist.com, request: "GET /post-sitemap.xml HTTP/1.1", upstream: "fastcgi://unix:/var/run/php/php8.0-fpm.sock:", host: "happist.com"Code language: PHP (php)
FastCGI sent in stderr: "PHP message: PHP Fatal error:  Allowed memory size of 268435456 bytes exhausted (tried to allocate 61440 bytes) in /home/happist/wp-includes/wp-db.php on line 2056" while reading response header from upstream, client: 13.66.139.121, server: happist.com, request: "GET /post-sitemap1.xml HTTP/1.1", upstream: "fastcgi://unix:/var/run/php/php8.0-fpm.sock:", host: "happist.com"Code language: PHP (php)

참고로 워드프레스 메모리 제한 문제가 발생 시 나오는 에러 메세지는 아래와 같습니다. 설정한 메모리 제한(memory_limit)에 따라 조금씩 다른 메세지를 냅니다. 메모리 사이즈를 바이트 단위로 표시해 주기 때문에 이를 MB로 환산하면 되는데요.

이 에러 메세지로 사용자 워드프레스에서 적용되고 있는 메모리 제한(memory_limit) 크기를 알 수가 있습니다.

  • PHP: Fatal Error: Allowed Memory Size of 8388608 Bytes Exhausted – 8 MB
  • PHP: Fatal Error: Allowed Memory Size of 16777216 Bytes Exhausted – 16 MB
  • PHP: Fatal Error: Allowed Memory Size of 33554432 Bytes Exhausted – 32 MB
  • PHP: Fatal Error: Allowed Memory Size of 67108864 Bytes Exhausted – 64 MB
  • PHP: Fatal Error: Allowed Memory Size of 134217728 Bytes Exhausted – 128 MB
  • PHP: Fatal Error: Allowed Memory Size of 268435456 Bytes Exhausted – 256 MB
  • PHP: Fatal Error: Allowed Memory Size of 536870912 Bytes Exhausted – 512 MB
  • PHP: Fatal Error: Allowed Memory Size of 1073741824 Bytes Exhausted – 1 GB

우선 시스템 상황 확인

우선은 에러 메세지를 통해서 현재 적용된 메모리 제한 크기를 알 수 있지만 보다 확실하게 알기 위해서 시스템 사양을 확인할 필요가 있습니다.

다행스러운 것은 워드프레스가 5.0 이상으로 업그레이드 되면서 시스템 상태에 대한 정밀한 정보 제공과 더불어 나름 시스템 상황을 체크해 준다는 것인데요. 샐각보다 유용합니다.

예전에는 이런저런 수동적인 명령을 사용해 시스템 상황을 파악해야 했는데 이제는 주제별로 아주 일목요욘하게 시스템 상황을 알 수 있고, 워드프레스 자체적으로 문제가 없는지도 진단해 주고 있습니다.

이 기능을 이용하려면 워드프레스 대시보드 도구 메뉴 아래에 있는 사이트 상태로 이동해 확인할 수 있습니다.

아래는 제 사이트 상태 정보인데요. 워드프레스 메모리 제한은 서버 카테고리에서 PHP 메모리 제한이란 항목에서 확인 가능합니다. 에러 메세지가 알려주는대로 256M가 적용되어 있습니다.

워드프레스 메모리 부족 문제 해결 방법 4가지 2

워드프레스 메모리 부족 문제 해결 방법 4가지

그러면 어떻게 이 워드프레스 메모리 제한 문제를 해결할까요? 여기에는 크게 몇가지 해결 방향이 있습니다.

  • 하나는 워드프레스가 사용할 수 있는 메모리를 늘리는 것입니다.
  • 두번째는 메모리를 많이 사용하는 프로그램이 무엇인지 찾아서 꼭 필요한지 아니면 다른 것으로 대체 가능한지 등을 점검해 볼 수 있습니다.
  • 세번째는 매우 고난이도 작업으로 불필요하게 메모리를 사용토록 프로그램된 부분이 있는지를 점검해 보는 것입니다. 이는 전문가 영역으로 초보가 하기에는 역부족인듯 싶습니다,

여기에서는 첫번째 방법인 워드프레스에서 사용 가능한 메모리를 늘리는 방법 4가지에 대해서 살펴 보도록 하겠습니다.

1. 워드프레스 메모리 확대 방법 1 – php.ini

워드프레스 메모리제 제한은 바로 php 메모리 제한의 영향을 받습니다. 그래서 가장 효율적인 방법은 php.ini에서 메모리 제한을 높이는 것입니다.

이 파일은 우분투 20.04의 경우 /etc/php/8.0/fpm 폴더에 있습니다. 저는 php 8을 사용하고 있으니 이런 폴더가 나오는 것이구요. 아직 php 7.4사용하고 있다면 /etc/php/7.4/fpm라는 폴더를 접속하면 됩니다.

그런데 내 시스템에서 php.ini 파일이 어디에 있는지 모르겠다면 아래 명령으로 위치를 찾을 수 있습니다.

php -i | grep 'php.ini'Code language: PHP (php)
nano /etc/php/8.0/fpm/php.iniCode language: PHP (php)

그러면 php 8.0 기준으로 430번째 줄에 memory_limit 값을 발견할 수 있습니다.

이 값을 적절한 값으로 조정합니다. 저는 256M 사용하다고 메모리 제한 문제를 발생했기 때문에 512M으로 올려 사용해 보기로 했습니다.

  • memory_limit 기본 값은 128M
  • 만약 php 메모리 제한을 두지 않겠다고 하면 -1값을 사용할 수 있습니다.
; Maximum amount of memory a script may consume
; http://php.net/memory-limit
memory_limit = 512M
Code language: PHP (php)

2. 웹서버 설정에서 변경

두번째 방법은 아파치나 NGIX와 같은 웹서버 설정에서 변경하는 것입니다.

아파치의 htaccess에서 아래와 같은 명령어를 추가하는 방법인데요. 아래와 같이 IfModule mod_php8.0를 이용하는 것입니다.

<code><IfModule mod_php8.0>     </code>
<code>php_value memory_limit 64M </code>
<code></IfModule></code>Code language: PHP (php)

3. 워드프레스 wp-config.php 파일 편집

다음으로 생각해 볼 방법은 워드프레스 설정 파일인 wp-config.php 파일에서 워드프레스 사용 메모리를 정의해 주는 것입니다.

워드프레스 루트에 있는 wp-config.php 파일을 열고 적절한 위치, 예를 들어 다른 define 명령 다음에 define(‘WP_MEMORY_LIMIT’, ‘512M’);와 같은 명령을 추가하는 것입니다.

/**
 * For developers: WordPress debugging mode.
 *
 * Change this to true to enable the display of notices during development.
 * It is strongly recommended that plugin and theme developers use WP_DEBUG
 * in their development environments.
 *
 * For information on other constants that can be used for debugging,
 * visit the documentation.
 *
 * @link https://wordpress.org/support/article/debugging-in-wordpress/
 */
define( 'WP_DEBUG'false );
define('WP_MEMORY_LIMIT', '512M');
Code language: PHP (php)

cPanel 같은 서버 대시보드에서 변경

많은 서버 호스팅 업체들은 사용자 경험을 강화하기 위해서 cPanel과 같은 대시보드를 제공합니다. 여기에서는 서버 터미널에서 제어할 수 있는 중요 변경을 아주 쉽게 할 수 있는데요.

서버 호스팅 업체에서 cPanel과 같은 대시보드 기능을 제공하는 경우 이를 이용해 변경하는 것도 좋은 방법입니다. 아래 이미지는 How to increase the PHP Memory Limit in cPanel라는 글에서 가져온 것으로 cPanel에서 메모리 변경 방법을 간단히 알려 주고 있습니다.

씨패널에서 워드프레스 PHP 메모리 제한 변경 방법, cPanel Software Select PHP Version, Image from chemicloud
씨패널에서 워드프레스 PHP 메모리 제한 변경 방법, cPanel Software Select PHP Version, Image from chemicloud

참고로 cPanel과 같은 기능을 예전에는 무료로 제공하는 업체가 많았지만 cPanel 사용 가격이 점점 오르면서 이제는 cPanel 사용 가격을 별도로 받는 업체들이 늘고 있습니다. 최근 2020년 12월 가격 인상된 것으로 보니 결코 저렴하지는 않네요.

CPanel Gereral Pricing은 아래와 같습니다.

  • For 5 accounts – $20/month
  • For 30 accounts – $30/month
  • For 100 accounts – $45/month + $0.20 for each additional account

마치며

여기에서 워드프레서 메모리 부족 문제를 풀기 위해 워드프레스 가용 메모리 증대 방안 4가지를 살펴 보았습니다.

여러가지 방법이 있기는 하지만 궁극적으로는 php.ini에서 제어하는 것이 가장 확실합니다. 여기에서 변경되지 않으면 워드프레스 설정 파일, wp-config.php 파일이나 아파치와 같은 웹서버에서 조정은 전혀 작동하지 않습니다. 제 경험 상..

따라서 가능하면 php.ini에서 변경할 수 있도록 하고, 호스팅의 경우 php.ini 파일 접근이 불가능하도록 되어 있을 가능성이 매우 높기 때문에 업체에 연락해 조정해 달라고 요청해야 합니다.

참고

우분투 20.04와 PHP 8 기반 워드프레스 설치 방법

가상 서버를 운영하고픈 勇者에게 전하는 가상 서버 운영 입문 노하우 – Vultr 가상서버호스팅(VPS)를 중심으로

워드프레스 최적화를 위한 18개월간의 고민, 그 노하우를 담다.

도쿄 리젼과 비교해 본 Vultr 서울 리젼 사용기

가성비가 뛰어난 Vultr 가상서버호스팅(클라우드호스팅,VPS) 사용기

[트렌드차트] 연도별 신문구독률 추이 96년 69.3% → 20년 6.3%

0

지난 2020년 12월 15일 한국언론진흥재단에서 2020 언론 수용도 조사 결과를 발표했길래 이중에서 몰락한 언론 매체이면서도 생존을 이어가도 있는 신문매체에 대해서 살펴보면서 신문에 대한 여러 지표 중 연도별 신문구독률과 신문 열독률을 살펴봤습니다.

이미 언론 매체로서 사망 수준에 이른 신문이지만 사회적 관계나 영향력을 유지하고자하는 정부나 기업의 광고비가 광고 효과와 별 상관없이 집행되면서 시한부 생명이 계속 연장되고 있다는 개인적인 해석입니다.

미국을 비롯한 유럽에서는 신문사 별로 엄청난 혁신을 통해서 인터넷 시대, 영상 중심 시대에 살아남는 방법을 성공적으로 찾아가고 있는 것에 비해서 우리나라 신문은 별다른 혁신의 모습이 보이지 않고 있습니다.

그런 으미에서 현실에 만족케하면서 정기적인 광고비에 의존케 만들고 있는 정부 지원금이나 기업 광고가 신문을 망치게하는 제1 원인이라는 생각도 들었습니다.

연도별 신문구독률 & 신문열독률 추이

  • 2020년 신문구독률은 6.3%로 전년 6.4%에 비해서 0.1%p 하락
    이러한 신문구독률은 조사 자료가 공개된 1996년 69.3%에서 무려 63%p가 하락한 것
  • 2020년 신문열독률은 10.2%로 전년 12.3%에 비해서 2.1%p 하락
    마찬가지로 1996년 신문열독율 85.2%에 비해서는 75%p 하락
연도별 신문구독률과 신문열독률 추이(1996년 ~ 2020년), Graph by Happist
연도별 신문구독률과 신문열독률 추이(1996년 ~ 2020년), Graph by Happist

이번 2020 언론 수용도 조사 결과를 보면 전반적으로 언론 매체 이용률이 늘었습니다. 이는 코로나 팬데믹으로 소셜 미디어 증가와 더불어 뉴스 소비가 증가한 덕분으로 해석되고 있는데요.

그럼에도 불구하고 신문구독률은 하락했고 신문열독률도 하락했습니다. 신문업계에서는 다행이라고 해석할 점은 하락폭이 예년과 달리 크지 않았다는 점입니다.

이처럼 신문구독률이나 신문열독률이 예년처럼 급적직하로 폭락하지 않은 것은 코로나 팬데믹으로 인하 뉴스 수요 증가의 덕을 보고 있다고 해석할 수 있습니다.

이는 신문을 구독하지는 않아도 TV뉴스 등에서 신문 정보를 인용하 뉴스를 들은 부분까지 포함하는 결합 열독률 지표는 신문에 대한 묘한 해석을 가능하게 하는데요. 아래는 보고서 일부 내용을 발췌했습니다.

종이신문 열독은 급감했지만, 뉴스 이용자들은 종이신문을 포함해 컴퓨터, PC, 스마트폰, TV등 다양한 경로를 통해 신문기사를 접하고 있다. 올해 결합 열독률은 89.2%로 지난해 88.7%와 비슷한 수준을 유지했다. 최근 몇 년간의 조사 결과를 보면 결합 열독률은 88~89% 선에서 유지되고 있어 신문사가 생산한 ‘뉴스’의 이용률은 여전히 높음을 알 수 있다. 뿐만아니라 결합 열독률은 20대 92.8%, 30대 96.8%, 40대94.0%, 50대 90.7%로 60대 이상(78.1%)을 제외한 모든 연령대에서 매우 높다.

  • 신문 결합 열독률은 2018년 86.1%에서 오히려 조금씩 늘어 2019년 88.7%로 올랐고 이어 2020년에는 89.2%로 상승
  • 2020년 결합 열독률 증가는 아래 연령별 추이에서 보여 주듯이 20대 결합 열독률이 2020년에 10%p 가까이 증가한 덕분
  • 또한 최근 몇년간 신문의 결합 열독률은 종이 신문을 통한 열곧율과 인터넷을 통한 열독률도 감소한 반면
    TV를 통한 열독률만 증가
    이는 뉴스 소비가 글을 읽는 소비에서 영상을 보는 방식으로 변하고 있다는 것을 의미
  • 그리고 2020년 열독률이 높아진 이유인 20대 증가는 코로나 팬데믹으로 집안에 머무르게 된 10대 TV 노출도가 높아지면서 TV를 통한 열독률이 높아진 것으로 해석
    이는 코로나 팬데믹 이후 집안에서 머무는 시간이 감소하면 바로 줄어들 가능성이 높음
연도별 신문 결합 열독률 추이

2020 언론 수용도 조사 보고서

참고

[톰 벤슨] 신문 몰락에도 뉴욕타임즈 성공 이유? 인터넷에 답이 있다.

경향신문 창간 70주년 1면 광고로 엿보는 신문 광고의 몰락 그리고 미래 방향

3분기 뉴욕타임스 실적이 보여 주는 비즈니스 모델 명암, 유망한 구독과 암울한 광고

콘텐츠 비즈니스에서 디즈니 비즈니스 모델과 뉴욕타임스 비즈니스 모델 비교

뉴욕타임스 CEO가 전하는 뉴욕타임스 디지탈 전환 성공 비결

웹서버 NGINX 핫링크 방지 방법 3가지와 유의 사항 3가지

지금 가장 많이 사용해 웹서버 점유율 상위에 랭크되어 있다는 웹서버 NGINX에 대한 관심이 높아지고 있죠. 이 NGINX를 적용한 사이트에서 이미지 핫링크 방지 방법은 여러가지가 있는데요. 오늘은 NGINX 핫링크 방집 방법 3가지를 살펴 보도록 하겟습니다.

NGINX 뿐만이 아니라 아파치 등에서 사용하는 방법에 대해서는 아래 글을 참조하시기 바랍니다.

들어가기 전, NGINX 웹서버 점유율

예전에서는 웹서버로 아파치를 가장 많이 사용했지면 최근 들어서는 가볍고 효율성이 좋은, 특히 많은 사람이 접속하는 사이트에서 자원을 효율적으로 사용할 수 있다는 점때문에 NGINX는 가장 많이 사용하는 웹서버가 되었습니다.

코로나 팬데믹으로 쇼핑 사이트들이 증가해서인지 모르지만 지난 2020년 8월인가를 기점으로 NGINX가 가장 높은 웹서버 점유율을 가진 웹서버로 등극했더군요. 쇼핑용을 위한 웹서버로 NGINX가 많이 선택된 것 같습니다.

2020년 11월 기준 NGINX 점유율 34%로 27%에 그친 아파치를 여유롭게 리드하고 있습니다.

웹서버 종류별 점유율 추이( ~2020년 11월), Graph by NETCRAFT
웹서버 종류별 점유율 추이( ~2020년 11월), Graph by NETCRAFT

아무튼 NGINX가 가장 많이 사용되는 웹서버가 되었기 때문에 NGINX 사용자가 많을 것이니 여기에서 이미지 핫링크 방지 방법이 더욱 더 유용할 수 있겠네요.

그러면 여기서부터 웹서버 NGINX에서 이미지 핫링크 방지 방법에 대해서 살펴보도록 하겠습니다.

리퍼러 룰 활용 NGINX 핫링크 방지 방안 – 고전적인 방식

첫번째로 소개할 것은 NGINX location 블럭에서 리퍼러를 활용하는 것인데요. 이 방법은 흔하게 소개되는 방법은 아니지만 검색하다가 How to Block Hotlinking with Nginx에서 발견한 방법입니다.

여기서 소개해는 코드 스니핏(code snippet)은 아파치에서 사용하는 형식과 닮아 있습니다.

  •  css, gif, ico, jpeg, js, png, woff, woff2, ttf, ttc, otf, eot 형식을 제어
    허용된 리퍼러가 아니면 403에러를 내라고 설계
  • 첫번째 룰은 블랭크 리퍼러를 허용
    일부 사용자는 웹 브라우저가 보내는 페이지 레퍼러 정보를 삭제하는 방화벽 설정 또는 바이러스 백신 프로그램을 사용하기 때문에 이 옵션을 추가할 필요가 있음
    이를 허용하지 않으면 해당 사용자에게는 모든 이미지가 보여지지 않게 될 수 있음
  • 두번째 룰은 자기 사이트 도메인 하위 부분 허용
    세번째 룰은 자기 사이트 도엠인
  • 네번째부터는 구글을 비롯한 사이트와 구글봇 등을 지정
  • 맨 마지막에는 첫번째 룰부터 마직막 룰까지 적용한다는 것 명시
location ~* \.(css|gif|ico|jpeg|jpg|js|png|woff|woff2|ttf|ttc|otf|eot)$ {
if ($http_referer !~ "^$"){
set $rule_0 1$rule_0;
}
if ($http_referer !~ "^http://mysite.com/.*$"){
set $rule_0 2$rule_0;
}
if ($http_referer !~ "^http://mysite.com$"){
set $rule_0 3$rule_0;
}
if ($http_referer !~* "google."){
set $rule_0 4$rule_0;
}
if ($http_referer !~* "search?q=cache"){
set $rule_0 5$rule_0;
}
if ($http_referer !~* "msn."){
set $rule_0 6$rule_0;
}
if ($http_referer !~* "yahoo."){
set $rule_0 7$rule_0;
}
if ($http_user_agent !~* "googlebot"){
set $rule_0 8$rule_0;
}
if ($http_user_agent !~* "msnbot"){
set $rule_0 9$rule_0;
}
if ($http_user_agent !~* "slurp"){
set $rule_0 10$rule_0;
}
if ($rule_0 = "10987654321"){
return 403;
break;
}
}Code language: PHP (php)

valid_referers 활용 NGINX 핫링크 방지 방안

허용된 리퍼러만 이미지 등 콘텐츠 링크를 허용하는 방안에 대해서는 거의 표준화된 방법인데요.

인터넷 검색하면 기본적으로 이 방법을 소개하고 있습니다. 그만큼 많이 사용되고 사용에도 편하다는 것이겠죠.

이 방법에 대한 수많은 설명이 많이 있지만 “NGINX 이미지 외부 링크 막기 설정 방법”에서 비교적 자세하게 설명되어 있기 때문에 이 글을 기반으로 (일부 먹히지 않는 부분은) 수정 설명해 봤습니다.

NGINX에서 이미지 핫링크 방지는 server 블럭 안의 위치하는 location에서 확장자를 지정, 해당 확장자 파일들은 valid_referers에서 요청하는 경우에만 제대로 보여주고 그 외 리퍼러 요청은 403에러 처리하는 하도록 합니다.

  • ($host)으로 해당 사이트가 반영되도록
  • ~.domain. 형식으로 이미지를 보여줘도 되는 사이트 지정
    도메인 지정 와이드카드는 오직 *만 제대로 작동하는 것 같음
    도메인 지정은 *.google.com 같은 포맷만 제대로 작동하고, ~.google.과 같은 방식은 작동하지 않음
  • 이미지 요청이 올 경우 보여줄 이미지를 설정하든지 아니면 403 에러 메세지 보여주기 결정
    . rewrite (.*)$ /custom/403_forbidden.png redirect;
    . return 403;
  • 어디에서 핫링크를 요청하는지 로그에서 기록
    access_log /var/log/nginx/hotlink-access.log;
<code>location ~* \.(jpeg|jpg|gif|png|bmp|svg|swf|ico|zip|7z|ttf|woff|webp|eot)$ {</code>
<code>     valid_referers none blocked</code>
<code>         server_names ~($host) ~.google. ~.bing. ~.yahoo.;</code>
<code>     if ($invalid_referer) {</code>
<code>         # rewrite (.*)$ /custom/403_forbidden.png redirect;</code>
<code>         return 403;</code>
<code>     access_log /var/log/nginx/hotlink-access.log;</code>
<code>     }</code>
<code> }</code>
Code language: PHP (php)

map 활용 NGINX 핫링크 방지 방안

이는 map에서 모든 리퍼러를 bad referer로 지정하고, 여기서 bad referer가 아닌 도메인을 지정해 주어 bad referer에 해당되는 모든 리퍼러는 403 또는 404 에러를 내도록 만드는 방법입니다.

이 방법은 이미지 뿐만이 아니라 모든 콘텐츠가 모두 해당되므로 매우 강력한 핫링크 방지 방법이 될 것 같습니다. 하지만 너무 광범위하게 막아 버리기 때문에 어떤 부작용이 있는지 확인해 보면서 계속 적용 유지할지 살펴 봐야 할 것 같습니다.

대개 map은 http 블럭안에 세팅합니다.

map $http_referer $bad_referer {
     default                  0;
     "~google.com"       1;
     "~bing.com"       1;
     "~yahoo.com"       1;
 }Code language: PHP (php)

그 다음 server 블럭안에 다음과 같이 bad referer에 해당하면 사정없이 404 에러를 내라고 지정하면 됩니다.

if ($bad_referer) {
     return 444;
 }Code language: PHP (php)

기타

이미지 핫링크 방지가 작동하는지 확인 방법

그러면 이렇게 다양한 핫링크 방지 방안을 적용 후 이러한 핫링크 방지가 제대로 작용하지는 확인할 필요가 있습니다.

가장 단순한 방식은 이미지 핫링크되어 있는 리퍼러에서 계속 이미지 핫링크가 이루어지고 있는지 확인하는 방법인데요. 이 방법은 캐시 등이 있기 때문에 단기간에 확인이 안될 수 있고, 잘못 판단할 수 있습니다.

이러한 문제를 풀려면 curl -I –referer 명령을 사용해 점검해 볼 수 있습니다. 이래와 같은 형식인데요.

curl -I --referer [러퍼러 도메인] [해당 사이트의 파일]Code language: PHP (php)

여기서 [해당 사이트의 파일]이라고 적시해 놓았는데요. 해당 사이트명만으는 제대로 확인할 수 없고요. 해당 사이트의 구체적인 파일 이름을 넣어서 확인하는 것이 제댜로 된 결과를 보여 줍니다.

이 작업을 https://risingsunsun.com/473에서 제 이미지를 무단으로 핫링크 걸어서 사용하기 때문에 이를 막고자 시작했기 때문에 다음과 같은 명령어를 사용했습니다. 한글 이름이 제대로 표현되지 않아 파일명이 지저분하게 보입니다.

curl -I --referer https://risingsunsun.com https://happist.com/wp-content/uploads/2017/08/%EC%9A%A9%EC%9D%B8-%EC%8B%A0%EA%B0%88-%EC%B4%9D%EA%B0%81%EC%B9%BC%EA%B5%AD%EC%88%98-%EC%9E%85%EA%B5%AC-7332.jpgCode language: PHP (php)

이 결과 아래와 같이 403에러 처리했다는 것을 보여 줍니다.

HTTP/2 403 
 server: nginx
 date: Tue, 22 Dec 2020 05:57:53 GMT
 content-type: text/html; charset=utf-8
 content-length: 146
 x-content-type-options: nosniff
 x-frame-options: SAMEORIGIN
 x-xss-protection: 1; mode=blockCode language: PHP (php)

중복 명령이 있는 경우는 합쳐야

저의 경우는 이미 jpg나 png 파일에 대해서는 webp 파일로 대체하하는 location 명령을 적용하고 있었습니다.

그런 상태에서 뒷부분에 아미지 파일에 대해서 location 블럭을 추가하고valid_referers 명령을 사용하지 제대로 작동하지 않았습니다.

그래서 webp를 적용한 jpg나 png 이미지 파일에 대해서는 webp 적용 명령과 valid_referers 적용 명령을 사용하고, 이어 나머지 이미지 파일 및 기타 파일 포맷에 대해서는 별도 location 블럭을 만들고 valid_referers 명령만을 적용했습니다.

아래는 제가 적용한 방법이니 참고하시기 바랍니다.

location ~* ^.+\.(jpg|jpeg|png) {
        valid_referers none blocked google.com *.google.com google.co.kr *.google.co.kr google.ch *.google.ch google.uk *.google.uk google.com.hk bing.com *.bing.com yahoo.com *.yahoo.com facebook.com *.facebook.com happist.com *.happist.com slowzin.com *.slowzin.com nextrend.co *.nextrend.co goodtrip.kr *.goodtrip.kr puripia.com *.puripia.com *.blog.naver.com/ihappist naver.com daum.net;
        if ($invalid_referer) {
            return 403;
            access_log /var/log/nginx/happist.com_hotlink-access.log;
            }       
        try_files $uri$webp_suffix $uri =404;
        expires max;
        log_not_found off; 
        access_log off;
    }

location ~* ^.+\.(asf|asx|wax|wmv|wmx|avi|bmp|class|divx|doc|docx|eot|exe|gif|gz|gzip|ico|webp|mdb|mid|midi|mov|qt|mp3|m4a|mp4|m4v|mpeg|mpg|mpe|mpp|odb|odc|odf|odg|odp|ods|odt|ogg|ogv|otf|pdf|pot|pps|ppt|pptx|ra|ram|svg|svgz|swf|tar|t?gz|tif|tiff|ttf|wav|webm|wma|woff|woff2|wri|xla|xls|xlsx|xlt|xlw|zip|css|js)$ {
        valid_referers none blocked google.com *.google.com google.co.kr *.google.co.kr google.ch *.google.ch google.uk *.google.uk google.com.hk bing.com *.bing.com yahoo.com *.yahoo.com facebook.com *.facebook.com happist.com *.happist.com slowzin.com *.slowzin.com nextrend.co *.nextrend.co goodtrip.kr *.goodtrip.kr puripia.com *.puripia.com *.blog.naver.com/ihappist naver.com daum.net;
        if ($invalid_referer) {
            return 403;
            access_log /var/log/nginx/happist.com_hotlink-access.log;
            }
        log_not_found off; 
        access_log off;
        expires max;
        #try_files $uri =404;
        include /etc/nginx/security-headers.conf;
    }
Code language: PHP (php)

구글 도메인 화이트 리스트

이미지 핫링크 방지를 위해서 리퍼러 화이트 리스트 세팅 시 고려할 것 중의 하나가 구글인데요. 구글 검색 결과를 중요한 트래픽 원천으로 삼는다면 가능하면 모든 구글 사이트를 화이트리스트에 등록하는 것이 좋습니다.

그런데 구글은 국가별로 아주 다양한 도메인을 운영하고 있습니다. google.com, google.co.kr 등등 최근까지 구글 도메인 리스트를 아래에 공유하니 화이트 리스트 작성 시 참고하시기 바랍니다. 저는 이 리스트 전체를 다 포함해 버렸습니다.

.google.com .google.ad .google.ae .google.com.af .google.com.ag .google.com.ai .google.al .google.am .google.co.ao .google.com.ar .google.as .google.at .google.com.au .google.az .google.ba .google.com.bd .google.be .google.bf .google.bg .google.com.bh .google.bi .google.bj .google.com.bn .google.com.bo .google.com.br .google.bs .google.bt .google.co.bw .google.by .google.com.bz .google.ca .google.cd .google.cf .google.cg .google.ch .google.ci .google.co.ck .google.cl .google.cm .google.cn .google.com.co .google.co.cr .google.com.cu .google.cv .google.com.cy .google.cz .google.de .google.dj .google.dk .google.dm .google.com.do .google.dz .google.com.ec .google.ee .google.com.eg .google.es .google.com.et .google.fi .google.com.fj .google.fm .google.fr .google.ga .google.ge .google.gg .google.com.gh .google.com.gi .google.gl .google.gm .google.gr .google.com.gt .google.gy .google.com.hk .google.hn .google.hr .google.ht .google.hu .google.co.id .google.ie .google.co.il .google.im .google.co.in .google.iq .google.is .google.it .google.je .google.com.jm .google.jo .google.co.jp .google.co.ke .google.com.kh .google.ki .google.kg .google.co.kr .google.com.kw .google.kz .google.la .google.com.lb .google.li .google.lk .google.co.ls .google.lt .google.lu .google.lv .google.com.ly .google.co.ma .google.md .google.me .google.mg .google.mk .google.ml .google.com.mm .google.mn .google.ms .google.com.mt .google.mu .google.mv .google.mw .google.com.mx .google.com.my .google.co.mz .google.com.na .google.com.ng .google.com.ni .google.ne .google.nl .google.no .google.com.np .google.nr .google.nu .google.co.nz .google.com.om .google.com.pa .google.com.pe .google.com.pg .google.com.ph .google.com.pk .google.pl .google.pn .google.com.pr .google.ps .google.pt .google.com.py .google.com.qa .google.ro .google.ru .google.rw .google.com.sa .google.com.sb .google.sc .google.se .google.com.sg .google.sh .google.si .google.sk .google.com.sl .google.sn .google.so .google.sm .google.sr .google.st .google.com.sv .google.td .google.tg .google.co.th .google.com.tj .google.tl .google.tm .google.tn .google.to .google.com.tr .google.tt .google.com.tw .google.co.tz .google.com.ua .google.co.ug .google.co.uk .google.com.uy .google.co.uz .google.com.vc .google.co.ve .google.vg .google.co.vi .google.com.vn .google.vu .google.ws .google.rs .google.co.za .google.co.zm .google.co.zw .google.catCode language: PHP (php)

참고

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

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

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

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

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

워드프레스 이미지 최적화에 필수적인 ImageMagick 설치 방법

검색엔진 최적화, SEO 전설 랜드 피쉬킨의 SEO 강의 – The One-Hour Guide to SEO

SEO 전설 중의 한명인 랜드 피쉬킨(Rand Fishkin)의 유명한 SEO 강의를 SEO 공부하던 차에 발견했습니다. 무료 SEO 강의라고 무시할 게 아니라 나름 깊이도 있기 때문에 공부겸 해서 여기에 MOZ가 제공하는 무료 SEO 강의를 공유해 봅니다.

여기 소개하는 The One-Hour Guide to SEO는 MOZ의 SEO 강의 중 하나로 MOZ의 콘텐츠를 시험적으로 청취해보고 나머지 강의도 들어보라는 의미에서 무료로 공개하고 있는 자료입니다. 이는 아래처럼 6개 주제에 대해서 약 15분 정도씩 설명하고 있습니다.

이 SEO 강의는 랜드 피쉬킨(Rand Fishkin)이 매주 금요일마다 SEO 관련 소주제를 기반의 강의했던  whiteboard friday 강의 중 하나라고 합니다. 이러한 금요일마다 진행되는 SEO 강의는 그가 복귀하면서 다시 시작한다고 하네요.

이 무료 SEO 강의에는 아래와 같은 6가지 주레를 다루고 있습니다.

  1. SEO Strategy
  2. Keyword Research
  3. Searcher Satisfaction
  4. On-page Optimization
  5. Technical SEO
  6. Link Building – Ready to dive in?

여기서 시원스럽게 강의하고 있는 랜드 피쉬킨(Rand Fishkin)는 MOZ에서 SEO 강의로 명성을 날리다 잠시 다른 일을 하느라 MOZ를 떠났다가 최근 다시 복귀했다고 합니다.

그는 이번에 복귀해서 시리즈별로 10분 씩 1시간에 걸쳐 SEO 기봉에 대한 강의한다고 해서 기대를 모으고 있습니다.

1. SEO Strategy

One-Hour Guide to SEO – 6 Free Videos – Moz

2. Keyword Research

One-Hour Guide to SEO – 6 Free Videos – Moz

3. Searcher Satisfaction

One-Hour Guide to SEO – 6 Free Videos – Moz

4. On-page Optimization

One-Hour Guide to SEO – 6 Free Videos – Moz

5. Technical SEO

One-Hour Guide to SEO – 6 Free Videos – Moz

6. Link Building – Ready to dive in?

Link Building – The One-Hour Guide to SEO, Part 6

참고

워드프레스 SEO 플러그인으로 유명한 Yoast SEO에서 공개한 SEO for beginners라는 기본 강의도 SEO를 이해하는 데 도움이 됩니다. 이 강의에서는 SEO 기본에 대해서 어느 정도 감을 잡을 수 있을 내용을 소개하고 있습니다.

Free SEO training: SEO for beginners

SEO 플러그인으로 유명한 Yoast SEO 강의
  1. SEO 소개
    . SEO 개념, 검색엔진 작동 방법, 검색엔진이 웹사이트 탐색 방식
    . Yoast SEO 플러그인을 이용 시 SEO 잇점
  2. SEO의 콘텐츠
    . 키워드
    . 구글이 좋아하는 텍스트 – 오리지널, 가독성, 쉽게 찾을 수 있는 글 선호
    . 사이트 구조
  3. SEO의 기술적 요소
    . 크롤링 가능성 (Crawlability)
    . 구글 검색엔진에게 호소력 있는 콘텐츠로 보이는 방법(Rich results)

이미지 무단 링크를 막는 워드프레스 핫링크 방지 방법 4가지

사이트 운영 시 필히 만날 수 밖에 없는 이미지 도용 핫링크를 방지해 트래픽을 안정적으로 유지하고, 서버 자원을 효율적으로 이용하는 워드프레스 핫링크 방지 방법에 대해서 알아봅니다.

오늘 서버 문제가 있어서 이런 저런 log 파일들을 살펴보다가 생각보다 많은 이미지와 폰트들이 다른 사이트에 핫링크되어 사용되고 있다는 것을 발견했습니다.

나름 서버단에서 이미지 핫링크에 대한 대비를 했다고 생각했는데 뭔가 문제가 있는지 이미지 핫링크 방지가 제대로 작동하지 않는 것 같았습니다. 어쩌면 제가 적용했던 코드가 완전하지 않았을 수 있을 것입니다.

그래서 다시 한번 이미지 핫링크 방지 방법에 대해서 살펴봤습니다.

이미지 핫링크(Image hotlink)란?

핫링크란 이미지나 동영상과 같은 콘텐츠를 보여줄 때, 이 콘텐츠 소스가 해당 사이트에서 제공하는 것이 아니라 다른 사이트의 이미지나 동영상을 가져다 보여주는 것을 말합니다.

우리 말로 이야기하면 이미지 무단 도용이라고도 할 수 있습니다. 대개 해당 사이트 주인장의 허락없이 이미지나 동영상 링크를 그대로 사용해기 때문에 여러가지 문제를 일으킵니다.

  1. 핫링크로 인해서 오리지널 사이트 소유자에게 비용이 발생합니다.
    아시다시피 사이트 운영이 공짜가 아니기 때문에 해당 사이트를 운영하기 위해서는 서버와 같은 물리적 하드웨어 사용 비용과 인터넷으로 데이타를 보내고 받는 트래픽에 대한 비용이 발생합니다.
    핫링크 규모가 커지면 사이트 운영자는 추가로 비용을 내야하는 문제가 발생합니다.
  2. 대부분 핫링트는 불법입니다.
    어쩌면 많은 사람들이 인식하지믄 못하지만 웹 이미지에는 라이센스 제한이 걸려 있기 때문에 이러한 핫링크로 불법 상태가 되어 버립니다.
    . “귀하가 소유한 사이트 또는 블로그에서만 사용”한다는 라이센스 규정에 위반
  3. 핫링크가 증가하면 해당 서버 자원이 금방 고갈될 수 있습니다.
    . 핫링크가 걸려 갑자기 트래픽이 증가되는 경우 평소의 몇백만배 이상의 서버 리퀘스트(요청)가 발생하면서 CPU등 사용 자원 여분이 줄어들고
    . 심지어는 공동으로 자원을 하용하는 호스팅에서는 해당 계정을 정지해 버릴 수 있습니다.
  4. 일반적으로 핫링트를 사용하는 사람들은 핫링크 행위가 문제가 된다는 의식이 별로 없는 경우가 많습니다.
    . 그러나 위에서 지적하다시피 불법이고, 해당 사이트 운영을 어렵게 만들기 때문에 사용해서는 안됩니다.

이미지 핫링크로 문제가 되었던 오트밀 사례

이미지 핫링크로 문제가 되었던 대표적인 사례가 오트밀 사례입니다.

한 때 인터넷 언론사로 성가를 올리고 있었던 허핑턴 포스트(Huffington Post)는 오트밀에서 제공하는 다양한 웹 만화를 핫링크 했습니다.

인기있는 만화를 영향력 있는 인터넷 매체인 허핑턴 포스트에서 링크를 걸자 엄청난 트래픽이 발생하고, 이에 다라 오트밀은 엄청난 트래픽 비용을 물어야 했습니다.

이에 대응해 오트밀은 핫링크 방지 기능을 추가하고 허핑턴 포스트에서 문단으로 링크를 걸었기 때문에 엄청난 비용이 발생했다는 내용의 메세지와 그래를 있는 이미지가 대신 보여지도록 만들었습니다.

허핑턴 포스트를 통해서 오트밀 만화 이미지를 보던 사람들에게 이는 도용된 이미지라는 것을 확실히 알려 준 것이죠.

아파치에서 이미지 핫링크 방지

우선 웹서버로 아파치를 사용한다면 .htaccess에서 다음과 같은 기본 코드를 적용할 수 있습니다.

  • 두번째 줄은 블랭크 리퍼러를 허용
    일부 사용자는 웹 브라우저가 보내는 페이지 레퍼러 정보를 삭제하는 방화벽 설정 또는 바이러스 백신 프로그램을 사용하기 때문에 이 옵션을 추가할 필요가 있음
    이를 허용하지 않으면 해당 사용자에게는 모든 이미지가 보여지지 않게 될 수 있음
  • 세번째 줄 부터는 이미지 등을 보여 줄 수 있는 사이트를 정의
    . 자기 사이트
    . 구글
    . 빙
    . 야후
    . 네이버 서치
    . 다음 서치
    . 피드버너
  • 마지막 줄은 옵션으로 보호 이미지 대신 보여줄 이미지를 정의
  • CDN을 사용하면서 이 규칙을 적용하는 경우 CDN 서브 도메인을 추가
RewriteEngine on
 RewriteCond %{HTTP_REFERER} !^$
 RewriteCond %{HTTP_REFERER} !^http(s)?://(www.)?yourdomain.com [NC]      #자기 사이트
 RewriteCond %{HTTP_REFERER} !^http(s)?://(www.)?google.com [NC]          #구글
 RewriteCond %{HTTP_REFERER} !^http(s)?://(www.)?bing.com [NC]            #빙
 RewriteCond %{HTTP_REFERER} !^http(s)?://(www.)?yahoo.com [NC]           #야후
 RewriteCond %{HTTP_REFERER} !search\.naver.com [NC]                      #네이버봇
 RewriteCond %{HTTP_REFERER} !ws\.daum\.net [NC]                           #다음봇
 RewriteCond %{HTTP_REFERER} !feedburner\. [NC]                            #피드버너
 RewriteRule \.(jpg|jpeg|png|gif|svg)$ https://yourdomain.com/hotlink-placeholder.jpg [NC,R,L]
Code language: PHP (php)

NGINX에서 이미지 핫링크 방지

예전에서는 웹서버로 아파치를 가장 많이 사용했지면 최근 들어서는 가볍고 효율성이 좋은 NGINX가 가장 많이 사용하는 웹서버가 되었습니다.

코로나 팬데믹으로 쇼핑 사이트드링 증가해서인지 모르지만 지난 2020년 8월인가를 기점으로 NGINX가 가장 높은 점유율을 가진 웹서버로 등극했더군요. 2020년 11월 기준 NGINX 점유율 34%로 27%에 그친 아파치를 여유롭게 리드하고 있습니다.

웹서버 종류별 점유율 추이( ~2020년 11월), Graph by NETCRAFT
웹서버 종류별 점유율 추이( ~2020년 11월), Graph by NETCRAFT

아무튼 NGINX가 가장 많이 사용되는 웹서버가 되었기 때문에 NGINX 사용자가 많을 것이니 여기에서 이미지 핫링크 방지 방법이 더욱 더 유용할 수 있겠네요.

이에 대해서 여러가지 설명이 많이 있지만 “NGINX 이미지 외부 링크 막기 설정 방법”에서 비교적 자세하게 설명되어 있기 때문에 이 글을 기반으로 (일부 먹히지 않는 부분은) 수정 설명해 봤습니다.

NGINX에서 이미지 핫링크 방지는 server 블럭 안의 위치하는 location에서 확장자를 지정, 해당 확장자 파일들은 valid_referers에서 요청하는 경우에만 제대로 보여주고 그 외 리퍼러 요청은 403에러 처리하는 하도록 합니다.

  • ($host)으로 해당 사이트가 반영되도록
  • ~.domain. 형식으로 이미지를 보여줘도 되는 사이트 지정
    도메인 지정 와이드카드는 오직 *만 제대로 작동하는 것 같음
    도메인 지정은 *.google.com 같은 포맷만 제대로 작동하고, ~.google.과 같은 방식은 작동하지 않음
  • 이미지 요청이 올 경우 보여줄 이미지를 설정하든지 아니면 403 에러 메세지 보여주기 결정
    . rewrite (.*)$ /custom/403_forbidden.png redirect;
    . return 403;
  • 어디에서 핫링크를 요청하는지 로그에서 기록
    access_log /var/log/nginx/hotlink-access.log;
<code>location ~* \.(jpeg|jpg|gif|png|bmp|svg|swf|ico|zip|7z|ttf|woff|webp|eot)$ {</code>
<code>     valid_referers none blocked</code>
<code>         server_names ~($host) ~.google. ~.bing. ~.yahoo.;</code>
<code>     if ($invalid_referer) {</code>
<code>         # rewrite (.*)$ /custom/403_forbidden.png redirect;</code>
<code>         return 403;</code>
<code>     access_log /var/log/nginx/hotlink-access.log;</code>
<code>     }</code>
<code> }</code>
Code language: PHP (php)

워드프레스 플러그인 사용

위에서는 조루 아파치나 NGIN와 같은 웹서버에서 직접 제어하는 방법을 사용했지만 일반 호스팅을 사용하는 경우 한 서버에 여러 사이트를 운영한다는 특성상 개별 사이트에 맞추어 서버 세팅을 할수 없기에 뽀족한 방법이 없습니다.

그럴 경우에는 이를 지원하는 플러그인을 사용해 대응할 수 있습니다. 워드프레스 플러그인에서 hotlink를 검색어로 입력하면 다양한 플러그인들이 나옵니다.

많은 플러그인들이 있지만 안전하고 계속 유지 관리가 잘 되는 플러그인은 많지 않다는 평가입니다.

워드프레스 이미지 핫링크 방비 플러그인 리스트

차리리 보안 플러그인 중에서 인기가 높은  All In One WP Security And Firewall을 사용하는 것을 추천하고 있습니다. 이 All In One WP Security And Firewall 플러그인은 보안 플러그인들 중에서도 좋은 평가를 받고 있고 보안과 관련한 다양한 기능들을 지원하고 있습니다.

올인원 WP 보안 및 방화벽 플러그인 주요 기능, All In One WP Security And Firewall plug in
올인원 WP 보안 및 방화벽 플러그인 주요 기능, All In One WP Security And Firewall plug in

CDN 활용 방법 외

최근에서는 글로벌 비즈니스를 위해서는 CDN 사용이 불가피해지고 있는데요. CDN 사용은 트래픽 절감이나 속도 개선등을 넘어서 디도스 방어와 같은 보안 관련 니즈에 의해서 활용도가 높이지고 있기도 합니다.

만약 CDN을 사용한다면 클라우드플레어나 KeyCDN과 같은 CDN 업체들은 무료로 성능이 뛰어난 핫링크 방지 기능을 제공하고 있습니다.

이들 CDN에서는 매우 세밍하게 리퍼러들에 대한 미세 조정할 수 있는 옵션이 있기 활용 가치가 높습니다.

더우기 CDN에서 핫링크 방지 기능을 사용하기로 했다면 서버나 워드프레스 자체에서는 아무런 조치를 취할 필요가 없습니다.

Amazon S3 사용 시 적용 코드

이 방법은 직접 사용해 보지는 않았고, How to Prevent Hotlinking in WordPress (7 Easy Methods)에서 소개하는 방법을 그대로 여기서도 소개하니 참고만 하시기 바랍니다. 그 글에도 자세한 설명은 별로 없긴 합니다.

Amazon S3의 bucket policies에서 아래와 같은 코드를 적용한다고 하네요.

{
   "Version": "2008-10-17",
   "Id": "preventHotLinking",
   "Statement": [
     {
       "Sid": "1",
       "Effect": "Allow",
       "Principal": {
         "AWS": "<em>"       },       "Action": "s3:GetObject",       "Resource": "arn:aws:s3:::my-brand-new-bucket/</em>",
       "Condition": {
         "StringLike": {
           "aws:Referer": [
             "http://yourwebsitename.com/<em>",             "http://www.yourwebsitename.com/</em>"
             "https://google.com/<em>"             "https://bing.com/</em>"
             "https://yahoo.com/*"
           ]
         }
       }
     }
   ]
 }Code language: PHP (php)

참고

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

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

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

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

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

워드프레스 이미지 최적화에 필수적인 ImageMagick 설치 방법

MySql 최적화로 빨라질 사이트 DB 튜닝 방법

이번에 운영 서버를 우분투 20.04PHP 8을 적용해 업그레이드 하면서 MySql 최적화 DB 설정 시 검토했던 내용을 여기에 정리해 봅니다.

여기는 워드프레스 사이트를 운영하기 위한 작은 사이트 기준이므로 이를 감안해 주시구요. DB 크기가 1G정도로 사이즈를 기준으로 했습니다. 이는 블로그 글 3~4,000개 정도 되는 사이트에 해당합니다.

MySql 최적화, Basic Settings

  • Basic Settings에서 생각해 볼 것은 tmpdir을 어디에 둘 것인지 여부입니다. 기본으로는 하드디스크인 /tmp에 설정되어 있습니다.
    전체 세팅을 잘 변경해 보아도 임시 테이블이 하드디스크에 생성되는 것을 막을 수는 없던데, 메모리 여유가 있다면 램에 tmpdir을 지정하는 것이 좋을 것 같습니다.

    여러 번 시행 착오 끝에 리눅스 tmpfs 파일시스템은 일부 임시 파일생성을 허용하지 않기 때문에 에러가 발생하다는 사실을 확인하고 임시 파일 폴더를 메모리에 올리는 것을 포기 했습니다.
    제가 받은 에러 메세지는 리눅스 커널에서 MariDB가 tmpfs 파일시스템에서 일부 임시 파일 생성하는 것을 허용하지 않아 에러가 발생, mariadbd: O_TMPFILE is not supported on /dev/shm (disabling future attempts).
    .
  • skip-external-locking 항목이 있는데, 이는 MySQL 4.0 이후에는, 모든 시스템에서 외부 잠금을 비활성화 하는 것이 디폴트로 외부 잠금을 사용하지 말라고 권고 되고 있습니다.
    .
  • skip-name-resolve
    Mysql 서버가 외부로부터 접속 요청을 받으면 인증을 위해 ip 주소를 호스트 네임으로 변경하면서 불필요한 부하가 발생할 수 있으므로
    skip-name-resolve를 설정하면 접속 시 IP 기반으로 접속을 하게 되어 hostname lookup 과정 생략되어 좀 더 빠르게 접속 가능하다고 합니다.
#
 * Basic Settings
#
user                    = mysql
pid-file                = /run/mysqld/mysqld.pid
basedir                 = /usr
datadir                 = /var/lib/mysql
tmpdir                  = /tmp
lc-messages-dir         = /usr/share/mysql
lc-messages             = en_US
skip-external-locking
skip-name-resolve
bind-address            = 127.0.0.1
Code language: PHP (php)

Fine Tuning

  • max_connection : 최대 동시 접속자 수,
    늘어나면 날수록 메모리가 고갈되고 스케줄링 오버헤드도 증가
    이전 최대 접속자 수의 2배 정도 잡는다.
  • connect_timeout : mysqld 서버가 패킷과 연결하기 위해서 대기하는 시간
    기본값은 10초
  • wait_timeout : 서버가 데이타 패킷과 연결된 후 연결을 유지하는 시간
    . 기본값은 28800초(8시간)
    . DB 서버 접속이 많다면 wait_timeout을 최대한 적게 (20~30 정도를 추천) 설정하여 불필요한 연결을 빨리 정리 필요.
    그러나 Connection Miss Rate(%)가 1% 이상이 된다면 wait_timeout 을 좀 더 길게 가져야 함.
  • . 그렇지 않다면 DB 연결 후 끊고 다시 연결하는 것은 속도를 지연 시키는 요인이기 때문에 연결 시간을 길게 유지하는 것이 성능 향상에 도움이 된다는 의견이 있음
  • max_allowed_packet : 허용 패킷 크기
    . 기본값 16MB이며 최대값은 1GB,
    . MySQL 서버가 잘못된, 너무 큰 패킷을 제어하는 데는 도움이 되지만
    규모 이상으로 큰 패킷을 수신하면 문제가 있다고 판단해 연결을 끊어 버리기 때문에 이를 피하려면 값을 새로 설정하고 mysql을 다시 시작해야 함
  • thread_cache_size :
    . 기본값 8
    . Cache Miss Rate(%)가 높다면 기본값보다 높게 잡는다
  • sort_buffer_size
    . 리눅스에는 256K 또는 2MB라는 임계점이 존재하는데
    이 이상의 값은 메모리 할당이 크게 느려질 수 있으므로 이보다 낮은 값을 사용하는 것으로 고려
  • join_buffer_size
    . MySqlTunner에서는 최소 1MB이상으로 제안
  • tmp_table_size
    . group by 시 디스크를 사용하지 않고 임시 테이블을 만들기 위해 사용하는 메모리 크기
  • max_heap_table_size
    . 내부 메모리 임시 테이블이 너무 커지면(tmp_table_size와 max_heap_table_size 를 넘어서는 경우) 자동으로 테이블을 메모리에서 디스크 내 형식으로 변환
max_connection             = 50
connect_timeout               = 20
wait_timeout               = 7200
max_allowed_packet         = 32M 
thread_stack              = 192K
thread_cache_size          = 128 
sort_buffer_size           = 2M
join_buffer_size           = 2M  
bulk_insert_buffer_size       = 16M
tmp_table_size               = 256M  
max_heap_table_size           = 256M
Code language: PHP (php)

InnoDB 세팅

MySql 최적화, 이노디비 구조, innodb architecture
이노디비 구조, innodb architecture
  • default_storage_engine = InnoDB
    기본 데이타베이스 엔진으로 InnoDB를 사용한다는 것 표시
  • innodb_buffer_pool_size
    . 운영중인 시스템의 DB 크기 이상을 할당

    (저의 경우 DB 크기가 970MB였기 때문에 1GB를 설정
    . 시스템 메모리의 65%~75% 권장, 시스템 메모리 8GB RAM라면 일반적으로 5~6GB 정도 할당
    . buffer pool이 너무 작으면 페이지가 buffer pool에서 플러시 되어 잠시 후 다시 필요하게 되므로 과도한 I/O 가 발생할 수 있으며,
    너무 큰 경우 메모리 경쟁으로 스와핑이 발생할 수 있음
  • innodb_log_file_size
    . 데이타베이스 충돌 발생 시 다시 실행하거나 이전으로 되돌릴 때 사용하는 메모리
    . 지나치게 크면 복구 시간이 길어지면서 비효율적이 될 수 있음
    . 위에서 설정한 innodb_buffer_pool_size의 25% 정도 할당
  • innodb_buffer_pool_instances
    . 인스턴스 수를 늘리면 트랜잭션 간 Lock 경합을 줄일 수 있음
    . 기본값은 8
    . 메모리가 많은 시스템에서는 buffer pool을 여러 개 buffer pool instance로 나누어 동시성을 향상 시키는 것이 가능
  • innodb_flush_log_at_trx_commit
    . 0은 성능 중심, 1은 안정성 중심
  • innodb_flush_method
    . O_DIRECT – 데이터 읽기/쓰기에 OS 캐시를 사용하지 않다 바로 MySql/MariaDB에서 가져 오겠다는 설정
    쓰기 성능은 나빠질 수 있지만 더블 버퍼링을 막아 메모리를 효율적으로 사용하겠다는 것
    . O_DSYNC – 데이터 읽기/쓰기에 OS 캐시를 사용
    속도는 더 빠르지만 대기 시간, 충돌로 데이타가 일관적이지 않을 수 있다고 함
  • innodb_io_capacity
    . InnoDB 변경 성능은 플러쉬 속도, 즉 스토리지 I/O 속도에 의존하므로 빠른 스토리지 사용 필요
    . 현재 사용하고 있는 디스크의 IOPS와 유사한 값 설정
    . SSD와 같이 속도가 빠른 스토리지는 값을 올리고, 일반 HDD라면 값을 내린다.
innodb_buffer_pool_size       = 1024M     
innodb_log_file_size            = 256M     
innodb_log_buffer_size          = 8M
innodb_file_per_table            = 1
innodb_open_files              = 400
innodb_flush_log_at_trx_commit  = 0     
innodb_flush_method             = O_DIRECT
innodb_stats_on_metadata        = 0
innodb_io_capacity              = 15000Code language: PHP (php)

MyISAM

가능하면 InnoDB를 사용하고 MyISAM을 사용하지 않는 방법을 찾는 게 좋다고 권고 받지만 때로는 MyISAM를 사용할 수 밖에 없는 경우도 있다고 합니다.

  • key_buffer_size
    . 인덱스를 메모리에 저장하는 버퍼의 크기로 총 메모리의 25% 정도로 설정
    . 기본 값은 256MB
    . 그렇지만 InnoDB 중심으로 운영한다면 이 값을 매우 낮게 유지 가능. 가이드에서는 64K까지 낮출 수 있다고..
  • myisam_sort_buffer_size
    . rlqhs rkqtdms 512K
key_buffer_size        = 36M
myisam_sort_buffer_size    = 512K  # default 2M
concurrent_insert    = 2
read_buffer_size    = 512K
read_rnd_buffer_size    = 512KCode language: PHP (php)

Table 세팅

  • table_definition_cache
    . 테이블 오픈 속도를 향상 시키기 위한 캐시 수
  • table_open_cache
    . 각 쓰레드별 오픈할 테이블 수
    . 기본 값은 2000
    . max_connection * N개가 되어야 함
    여기서 N은 실행하는 쿼리에서 조인 당 최대 테이블 수
    . MySql에서 show global status like ‘%table_open_cache%’ ; 명령 결과에서 miss가 있다면 늘려 봄
  • open_files_limit
    . table_open_cache 값의 2배 또는 3배
    . file-max 값은 리눅스에서 한 번에 운용할 수 있는 파일 수를 의미하며,
    보통 4MB 메모리 당 256개의 파일을 운용할 수 있다고 한다.
    대략 1G -> 65536개, 2G -> 131072 개
table_definition_cache          = 2000 
table_open_cache                = 15000
open_files_limit                = 7260000 Code language: PHP (php)

Query Cache Configuration

MySqlTunner에서는 쿼리 캐시를 사용하지 말라고 권고하고 있네요

  • query_cache_limit
    . 이 변수 값 보다 큰 값은 캐싱이 안됨
  • query_cache_size
    . 쿼리 결과를 캐싱하기 위해서 할당된 메모리 크기
    . query_cache_size가 너무 크다면 갑자기 엄청난 쓰기 작업이 발생 시 서버는 바로 쿼리 작업을 하는 대신 cache를 찾아 작동하는데 집중해 오히려 속도가 느려짐
    . 시스템에서 사용하지 말라고 권고
  • query_cache_type
    . 쿼리캐시 사용하지 말라는 권고
query_cache_limit        = 2M   
query_cache_size        = 0    
query_cache_type        = OFF 
binlog_cache_size       = 16MCode language: PHP (php)

로그 세팅

  • binlog_cache_size
    . 이 값은 버퍼 명령문에 할당되어, 명령문이 이 값보다 크면 쓰레드는 트랜젝션을 저장하기 위해 임시 파일을 사용
  • binlog_cache_use 상태 변수는 명령문을 저장하기 위한 용도로 이 버퍼(또는 임시 파일)를 사용한 트랜젝션 숫자를 의미하며, binlog_cache_disk_use 상태 변수는 이 임시 파일을 실제로 사용한 트랜젝션의 숫자를 표시
    . 이 두 가지 변수를 이용해 임시 파일 사용을 피하기 위한 binlog_cache_size를 튜닝하는 데 사용
  • general_log / slow_query_log
    . 로그 활성화 시 1, 비활성 시 0 사용
  • long_query_time
    . 이 변수 값보다 쿼리 처리가 길게 걸리면 에러 로그에 기록
binlog_cache_size       = 16M
general_log_file       = /var/log/mysql/mysql.log
general_log            = 1
slow_query_log      = 1
slow_query_log_file    = /var/log/mysql/mariadb-slow.log
long_query_time        = 1
log_slow_verbosity     = query_plan,explain
log_bin                = /var/log/mysql/mysql-bin.log
expire_logs_days        = 10
max_binlog_size        = 100MCode language: PHP (php)

참고

우분투 20.04와 PHP 8 기반 워드프레스 설치 방법

가상 서버를 운영하고픈 勇者에게 전하는 가상 서버 운영 입문 노하우 – Vultr 가상서버호스팅(VPS)를 중심으로

워드프레스 최적화를 위한 18개월간의 고민, 그 노하우를 담다.

도쿄 리젼과 비교해 본 Vultr 서울 리젼 사용기

가성비가 뛰어난 Vultr 가상서버호스팅(클라우드호스팅,VPS) 사용기

우분투 20.04와 PHP 8 기반 워드프레스 설치 방법

근래 사이트 운영 환경이 급격하게 변동되면서 우분투 20.0와 PHP 8 등 최신 버전을 적용 가상 서버 설치 및 워드프레스 설치 가이드를 재 작성해 기존 정보들을 업데이트할 필요가 있었습니다.

오래 전부터 우분투와 PHP를 적용한 서버 설치 및 이 서버에서 워드프레스 설치 및 워드프레스 운영 가이드를 작성해 공유해 왔습니다. 그렇지만 시간이 흐르면서 이 사이트에서 제공하는 정보가 낡았다는 지적이 있기도 했습니다. 그럼에도 정보가 유용하다는 병주고 약주는 그런 평가도 있기도 했습니다.

그래서 이번 PHP 8 출시 및 이에 맞춘 워드프레스 5.6버전이 나왔기 때문에 이를 모두 반영한 설치 가이드를 정리해 보기로 했습니다.

여기 설치 가이드에서는 2020년에 출시한 운영체제 20.04 LTS와 PHP 8 그리고 MariaDB 10.5를 반영했습니다. 그리고 그 동안 업데이트 된 보안 관련 내용도 반영하였습니다.

1. 운영체제 우분투 20.04을 선택하다.

리눅스를 기반 운영체제 중에서 우분투가 상대적으로 업그레이드가 빠르다는 평이 많기 때문에 선택했습니다.

새로운 리눅스 버전이 나오면 각 운영체제들은 그들이 가진 비즈니스 전략과 운영 전략에 따라 적절한 시기에 업데이트를 진행하는데요.

우분투는 상대적으로 이런 업데이트가 빠르기에 바로 사용하고 싶은 욕구가 크기 때문에 선택 했습니다. 그리고 가장 많은 사용자는 아니지만 상대적으로 많은 사용자가 있어 관련 정보 획득에 용이하다는 점도 고려했습니다.

우분투 20.04 LTS, ubuntu 20.04 LTS

1.1. 20.04는 18년 4월 버전이라는 의미이다.

우분투 버전은 출시한 연도와 월에서 따옵니다. 만약 우분투 24.08이 있다면 이는 2024년 8월에 출시한 버젼입니다.

마찬가지로 최근에 출시된 우분투 20.10은 2020년 10월에 출시한 우분투 버전을 의미합니다.

1.2. 우분투 20.04는 LTS 버전이다.

우분투의 탄생 배경은 기존 데비안의 업데이트가 너무 느리기 때문에 이에 불만을 품고 우분투가 시작되었기 때문에 업데이트가 잦은 편이며 이에 따라 잦은 판올림이 이루어 집니다.

그런데 우분투 버젼이 빠르게 변하기 때문에 지원 기간이 짧아질 수 밖에 없습니다.

우분투 자체로 어떤 비즈니스 모델을 만들고 이를 통해서 떼돈을 버는 것이 아닌 비영리기관에서 운영하는 것이기 때문에 버젼별로 무한정 지원할 수 없기때문에 짧을 수 밖에 없습니다. 최근에는 평균 지원기간이 9개월 정도로 짧습니다.

그런데 서버 운영 입장에서는 그렇게 자주 서버 운영체제를 업그레이드 할 수 없습니다. 대규모 사이트에서는 업그레이드하려면 챙겨야 하는 점들이 많을 수 밖에 없기 때문에 조금만 잘못해도 커다란 비즈니스 손실을 봐야 하기 때문에 조심스러울 수밖에 없습니다.

그렇게 때문에 우분투에서는 기업용으로 5년동안 지원하는 LTS(Long Term Support) 버젼을 출시합니다. 이 LTS 버젼은 짝수년도 4월에 출시합니다.

현재 사용 가능한 LTS 버전은 16.04, 18.04 그리고 20.04가 있습니다.

1.3. 버전명과 코드네임이 다 활용된다.

일반적인 프로젝트에서 코드네임은 프로젝트가 끝나면 사용되지 않죠.

그렇지만 우분투에서 코드네임은 패키지 저장소나 관련 앱 버젼 관리 시 사용되므로 서버를 관리하려면 버젼명과 코드네임을 알고 있어야 합니다.

지금 현재 설치 가능한 버젼은 16.04, 18.04, 20.04, 20.10이 있는데 이들의 코드 네임은 아래와 같습니다.

  • 16.04 : Xenial Xerus
  • 18.04 : Bionic Beaver
  • 20.04 : Focal Fossa
  • 20.10 : Groovy Gorilla

2. Vultr에서 우분투 20.04 설치 준비

여기에서는 Vultr에서 서버 설치를 위해 서버 위치, 서버 종류, 운영체제 선택, 운영 플랜 등 기본적인 사항을 선택하는 방법을 소개합니다.

Vultr를 사용하지 않고 다른 회사를 선택한다면 넘어가 주세요.

Vultr에서는 개개의 서버를 Instance라고 부릅니다. 서버 세팅, Vultr에서 이야기하는 Deploy New Instance 화면의 Vultr Cloud Compute(VC2)화면에서 세팅을 시작할 수 있습니다.

아래는 간단히 서버 세팅 과정을 보여주고 있습니다.

2.0. 서버 종류 선택

예전 Vultr 서버 종류는 그리 복잡하지는 않았지만 지금은 High Frequency가 추가되어 Cloud Compute, High Frequency, Bere Metal, Dedicated Cloud의 4가지 종류를 선택할 수 있습니다.

우리가 가장 일반적으로 저렴한 버전은 Cloud Compute이구요.

이보다 더 나은 CPU와 NVme라는 고성는 디스크를 사용해 성능을 높인 High Frequency를 선택할 수 있습니다. 다면 가격이 20% 더 비쌉니다.

독립형 서버를 사용하고 싶다면 Dedicated Cloud를 선택할 수 있지만 지원 지역이 많지는 않습니다. 당근 가격도 비싸겠죠.

면서버 설치, 가상서버호스팅 vultr 서버 종류 선택 장면, Cloud Compute, High Frequency, Bere Metal, Dedicated Cloud의 4가지 종류를 선택 가능

2.1. 서버 위치 선택

서버 위치는 2020년 12월 6일 현재 18년 1월 현재 글로벌로 17군데가 있는데요. 아시아권에는 서울, 일본 도쿄 그리고 싱가폴에 있습니다.

주요 비즈니스 영역이 한국이라면 당연 서울을 선택하면 될 것 같습니다. 그렇지만 한국과 북미를 비슷한 비중으로 운영한다면 LA 지역도 좋을 것 같습니다.

서버 설치, 가상서버호스팅 vultr 서버 위치 선택 장면
▽ 서버 위치를 설정 장면

2.2. 서버 운영 체제

이번에는 서버 운영 체제를 선택합니다.
서버를 선택, 설치하는 데에는 여러가지 방법이 있는데요. 아래를 보시면 알겠지만 굉장히 다양한 방법을 제공하고 있습니다.

2.2.1. Vultr에서 제공하는 서버 운영 체제 설치 방법

첫째, 일반 프로그램 설치하듯이 자신에게 맞는 운영 체제를 선택해 설치하고, 이어서 필요한 프로그램을 설치하는 방식

둘째, Application이라고 해서 운영체제 + 제반 프로그램을 일괄 설치하는 방법

셋째, 다른 곳에서 만들어 놓은 ISO 파일을 업로드해서 그대로 사용하는 방법

넷째, Vultr에서 제공하는 ISO 파일을 그대로 사용하는 방법

다섯째, 이미 Vultr을 이용하는 상태라면 유료로 백업 서비스를 받고 있다면 이 백업 파일로부터 서버를 생성하는 방법

여섯째, 이미 Vultr을 이용하는 상태라면 기존에 만들어 놓은 Snapshot으로 그대로 서버를 떠주는 방법

Application 설치 방식은 운영 체제과 관련 프로그램을 한꺼번에 설치해주므로 편하긴 하지만 원하는 프로그램을 선택할 수 없고 최신 프로그램은 지원하지 않은 경우가 많습니다.

예를 들어 20년 12월 현재 wordpress 설치 Application은 우분투 18.04를 설치하도록 되어 있습니다. 센토스를 선택하거나 우분투(Ubuntu) 최신 버젼, 20.04 또는 20.10를 선택하고 싶다면 사용할 수 없지요.

전문가라면 다른 곳에서 만들어 놓은(제대로 잘 세팅된) ISO를 업로드 하는 것도 괜찮을 겁니다. 그렇지만 초심자에게는 너무 먼 이야기이지요.

Vuktr에서 제공하는 ISO는 일반 프로그램 설치와 거의 같은 방식입니다.

따라서 저는 일반 프로그램처럼 설치하는 첫번째 방식을 사용했습니다.

2.2.2. 32비트? 64비트?

윈도우즈도 32비트 64비트가 있듯이 리눅스계열도 32비트와 64비트로 나누어져 있습니다. 그래서 64비트를 설치할 것 인지, 32비트를 설치할 것 인지를 선택해야 합니다.

일반적으로 RAM이 512MB, 765MB 적을 경우 32비트를 설치하는 게 좋다고 하네요. 32비트가 최소 메모리를 사용하기 때문이라고 합니다.

그리고 최소 1GB정도 되어야 64비트가 아주 원활합니다. 실제로 워드프레스 등 운영 시 최소 메모리를 1GB로 권장하고 있습니다.

2.2.3. 어떤 운영 체제, 어떤 버전을 선택할 것인가?

운영체제를 무엇으로 할 것 인지도 고민인데요. 센토스나 우분투등이 일반적으로 많이 사용되므로 둘 중 하나를 고르면 됩니다. 저는 최근 뜨고 있다는 우분투를 선택했습니다.

우분투 버전을 선택해야하는데, 우분투는 16.04, 18.04 그리고 20.04 버젼이 출시 후 5년동안 지원하는 LTS 버젼이므로 가능하면 이를 선택하라고 조언하고 있습니다. 이외에 가장 최근에 나온 20.10을 사용해 볼 수 있습니다.

버젼별로 새로운 기능이 추가되기는 했지만 성능에 큰 영향을 미치지는 않은 것 같습니다. 최신이면서 오랬동안 지원되는 LTS 버젼을 사용하면 될 듯 합니다.

이 글을 업데이튼 하는 20년 12월 현재 저는 20.04 버전을 적용하고 하고 있습니다. Vultr는 항상 최신 버전을 설치할 수 있도록 빠르게 대응하고 있습니다. 국내 서버 업체들을 보면 대부분 최신 버전 지원 시기는 출시 한참 시간이 지낭 후 지원하는 것 같습니다.

최신 버전에 민감하고 이를 빨리 테스트해보고 싶다면 그런 의미에서 Vultr도 좋은 대안이 될 듯 하네요.

서버 운영체제로 우분투 버전 선택 모습

서버 설치, 가상서버호스팅 vultr 서버 운영체제 선택 장면

서버 운영체제를 어플리케이션과 함께 선택

서버 설치, 가상서버호스팅 vultr 서버 운영체제와 어플리케이션 선택 장면
▽ 서버 타입 선정 화면 – Application을 중심으로 선택, 설치 할 수 있다.
서버 설치, 가상서버호스팅 vultr 서버 운영체제 ISO 라이브러리에서 선택 장면
▽ 서버 타입 선정 화면 – Vultr에서 제공하는 ISO List에서 선택, 설치할 수 있다.

2.3. 플랜 결정 – 서버 크기

이 단계에서는 가장 중요한 가격대를 선택해야 합니다.
국내의 많은 웹호스팅과 마찬가지로 상위 플랜으로 업그레이드는 가능하지만, 다운그레이드는 허용하지 않기 때문에 처음에는 당장 사용할 수준 정도로 시작하고 점차 업그레이들 하면 좋습니다.

나중에 다시 정리하겠지만 상위 플랜으로 업그레이드는 서버를 유지한 채 버튼 하나만 눌러서 몇분 내에 끝납니다. 아주 쉽고 간단합니다.

저는 데이타베이스 크기가 300MB 정도이고 하루 방문객이 5,000명이 안되기 때문에 처음에 5$ 플랜으로 시작했었습니다. 아무래도 워드프레는 램을 비롯한 자원을 많이 사용하는 경향이 있어서 충분한 속도를 내기 위해서 4GB 램과 120GB 스토리지의 월 24$ 플랜으로 업그래이드 하려고 합니다.

▽ 서버 크기를 선정 화면

면서버 설치, 가상서버호스팅 vultr 서버 크기, 플랜 선택 장면
서버 설치, 가상서버호스팅 vultr 서버 크기, 플랜 선택 장면

2.4. 추가 기능 설정

이어서 추가 기능을 선택할 수 있습니다.

  • IPv6를 추가할 수 있고(무료)
  • 자동백업 선택(이는 요금 플랜의 20%가 붙습니다. 위에서 5$ 플랜을 선택 시 1$, 10$ 플랜을 선택 시 2$ 등)
  • DDOS Protection 항목이 있는데 이는 미국 일부 지역만 현재 가능하다고 함
  • Private Networking 선택, 이는 Vultr에 여러 개 서버를 운영하는 경우 서버별 내부 IP를 할당받아 내부 트랜지션을 할 수 있는 기능
서버 설치, 가상서버호스팅 vultr 서버 추가 기능(Additional Features) 선택 장면

3. 웹서버 보안 기본 설정

위에서 서버가 설치되면 가장 먼저 해야할 것이 바로 웹 서버 보안 설정입니다.

일반적으로 웹 서버 세팅이 끝난 후 보안 설정을 하는 경우가 있는데 그동안에는 무방비 상태이므로 가능하면 SSH에 처음 접속하는 순간부터 바로 보안 설정을 하도록 합니다.

3.1. ssh 포트 변경

일반적으로 ssh포트s는 22번으로 할당됩니다. 그렇기 때문에 너무 잘 알려쟜기 때문에 이를 이용해 공격해오는 경우가 있다고 합니다.

따라서 자기만 아는 포트 번호로 변경 사용하는 게 필요합니다. 이렇게 개인만 아는 포트로 변경하면 서버 공격이 확 줄어듭니다.

특정 서버를 목표로 공략한다면 또 다른 강력한 보안 정책이 더 필요하지만 일반적으로는 22포트를 기반으로 무작위적 공격하는 경우가 많기 때문에 포트 변경 시 상대적으로 공격을 덜 받을 수 있습니다.

22번 포트를 변경하려면 먼저 sshd_config에서 22번대신 사용할 포트 번호로 바꾸어 준다. 즉

/etc/ssh/sshd_config 에서 Port 22 를 찾아서 자기가 사용할 포트 숫자를 기억하기 쉽고 10,000자리이상에서 임의의 숫자를선택한다. 예를 들어 58722, 65322 등등

Port 번호는 1에서 65535 사이의 사용하지 않는 포트를 사용할 수 있습니다. 루트에서만 사용할 수 있는 권한있는 포트 (포트 1-1024)를 선택하는 것이 좋다는 의견이 있습니다만 저의 경우 루트를 10000이상 포트를 사용하는데 별다른 기능 사용 한계를 느낄 수 없었습니다.

nano /etc/ssh/sshd_config Code language: PHP (php)

아래는 ssh 포트로 26977을 사용하겠다고 수정한 경우입ㄴ다.

#Port 22
<span class="highlight">Port 26977</span>
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::Code language: PHP (php)

이렇게 포트를 변경한 후 ssh 서비스를 재시작 합니다.

service ssh restartCode language: PHP (php)

3.2. ssh 사용자 및 사용 ip 제한

더욱 더 강력한 조치는 ssh 사용자 또는 ip 자체를 제한하는 방법입니다.

특정 ip만 허용

저의 경우는 집에서 사용하는 ip와 태블릿에서 사용할 수 있는 ip만으로 제한했습니다. 다만 태블릿은 LTE 데이타를 사용하는 관계로 일정 ip대를 제한했는데요. 계속 변경되기 때문에 막히기 일수 입니다.

그러면 집에 가서 허용 ip를 변경해 주거나 급하면 vultr.com 계정 터미널 접속해 ip를 변경해 주어야 합니다. 아마 Vultr가 아닌 다른 회사들도 계정을 통해서 현재 접속 ip와 상관없이 서버에 접속할 수 있는 방법이 있을 것으로 보입니다.

항상 태블릿에서 사용할 필요가 없기 때문에 이런식으로 대응할 수 있지만 업무상 항상 접속해야 한다면 문제가 생기면 ip 제한을 푸는 방법도 고려해 볼 수 있습니다.

먼저 편집기를 이용해 /etc/hosts.allow에 접속합니다.

nano /etc/hosts.allowCode language: PHP (php)

여기에서 허용하려는 ip를 추가해 줍니다.

sshd:124.50.187.177
sshd:211.36.Code language: PHP (php)

그리고 나머지 ip는 모두 사용 중지 시킵니다. 이는 /etc/hosts.deny 파일을 수정합니다.

nano /etc/hosts.denyCode language: PHP (php)

여기에서 ALL을 추가합니다. 허용된 ip외는 모두 거부하라는 명령으로 아주 강력합니다.

sshd: ALLCode language: PHP (php)

3.3. 특정 사용자만 허용 또는 금지

또 sshd_config 파일에서 특정 사용자를 허용하든지 금지시킬 수 있습니다.

nano /etc/ssh/sshd_configCode language: PHP (php)

이 파일에서 아래처럼 AllowUsers 다음에 허용할 사용자를 추가합니다. 예를 들면 daisy 사용자만 추가한다면 다음과 같은 명령을 사용합니다.

AllowUsers daisyCode language: PHP (php)

4. 웹서버 보안 설정

여기에서는 웹서버 보안 설정 방법에 대해서 설명합니다.

우분투에서 기본적으로 사용할 수 있는 ufw를 사용할 수 있고 아니면 조금 더 정교하게 보안을 설정하기 위해서는 iptales을 이용할 수도 있습니다.

4.1. 웹서버 보안 ufw 설정

ufw는 우분투에서 제공하는 방화벽 도구로 아래에서 설명하는 iptales를 간단히 사용할 수 있도록 만든 것입니다.

운영체제별로 이와 같은 간단히 편하게 사용할 수 있는 보안 설정 방법을 제공하고 있습니다.

전는 아래에서 사용하는 iptales를 이용하려고 하기 때문에 기본적인 ufw 설명만 소개하고 넘어가도록 하겠습니다.

ufw enable # 방화벽을 활성화한다.
ufw allow 80/tcp  # 일반 웹 정보 관련 입출력 통로
ufw allow 443/tcp  # SSL 설치 시 웹 정보 관련 입출력 통로 
ufw allow 26977/tcp  # ssh용 신규 포트 위에서 개인적으로 설정한 포트 번호Code language: PHP (php)

4.2. 우분투에서 IPtables 사용하기

우분투에서는 기본 방화벽으로 UFW(Uncomplicated Firewall)를 사용하고 있습니다. UFW는 아주 간단하고 명료한 방화벽을 구성할 수 있고, 무엇보다도 쉽기 때문에 초보가 사용하기에 좋습니다.

그러나 UFW는 IPtables를 조금 더 편리하게 사용할 수 있도록 만든 것에 불과하므로 조금 더 복잡하고 디테일한 방화벽을 구성하려면 IPtables를 사용하는 것도 좋습니다.

IPtables 사용전에 UFW 사용 중지

처음 서버 세팅 시라면 UFW를 적용하지말고 바로 IPtables을 설치하면됩니다.

그러나 방화벽으로 UFW를 사용하다가 IPtables로 바꾼다면, 우분투 서버에서 Iptables를 설정하기 전에 먼저 UFW를 사용 중지합니다.

UFW 중지 명령은 아래와 같습니다.

ufw disableCode language: PHP (php)

그리고 UFW를 기반으로 설정되어 있는 방화벽 설정을 모두 초기화 시킵니다. 이는 UFW도 IPtables를 기본으로 활용하므로 아래와 같은 명령을 사용합니다.

iptables -FCode language: PHP (php)

IPtables를 안정적으로 사용하기 위한 패키지 설치

IPtables이나 Fail2Ban과 같은 보안 프로그램들은 다시 시작하면 기존 설정이 초기화됩니다. IPtables도 마찬가지로 시스템을 다시 시작한다든지 다시 시작하게되면 설정이 초기화됩니다.

최신 버전의 우분투(Ubuntu)에서 이는 특히 피할 수 없이 나타는 현상이므로 이를 해소할 수 있는 패키지를 설치합니다.

이러한 패키지로 추천되는 것이 바로 iptables-persistent입니다. 여기서는 이를 사용하도록 합니다.

그리고 netfilter-persistent도 같이 설치합니다. netfilter는 IPtabels를 이용하면서도 이를 뛰어넘을 솔류션으로 인기를 끌고 있다고 하네요.

apt-get install iptables-persistent netfilter-persistentCode language: PHP (php)

설치 도중에 ip4/ip6 저장 여부를 묻는데 yes를 선택합니다. 설정파일은 /etc/iptables 폴더에 저장됩니다.

이 설치를 마치고나면 /etc/iptables 라는 폴더에 rules.v4와 rules.v6가 생성됩니다.

IPtables 설정을 변경했다면 netfilter-persistent save 명령어로 저장하고, 나중에 netfilter-persistent reload 명령어로 다시 설정을 불러올 수 있습니다.

sudo netfilter-persistent save
sudo netfilter-persistent reloadCode language: PHP (php)

재부팅 후 iptables -S 로 정책이 유지되는지 확인해 봅니다. 혹시나 정책이 제대로 유지되지 않았다면 netfilter-persistent reload 명령으로 다시 방화벽 정책을 불러올 수 있습니다.

sudo  iptables -SCode language: PHP (php)

우분투 Iptables 기본 설정

이제 안정적으로 IPtables를 사용할 수 있게되었기 때문에 본격적으로 방화벽을 설정해 보기로 하죠.

일반적으로 아래와 같은 기본 설정등을 합니다.

established and related 접속 허용

일반적으로 네트워크 트래픽은 양방으로 흘러야 합니다. 때문에 established and related 접속 허용합니다.

sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -A OUTPUT -m conntrack --ctstate ESTABLISHED -j ACCEPTCode language: PHP (php)

loopback 허용

일반적으로 많은 소프트웨어들이 localhost 어댑터와 통신이 되어야 하기때문에 필요합니다.

sudo iptables -A INPUT -i lo -j ACCEPT Code language: PHP (php)

핑을 허용

만약 핑(ping)을 허용하려면 아래 명령을 추가합니다.

sudo iptables -A INPUT -p icmp -j ACCEPT  Code language: PHP (php)

HTTP/HTTPS 허용

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/SFTP용 포트

SSL/SFTP를 이용하기 위한 포트를 엽니다.

sudo iptables -I INPUT -p tcp --dport (SSL/SFTP용 포트) -j ACCEPT Code language: PHP (php)

INPUT과 FORWARD 차단

위에서 기본적인 것을 허용했기 때문에 나머지는 차단합니다.

sudo iptables -P INPUT DROP
sudo iptables -P FORWARD DROPCode language: PHP (php)

~

어느 정도 기본 설정을 했으면 저장합니다.

netfilter-persistent save Code language: PHP (php)

Iptables 방화벽 설정 방법에 대해서는 아래 글을 참조하세요.

5. Fail2ban을 설치하여 보안을 강화

로그를 분석해 의심스러운 접근을 금지시키는 방법이 DenyHosts나 Fail2Ban이라는 프로그램입니다.

이 중 Fail2ban은 DenyHosts보다 훨씬 진보된 방식으로 SSH, Apache, Courier, FTP 등등에서 의심스러운 접근을 차단할 수 있는 프로그램입니다.

Fail2ba은 로그 파일을 모니터링해서 넘 많은 패스워드 입력 실패나 공격 감행 징후들이 보이면 IP를 차단합니다.

예전에도 Fail2Ban을 소개한적이 있지만 오늘은 Fail2Ban을 보다 적극적으로 활용해 서버 보안을 한단계 업그레이드해보도록 하죠.

기본적으로 Fail2Ban 설치를 다시 해보면서 시작하도록 합시다.

apt-get install fail2banCode language: PHP (php)

5.1. Fail2Ban 설정 변경 옵션 설명

그 다음 설정을 변경합니다. 보통 세팅 시 다음과 같은 항목을 중점적으로 설정합니다.

  • ignoreip : 절대로 믿을 수 있는 white ip 리스트, 예를들어 관리자가 항상 접속하는 ip 등등
    이는 123.123.123.123/32와 같은 형태로 적고 스페이스바로 구분
  • bantime : 접속을 차단할 시간, 기본은 86400초
    영구 접속 차단을 원할 경우 -1을 사용
    영구 차단 또는 차단 시간을 길게 주면 재부팅시 fail2ban 다시 ip차단 리스트를 읽어오기 때문에 느려질 수 있다고 합니다. 그러나 요즘 서버 컴퓨터 성능도 좋아지고 있으므로 이는 어느정도 감수할 만한 수준으로 보여집니다.
  • findtime : 통계를 찾을 시간, 기본 10m
  • maxretry : 허용 fail 횟수, 기본은 5
  • banaction : ip 차단 방법
    이는 /etc/fail2ban/action.d 폴더에 있는 action을 입력할 수 있습니다.
    firewalld 을 사용한다면 “firewallcmd-new” 값 입력.
    iptables 을 사용한다면 “iptables-multiport” 값 입력.
    기본은 banaction = iptables-multiport로 설정되어 있음
  • banaction_allports
    기본은 iptables-allports
  • action : 알림 메일등을 받을 것인지 결정
    action에 “%(action_mw)s” 값 입력 시 ip차단하면 알림메일이 전송.
    알림메일을 받지않으려면 “%(action_)s” 값으로 변경
  • [sshd] enabled : sshd를 모니터링 할것인지 결정
    fail2Ban에서 가장 중요한 설정으로 설치 시 기본 사용토록 되어 있습니다.
    우분투에서는 /etc/fail2ban/jail.d 폴더에 있는 defaults-debian.conf에서 설정되어 있습니다.

5.2. 기본 설정 변경 파일

Fail2Ban의 기본 설정 파일은 /etc/fail2ban/jail.conf 입니다.

대부분 여기서 수정해도 문제가 없지만 몇가지 경우에는 업데이트 시 기본 설정 파일이 초기된다고 합니다. 예를 들어 yum을 사용해서 설치한 경우 yum업데이트 시 자동으로 기본 세팅으로 바뀝니다.

이럴경우 기본설정 파일을 직접 수정하지 않고, 기본 설정파일을 참조하여 새로 생성한 사용자 설정파일에서 설정해주는 방법으로 하면 업데이트가 되는 경우에도 사용자 설정 파일을 덮어쓰지 않게 됩니다.

이 파일은 /etc/fail2ban/jail.d 폴더에 위치하게 됩니다. 보통 local.conf라는 이름으로 많이 사용하네요.

우분투를 설치하면 defaults-debian.conf를 수정하면 됩니다.

nano /etc/fail2ban/jail.d/defaults-debian.confCode language: PHP (php)
[wordpress]
enabled  = true
port     = http,https
filter   = wordpress
action   = iptables-multiport[name=wordpress, port="http,https", protocol=tcp]
logpath  = /var/log/nginx/access.log
maxretry = 3
findtime  = 86400
bantime  = -1Code language: PHP (php)

보다 자세한 Fail2Ban 설정 방법에 대해서는 아래 글을 참조하세요.

6. 기본 확인

6.1. 쉘 기본 언어값 확인

거의 가능성이 없기는 한데 쉡 기본 언어가 영어가 아닌 다른 특정 언어로 된 경우가 있다고 합니다. 저는 한번도 본적이 없습니다만.

그래서 제일 먼저 쉘 기본 언어값 확인합니다. apache2 명령어을 적용 시 영어로만 나오면 그냥 넘어가고 중국어나 일본어 나온다면 영어로 바꾸면 됩니다.

apache2Code language: PHP (php)

이번 작업의 경우 아래처럼 영어로 나와서 문제없이 넘어갈 수 있습니다.

Command 'apache2' not found, but can be installed with:
apt install apache2-binCode language: PHP (php)

만약 영어가 아닌 다른 언어가 나온다면 /etc/default/locale 의 파일 내용을 변경한다.

# vi /etc/default/localeCode language: PHP (php)

에서 아래 내용을 반영한다.

LANG="en_US.UTF-8"
LANGUAGE="en"Code language: PHP (php)

6.2. 현 운영체제의 프로그램을 최신으로 업데이트

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

6.3. 시스템 시간 설정

여기는 서버 시스템의 시간을 한국 시간에 맞춥니다.

dpkg-reconfigure tzdataCode language: PHP (php)

GUI 환경에서 Asia를 선택하고 이어서 Seoul을 선택합니다. .

서버 시간 세팅_Seoul

그러면 아래와 같은 결과를 출력하죠.

Current default time zone: 'Asia/Seoul'
Local time is now:      Mon Jun 18 21:57:36 KST 2020.
Universal Time is now:  Mon Jun 18 12:57:36 UTC 2020Code language: PHP (php)

6.4. 메일 발송 프로그램 설치하기

메일을 발송할 수 있는 sendmail 프로그램을 설치, 압축 해제 프로그램 그리고 SSL을 위한 letsencrypt도 같이 설치합니다.

다만 메일발송 프로그램으로 요즘 핫하다는 Postfix를 이용한다면 여기서 설치할 필요는 없습니다.

메일 발송 프로그램은 시간이 조금 걸립니다. 잘못되었나 걱정하지 말고 인내를 가지고 기다리면 됩니다. 그렇다고 몇분이상 걸리는 것을 아닌데 다른 프로그램에 비해서 조금 더 걸립니다.

apt-get install sendmail unzip  letsencrypt -yCode language: PHP (php)

6.5. APT 소스리스트에 Nginx, MariaDB 저장소 추가

이는 웹서버 nginx와 PHP 그리고 데이타베이스 프로그램인 MariaDB를 설치하고 이후 업데이트 유지를 위해 원본 소스를 받아오기 위해서 sources.list를 업데이트 합니다.

이는 sources.list 파일을 열어서 파일 맨 끝에 소스리스트를 추가합니다.

nano /etc/apt/sources.listCode language: PHP (php)

파일 맨 끝에 아래 내용 추가

# Nginx로부터 NGINX 설치
# https://www.nginx.com/resources/wiki/start/topics/tutorials/install/
deb http://nginx.org/packages/mainline/ubuntu/ focal nginx
deb-src http://nginx.org/packages/mainline/ubuntu/ focal nginx


# MariaDB 10.5 repository list - created 2020-07-10 13:10 UTC
# http://downloads.mariadb.org/mariadb/repositories/
deb [arch=amd64] http://mirror.yongbok.net/mariadb/repo/10.5/ubuntu focal main
deb-src http://mirror.yongbok.net/mariadb/repo/10.5/ubuntu focal mainCode language: PHP (php)

6.6. 각 저장소 보안키 다운로드 후 시스템에 등록

우선 nginx 보안키 다운로드 후 적용합니다.

cd /root 
wget http://nginx.org/keys/nginx_signing.key && 
apt-key add nginx_signing.key 
rm nginx_signing.keyCode language: PHP (php)

다음으로는 MariaDB 보안키 다운로드 후 적용합니다.

아래는 MariaDB 재단에서 제공하는 Ubuntu 20.04에서 MariaDB를 설치하는 명령어입니다.

sourcelist에서 PPA와 키를 등록하지 않았다면 아래 명령을 사용합니다.

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] http://mirror.yongbok.net/mariadb/repo/10.5/ubuntu focal main'Code language: PHP (php)

다음으로는 PHP 저장소 추가 및 보안키 등록합니다.

apt-get install software-properties-common

add-apt-repository ppa:ondrej/phpCode language: PHP (php)

add-apt-repository ppa:ondrej/php를 실행하면 여기서 아래와 같은 메세지가 나오면서 엔터를 치라는 메세지가 나오는데요. 고민하지말고 엔터를 치면됩니다.

추가된 보안키 목록을 보려면 아래 명령어를 사용합니다.

apt-key listCode language: PHP (php)

지금까지 작업한 APT 패키지 정보를 업데이트 합니다.

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

7. Nginx 설치

여기에서는 웹서버로 Nginx를 설치하기 했으므로 Nginx를 설치하고 nginx를 다시 가동(restart)시킵니다.

일반적으로 웹서버는 NGINX가 작은 자원을 가지고 효율적으로 운영될 수 있어서 처름 시작하는 소규모 사이트에서 각광을 받고 있으며 아파치(Apache)는 기준 풍부한 운영 경험을 토대로 대규모 사이트에서 선호된다고 합니다.

예전에서는 웹서버로 아파치를 가장 많이 사용했지면 최근 들어서는 가볍고 효율성이 좋은 NGINX가 가장 많이 사용하는 웹서버가 되었습니다.

코로나 팬데믹으로 쇼핑 사이트드링 증가해서인지 모르지만 지난 2020년 8월인가를 기점으로 NGINX가 가장 높은 점유율을 가진 웹서버로 등극했더군요. 2020년 11월 기준 NGINX 점유율 34%로 27%에 그친 아파치를 여유롭게 리드하고 있습니다.

웹서버 종류별 점유율 추이( ~2020년 11월), Graph by NETCRAFT
웹서버 종류별 점유율 추이( ~2020년 11월), Graph by NETCRAFT

Nginx를 설치하고 nginx를 다시 가동(restart)시킵니다.

apt-get install nginx 
service nginx restart 
nginx -v Code language: PHP (php)

7.1. nginx와 관련 몇 가지 이슈

최근 우분투 20.04에서 nginx를 재구동 하면 이미 메모리가 사용되고 있다고 하면서 nginx가 구동되지 않는 현상을 흔하지는 않지만 만날 수 있었습니다.

이 경우 메모리를 점유하고 있는 프로그램을 보니 apache2관련 된 것이라 apache2를 중단시켜 줍니다.

nginx를 설치해도 apache 기본 파일은 설되어 있더군요.

sudo /etc/init.d/apache2 stopCode language: PHP (php)

또 Nginx가 마스크되었다는 메세지와 함께 작동하지 않는 경우를 만날 수도 있습니다. 흔하지는 않습니다.

Failed to restart nginx.service: Unit nginx.service is masked.

이에 대한 해결책은 unmask는 것이라고 합니다. 아래 명령어를 사용합니다.

sudo systemctl unmask nginx.serviceCode language: PHP (php)

그리고 nginx를 다시 가동 시킵니다.

sudo systemctl start nginx
sudo systemctl enable nginxCode language: PHP (php)

7.2. NGINX 설정

다음 명령어를 사용해 기본 nginx 설정을 합니다.

sudo nano /etc/nginx/nginx.confCode language: PHP (php)

여기서 user nginx;를 user www-data;로 변경합니다.

저장 후 NGINX를 다시 시작합니다.

sudo systemctl reload nginxCode language: PHP (php)

8. PHP 8.0설치

지난 2020년 11월 26일 드디어 PHP 8.0이 발표되었기 때문에 여기에서는 PHP 8.0을 기준으로 설치합니다. PHP 최신 버전은 아래 링크에서 확인해 볼 수 있습니다.

PHP 최신 다운로드 버젼 확인 하러 가기

8.1. PHP 8 설치를 위한 PPA 등록

이는 앞에서 설명했기 때문에 별도로 자세한 설명을 생략합니다. 혹시 PPA 등록이 안되어 있다면 아래 명령어를 사용합니다.

sudo add-apt-repository ppa:ondrej/php 
sudo apt-get updateCode language: PHP (php)

8.2. PHP 8 기본 설치

다른 php 패키지와 마찬가지로 php 8 패키지는 “php8.0-NAME”과 형식으로 이름이 붙습니다.

php 8 기본 패키지 이름은 php8.0-common인데요. 여기에는 php8.0과 같은 기본 프로그램이 포함되어 있습니다.

그리고 php 8 패키지를 한번에 여러가지 설치 시 패키지 이름을 한 칸 띄워 적으면 됩니다. 아래는 php 8 기본 패키지와 CLI 패키지를 같이 설치할 때 아래와 같은 방식으로 적용합니다.

sudo apt install php8.0-common php8.0-cli -yCode language: PHP (php)

위 명령어는 위에서 설명한 대로 php8.0-common 명령에 따라 몇 가지 php 8 기본 패키지와 CLI 패키지를 설치합니다

PHP 8 로고와 데비안 및 우분투 로고 php 8 vs debian vs ubuntu logo
PHP 8 로고와 데비안 및 우분투 로고 php 8 vs debian vs ubuntu logo

8.3. PHP 8 서버 API 설치

사용하는 웹서버에 따라 php 8과 웹서버를 통합할 추가 패키지를 설치합니다.

웹서버로 NGINX를 사용 시 아래와 같이 php8.0-fpm을 설치합니다.

sudo apt install php8.0-fpmCode language: PHP (php)

8.4. PHP 8 extensions

이어서 php 8 추가 확장 프로그램(extensions)을 설치합니다.

여기서 PHP7에서 설치해야 했던 json을 따로 설치할 필요가 없어졌습니다. PHP 8에서는 php8.0-json이 기본으로 포함되어 있습니다.

sudo apt install php8.0-{bcmath,bz2,cgi,cli,curl,dba,dev,enchant,fpm,gd,gmp,imap,interbase,intl,ldap,mbstring,mysql,odbc,opcache,pgsql,phpdbg,pspell,readline,snmp,soap,sqlite3,sybase,tidy,xml,xmlrpc,zip,,xsl}Code language: PHP (php)

8.5. php handler 수정

NGINX를 사용한다면 php handler에서 서버 API를 연결하도록 되어 있는데요. 여기서 php 8로 변경 설정해야 합니다.

nginx에서 변경해야 하는 파일은 /etc/nginx/conf.d/default.conf 인데요.

사람에 따라선 이를 다른 이름으로 사용하는 분도 있습니다. 여러 개의 사이트를 운영하는 경우 사이트명을 변경하는 경우도 있습니다. 저도 이를 happist.com.conf라는 이름으로 사용하고 있습니다.

이 파일에서 fastcgi_pass unix:/run/php/php7.4-fpm.sock; 을 fastcgi_pass unix:/run/php/php8.0-fpm.sock;으로 바꾸어줘야 합니다. 그래야 php8.0을 인식하고 php8.0으로 작동합니다.

# Add PHP handler
    location ~ \.php$ {

    try_files $uri =404; # comment out this line if php-fpm is hosted on a remote machine
    include /etc/nginx/fastcgi.conf;
    fastcgi_cache WORDPRESS;
    # add_header X-Cache $upstream_cache_status;
    # fastcgi_pass unix:/run/php/php7.4-fpm.sock;   --> 아래로 변경
    <span class="highlight">fastcgi_pass unix:/run/php/php8.0-fpm.sock;</span> 
    fastcgi_no_cache $skip_cache;

    fastcgi_split_path_info ^(.+?\.php)(/.*)$;
    if (!-f $document_root$fastcgi_script_name) {
        return 404;
        }
    }Code language: PHP (php)

이렇게 php handler 수정이 끝나면 php8.0-fpm을 재가동합니다.

systemctl restart nginx.service php8.0-fpm.serviceCode language: PHP (php)

8.6. php.ini 파일 수정

PHP 8 설치가 끝났으면 php 설정을 변경합니다. 파일 수정은 fpm 폴더의 php.ini를 수정합니다.

nano /etc/php/8.0/fpm/php.iniCode language: PHP (php)
  • date.timezone을 찾아 Asia/Seoul로 변경
  • cgi.fix_pathinfo=0 값으로 변경
  • 쿠키값 보안을 위해서 session.cookie_httponly 와 session.cookie_secure 값을 1을 준다.

php.ini 파일 수정이 끝나면 PHP-FPM service를 다시 시작합니다.

systemctl restart php8.0-fpm.serviceCode language: PHP (php)

9. MariaDB 설치

안정화된 MariaDB는 10.5까지 출시되어 있습니다.

MariaDB Downloads, Setting up MariaDB Repositories

9.1. MariaDB 10.5 설치

위에서 키와 저장소 정보를 가져오게 되면 아래 명령어로 MariaDB를 설치할 수 있습니다.

아래는 소스리스트에 MariaDB repository가 등록되지 않았다면 아래 명령어로 등록 가능합니다.

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] http://mirror.yongbok.net/mariadb/repo/10.5/ubuntu focal main'Code language: PHP (php)

아래 명령으로 MariaDB를 설치합니다. 그 이전에 먼저 업데이트를 시작합니다.

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

예전 MariaDB 버전 설치 시 설치 도중에 mysql 비밀번호 설정 화면이 나왔지만 최근 10.4부터는 그런 화면이 나오지 않습니다.

MariaDB는 서버 관리자와 권한을 공유하기로 정책을 변경했기 때문입니다.

9.2. PHP-FPM에 DB 연동관련 모듈설치

apt-get install php8.0-mysqlCode language: PHP (php)

기본 언어셋 설정

이는 매우 중요한 세팅으로 반드시 필요합니다. 우분투 18.04부터는 위치가 조금 바뀌었습니다.

예전에는 my.cnf 파일을 직접 편집하도록 되어 있지만 지금은 mariadb.cnf를 편집하면 my.cnf에 그대로 반영됩니다.

nano /etc/mysql/mariadb.cnfCode language: PHP (php)

아래 내용으로 변경한다.

# MariaDB-specific config file.
# Read by /etc/mysql/my.cnf

[client]
 Default is Latin1, if you need UTF-8 set this (also in server section)
 default-character-set = utf8mb4
 [mysqld]
 #
 * Character sets
 #
 Default is Latin1, if you need UTF-8 set all this (also in client section)
 #
 character-set-server = utf8mb4
 collation-server = utf8mb4_unicode_ci
 character_set_server = utf8mb4
 collation_server = utf8mb4_unicode_ciCode language: PHP (php)

변경 내용을 반영해 DB를 다시 시작합니다.

service mysql restartCode language: PHP (php)

9.3. Nginx와 PHP-FPM 연결

nginx는 기본적으로 nginx 사용자 권한으로 실행되고, PHP-FPM 프로그램은 기본적으로 www-data 사용자 권한으로 실행되므로 둘의 사용자 권한을 www-data로 일치시킨다.

nano /etc/nginx/nginx.confCode language: PHP (php)
  • user nginx; 를 user www-data; 로 변경
  • worker_processes 1; 를 worker_processes auto; 로 바꾼다. 고사양 서버에서 성능이 더 좋아진다고. 일반적으로 트래픽이 적은면 1을 사용하고 트래픽이 많아지면 auto를 사용한다.
service nginx restartCode language: PHP (php)

9.4. fastcgi_params 내용 수정

fastcgi_params를 열어서 아래 내용으로 변경합니다.

nano /etc/nginx/fastcgi_paramsCode language: PHP (php)

아래와 같이 변경
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 등이 추가하라고 합니다.

fastcgi_param   QUERY_STRING            $query_string;
fastcgi_param   REQUEST_METHOD          $request_method;
fastcgi_param   CONTENT_TYPE            $content_type;
fastcgi_param   CONTENT_LENGTH          $content_length;

fastcgi_param   SCRIPT_FILENAME         $document_root$fastcgi_script_name;
fastcgi_param   SCRIPT_NAME             $fastcgi_script_name;
fastcgi_param   PATH_INFO               $fastcgi_path_info;
fastcgi_param   PATH_TRANSLATED         $document_root$fastcgi_path_info;
fastcgi_param   REQUEST_URI             $request_uri;
fastcgi_param   DOCUMENT_URI            $document_uri;
fastcgi_param   DOCUMENT_ROOT           $document_root;
fastcgi_param   SERVER_PROTOCOL         $server_protocol;

fastcgi_param   GATEWAY_INTERFACE       CGI/1.1;
fastcgi_param   SERVER_SOFTWARE         nginx/$nginx_version;

fastcgi_param   REMOTE_ADDR             $remote_addr;
fastcgi_param   REMOTE_PORT             $remote_port;
fastcgi_param   SERVER_ADDR             $server_addr;
fastcgi_param   SERVER_PORT             $server_port;
fastcgi_param   SERVER_NAME             $server_name;

fastcgi_param   HTTPS                   $https;

# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param   REDIRECT_STATUS         200;Code language: PHP (php)

10. Let’s Encrypt SSL인증서 발급 – 서버를 통한 발급

Let’s Encrypt SSL인증서 발급 방법에는 여러가지가 있으나 여기에서는 서버를 통한 발급 방법을 선택합니다. 제가 여러 방법으로 설치해 보았는데 서버를 통한 Let’s Encrypt SSL인증서 발급이 가장 안정성이 높았습니다.

다른 방법을 적용 시 S전자와 같은 회사 방화벽과 충돌이 나서인지 사이트를 이용할 수 없는 경우가 발생했었습니다.

그리고 Let’s Encrypt SSL인증서 발급을 위해서 일부에서 안내하는 것 처럼 certbot을 추가로 설치할 필요가 없습니다. 앞에서 letsencrypt를 설치했다면 이를 이용하면 됩니다.

먼저 nginx를 중단시킵니다. 이는 인증서 설치 시 80포트를 사용하지 않도록 하기 위해 nginx를 중단 시키는 것이라고 해요.

service nginx stop   Code language: PHP (php)

그리고 certbot 명령으로 SSL 인증서를 발급하도록 합니다. 가장 안정적인 옵션이 certonly라서 이를 사용합니다.

certbot certonly --standalone -d happist.com -d www.happist.com Code language: PHP (php)

인증서 발급이 성공적으로 끝나면 다시 nginx를 가동 시킵니다.

service nginx restartCode language: PHP (php)

이 명령을 사용해서 여러 사이트를 동시에 인증받을 수 있습니다.

하지만 인증 파일이 특정 폴더에 한 파일로 묶여버리기 때문에 나중 관리가 어려울 수 있습니다.

따라서 사이트마다 별도로 폴더를 만드려면 따로 따로 인증 명령을 주어야 합니다.

Let’s Encrypt SSL 인증서의 만료일자 확인하기

아래 명령어를 사용합니다.

echo | openssl s_client -connect [your-hostname]:443 2>/dev/null | openssl x509 -noout -datesCode language: PHP (php)

DH Param 생성, 적용하기

앞의 작업으로 인증서 설치는 끝나지만 보다 보안을 강화하기 위해서 DH Param 생성합니다.

mkdir /etc/nginx/ssl  
cd /etc/nginx/ssl
openssl dhparam -out dhparams.pem 4096 

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

nginx conf 파일에 추가

인증서를 획득하는게 중요한게 아니고 얼마나 철저한 암호화 설정을 하느냐가 중요하기에 암호화 알고리즘을 적용합니다.

이 중에서 중요한 것은 ssl_ciphers인데요. 이에 대해서는 모질라 재단에서 제공하는 SSL Configuration Generator를 사용하면 좋을 것 같습니다.

여기에서는 nginx 1.17.7을 기준으로 보안 설정을 추천하고 있습니다. 여기서는 NGINX 기준으로 모던 브라우저와 올드 브라오져 중간에 있는 Intermediate를 선택해 설정한 내용을 여기에 옮겨 봅니다.

server {
     listen 443 ssl http2;
     listen [::]:443 ssl http2;

     <code>ssl_certificate /path/to/signed_cert_plus_intermediates; </code>
     <code>ssl_certificate_key /path/to/private_key; </code>
     <code>ssl_session_timeout 1d; </code>
     <code>ssl_session_cache shared:MozSSL:10m;  # about 40000 sessions </code>
     <code>ssl_session_tickets off; </code>

     <code># curl https://ssl-config.mozilla.org/ffdhe2048.txt > /path/to/dhparam </code>
     <code>ssl_dhparam /path/to/dhparam; </code>

    <code># intermediate configuration </code>
    <code>ssl_protocols TLSv1.2 TLSv1.3; </code>
    <code>ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; </code>
    <code>ssl_prefer_server_ciphers off; </code>

    <code># HSTS (ngx_http_headers_module is required) (63072000 seconds) </code>
    <code>add_header Strict-Transport-Security "max-age=63072000" always; </code>

    <code># OCSP stapling ssl_stapling on; </code>
    <code>ssl_stapling_verify on; </code>

    <code># verify chain of trust of OCSP response using Root CA and Intermediate certs</code>
    <code>ssl_trusted_certificate /path/to/root_CA_cert_plus_intermediates; </code>

    <code># replace with the IP address of your resolver </code>
    <code>resolver 127.0.0.1;</code>
 }Code language: PHP (php)

SSL 인증서 발급 관련해 보다 자세한 내용을 아래 글을 참조해 보시면 좋을 것 같습니다.

참고 Let’s Encrypt SSL인증서 발급 관련 참고 – 1주일에 5번만 발급 가능

서버를 세팅하다보면 본의아니게 서버 설치를 반복하게 됩니다.

이런 저런 문제를 해결하고자 고민하다 문제 원인을 못 잡으면 다시 설치하고 또 다시 설치하고를 반복하게 되죠.

그런데 Let’s Encrypt SSL인증서는 1주일에 5번까지 발급 받을 수 있도록 제한되어 있습니다. 여러번 시행 착오를 통해서 5번이 넘어서면 아래와 같은 메세지가 나오면서 발급이 안됩니다.

An unexpected error occurred:
There were too many requests of a given type :: Error creating new cert :: too many certificates already issued for exact set of domains: test.com www.test.comCode language: PHP (php)

참고하시기 바랍니다.

11. FastCGI 캐시를 메모리에서 작동시키기

nano  /etc/fstabCode language: PHP (php)

fstab에서 아래와 같이 RAM 디스크를 등록해 줍니다.

tmpfs /dev/shm/fastcgi tmpfs defaults,size=1024M 0 0Code language: PHP (php)

다음에는 RAM Disk를 구성할 디렉토리와 소유권등을 정리해 줍니다. RAM Disk로 /dev/shm/fastcgi를 만들겠습니다.

mkdir /dev/shm/fastcgi
chown www-data:www-data /dev/shm/fastcgi
chmod +x /dev/shm/fastcgiCode language: PHP (php)

이러면 자동으로 디렉토리를 만들게 됩니다.
그리고 나서 NGINX 시스템을 다시 실행합니다. –> 이제 새로운 RAM Disk를 마운트합니다.

service nginx restart
mount -a  
df -h  # 메모리 및 저장 공간 사용 현황을 보여줍니다. Code language: PHP (php)

참고로 RAM Disk를 없애려면 /etc/fstab에서 Ram 디스크를 지우고, 터미널에서 umount 명령을 사용합니다.

umount /dev/shm/fastcgiCode language: PHP (php)

Object Cache Redis

조금 더 성능을 강화하기 위해서는 Object Cache를 설치하면 도움이 됩니다. 그렇지만 워드프레스에서 이 Object Cache를 할용하려면 별도 플러그인을 사용하라고 하는데요.

이 플러그인들은 워드프레스 업데이타나 PHP 업그레이드 등에서 충돌을 일으키는 경우가 종종 있어 불안정 합니다.

저도 사용하다가 지금은 중단한 상태입니다. 참고로만 보시기 바랍니다. PHP 8.0에서는 에러를 내기 때문에 조금 더 안정화되기를 기다리면 좋을 것 같습니다.

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

워드프레스에서 이 오브젝트 캐시를 사용하려면 edis Object Cache 플러그인을 사용합니다. Redis Object Cache by Till Krüss가 추천된다고 합니다.

[참고] MySQL tmp 디렉토리를 램에 올리면 안되는 이유

mysql을 최적화해도 상당수의 데이타를 처리하기 위해서 디스크에 temp 파일을 저장하면서 사용합니다.

이를 막기 위해서 tmp 폴더를 램으로 지정해 주는 것을 추천했었는데요. 이는 에러 요인이 되기 때문에 tmp 디렉토를 메모리에 올리면 안됩니다.

처음에는 아애 소개하는 방법대로 /tmp 디렉토리를 메모리에 올려 사용했으나 치명적인 문제는 없지만 지속적으로 에러가 발생한다는 것을 알았습니다.

여러 번 시행 착오와 error log 분석을 통해서 결국 리눅스 tmpfs 파일시스템은 일부 임시 파일생성을 허용하지 않기 때문에 에러가 발생하다는 사실을 확인하고 임시 파일 폴더를 메모리에 올리는 것을 포기 했습니다.

제가 받은 에러 메세지는 리눅스 커널에서 MariDB가 tmpfs 파일시스템에서 일부 임시 파일 생성하는 것을 허용하지 않아 에러가 발생하는 “mariadbd: O_TMPFILE is not supported on /dev/shm (disabling future attempts)” 였습니다.

아래는 기록용으로 잘못 가이드 내용을 휘소선을 추가해 남겨 놓았습니다.

이 폴더의 권한을 mysql이 사용할 수 있도록 변경합니다.

<s>chown mysql:mysql /dev/shm/mysql</s>Code language: PHP (php)

그리고 mysql 설정 파일에서 tmp 폴더를 변경합니다.

<s>nano /etc/mysql/my.cnf</s>Code language: PHP (php)
<s>[mysqld]
tmpdir = /dev/shm</s>Code language: PHP (php)

마지막으로 mysql을 다시 가동 시킵니다.

<s>service mysqld restart  

or

service mysql restart</s>Code language: PHP (php)

12. 워드프레스 설치

지금부터는 워드프레스를 설치해 보도록 하겟습니다.

12.1. 루트 폴더(document root) 지정

워드프레스를 설치하려면 어떤 위치에 설치할 것 인지를 정해야 합니다. 그리고 위치 폴더를 만들고 그 폴더 소유권을 변경합니다.

예를 들어 /home/etrend라는 위치에 워드프레스를 설치한다고 해보죠.

우선 워드프레스를 설치할 폴더를 만듭니다.

mkdir /home/etrend Code language: PHP (php)

다음으로는 폴더 소유권을 root에서 nginx로 바꿉니다. 그래야 nginx가 제대로 작동하면서 작업을 할 수 있습니다.

chown -R www-data:www-data /home/etrend/ Code language: PHP (php)

다음으로는 폴더 전체 권한을 755로 변경합니다.

chmod -R 755  /home/etrend/  Code language: PHP (php)

12.2. 워드프레스 설치를 위한 DB 생성

워드프레스가 사용한 데이타베이스를 만듭니다. 이는 아래 명령어를 사용합니다.

우선 mysql로 진입합니다. MariaDB 최근 버전부터는 시스템 비밀번호를 공유하기 때문에 이미 시스템에 들어와 있으면 별다른 비밀번호가 필요하지는 않습니다.

mysqlCode language: PHP (php)

아래와 같은 명령어를 사용해 db이름과 db 사용자 및 비밀번호를 등록합니다.

CREATE DATABASE wp; 
CREATE USER username@localhost; 
SET PASSWORD FOR happist@localhost= PASSWORD('password'); 
GRANT ALL PRIVILEGES ON wp.* TO username@localhost IDENTIFIED BY 'password'; 
FLUSH PRIVILEGES;Code language: PHP (php)

백업 방법

데이타베이스 백업은 아래와 같은 명령을 사용합니다.

mysqldump --opt --single-transaction -u username -ppassword dbname > backup_file_name.sql Code language: PHP (php)

복원 방법

위에서 백업 받은 데이타베이스는 아래 명령을 사용해서 복원할 수 있습니다.

mysql -u username -ppassword dbname < backup_file_name.sql Code language: PHP (php)

12.3. 워드프레스 설치

이제 워드프레스를 설치해 보시죠. .

워드프레스 관련 디렉토리 소유권을 nginx인 www-data로 넘겼지만 가끔 플러그인들이 제대로 설치가 안되는 경우도 나타납니다.

이럴 경우는 플러그인 설치 시 만들어진 폴더에 제대로 된 권한 부여가 안된 상태인 경우가 대부분입니다.

이때는 다시 한번 파일 권한 명령을 주면 대부분 해결됩니다.

chown -R www-data:www-data /home/etrend/ 
chmod -R 755  /home/etrend/  Code language: PHP (php)

워드프레스 파일 받아 설치하기

워드프레스 한국 버젼은 워드프레스의 공홈이라하 할 수 있는 https://ko.wordpress.org에서 다운 받을 수 있습니다.

워드프레스 최신 버젼을 릴리즈 하는 곳

우선 워드프레스를 설치하려는 폴더로 이동합니다. 위에서 이야기한 대로 /home/etrend에 설치한다고 해보죠,

cd /home/etrendCode language: PHP (php)

여기에서 최신 버젼의 워드프레스를 다운 받아 압추을 풉니다.

wget https://wordpress.org/latest.tar.gz

tar -xzf latest.tar.gzCode language: PHP (php)

그러면 /home/etrend/wordpress라는 폴더가 생기고 여기에 워드프레스 관련 파일들이 생깁니다.

그러면 이 파일 및 하위 폴더들을 전부 설치 폴더인 /home/etrend로 복사하도록 하죠.

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

cp -r /home/etrend/wordpress/*  /home/etrendCode language: PHP (php)

그리고 다운받은 워드프레스 파일 및 wordpress 폴더를 삭제합니다.

rm -rf /home/etrend/wordpress Code language: PHP (php)

다시 한번 파일 권한을 지정합니다. 워드프레스에서 권장하는 권한은 폴더의 경우는 755 파일들은 644이며 wp-config.php파일은 매우 중요한 정보를 담고 있으므로 660으로 제한하고 있습니다.

chown -R www-data:www-data /home/etrend

find . -type f -exec chmod 644 {} +
find . -type d -exec chmod 755 {} +
chmod 660 wp-config.phpCode language: PHP (php)

12.4. nginx 설정에서 루트 폴더 지정

워드프레스 설치 위치가 정해지고 여기에 워드프레스 설치 파일들을 복사해 놓았다면 웹서버 nginx에서 이 위치를 루트 디렉토리로 지정해 줍니다.

기본적으로 루트 디렉토리는 /usr/share/nginx/html로 되어 있습는데요. 이를 설치하고자 하는 /home/etrend로 변경합니다.

그래야 nginx가 이곳에 와서 워드프레스 파일들을 실행시킵니다.

nano /etc/nginx/conf.d/도메인주소Code language: PHP (php)

여기서 아래와 같은 내용으로 변경합니다.

server_name happist.com www.happist.com;
root   /home/etrend;Code language: PHP (php)

12.5. 워드프레스 설치

워드프레스 설치파일을 /home/사용자계정/www에 올려놓았다면 인터넷상에서 사이트 주소를 치면 바로 워드프레스 설치 화면으로 들어 갑니다.

여기까지왔다면 거의 성공한 것이나 마찬가지 입니다.

여기서부터는 그 유명한 워드프레스 5분 설치가 가능합니다. 기존에 준비했던 정보들을 입력하면서 진행하면 됩니다.

아래 설치 단계별 이미지를 순서대로 소개한다. 이를 참조하면 된다.

워드프레스에 오신 것을 환영합니다.

처음으로 나오는 화면

워드프레스 설치 시작 화면_워드프레스에 오신 것을 환영합니다.

데이타베이스 연결 설정

위 장면에서 let’s go를 누르면 아래 화면이 나옵니다. 여기에서 데이타베이스 연결을 위한 세팅합니다.

  • db name
  • db user
  • 비밀번호
  • 데이타베이스 호스트 대개 그냥 localhost를 사용한다.
  • 데이타베이스 접두어, wp를 대부분 사용하는 듯
워드프레스 설치 시작 화면_데이타베이스 연결 설정

데이타베이스 설치과정 완료

데이타베이스 세팅이 완료되면 아래와 같이 설치과정을 마쳤다는 메세지가 나온다.
정말로 간단하게 설치가 끝난 것이다.

워드프레스 설치 시작 화면_데이타베이스 설치과정 완료

워드프레스 5분 설치과정에 오신 것을 환영합니다.

위에서 데이타베이스 설정이 끝나면 바로 본격적인 워드프레스 설치과정이 시작된다.
이 단계가 너무 쉽고 간단하기때문에 워드프레스에서는 5분 워드프레스 설치 과정이라고 홍보하고 있다.

여기에서는 관리자가 필요한 항목들을 입력하고 워드프레스 설치하기를 누른다.

  • 사이트제목
  • 사용자명
  • 비밀번호
  • 이메일주소
워드프레스 설치 시작 화면_워드프레스 5분 설치과정에 오신 것을 환영합니다

워드프레스 설치 완료

그러면 몇분 걸리지 않아 워드프레스가 설치되고 대시보드 화면이 나타납니다.

이제부터는 정상적으로 워드프레스로 사이트를 운영하면 됩니다.

워드프레스 설치성공 후 첫 시작 화면05

워드프레스 세팅

워드프레스가 설치 되었으면 몇가지 세팅 합니다.

  • 먼저 고유주소를 세팅, SEO에 좋다고 누가 그래서 ID와 이름으로 고유주소를 만들었다. 이는 생각보다 길어지고 한글 문제는 속을 썩힌다. – /%post_id%/%postname%/
  • 적절한 테마 설정
  • 테마에 따른 위젯 등 설정

12.6. 워드프레스 설치 시 가끔 나오는 에러들

워드프레스 설치 시 후 완전히 세팅되기 전에 만날 수 있는 몇가지 에러를 정리해 봤습니다.

FTP 증명서를 입력하세요.

워드프레스 설치 후 플러그인을 지운다든지 뭐가 영향을 미치는 행동을 할 시 아래와 같은 메세지가 나오면서 진행이 안되는 경우가 있습니다.

요청한 작업을 수행하려면, 워드프레스는 웹 서버에 접속해야 합니다. 계속 진행하기 위해 FTP 증명서를 입력하세요. 증명서가 기억나지 않는다면 웹 호스트에게 연락하세요.

이는 서버가 이 폴더에 대한 권한이 없기 때문이므로 nginx가 이 폴더를 소유할 수 있도록 권한을 변경하면 됩니다. 권한 변경은 위에서 설명한대로..

chown -R www-data:www-data /home/etrend/ 
chmod -R 755 /home/etrend/Code language: PHP (php)

403 error

나름 제대로 세팅했다고 생각하고 인터넷에서 주소를 입력하면 403에러가 뜨면서 연결이 아예 안되는 경우가 있습니다.

이에 대한 여러 이유가 있는데 그중 하나가 index.php파일 없을 때도 뜬다고 합니다.

워드프레스 파일을 올리는 과정에서 이 파일만 빠지거나 어떤 이유로 삭제되어서 발생하는 경우입니다.

기타

Postfix와 구글 지메일을 이용해 메일 보내기

postfix를 이용해 우분투에서 메일 서버를 구축하고 외부로 메일을 보내는 방법에 대해서는 아래 글을 참조하세요.

아래 글은 우분투 서버에서 직접 메일 서버를 구축해 메일을 보내는 것이 아니라 구글 지메일 메일 서를 이용해 메일이 보내 안전하고 안정적으로 메일을 보낼 수 있는 방법에 대한 소개입니다.

메일 서버 운영은 상당한 보안ㅇ위험이 따르기 때문에 메일을 받는 기능은 일반적으로 채택하지 않습니다.

참고

도쿄 리젼과 비교해 본 Vultr 서울 리젼 사용기

가성비가 뛰어난 Vultr 가상서버호스팅(클라우드호스팅,VPS) 사용기

Vultr 가상서버호스팅의 새상품 High Frequency 사용기

가상 서버를 운영하고픈 勇者에게 전하는 가상 서버 운영 입문 노하우 – Vultr 가상서버호스팅(VPS)를 중심으로

해외 가상서버호스팅(VPS)이 국내 호스팅보다 빠르다? – 아이비호스팅과 해외 가상서버호스팅 VULTR간 비교

사이트 운영을 위한 안내 – 웹서버 세팅에서 워드프레스 설치까지(우분투 17.10, NGINX 1.13.6, Marian DB 10.2, PHP7.2)

워드프레스 최적화를 위한 18개월간의 고민, 그 노하우를 담다.