ALB와 TLS/SSL 인증서로 HTTPS 암호화 통신 구현하기

2026. 5. 15. 12:37·Computer Science

 현대 웹 서비스에서 HTTPS 암호화 통신은 보안뿐만 아니라 사용자 신뢰도와 검색엔진 최적화를 위해서도 선택이 아닌 필수입니다. AWS 환경에서는 AWS Certificate Manager를 활용해 간편하게 TLS/SSL 인증서를 발급받고, 이를 Application Load Balancer에 연결하여 손쉽게 HTTPS 접속 환경을 구축할 수 있습니다. 이번 포스팅에서는 ACM을 통한 도메인 인증서 발급 과정부터 ALB 리스너 규칙을 설정하여 실제 웹 서비스에 안전한 HTTPS 통신을 적용하는 방법까지, 전체 과정을 단계별로 차근차근 알아보겠습니다.

 


 

목차

1. Route53과 ACM을 통해 인증서 발급
2. ALB에 인증서 연결하고 설치
3. Terraform 실습
4. 결론

 


 

#1 Route53과 ACM을 통해 인증서 발급

<그림 1>. Route53 도메인 생성

 

 ACM 인증서를 발급받기 위해서는 먼저 웹사이트에서 사용할 도메인이 필요합니다. 이미 Route53에서 관리 중인 도메인이 없다면, AWS 콘솔에서 Route53-등록된 도메인 탭으로 이동하여 도메인을 등록해줘야 합니다. 이번 글에서는 저의 계정에서 관리 중인 도메인을 기준으로 apex 도메인 1개 seoul-place.com , www 서비스 도메인 1개 www.seoul-place.com 두 주소 모두 HTTPS로 접속할 수 있도록 설정해 보겠습니다.

 

<그림 2>. ACM 인증서 요청

 

 도메인 2개를 생성해 주었다면, 각각의 도메인에 암호화 접속이 가능하도록 인증서를 요청해주어야 합니다. AWS 콘솔의 AWS Certificate Manager-인증서 탭으로 들어가 퍼블릭 인증서 요청을 선택합니다.

 

<그림 3>. ACM 인증서 요청

 

 인증서 요청 화면에서는 도메인 이름에 apex 도메인과 www 도메인을 모두 적어줍니다.

  • seoul-place.com
  • www.seoul-place.com

 여기서 apex 도메인은 seoul-place.com 처럼 앞에 www가 붙지 않은 최상위 도메인을 의미합니다. 반면 www.project.com 처럼 apex 도메인 앞에 www라는 서브도메인이 붙은 주소입니다.

 

<그림 4>. ACM 인증서 요청

 

 이후 추가 옵션들은 디폴트값을 사용해도 됩니다. 주요 옵션의 의미는 다음과 같습니다.

  • 내보내기 활성화/비활성화 : On-premise 서버, 외부 Nginx 서버, 다른 클라우드 서버 등에 인증서를 사용해야 한다면 활성화가 필요하지만, 보안 위협을 감안하여 ALB나 CloudFront에 검증하는 용도로 사용할 예정이면 비활성화가 권장됩니다.
  • DNS 검증 / 이메일 검증 : 인증서 검증을 CNAME 레코드를 활용하여 검증할 것인지, 이메일을 발송하여 검증할 것인지를 선택합니다. Route53을 사용한다면 DNS 검증이 가장 편리합니다.
  • 키 암호화 알고리즘 : 높은 성능과 짧은 키가 필요하다면 ECDSA 알고리즘을 선택할 수 있지만, RSA2048 알고리즘이 안정성과 호환성이 좋아 권장됩니다.

 인증서 요청을 완료하면 인증서는 바로 발급되지 않고, 검증 대기 상태가 됩니다. ACM은 이때 도메인 소유권을 확인하기 위해 CNAME 이름과 CNAME 값을 생성합니다.

 

