Outsider's Dev Story

Stay Hungry. Stay Foolish. Don't Be Satisfied.

블로그 서버 마이그레이션

블로그를 운영한 지 오래되었는데 수년 전에 Digital Ocean이 인기를 끌었을 때 코로케이션 서버에서 Digital Ocean으로 갈아탔다.

Digital Ocean 기존 droplet

DIgital Ocean에서 드롭렛을 만든 지 6년이나 됐다. 이땐 인프라 개념도 많지 않았고 호스팅에서 넘어왔기에 자연스레 서버 한대를 띄워놓고 그 위에서 버전 올리고(대부분은 올리지 못했지만...) 성능 튜닝하면서 버텨왔다. 중간에 너무 느려서 서버 사양을 약간 올렸었는데 그 외에는 그대로 사용하고 있었고 서버는 샌프란시스코 리전에 있었다.

2014년에 개선 작업을 한 번 했지만 그 뒤로 점점 블로그가 느려지고 있다는 느낌이 있었고 나는 내 블로그의 사용자가 아니라 글 작성자이기 때문에 블로그가 느린 건 나한테는 크게 불편함으로 다가오지 않았지만, 종종 블로그가 느리다는 피드백을 받고 있었다.

블로그 마이그레이션 계획

블로그 서버 이전해야지 생각만 하고 있다가 결심을 한 건 올 초에 Digital Ocean이 새로운 가격 정책을 발표했을 때인 것 같다. 새 가격 정책대로라면 같은 사양을 더 싸게 운영하거나 같은 돈이면 더 좋은 사양의 서버를 이용할 수 있었다. 이전해야 한다고 생각하고는 있었지만 2018년의 숙원 사업처럼 조금 작업하다가 멈추기를 반복하면서 한해를 그냥 보냈다.

지금 서버 이전 작업이 힘든 이유가 자동화가 되어있지 않아서 서버 자체가 내 관리하에 있지 않기 때문이므로 다음에 또 이전 작업을 쉽게 하려면 지금 잘 작업해놔야겠다는 생각을 했다. 아무래도 크게 생각하니까 작업하다가 자꾸 멈추게 된 것 같다.

아무래도 요즘 인프라의 추세대로 처음에는 당연히 Docker 기반의 컨테이너 환경으로 가려고 했다. 그래서 가장 먼저 한 일은 도커라이징이었는데 Textcube가 PHP라서 내가 다룰 수 있는 애플리케이션도 아니었고 시크릿 정보 등을 잘 관리하면서 컨테이너로 관리하려니 생각보다 신경 쓸 일이 많았다.

그러다가 Digital Ocean에서 서비스형 Kubernetes를 발표했고 가을쯤에 베타를 받았고 올 상반기에 Kubernetes 스터디를 하고 앞으로 Kubnernetes를 더 많이 써야겠다는 생각에 아예 도커라이징하고 나서 Kubernetes로 운영하면 좋겠다 하는 생각이 들었다.

막상 작업을 진지하게 하다 보니 개인 용도로 Kubernetes 클러스터를 운영하기는 비용 부담이 되고(서비스가 많다면 오히려 좋겠지만...) 노드를 1대로 운영하기에는 Kubernetes로 운영하는 의미가 적어서 애매하게 느껴졌다. 그리고 블로그의 방문자가 국내가 많아서 최대한 국내에서 가까운 싱가포르 리전의 서버로 옮겨오려고 했는데 Digital Ocean의 Kubernetes 서비스는 아직 싱가포르 리전을 지원하지 않았다. 이전하는 김에 다시 샌프란시스코나 뉴욕에 남겨두는 것 자체는 큰 의미가 없어 보였다.

결국 Amazon Lightsail을 검토하기 시작했다. Lightsail은 AWS의 서비스라는 것 외에는 Digital Ocean과 다를 바 없는 서비스이지만 서울 리전을 제공한다는 장점이 있었다. 다른 개인 프로젝트를 AWS에 설정해 두기도 했고 앞으로도 AWS를 다양하게 사용해 보고 싶었으므로 Lightsail를 최종적으로 선택했다. EC2 대신 선택하지 않은 이유는 호스팅 서버처럼 좀 더 간편하게 사용할 수 있기 때문이고 Terraform으로 서버를 띄우려고 보니 Terraform 사용자는 Lightsail을 많이 사용하지 않는지 기능을 충분히 지원하지 않아서 좀 불편했지만 일단 그냥 사용하기로 했다.

