ACME(Automated Certificate Management Environment)는 무료 자동화 SSL 인증서를 가능하게 하는 프로토콜입니다. Let’s Encrypt와 ACME 클라이언트(GetHTTPS, Certbot, acme.sh)가 인증 기관과 실제로 통신하는 방법입니다.
RFC 8555에 정의된 ACME는 이전의 수동 프로세스(CA에 CSR을 이메일로 보내고 사람의 검토를 기다림)를 완전히 자동화된 암호학적으로 안전한 프로토콜로 대체했습니다.
ACME 작동 방식 — 5단계
┌──────────┐ ┌──────────────┐
│ 클라이언트│ ① 계정 등록 │ CA 서버 │
│ (GetHTTPS)│ ──────────────────────────→ │ (Let's Encrypt)
│ │ ② 새 주문 (도메인들) │ │
│ │ ──────────────────────────→ │ │
│ │ ③ 챌린지 완료 │ │
│ │ ←─────────────────────────── │ │
│ │ ──────────────────────────→ │ │
│ │ ④ 완료 (CSR 전송) │ │
│ │ ──────────────────────────→ │ │
│ │ ⑤ 인증서 다운로드 │ │
│ │ ←─────────────────────────── │ │
└──────────┘ └──────────────┘
1단계: 계정 등록
클라이언트가 ACME 계정 키 쌍을 생성하고 공개키를 CA에 등록합니다. 이 키가 향후 요청에서 사용자를 식별합니다 — 모든 ACME 메시지가 이것으로 서명됩니다.
이메일, 비밀번호, 개인 정보가 필요하지 않습니다.
2단계: 새 주문
클라이언트가 인증서를 원하는 도메인 이름 목록을 제출합니다. CA가 “주문”을 생성하고 “인가” 세트를 반환합니다 — 도메인당 하나 — 각각 완료할 챌린지가 있습니다.
3단계: 챌린지 완료
각 도메인에 대해 클라이언트가 관리 여부를 증명해야 합니다. CA가 챌린지 유형을 제공합니다:
| 챌린지 | 작동 방식 | 사용 사례 |
|---|---|---|
| HTTP-01 | /.well-known/acme-challenge/에 파일 배치 | 가장 일반적, 가장 간단 |
| DNS-01 | _acme-challenge.domain에 TXT 레코드 추가 | 와일드카드, 포트 80 없음 |
| TLS-ALPN-01 | 포트 443에서 특수 TLS 인증서로 응답 | 포트 80 차단, DNS 접근 없음 |
클라이언트가 챌린지를 완료하면 CA에 검증을 알립니다. CA가 서버에서 확인하고 — 챌린지를 통과하면 인가가 유효로 표시됩니다.
4단계: 완료 (CSR 전송)
모든 도메인이 인가되면 클라이언트가 인증서의 공개키가 포함된 CSR(인증서 서명 요청)을 전송합니다. CA가 이를 서명하고 인증서를 생성합니다.
5단계: 인증서 다운로드
클라이언트가 서명된 인증서 체인 — 인증서 + 중간 CA 인증서를 다운로드합니다. 완료.
ACME 보안 모델
모든 ACME 요청은 계정 키를 사용하여 **JWS(JSON Web Signature)**로 서명됩니다. 이를 통해 방지:
- 재생 공격 — 각 요청에 고유 논스 포함
- 변조 — 서명이 전체 요청 본문을 포함
- 사칭 — 계정 키 보유자만 요청 가능
계정 키는 클라이언트를 떠나지 않습니다. GetHTTPS에서는 Web Crypto API를 통해 브라우저에서 생성됩니다.
GetHTTPS의 ACME 사용
GetHTTPS는 브라우저에서 실행되는 JavaScript로 전체 ACME 프로토콜을 구현합니다:
crypto.subtle.generateKey()(Web Crypto API)로 계정 키 생성- 같은 방법으로 인증서 키 생성
crypto.subtle.sign()으로 ACME 메시지 서명- pkijs 라이브러리로 CSR 구축
acme-v02.api.letsencrypt.org와 직접 HTTPS 통신
서버 측 프록시도, 미들웨어도 없습니다. 브라우저가 Let’s Encrypt의 ACME API와 직접 대화합니다. 이것은 독특합니다 — 대부분의 ACME 클라이언트는 서버에서 실행됩니다.
ACME 클라이언트 비교
| 클라이언트 | 실행 환경 | ACME v2 | 자동 갱신 | 언어 |
|---|---|---|---|---|
| GetHTTPS | 브라우저 | ✅ | ❌ 수동 | JavaScript |
| Certbot | 서버 CLI | ✅ | ✅ | Python |
| acme.sh | 서버 CLI | ✅ | ✅ | Shell |
| Caddy | 웹 서버 | ✅ | ✅ | Go |
| Traefik | 리버스 프록시 | ✅ | ✅ | Go |
| Lego | CLI 라이브러리 | ✅ | ✅ | Go |
ACME를 지원하는 CA
ACME는 Let’s Encrypt가 만들었지만 이제 여러 CA가 사용하는 개방 표준입니다:
| CA | ACME 디렉토리 URL | 무료? |
|---|---|---|
| Let’s Encrypt | acme-v02.api.letsencrypt.org/directory | ✅ |
| ZeroSSL | acme.zerossl.com/v2/DV90 | 제한적 무료 |
| Buypass | api.buypass.com/acme/directory | ✅ |
| Google Trust Services | Google Cloud ACME를 통해 | ✅ |
| DigiCert | 엔터프라이즈 ACME 엔드포인트 | 유료 |
| Sectigo | 엔터프라이즈 ACME 엔드포인트 | 유료 |
자주 묻는 질문
ACME와 Let’s Encrypt는 같은 건가요?
아닙니다. ACME는 프로토콜(RFC 8555)입니다. Let’s Encrypt는 ACME를 사용하는 인증 기관입니다. 다른 CA들(ZeroSSL, Buypass, Google)도 ACME를 지원합니다. HTTP와 Google의 관계처럼 생각하세요 — HTTP는 프로토콜이고, Google은 이를 사용하는 서비스입니다.
자체 ACME 클라이언트를 구현할 수 있나요?
네. 프로토콜은 RFC 8555에 완전히 규정되어 있습니다. GetHTTPS는 브라우저 기반 구현의 예시입니다. 대부분의 언어에 라이브러리가 있습니다(Python의 certbot, Go의 lego, JavaScript의 acme.js).
ACME v2가 무엇인가요?
ACME v2는 현재 버전(RFC 8555)으로, 와일드카드 인증서 지원이 추가되고 초안 v1 프로토콜을 대체했습니다. 모든 최신 ACME 클라이언트가 v2를 사용합니다. Let’s Encrypt는 2021년에 v1 엔드포인트를 종료했습니다.
ACME 서버가 다운되면?
기존 인증서는 계속 작동합니다(홈 서버에 연결하지 않음). 서버가 복구될 때까지 발급이나 갱신만 할 수 없습니다. Let’s Encrypt는 높은 가용성과 이중화된 인프라를 갖추고 있습니다.