<그림 5>. 호스팅 영역 생성

 

 이제 도메인으로 들어오는 요청을 처리하는 프로세스를 구성해야 합니다. 우리는 인터넷에서 들어오는 요청을 라우팅 해주어야 하므로, 퍼블릭 호스팅 영역을 생성해야 합니다. 프라이빗 호스팅 영역은 VPC 내부 통신을 위해 도메인을 사용하는 경우에 선택해야 합니다. 이번 구조에서는 외부 사용자가 웹사이트에 접속해야 하므로 퍼블릭 호스팅 영역을 선택합니다.

 

<그림 6>. 레코드 목록

 

 방금 생성한 호스팅 영역으로 이동해 보면, 레코드 목록이 출력됩니다. 최초에는 NS와 SOA 타입의 레코드가 기본적으로 자동 생성됩니다.

 

 자주 사용되는 레코드 타입의 종류는 다음과 같습니다.

  • NS: 이 도메인의 DNS 관리를 어떤 네임서버가 담당하는지 알려주는 레코드.
  • SOA: 이 DNS 영역의 기본 정보와 관리 기준을 담은 시작 레코드.
  • A: 도메인을 IPv4 주소로 연결하는 레코드.
  • CNAME: 한 도메인을 다른 도메인의 별칭으로 연결하는 레코드.

 여기서 우리는 도메인 주소를 IPv4 주소로 매핑해 주는 DNS 레코드가 필요하므로 A 레코드를 apex 도메인과 www 도메인에 각각 만들어주어야 합니다. 또한, 두 도메인을 인증서로 검증해야 하므로 두 도메인에 CNAME 레코드도 각각 만들어주어야 합니다.

 

<그림 7>. A 레코드 생성

 

 레코드 생성 시에는 다음과 같이 설정합니다.

  • 레코드 유형: A
  • 별칭: 활성화
  • 라우팅 대상: Application Load Balancer
  • 리전: ALB가 생성된 리전
  • 로드밸런서: 연결할 ALB 선택

 apex 도메인용 레코드는 레코드 이름을 비워두고, www 도메인용 레코드는 레코드 이름에 www를 입력합니다.

 

<그림 8>. CNAME 레코드 생성

 

 ACM 인증서를 발급받기 위해서는 도메인 소유권 검증이 필요합니다. DNS 검증 방식을 선택하면 ACM에서 각 도메인에 대한 CNAME 이름과 CNAME 값을 생성해 줍니다. 이 값은 AWS Certificate Manager에서 요청한 인증서 상세 화면으로 들어가면 확인할 수 있습니다.

Route53에서 CNAME 레코드를 생성할 때는 다음 값을 입력합니다.

 

  • 레코드 유형: CNAME
  • 레코드 이름: ACM에서 제공한 CNAME 이름
  • 레코드 값: ACM에서 제공한 CNAME 값

A 레코드와 마찬가지로 apex 도메인과 www 도메인을 인증서에 포함했으므로, CNAME 레코드도 각각 생성해 줍니다.

 

<그림 8>.인증서 CNAME 이름, 값

 

 인증서 상세 화면으로 이동하면 다음과 같이 두 도메인의 인증 상태가 보이게 됩니다. 여기서 apex 도메인과 www 도메인의 CNAME 이름과 CNAME 값을 각각 복사하여 레코드 생성에 사용합니다.

 

<그림 9>. 레코드 전체 목록

 

 A 레코드 2개, CNAME 레코드 2개를 생성하면 총 6개의 레코드가 출력되는 것을 확인할 수 있습니다. CNAME 레코드 생성 후에는 보통 몇 분에서 수십 분 정도 기다리면 ACM 인증서 검증이 완료됩니다. 검증이 완료되면 인증서 상태가 발급됨(Issued)으로 변경됩니다.

 


 

#2 ALB에 인증서 연결하고 설치

<그림 10>. ALB 생성

 

 이제 발급받은 ACM 인증서를 ALB에 연결하여 HTTPS 접속이 가능하도록 설정합니다. ALB는 외부 사용자의 요청을 받아 내부의 EC2, ECS, Target Group 등으로 트래픽을 전달하는 역할을 합니다. 인터넷 사용자가 웹사이트에 접속해야 하므로 ALB의 체계는 인터넷 경계(Internet-facing)로 설정합니다. 주소 유형은 일반적인 웹서비스라면 IPv4를 선택하면 됩니다.

 