블로그 마이그레이션 작업

한번 설정하면 한참 동안은 설정을 건드리지 않을 것을 알고 있었고 PHP도 전혀 다룰 일이 없으므로 나중에도 언제든지 작업할 수 있도록 자동화하고 싶었다. 물론 100% 자동화하려면 작업이 많이 필요하므로 적당한 선에서 나중에 추가 작업을 할 수 있는 선으로 만족했다. 컨테이너 대신 서버에 직접 올리기로 했으므로 서버와 기본 설정은 Terraform을 이용했다. 앞에서 말한 대로 현재 Terraform은 Lightsail을 전부 지원하지 않는다. 이슈도 많지 않은 것으로 보아 Terraform 사용자와 Lightsail 사용자가 겹치지 않는 것 같다. 예를 들어 Lightsail에서는 데이터베이스도 있고 포트 규칙도 있지만, Terraform에서 이를 제어하는 방법은 아직 찾지 못했다.

그래서 서버를 띄우고 Ansible을 사용하려고 Python 설치와 inventory 파일 설정만 하고 나머지 서버 설정은 Ansible로 했다.

provisioner "remote-exec" {
  inline = [
    "sudo apt-get update",
    "sudo apt-get install -y python software-properties-common",
  ]
}

provisioner "local-exec" {
  command = <<EOF
    echo "[blog]\n${self.public_ip_address} ansible_connection=ssh ansible_ssh_user=ubuntu" > inventory
    EOF
}

Ansible에서는 필요한 패키지를 설치하고 ngx_pagespeed를 사용하고 있어서 pagespeed를 지원하는 nginx를 빌드하고 설정 파일을 업로드한 뒤 MySql의 사용자를 만들고 기존 덤프 파일에서 데이터베이스를 복구하고 관리하는 Blog의 Git 저장소를 가져와서 복구했다. 기존에 블로그는 HTTPS로 제공하고 있었기 때문에 이번에 Let's Encrypt도 자동갱신되도록 설정했는데(기존에는 3개월마다 수동으로 하고 있었다) 이는 nginx에서 HTTP가 설정되어 있어야 Let's Encrypt를 인증할 수 있으므로 별도로 돌렸다. 자동화했으므로 작업하면서 계속 인스턴스를 지웠다 띄우면서 Ansible로 필요한 설정을 최대한 할 수 있도록 작업을 했다. 100% 자동화하려면 작업이 많이 필요해서 나중에 관리할 수 있는 정도로만 작업했다.

기존에 네임 서버가 Digital Ocean에서 관리하고 있었는데 어차피 AWS로 넘어왔으므로 DNS도 Route 53으로 갈아탔다. 자동화를 하고 외부에서 인증서도 인증받아야 하다 보니 DNS가 충분히 전파되어야 해서 이전 작업을 하는데 꽤 시간이 걸렸다. DNS 전파를 기다리다가 그냥 자고 일어나서 마저 작업했다. DNS 변경이 있었으면 미리 DNS만 수정해놨어야 했는데 미처 생각하지 못했다.

uptime robot 다운타임 알림


블로그 마이그레이션 결과

기존에 1vCPU, 2GB 메모리, 20GB SSD를 사용하고 있었는데 2vCPU, 4GB 메모리, 80GB SSD로 올렸다. 물론 가격도 좀 더 비싼데 기존에 서버가 느린 것 같아서 이 기회에 올렸다.(나중에 필요하면 내리면 되니까...) 그리고 샌프란시스코에 서버가 있었는데 이번에 서울 리전으로 옮겨와서 대다수인 국내 방문자가 더 빠르게 블로그를 이용할 수 있게 되었다. 새 사양에 맞게 서버를 튜닝해야 하지만 일단은 기본 설정으로 서버를 띄우고 튜닝은 다음 기회에 하려고 한다.

추가로 좀 더 설명하면 마이그레이션 이전에는 Ubuntu 13.04, PHP 5.5.9, nginx 1.11.1(OpenSSL 1.0.2h)였고 이후에는 Ubuntu 18.04, PHP 5.6.39, nginx 1.15.8(OpenSSL 1.1.1a)로 바뀌었다.

서버 이전 후 성능이 궁금해서 간단한 테스트를 돌렸다.

WebPageTest: 서울

WebPageTest의 서울 EC2에서 테스트를 돌렸다.

before

