Let's Encrypt: 무료 인증서가 HTTPS의 문턱을 어떻게 낮췄나
HTTPS를 처음 켜본 사람이라면 한 번쯤 같은 장면을 거칩니다. 인증서를 사려고 검색하다 보니 1년에 몇 만 원짜리부터 수십만 원짜리까지 등급이 나뉘어 있고, 어떤 걸 골라야 할지부터 막막한데요. 사이드 프로젝트 하나 띄워보자고 비싼 인증서를 사기는 부담스럽지만, HTTP로 두자니 브라우저가 “안전하지 않음”이라고 경고를 띄웁니다.
이 진입 장벽을 거의 무너뜨린 것이 Let’s Encrypt입니다. ISRG(Internet Security Research Group)라는 비영리 단체가 운영하는 무료 인증 기관인데, 발급 절차를 자동화해서 사람이 사이트를 운영하면서 인증서 일을 거의 의식하지 않아도 되게 만들어 주었죠. 이번 글에서는 Let’s Encrypt가 어떻게 동작하는지, 그리고 처음 도입할 때 알아두면 좋은 실용적인 사항들을 정리해 보겠습니다.
자동화가 만든 차이
전통적인 인증 기관에서 인증서를 받으려면 사람이 손으로 해야 하는 일이 꽤 많았습니다. 신청서를 작성하고, 도메인 소유를 증명하기 위해 메일을 받고, 파일을 업로드하고, 결제하고, 발급된 인증서를 서버에 가져다 붙이는 단계를 거쳐야 했는데요. 이 모든 과정이 사람의 손을 거치다 보니 비용이 들 수밖에 없었고, 1년에 한 번씩 갱신할 때마다 같은 일을 반복해야 했습니다.
Let’s Encrypt는 이 절차를 통째로 자동화했습니다. 도메인 소유 검증부터 인증서 발급, 갱신, 폐기까지 모두 사람이 끼지 않는 프로토콜로 정의해 두고, 그 프로토콜대로 동작하는 클라이언트 도구가 모든 일을 처리하게 만든 셈인데요. 인간이 빠지면 비용도 빠지므로, 인증서 자체를 무료로 풀어도 운영이 가능해진 것입니다.
이 결정은 결과적으로 웹 전체의 풍경을 바꿔 놓았습니다. 2016년 공개 직후만 해도 HTTPS를 쓰는 사이트가 절반에 못 미쳤는데, 지금은 인터넷 트래픽 대부분이 HTTPS로 흐르는 상황이 됐죠. 대형 서비스는 물론이고 사이드 프로젝트, 토이 도메인까지 자물쇠 표시가 기본이 된 셈인데, 그 흐름의 가장 큰 한 축이 Let’s Encrypt와 ACME입니다.
ACME 프로토콜과 도메인 검증
자동화의 핵심에는 ACME(Automatic Certificate Management Environment)라는 프로토콜이 있습니다. RFC 8555로 표준화된 이 프로토콜은 클라이언트와 인증 기관 사이에 일어나는 모든 절차를 HTTP API 호출로 정의해 두었는데요. 다른 인증 기관들도 ACME를 채택하기 시작해서, 요즘은 Let’s Encrypt 외에도 ZeroSSL이나 Buypass 같은 곳에서 같은 도구를 쓸 수 있습니다.
도메인 소유를 증명하는 단계가 가장 흥미롭습니다. ACME는 두 가지 검증 방식을 제공하는데, 하나는 HTTP-01이고 다른 하나는 DNS-01입니다.
HTTP-01은 인증 기관이 “당신 도메인의 특정 경로에 이 토큰을 올려두라”고 요구하면, 클라이언트가 그 자리에 파일을 올려두는 방식입니다. 인증 기관이 그 도메인 이름으로 직접 접근해 토큰을 확인하면, “아 이 사람이 그 도메인을 정말 운영하는구나”라고 판단하는 셈이죠. 가장 단순하고, 80번 포트로 외부 접근만 열려 있으면 동작합니다.
DNS-01은 한 단계 더 유연한 방식입니다.
인증 기관이 요구하는 토큰을 도메인의 TXT 레코드로 추가하면, 인증 기관이 DNS 조회로 확인하는 식인데요.
서버가 외부에서 접근 불가능한 환경(내부망 서비스)이라도 DNS 권한만 있으면 인증서를 받을 수 있고, 와일드카드 인증서(*.example.com)는 이 방식으로만 발급할 수 있습니다.
certbot으로 처음 시작하기
가장 널리 쓰이는 ACME 클라이언트는 EFF가 개발한 certbot입니다. nginx와 Apache 같은 흔한 웹 서버에 대해서는 설정 파일까지 자동으로 손봐 주는 플러그인을 갖추고 있어, 한 줄짜리 명령어로 HTTPS를 켤 수 있죠.
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d example.com -d www.example.com
위 명령어를 실행하면 certbot이 기본 메일 주소와 약관 동의 정도만 묻고, 나머지는 모두 알아서 처리합니다.
nginx 설정에 SSL 블록을 추가하고, 인증서를 적절한 위치에 가져다 두고, 자동 갱신을 위한 systemd timer까지 등록해 주는데요.
명령이 끝나면 같은 도메인을 https://로 열어보면 자물쇠가 켜져 있는 모습을 볼 수 있습니다.
웹 서버를 직접 다루지 않고 인증서만 받고 싶다면 standalone 모드도 있습니다. 이 모드는 certbot이 80번 포트에 임시 서버를 띄워 검증을 처리하므로, 기존 서버를 잠깐 멈춰야 합니다.
sudo certbot certonly --standalone -d example.com
발급된 인증서는 보통 /etc/letsencrypt/live/example.com/ 아래에 저장되고, 그 안의 fullchain.pem과 privkey.pem을 웹 서버 설정에 가리켜 주면 됩니다.
90일이라는 짧은 유효 기간
Let’s Encrypt 인증서의 유효 기간은 90일로 짧은 편입니다. 처음 도입하는 사람이라면 “왜 이렇게 짧지?” 싶지만, 짧은 유효 기간은 의도된 설계입니다. 키가 어딘가에서 새거나 잘못 발급된 인증서가 돌아다닐 때, 그 영향이 90일을 넘기지 않도록 한정하는 효과가 있는데요.
그 대신 갱신을 사람이 챙기지 않아도 되게 만들었습니다. certbot은 설치 시 자동으로 갱신 작업을 등록하고, 만료 30일 전부터는 매일 한 번씩 갱신을 시도합니다.
sudo certbot renew --dry-run
--dry-run 옵션을 붙이면 실제로 새 인증서를 받지 않고도 갱신 절차가 잘 돌아가는지 시험해 볼 수 있어, 운영 환경에서 갱신 시점이 다가오기 전에 미리 점검할 때 유용합니다.
요즘은 흐름이 더 짧아지는 방향으로 가고 있습니다. 2025년에는 주요 인증 기관들이 인증서 유효 기간을 점진적으로 줄여서 결국 90일보다도 더 짧게 가져가기로 합의했는데요. 이 흐름 덕분에 자동 갱신은 선택이 아니라 사실상 필수가 됐습니다.
DNS 검증과 와일드카드
*.example.com 같은 와일드카드 인증서를 받으려면 DNS-01 검증을 거쳐야 합니다.
이 방식은 클라이언트가 인증 기관이 준 토큰을 도메인의 TXT 레코드로 추가해야 하는데, 자동화하려면 DNS 제공자의 API를 통해 레코드를 추가/삭제할 권한이 필요합니다.
sudo certbot certonly --dns-cloudflare \
--dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \
-d example.com -d "*.example.com"
certbot은 Cloudflare, Route 53, Google Cloud DNS 같은 주요 DNS 제공자에 대해 별도의 플러그인을 제공해서, API 토큰만 설정 파일에 적어두면 나머지는 자동으로 처리합니다. 와일드카드는 한 인증서로 모든 하위 도메인을 보호할 수 있어 운영이 편리하지만, 키가 새면 모든 하위 도메인이 함께 영향을 받는다는 점은 HTTPS 글에서 짚었듯 기억해둘 필요가 있습니다.
certbot 외의 선택지
certbot은 가장 널리 쓰이지만 유일한 도구는 아닙니다. 요즘은 웹 서버 자체가 ACME 클라이언트를 내장한 형태가 늘어나고 있어, 별도의 도구를 설치하지 않아도 인증서 일이 자동으로 처리되는 경우가 많은데요.
대표적인 예가 Caddy입니다. 설정 파일에 도메인만 적어두면 처음 실행할 때 자동으로 인증서를 발급받고, 만료가 다가오면 알아서 갱신합니다.
example.com {
reverse_proxy localhost:8080
}
이 한 줄만으로 HTTPS가 동작하는 리버스 프록시가 완성되는 셈이죠. Traefik이나 nginx 최신 버전도 비슷한 기능을 제공해서, 도구를 잘 고르면 인증서를 거의 의식하지 않고 운영할 수 있습니다.
쉘 스크립트 한 파일로 동작하는 acme.sh도 인기 있는 선택지입니다. 의존성이 거의 없어 가벼운 환경(소형 서버, 컨테이너 안)에서 편하게 쓸 수 있고, 다양한 DNS 제공자를 지원합니다.
발급 한도와 주의사항
Let’s Encrypt는 무료지만, 무한정 발급할 수 있는 것은 아닙니다. 한 도메인당 일정 시간 안에 발급할 수 있는 인증서 수에 한도가 있어, 테스트하면서 같은 도메인으로 인증서를 자꾸 새로 받으면 한도를 넘겨 한동안 발급이 막힐 수 있는데요.
이런 사고를 피하려면 staging 환경을 활용하면 됩니다. Let’s Encrypt는 운영 환경과 별도로 staging 환경을 두어, 한도 걱정 없이 절차를 시험해 볼 수 있도록 해 두었습니다.
sudo certbot certonly --staging -d example.com
staging에서 발급된 인증서는 브라우저가 신뢰하지 않으니 실제 사이트에 쓸 수는 없지만, 자동화 스크립트가 잘 동작하는지 확인하는 용도로는 충분합니다.
운영 환경으로 옮길 때 --staging 옵션만 빼고 다시 실행하면 됩니다.
처음 도입할 때 자주 막히는 부분
설명은 단순하지만 막상 도입할 때 발이 걸리는 자리가 몇 군데 있습니다. 가장 흔한 함정은 80번 포트입니다. HTTP-01 검증을 쓰려면 인증 기관이 도메인의 80번 포트로 접근할 수 있어야 하는데, 클라우드 환경에서 보안 그룹이나 방화벽이 80번을 막아두고 443번만 열어둔 경우가 의외로 많은데요. 이때는 일시적으로 80번을 열거나, 아예 DNS-01 검증으로 전환하는 편이 깔끔합니다.
또 자주 마주치는 것이 권한 문제입니다.
certbot은 인증서를 /etc/letsencrypt/에 저장하는데, 이 디렉토리 안 파일들은 root 권한이 아니면 읽을 수 없도록 막혀 있습니다.
일반 사용자로 동작하는 웹 서버 프로세스가 인증서를 못 읽어 SSL 핸드셰이크에서 실패하는 경우가 가끔 있는데, 그룹 권한을 조금 손보거나 웹 서버를 root로 시작해 권한을 떨어뜨리는 식의 일반적인 운영 패턴을 따르면 해결됩니다.
마지막으로, 도메인이 두 IP를 가리키는 환경(예: 다중 데이터센터)에서는 검증 단계에서 어느 쪽으로 가더라도 같은 토큰을 응답하도록 만들어 두어야 합니다. 이 부분은 설정 자동화 도구에서 자주 빠뜨리는 항목이라, 첫 발급 때 한 번 점검해 두는 것이 좋습니다.
마치며
HTTPS가 한때 비싸 보였던 가장 큰 이유는 인증서 비용과 운영 부담이었습니다. Let’s Encrypt는 ACME 프로토콜로 그 두 가지를 한꺼번에 풀어내, 사이드 프로젝트부터 대형 서비스까지 누구나 HTTPS를 기본으로 쓸 수 있게 만들었는데요. 이제는 새 도메인을 띄울 때 가장 먼저 하는 일이 인증서 자동 발급 설정이 되었다고 해도 과언이 아닙니다.
처음 도입한다면 운영 중인 서버에 certbot을 설치하고 한 줄 명령부터 시도해 보길 권합니다. ACME 동작이나 다른 클라이언트가 궁금하다면 Let’s Encrypt 공식 문서를 참고하세요.
This work is licensed under
CC BY 4.0