<그림 11>. ALB 서브넷 할당

 

 VPC를 선택하고, ALB를 설치할 서브넷을 선택합니다. 이때, ALB는 인터넷 게이트웨이를 통하여 들어오는 트래픽을 프라이빗 서브넷으로 전달해 주기 위해 퍼블릭 서브넷에 설치해야 하며, 고가용성을 위해 최소 2개의 서로 다른 가용영역에 있는 퍼블릭 서브넷을 선택해야 합니다. 이 구조를 사용하면 사용자는 ALB까지만 직접 접근하고, 실제 애플리케이션 서버는 프라이빗 서브넷에 둬서 보안을 강화할 수 있습니다.

 

<그림 12>. ALB 보안그룹 생성 및 리스너 추가

 

 ALB에 적용할 보안 그룹에는 외부 사용자의 HTTPS 요청을 받을 수 있도록 인바운드 규칙을 추가합니다. 기본적으로 필요한 규칙은 다음과 같습니다.

유형 포트 소스
HTTP 80 0.0.0.0/0
HTTPS 443 0.0.0.0/0

 

<그림 13>. ALB 라우팅 설정

 

 ALB에 들어온 트래픽을 라우팅할 대상그룹을 선택해 줍니다. HTTP 80 포트는 필수는 아니지만, 사용자가 http://로 접속했을 때 https://로 리디렉션하기 위해 열어두는 경우가 많습니다. 실제 서비스 트래픽은 HTTPS 443 포트를 통해 처리되도록 구성합니다.

리스너는 다음과 같이 구성할 수 있습니다.

 

유형 동작
HTTP:80 HTTPS:443으로 리디렉션
HTTPS:443 Target Group으로 전달

<그림 14>. ALB 보안 리스너 설정

 

 HTTPS 리스너를 설정할 때는 TLS 보안 정책을 선택해야 합니다. 이 정책은 클라이언트와 ALB 사이에서 어떤 TLS 버전과 암호화 방식을 사용할지 결정합니다.

 

 AWS 콘솔에서는 보안 정책을 다음과 같은 카테고리로 나누어 보여줍니다.

  • 포스트 퀀텀 TLS : 미래의 양자컴퓨터 공격에 대비한 TLS 정책이며, 장기적으로 보호해야 하는 개인정보, 금융성 데이터, 민감 로그, 계약/의료/연구 데이터처럼 나중에 복호화되면 위험한 데이터를 다룰 때 선택합니다.
  • FIPS 포스트 퀀텀 TLS : 포스트 퀀텀 TLS에 FIPS 규정 준수 기준까지 붙은 정책이며, 정부, 공공, 금융, 국방, 규제 산업처럼 FIPS 준수 요구사항이 명확할 때 선택합니다.

일반적인 웹 애플리케이션에 HTTPS를 적용하는 목적이라면, 최신 TLS 1.3 계열 보안 정책을 선택하면 충분합니다.

 

<그림 15>. ALB 인증서 적용

 

 마지막으로 HTTPS 리스너에 ACM 인증서를 연결합니다. 인증서 소스는 ACM을 선택하고, 앞에서 발급받은 인증서를 선택합니다. 인증서 연결이 완료되면 ALB는 443 포트에서 HTTPS 요청을 받을 수 있게 됩니다.

 

 이제 브라우저에서 https://seoul-place.com 또는 https://www.seoul-place.com으로 접속하면, ACM 인증서가 적용된 HTTPS 웹사이트로 접근할 수 있습니다. http로 해도 HTTPS 웹사이트로 자동 리디렉션이 가능합니다.

 


 