WebPageTest 서울 마이그레이션 이전 결과

  • 페이지 로딩: 4.389초
  • 첫 바이트: 0.774초
  • 렌더링 시작: 1.6초
  • 전체 문서 로딩: 6.295초

after

WebPageTest 서울 마이그레이션 이후 결과

  • 페이지 로딩: 3.416초
  • 첫 바이트: 0.189초
  • 렌더링 시작: 1.2초
  • 전체 문서 로딩: 4.810초

대다수 방문자가 있는 국내에서는 1초 이상 속도가 빨라졌다. 튜닐을 하면 좀 더 빨라지기를 기대하고 있다.

WebPageTest: 뉴욕

서버를 샌프란시스코에서 서울로 이동했으므로 뉴욕에서의 속도는 어떤지 궁금했다. 참고로 WebPageTest에서는 원하는 사이트를 지원하는 전 세계 지역의 브라우저를 통해서 테스트해볼 수 있다.

before

WebPageTest 뉴욕 마이그레이션 이전 결과

  • 페이지 로딩: 17.325초
  • 첫 바이트: 3.274초
  • 렌더링 시작: 15.5초
  • 전체 문서 로딩: 37.394초

after

WebPageTest 뉴욕 마이그레이션 이후 결과

  • 페이지 로딩: 5.856초
  • 첫 바이트: 0.998초
  • 렌더링 시작: 2.1초
  • 전체 문서 로딩: 6.872초

마이그레이션 이전에 테스트할 때 뭔가 문제가 있었는지 모르겠지만 오히려 뉴욕에서의 속도 향상이 엄청나게 늘어났다. 서울로 이전해와서 해외에서의 속도가 좀 걱정됐는데 크게 걱정하지 않아도 될 것 같다.

PageSpeed Insights: Before

PageSpeed는 수정을 더 해야 하지만 기록용으로 일단 남겨둔다. 전에는 이 정도까지는 아닌 것 같았는데 Lighthouse 기분으로 바뀐 뒤 모바일 쪽 점수는 많이 낮아진 것 같다.

PageSpeed Insights 모바일 마이그레이션 이전

PageSpeed Insights 데스크톱 마이그레이션 이전


PageSpeed Insights: After

이유는 잘 모르겠지만 서버 이전을 한 뒤 PageSpeed는 오히려 속도가 더 느리게 나왔다. PageSpeed Insights의 내부 구조는 모르지만, 이상하게 다른 서비스에서는 문제가 안 되었는데 PageSpeed Insights에서는 계속 페이지 로딩 오류가 발생했다. 어차피 이전 후에 개선해야 할 부분이니 나중에 튜닝하면서 이 부분도 수정할 예정이다.

PageSpeed Insights 모바일 마이그레이션 이후

PageSpeed Insights 데스크톱 마이그레이션 이후


New Relic

마이그레이션 이전 new relic

주말이라 트래픽이 많지는 않지만, New Relic 기준으로도 꽤 빨라졌다.

마이그레이션 이후 new relic



블로그 마이그레이션은 올해 숙원 사업 중 하나였는데 해를 넘기기 전에 마이그레이션을 끝내서 다행이다. 그리고 Terraform과 Ansible로 테스트용 인스턴스를 언제든 띄워서 테스트할 수 있으므로 이후 개선 작업도 쉽게 할 수 있을 것 같다.

P.S. 혹시 마이그레이션 이후 블로그에 이상한 부분이 있으면 댓글로 남겨주시면 감사하겠습니다.

2018/12/31 05:41 2018/12/31 05:41

netlify로 정적 사이트 배포하기

netlify를 알게 된 건 한 1년 정도 된 것 같다. 언제부터 서비스했는지는 모르지만 내가 해외에서 자주 듣기 시작한 건 그 정도 된 것 같다. 기능이 계속 추가되고 있는 것 같지만 React, Vue 등이 나오면서 소위 JAMstack이라고 부르는 JavaScirpt, API, Markup으로만 구성된 스택, 다른 말로는 SPA(Single Page Application)가 유행하면서 이러한 정적 사이트을 쉽게 배포할 수 있는 서비스로 같이 인기를 얻고 있다.