#3 Terraform 실습

 

 앞에서는 AWS 콘솔을 통해 Route53, ACM, ALB를 직접 설정하는 과정을 살펴보았습니다. 이번에는 동일한 구성을 Terraform 코드로 작성해 보겠습니다. 이번 Terraform 구성은 앞에서 직접 콘솔을 활용하여 진행했던 순서와는 차이가 존재합니다. 구성 순서는 다음과 같으며, 차근차근 진행해 보겠습니다.

 

  • ACM 인증서 요청
  • Route53 DNS 검증 레코드 자동 생성
  • ACM 인증서 검증 완료 처리
  • Route53 A 레코드로 도메인을 ALB에 연결
  • ALB 생성
  • HTTPS 443 리스너에 ACM 인증서 연결
  • HTTP 80 요청을 HTTPS 443으로 리디렉션

 

1. ACM 인증서 요청

resource "aws_acm_certificate" "main" {
  domain_name               = var.domain_name
  subject_alternative_names = ["www.${var.domain_name}"]
  validation_method         = "DNS"

  lifecycle {
    create_before_destroy = true
  }

  tags = {
    Name = "${var.project_name}-${var.environment}-cert"
  }
}

 

 위 코드는 ACM에서 퍼블릭 인증서를 요청하는 코드입니다. domain_name에는 apex 도메인 값을 넣고, subject_alternative_names에는 www을 붙여 추가로 인증서에 포함할 도메인을 넣습니다.

 

 validation_method = "DNS" 는 인증서 검증 방식을 DNS 검증으로 선택한다는 의미입니다. Route53을 함께 사용할 경우 DNS 검증 레코드를 Terraform으로 자동 생성할 수 있기 때문에 이메일 검증보다 관리가 편합니다.

 

 lifecycle { create_before_destroy = true }는 인증서를 교체해야 하는 상황에서 기존 인증서를 먼저 삭제하지 않고, 새 인증서를 먼저 생성한 뒤 기존 인증서를 제거하도록 합니다. 인증서가 먼저 삭제되면 HTTPS 연결에 문제가 생길 수 있으므로, 인증서 리소스에는 자주 사용하는 설정입니다.

 

2. 퍼블릭 호스팅 영역 생성

resource "aws_route53_zone" "main" {
  name = var.domain_name

  tags = {
    Name        = "${var.project_name}-${var.environment}-hosted-zone"
    Environment = var.environment
  }
}

 

 이 코드는 Route53에 생성되어 있는 호스팅 영역을 생성하는 코드입니다. 생성 후 퍼블릭 호스팅 영역을 Terraform에서 참조합니다.

 

3. ACM DNS 검증 레코드 생성

resource "aws_route53_record" "cert_validation" {
  for_each = {
    for dvo in aws_acm_certificate.main.domain_validation_options : dvo.domain_name => {
      name   = dvo.resource_record_name
      record = dvo.resource_record_value
      type   = dvo.resource_record_type
    }
  }

  zone_id         = data.aws_route53_zone.main.zone_id
  name            = each.value.name
  type            = each.value.type
  records         = [each.value.record]
  ttl             = 60
  allow_overwrite = true
}

 

 ACM 인증서를 DNS 방식으로 검증하려면 CNAME 레코드가 필요합니다. 콘솔에서는 ACM 화면에서 CNAME 이름과 CNAME 값을 확인한 뒤 Route53에 직접 입력했지만, Terraform에서는 이 과정을 자동화할 수 있습니다.

 

aws_acm_certificate.main.domain_validation_options에는 ACM이 생성한 DNS 검증용 레코드 정보가 들어 있습니다. 우리는 이 정보를 통해 간편하게 CNAME 레코드를 생성할 수 있습니다.

 

추가적으로 allow_overwrite = true는 동일한 이름의 검증 레코드가 이미 존재하더라도 덮어쓸 수 있게 해주는 옵션입니다. ACM 인증서를 재생성하거나 Terraform을 다시 적용할 때 충돌을 줄이는 데 도움이 됩니다.

 

4. ACM 인증서 검증 완료 리소스 생성

resource "aws_acm_certificate_validation" "main" {
  certificate_arn         = aws_acm_certificate.main.arn
  validation_record_fqdns = [for r in aws_route53_record.cert_validation : r.fqdn]
}

 

이 코드는 ACM 인증서의 DNS 검증이 완료될 때까지 Terraform이 기다리도록 하는 역할을 합니다. 앞에서 aws_route53_record.cert_validation 리소스를 통해 DNS 검증용 CNAME 레코드를 생성했습니다. 이후 aws_acm_certificate_validation 리소스는 해당 레코드들이 정상적으로 반영되어 인증서 검증이 완료되었는지 확인합니다.

 

certificate_arn = aws_acm_certificate.main.arn로 검증할 ACM 인증서를 지정하고, validation_record_fqdns = [for r in aws_route53_record.cert_validation : r.fqdn]처럼 fqdn값만 뽑아 이 도메인들을 ACM 검증에 사용합니다.

 

5. ALB 생성

resource "aws_lb" "app" {
  name               = "${var.project_name}-${var.environment}-alb"
  internal           = false
  load_balancer_type = "application"
  security_groups    = [aws_security_group.alb_sg.id]

  subnets = [
    aws_subnet.public_a.id,
    aws_subnet.public_c.id,
  ]

  tags = {
    Name        = "${var.project_name}-${var.environment}-alb"
    Environment = var.environment
  }
}

 

 위 코드는 Application Load Balancer를 생성하는 코드입니다. internal = false는 인터넷에서 접근 가능한 외부용 ALB를 생성한다는 의미입니다. 즉, 아까 AWS 콘솔에서 봤던 ALB 체계를 인터넷 경계(internet-facing)로 선택하는 것과 같습니다. 로드밸런서 유형과 보안 그룹, 설치할 퍼블릭 서브넷 2개를 적어줍니다.

 

6. A 레코드로 도메인을 ALB에 연결

resource "aws_route53_record" "apex" {
  zone_id = data.aws_route53_zone.main.zone_id
  name    = var.domain_name
  type    = "A"

  alias {
    name                   = aws_lb.app.dns_name
    zone_id                = aws_lb.app.zone_id
    evaluate_target_health = true
  }
}

resource "aws_route53_record" "www" {
  zone_id = data.aws_route53_zone.main.zone_id
  name    = "www.${var.domain_name}"
  type    = "A"

  alias {
    name                   = aws_lb.app.dns_name
    zone_id                = aws_lb.app.zone_id
    evaluate_target_health = true
  }
}

 

 위 코드는 apex 도메인과 www 도메인을 ALB에 연결하는 Route53 A 레코드를 ALB에 연결하는 코드입니다. 일반적인 A 레코드는 도메인을 IPv4 주소에 연결합니다. 하지만 ALB는 고정 IP 하나로 직접 연결하는 방식이 아니라, AWS가 관리하는 DNS 이름을 사용합니다. 따라서 Route53에서는 ALB를 대상으로 연결할 때 alias를 사용합니다.

 

name에는 ALB의 DNS 이름을 넣고, zone_id에는 ALB의 Hosted Zone ID를 넣으며, 이 값들은 aws_lb.app 리소스에서 참조합니다.

 

추가적으로 evaluate_target_health = true는 ALB 대상의 상태를 Route53 라우팅 판단에 반영하겠다는 의미입니다.

 

7. HTTPS 443 리스너 생성

resource "aws_lb_listener" "prod_https" {
  load_balancer_arn = aws_lb.app.arn
  port              = 443
  protocol          = "HTTPS"
  ssl_policy        = "ELBSecurityPolicy-TLS13-1-2-2021-06"
  certificate_arn   = aws_acm_certificate_validation.main.certificate_arn

  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.blue.arn
  }

  lifecycle {
    ignore_changes = [default_action]
  }

  tags = {
    Name = "${var.project_name}-${var.environment}-listener-https"
  }
}

 

 위 코드는 ALB에 HTTPS 443 리스너를 생성하는 코드입니다. 여기서는 사용자의 HTTPS 요청을 받기 위해 443 포트와 HTTPS 프로토콜을 사용합니다.