정적 사이트같은 경우 AWS 기준이라면 S3에 파일을 올려놓고 CloudFront를 연결해서 배포하면 별로 어렵지 않지만, 막상 회사에서 운영하려면 S3 버킷 만들고 권한 설정하고 CloudFront 설정하고 하려면 은근히 손이 많이 간다. 한번 설정하면 운영에 대한 노력은 들지 않지만, 막상 이런 스택이 많아지면 은근 귀찮은 일이기도 하다. 그전에는 내가 참여하는 오픈소스 프로젝트에서 쓰고 있어서 좀 쓰고 있었는데 요즘은 S3 세팅하는 것도 귀찮아서 가능하면 Netlify를 쓰는 쪽으로 가고 있는데 정말 편하게 잘 만들어진 서비스다.

netlify 웹사이트


netlify

앞에서 설명한 대로 서버 없이(정확히는 서버는 API랑 통신하고) 프론트엔드 스택으로만 구성된 정적 애플리케이션을 배포하는 용도로 최적화된 서비스다. 최근 프론트엔드 기술의 복잡도가 크게 높아지는 동시에 설정이 거의 필요 없는(zero configration) 도구도 등장하고 있다고 느껴지는데 netlify도 그렇게 느껴지는 서비스 중 하나다.

일단 예시로 사용할 SPA 프로젝트가 필요해서 React 예제 프로젝트 중에서 bitcoin-price-index를 포크했다.

netlify 회원 가입을 한 뒤 "New site from Git" 버튼을 누르면 GitHub, GitLab, Bitbucket에 연결할 수 있다.

netlify git 프로바이더 설정

여기선 GitHub과 연결했는데 원하는 저장소를 선택하면 된다. 앞에서 포크한 bitcoin-price-index 저장소를 선택했다.

GitHub 저장소 선택

마지막 단계는 프로젝트를 빌드하는 옵션만 지정하면 된다. 보통 정적 사이트를 프로덕션용으로 빌드하는 명령어가 있으므로 여기에서 지정하면 된다. 예시에서는 npm run build 명령어를 지정했고 빌드된 파일이 만들어지는 build 디렉터리를 지정했다.

빌드 및 배포 설정

설정은 이게 끝이다. 이제 "Deploy site"를 누르면 배포가 된다.

netlify 배포 진행 중 화면

따로 런타임 설정이나 의존성 설치를 할 필요도 없이 빌드 명령어 지정만으로 바로 빌드해서 배포할 수 있다. 이후부터도 저장소에 소스만 푸시하면 바로 빌드가 시작되고(자동 배포가 설정되어 있으면) 사이트가 배포된다.

netlify 배포가 완료된 화면

빌드가 성공적으로 완료되면 상태가 PUBLISHED로 바뀌고 사이트의 주소가 자동으로 생성된다. 물론 Deploy를 클릭하면 빌드 로그도 확인할 수 있다. 사이트에 표시된 https://elastic-kilby-e08c16.netlify.com/를 클릭하면 배포된 사이트를 바로 볼 수 있다.(이 사이트를 예시용이라서 언제까지 유지할지는 잘 모르겠다.)

netlify로 배포한 bitcoin-price-index 사이트

단계를 설명하느라고 길어졌지만, 저장소는 당연히 유지해야 하니 몇 번의 클릭만으로 사이트 배포를 간단하게 할 수 있다. 그리고 저장소에 푸시할 때마다 자동 배포하도록 할 수 있으니 운영에 대한 노력이 거의 안 든다고 할 수 있다. 가격도 개인 사이트 목적으로는 무료로 이용할 수 있어서 편하다.

새로운 사이트를 만들 때 임의의 주소를 자동으로 만들어 주지만 당연히 커스텀 도메인도 설정할 수 있다. 최근에 업무에서 사용하면서 커스텀 도메인을 추가해 보았는데 설정에서 도메인을 추가한 다음에 안내에 나온 대로 DNS에서 해당 도메인을 CNAME을 바꿔주니까 모든 설정이 끝났다. 도메인 추가하고 CNAME 추가 요청만 해놓고 다른 작업을 하고 돌아오니 모든 설정이 완료되어서 운영되고 있었다.

자동으로 발급된 Let's encrypt 인증서

HTTPS 인증서도 자동으로 Let's Encrypt에서 만들어서 연결해 주고 자동으로 갱신해 주므로 따로 신경 쓰지 않아도 된다. 이 과정은 AWS에 S3 같은 곳에 배포하는 과정에서 필요한 S3 버킷 생성, 빌드 결과 배포, CDN 연결, HTTPS 인증서 생성 및 연결 등과 비교했을 때 얼마나 간단한지 알 수 있다.

2018/12/26 16:40 2018/12/26 16:40