ssl_policy는 클라이언트와 ALB 사이에서 사용할 TLS 버전과 암호화 정책을 의미합니다. 여기서는 TLS 1.3과 TLS 1.2를 지원하는 보안 정책을 사용했습니다.

 

 이 코드에서 주의할 점은 certificate_arn에 aws_acm_certificate.main.arn이 아닌 aws_acm_certificate_validation.main.certificate_arn을 사용해야 인증서 검증이 완료된 뒤 리스너에 연결이 됩니다.

default_action {
  type             = "forward"
  target_group_arn = aws_lb_target_group.blue.arn
}

 HTTPS 요청이 들어오면 기본적으로 blue 대상 그룹으로 전달합니다.

lifecycle {
  ignore_changes = [default_action]
}

 이 설정은 default_action의 변경을 Terraform이 무시하도록 합니다. 저는 프로젝트에서 CodeDeploy를 사용하여 블루/그린 배포를 구현했기 때문에, 리스너의 대상 그룹이 일시적으로 변경될 수 있어 추가했습니다.

 

8. HTTP 요청 리디렉션

resource "aws_lb_listener" "http_redirect" {
  load_balancer_arn = aws_lb.app.arn
  port              = 80
  protocol          = "HTTP"

  default_action {
    type = "redirect"
    redirect {
      port        = "443"
      protocol    = "HTTPS"
      status_code = "HTTP_301"
    }
  }
}

 

위 코드는 HTTP 80 포트로 들어온 요청을 HTTPS 443 포트로 리디렉션하는 리스너입니다.

 

 


#4 결론

 

이번 실습을 통해 Route53, ACM, ALB를 연결하여 사용자가 도메인으로 안전하게 HTTPS 접속할 수 있는 구조를 구성해 보았습니다. 이러한 구조는 단순히 웹사이트를 띄우는 것에서 끝나는 것이 아니라, 인증서를 적용하고 HTTP 요청을 HTTPS로 리디렉션함으로써 전송 구간의 보안을 강화할 수 있습니다. 결론적으로, HTTPS 설정은 실제 서비스 환경에서 사용자 신뢰성과 보안성을 확보하기 위한 필수적인 구성입니다.

'Computer Science' 카테고리의 다른 글

Amazon Bedrock 기반 RAG와 Agent 아키텍처 설계  (0) 2026.05.22
Terraform Remote Backend & State Locking  (0) 2026.05.08
ISMS-P 인증 받는 클라우드 아키텍처 핵심 7가지  (0) 2026.05.01
ECS on EC2와 ECS on Fargate를 비용과 운영 관점에서 비교하기  (0) 2026.04.15
Terraform을 활용하여 안전한 SG 및 NACL 인바운드/아웃바운드 아키텍처 설계하기  (0) 2026.04.09
'Computer Science' 카테고리의 다른 글
  • Amazon Bedrock 기반 RAG와 Agent 아키텍처 설계
  • Terraform Remote Backend & State Locking
  • ISMS-P 인증 받는 클라우드 아키텍처 핵심 7가지
  • ECS on EC2와 ECS on Fargate를 비용과 운영 관점에서 비교하기
Cloud9Ops
Cloud9Ops
CloudOps 지망생입니다. 스스로의 공부를 위한, 더 많은 사람들이 양질의 지식을 습득하는 공간입니다.
  • Cloud9Ops
    CloudOps Engineer
    Cloud9Ops
  • 전체
    오늘
    어제
    • 전체 (20)
      • Computer Science (15)
      • Programming (2)
      • Projects (3)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    SQL 인젝션
    컨시스턴트 해싱
    해싱
    샤딩
    단방향 알고리즘
    캐시
    데이터베이스 인덱싱
    비동기적 처리
    해시 테이블
    해시 체이닝
    정규화
    성능 최적화
    B+트리
    BruteForce
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
Cloud9Ops
ALB와 TLS/SSL 인증서로 HTTPS 암호화 통신 구현하기
상단으로

티스토리툴바