🤖

본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.

⚠️

본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.

이미지 로딩 중...

Application Load Balancer 완벽 가이드 - 슬라이드 1/7
A

AI Generated

2025. 12. 20. · 3 Views

Application Load Balancer 완벽 가이드

AWS의 Application Load Balancer를 처음 배우는 개발자를 위한 실전 가이드입니다. ALB 생성부터 ECS 연동, 헬스 체크, HTTPS 설정까지 실무에 필요한 모든 내용을 다룹니다. 초급 개발자도 쉽게 따라할 수 있도록 단계별로 설명합니다.


목차

  1. ALB란_무엇인가
  2. ALB_생성하기
  3. 타겟_그룹_설정
  4. ECS_서비스_연동
  5. 헬스_체크_설정
  6. HTTPS_설정

1. ALB란 무엇인가

김개발 씨가 회사에서 처음으로 서버를 배포하게 되었습니다. 선배 박시니어 씨가 물었습니다.

"서버가 한 대면 괜찮은데, 나중에 트래픽이 늘어나면 어떻게 할 거예요?" 김개발 씨는 난감해졌습니다.

**Application Load Balancer(ALB)**는 AWS에서 제공하는 로드 밸런서입니다. 마치 백화점 안내 데스크 직원처럼, 들어오는 트래픽을 여러 서버에 골고루 분배해줍니다.

사용자 요청을 받아서 가장 적절한 서버로 연결해주는 역할을 합니다. 이를 통해 서비스의 가용성과 확장성을 높일 수 있습니다.

다음 코드를 살펴봅시다.

// AWS CLI로 ALB 생성하기
aws elbv2 create-load-balancer \
  --name my-application-lb \
  --subnets subnet-12345678 subnet-87654321 \
  --security-groups sg-12345678 \
  --scheme internet-facing \
  --type application \
  --ip-address-type ipv4 \
  --tags Key=Environment,Value=production

// 결과: ALB의 DNS 이름을 받습니다
// my-application-lb-1234567890.ap-northeast-2.elb.amazonaws.com

김개발 씨는 입사 2개월 차 백엔드 개발자입니다. 드디어 자신이 만든 API 서버를 실제 서비스에 배포하게 되었습니다.

설레는 마음으로 AWS 콘솔을 열었지만, 선배 박시니어 씨의 한마디에 멈칫했습니다. "서버 한 대로만 서비스하면, 그 서버가 죽으면 전체 서비스가 중단돼요.

그리고 사용자가 많아지면 감당할 수 없게 되죠." 김개발 씨는 고개를 끄덕였습니다. 그렇다면 어떻게 해야 할까요?

로드 밸런서의 필요성 쉽게 비유하자면, ALB는 마치 백화점 안내 데스크와 같습니다. 손님이 들어오면 "1층 화장품 코너는 지금 붐비니 2층 매장으로 안내해드릴게요"라고 말하는 직원을 상상해보세요.

ALB도 똑같이 사용자의 요청을 받아서 가장 여유 있는 서버로 안내해줍니다. 백화점에 안내 데스크가 없다면 어떻게 될까요?

모든 손님이 한 곳에만 몰려서 혼잡해질 것입니다. 서버도 마찬가지입니다.

로드 밸런서가 없던 시절 예전에는 개발자들이 직접 DNS 라운드 로빈을 설정하거나, 별도의 프록시 서버를 관리해야 했습니다. 서버 하나가 죽으면 수동으로 트래픽을 다른 서버로 옮겨야 했습니다.

새벽에 장애 알림을 받고 급하게 서버를 교체하는 일도 흔했습니다. 더 큰 문제는 확장성이었습니다.

갑자기 사용자가 늘어나면? 서버를 추가하더라도 수동으로 설정을 바꿔야 했습니다.

배포할 때마다 긴장의 연속이었습니다. Application Load Balancer의 등장 바로 이런 문제를 해결하기 위해 AWS는 ALB를 제공합니다.

ALB를 사용하면 자동으로 트래픽이 여러 서버에 분산됩니다. 어떤 서버가 응답하지 않으면 자동으로 다른 서버로 요청을 보냅니다.

무엇보다 헬스 체크를 통해 서버의 상태를 실시간으로 모니터링합니다. ALB vs CLB vs NLB AWS에는 세 가지 종류의 로드 밸런서가 있습니다.

**Classic Load Balancer(CLB)**는 예전 버전이고, **Network Load Balancer(NLB)**는 초고성능 TCP/UDP 트래픽을 처리합니다. 그렇다면 ALB는 언제 사용할까요?

ALB는 HTTP/HTTPS 트래픽을 처리하는 데 특화되어 있습니다. 웹 애플리케이션이나 REST API 서버에 최적화되어 있습니다.

URL 경로에 따라 다른 서버로 라우팅할 수도 있습니다. 예를 들어 /api로 시작하는 요청은 API 서버로, /web으로 시작하는 요청은 웹 서버로 보낼 수 있습니다.

구성 요소 이해하기 ALB를 생성하려면 몇 가지 필수 정보가 필요합니다. 첫째, 서브넷을 지정해야 합니다.

ALB는 최소 두 개의 가용 영역(AZ)에 배치되어야 합니다. 이렇게 하면 한 데이터센터에 문제가 생겨도 서비스가 계속 운영됩니다.

둘째, 보안 그룹을 설정합니다. 어떤 포트로 들어오는 트래픽을 허용할지 정의합니다.

보통 HTTP(80)와 HTTPS(443) 포트를 엽니다. 셋째, 스키마를 선택합니다.

internet-facing은 인터넷에서 접근 가능한 공개 로드 밸런서이고, internal은 VPC 내부에서만 접근 가능한 내부 로드 밸런서입니다. 실제 생성 과정 위의 코드를 살펴보겠습니다.

create-load-balancer 명령어로 ALB를 생성합니다. --name으로 로드 밸런서의 이름을 지정하고, --subnets로 두 개의 서브넷을 지정합니다.

--security-groups로 보안 그룹을 연결하고, --scheme internet-facing으로 인터넷에서 접근 가능하게 만듭니다. 명령어를 실행하면 AWS가 자동으로 DNS 이름을 생성해줍니다.

이 DNS 이름으로 사용자가 접근하게 됩니다. 예를 들어 my-application-lb-1234567890.ap-northeast-2.elb.amazonaws.com 같은 형태입니다.

실무 활용 사례 실제 스타트업 A사의 이야기입니다. 처음에는 EC2 인스턴스 한 대로 서비스를 시작했습니다.

그런데 TV 광고를 한 번 나가자 서버가 다운되었습니다. 급하게 ALB를 도입하고 서버를 세 대로 늘렸습니다.

그 후로는 트래픽이 몰려도 문제없이 서비스할 수 있었습니다. 대형 커머스 B사는 ALB의 경로 기반 라우팅을 활용합니다.

/admin으로 시작하는 요청은 관리자용 서버로, /shop으로 시작하는 요청은 쇼핑몰 서버로 분산합니다. 하나의 도메인으로 여러 마이크로서비스를 운영하고 있습니다.

주의사항 초보 개발자들이 흔히 하는 실수가 있습니다. ALB를 만들기만 하고 타겟 그룹을 연결하지 않는 것입니다.

ALB는 단지 교통 정리만 할 뿐, 실제로 요청을 받을 서버(타겟)를 등록해야 동작합니다. 또 다른 실수는 보안 그룹 설정을 잘못하는 것입니다.

ALB의 보안 그룹에서 80/443 포트를 열어야 하고, 백엔드 서버의 보안 그룹에서는 ALB의 보안 그룹으로부터의 접근을 허용해야 합니다. 정리 박시니어 씨의 설명을 들은 김개발 씨는 이제 이해했습니다.

"그래서 대부분의 상용 서비스에서 로드 밸런서를 사용하는 거군요!" ALB는 단순히 트래픽을 분산하는 것을 넘어, 서비스의 안정성과 확장성을 보장하는 핵심 인프라입니다. 처음에는 복잡해 보일 수 있지만, 한 번 설정해두면 서비스 운영이 훨씬 편해집니다.

실전 팁

💡 - ALB는 시간당 과금되므로, 개발 환경에서는 사용하지 않을 때 삭제하세요

  • DNS 이름이 길다면 Route 53으로 짧은 도메인을 연결하세요
  • 태그를 활용하여 환경별(dev, staging, prod)로 관리하세요

2. ALB 생성하기

김개발 씨가 AWS 콘솔에 로그인했습니다. EC2 메뉴에서 로드 밸런서를 찾았지만, 설정 항목이 너무 많아 어디서부터 시작해야 할지 막막했습니다.

박시니어 씨가 옆에서 단계별로 알려주기 시작했습니다.

ALB 생성은 AWS Management Console, AWS CLI, Terraform 등 다양한 방법으로 할 수 있습니다. 기본적으로 이름, 네트워크 설정, 보안 그룹, 리스너 설정이 필요합니다.

각 단계마다 신중하게 선택해야 나중에 수정하는 수고를 덜 수 있습니다. VPC와 서브넷 구성을 미리 이해하고 있으면 훨씬 쉽습니다.

다음 코드를 살펴봅시다.

// Terraform으로 ALB 생성하기
resource "aws_lb" "main" {
  name               = "my-app-alb"
  internal           = false
  load_balancer_type = "application"
  security_groups    = [aws_security_group.alb.id]
  subnets            = [aws_subnet.public_a.id, aws_subnet.public_c.id]

  enable_deletion_protection = false

  tags = {
    Environment = "production"
    Service     = "api"
  }
}

김개발 씨는 처음으로 실제 프로덕션 환경에 ALB를 생성하게 되었습니다. 회사 위키에 있는 가이드를 보면서 따라 하려 했지만, 용어들이 생소했습니다.

VPC는 뭐고, 서브넷은 또 뭔가요? 박시니어 씨가 옆에서 설명해주었습니다.

"걱정하지 마세요. 하나씩 차근차근 해봅시다." 콘솔 vs CLI vs IaC ALB를 생성하는 방법은 크게 세 가지입니다.

AWS Management Console은 웹 브라우저에서 클릭으로 설정하는 방식입니다. 처음 배울 때는 이 방법이 가장 직관적입니다.

각 항목이 무엇을 의미하는지 바로 확인할 수 있습니다. AWS CLI는 명령줄 인터페이스로 스크립트를 작성하여 자동화할 수 있습니다.

여러 개의 ALB를 반복적으로 생성할 때 유용합니다. Terraform이나 CloudFormation 같은 IaC(Infrastructure as Code) 도구를 사용하면 인프라를 코드로 관리할 수 있습니다.

버전 관리가 가능하고, 팀원들과 공유하기 좋습니다. 실무에서는 주로 이 방법을 사용합니다.

VPC와 서브넷 이해하기 ALB를 만들기 전에 먼저 네트워크 구조를 이해해야 합니다. **VPC(Virtual Private Cloud)**는 여러분만의 가상 네트워크 공간입니다.

마치 아파트 단지라고 생각하면 됩니다. 그 안에서 여러분의 리소스들이 안전하게 운영됩니다.

서브넷은 VPC 내부의 작은 네트워크 구역입니다. 아파트 단지 안에서 동별로 나눈 것과 비슷합니다.

퍼블릭 서브넷은 인터넷과 연결되고, 프라이빗 서브넷은 외부에서 직접 접근할 수 없습니다. 가용 영역의 중요성 ALB는 최소 두 개의 **가용 영역(Availability Zone, AZ)**에 배치해야 합니다.

이게 왜 중요할까요? 서울 리전을 예로 들어봅시다.

서울 리전에는 ap-northeast-2a, ap-northeast-2c 같은 여러 가용 영역이 있습니다. 각 가용 영역은 물리적으로 떨어진 데이터센터입니다.

만약 한 데이터센터에 정전이 발생하더라도, 다른 가용 영역에 있는 ALB가 계속 서비스를 제공합니다. 이것이 바로 **고가용성(High Availability)**입니다.

보안 그룹 설정 보안 그룹은 방화벽과 같습니다. 어떤 트래픽을 허용하고 차단할지 정의합니다.

ALB의 보안 그룹에서는 일반적으로 인터넷에서 들어오는 HTTP(80)와 HTTPS(443) 포트를 엽니다. 모든 IP(0.0.0.0/0)에서 접근 가능하게 설정합니다.

하지만 관리자 페이지처럼 특정 IP에서만 접근해야 한다면, 회사 사무실 IP만 허용하도록 제한할 수 있습니다. Terraform 코드 분석 위의 Terraform 코드를 살펴보겠습니다.

resource "aws_lb" "main"으로 ALB 리소스를 정의합니다. name은 로드 밸런서의 이름이고, internal = false는 인터넷에서 접근 가능한 공개 로드 밸런서를 의미합니다.

load_balancer_type = "application"으로 ALB 타입을 지정합니다. security_groups는 보안 그룹 ID를 배열로 받고, subnets는 최소 두 개의 서브넷 ID를 지정합니다.

enable_deletion_protection은 실수로 삭제하는 것을 방지하는 옵션입니다. 프로덕션 환경에서는 true로 설정하는 것이 좋습니다.

태그 전략 tags는 리소스를 분류하고 관리하는 데 매우 유용합니다. 대부분의 회사에서는 태그 전략을 가지고 있습니다.

Environment로 개발/스테이징/프로덕션을 구분하고, Service로 어떤 서비스에 속하는지 표시합니다. Team, Owner, CostCenter 같은 태그를 추가하면 비용 관리도 쉬워집니다.

나중에 AWS Cost Explorer에서 "프로덕션 환경의 API 서비스가 얼마나 비용이 들었지?"라고 쉽게 조회할 수 있습니다. 실무 시나리오 실제 회사에서는 어떻게 진행될까요?

먼저 인프라 팀이 VPC와 서브넷을 미리 구성해둡니다. 개발자는 이미 만들어진 네트워크 환경에서 ALB를 생성하면 됩니다.

회사 표준 Terraform 모듈이 있다면 몇 줄만 수정해서 바로 사용할 수 있습니다. 한 스타트업에서는 개발 환경 ALB는 오전 9시에 자동으로 생성하고, 저녁 6시에 자동으로 삭제하도록 스케줄링했습니다.

비용을 크게 절감할 수 있었습니다. 주의사항 초보자들이 자주 하는 실수 중 하나는 서브넷을 한 가용 영역에만 배치하는 것입니다.

"왜 안 만들어지지?"하고 고민하다가 에러 메시지를 자세히 읽어보면 "두 개 이상의 AZ가 필요합니다"라고 나옵니다. 또 다른 실수는 프라이빗 서브넷에 ALB를 만드는 것입니다.

인터넷에서 접근해야 하는데 퍼블릭 서브넷에 배치하지 않으면 접근이 불가능합니다. 정리 김개발 씨는 박시니어 씨의 도움으로 무사히 첫 ALB를 생성했습니다.

"생각보다 복잡하지 않네요!" 처음에는 설정 항목이 많아서 어렵게 느껴지지만, 한 번 만들어보면 패턴이 보입니다. VPC, 서브넷, 보안 그룹의 개념만 이해하면 나머지는 자연스럽게 따라옵니다.

실전 팁

💡 - 개발 환경에서는 deletion protection을 false로 설정하여 쉽게 삭제할 수 있게 하세요

  • 회사에서 정한 네이밍 컨벤션이 있다면 반드시 따르세요 (예: {env}-{service}-alb)
  • Terraform state를 S3에 저장하고 팀원과 공유하세요

3. 타겟 그룹 설정

김개발 씨가 ALB를 만들었지만, 접속해보니 503 에러가 발생했습니다. 박시니어 씨가 웃으며 말했습니다.

"ALB만 만들면 뭐해요. 트래픽을 받을 서버를 연결해야죠." 타겟 그룹이 필요한 시점이었습니다.

**타겟 그룹(Target Group)**은 ALB가 트래픽을 전달할 서버들의 집합입니다. 마치 택배 기사가 물건을 배달할 주소록과 같습니다.

EC2 인스턴스, ECS 태스크, Lambda 함수, IP 주소 등을 타겟으로 등록할 수 있습니다. 헬스 체크 설정을 통해 건강한 타겟에만 트래픽을 보냅니다.

다음 코드를 살펴봅시다.

// Terraform으로 타겟 그룹 생성
resource "aws_lb_target_group" "app" {
  name     = "my-app-tg"
  port     = 3000
  protocol = "HTTP"
  vpc_id   = aws_vpc.main.id
  target_type = "ip"  // ip, instance, lambda 중 선택

  health_check {
    enabled             = true
    healthy_threshold   = 2
    interval            = 30
    matcher             = "200"
    path                = "/health"
    port                = "traffic-port"
    protocol            = "HTTP"
    timeout             = 5
    unhealthy_threshold = 2
  }

  deregistration_delay = 30

  tags = {
    Name = "my-app-target-group"
  }
}

김개발 씨는 신이 나서 ALB의 DNS 주소로 접속했습니다. 그런데 화면에 503 Service Unavailable이라는 에러가 나타났습니다.

뭔가 잘못된 걸까요? 박시니어 씨가 설명했습니다.

"ALB는 교통 정리만 하는 거예요. 실제로 요청을 처리할 서버를 연결해야 합니다.

그게 바로 타겟 그룹이에요." 타겟 그룹이란? 타겟 그룹은 쉽게 말하면 전화번호부입니다. ALB가 "이 요청을 누구한테 전달하지?"라고 물어보면, 타겟 그룹이 "A 서버, B 서버, C 서버 중에 선택하세요"라고 알려줍니다.

택배 회사를 생각해보세요. 고객 주문이 들어오면 배송 기사가 주소록을 보고 해당 지역 담당자에게 전달합니다.

타겟 그룹도 똑같이 ALB에게 "이 요청은 여기로 보내세요"라고 알려주는 역할입니다. 타겟 타입의 종류 타겟 그룹에는 세 가지 타입이 있습니다.

instance 타입은 EC2 인스턴스 ID를 직접 등록합니다. "i-1234567890abcdef0" 같은 인스턴스 ID로 관리합니다.

EC2를 직접 운영할 때 사용합니다. ip 타입은 IP 주소로 등록합니다.

ECS Fargate처럼 인스턴스가 추상화된 환경이나, VPC 외부의 온프레미스 서버를 등록할 때 유용합니다. lambda 타입은 Lambda 함수를 타겟으로 등록합니다.

서버리스 아키텍처에서 ALB가 Lambda를 호출할 때 사용합니다. 헬스 체크의 중요성 타겟 그룹의 핵심 기능 중 하나가 헬스 체크입니다.

실제 서비스를 운영하다 보면 서버가 갑자기 응답하지 않는 경우가 있습니다. 데이터베이스 연결이 끊기거나, 메모리가 부족하거나, 버그로 인해 크래시가 날 수 있습니다.

ALB는 주기적으로 각 서버에 "살아 있니?"라고 물어봅니다. 정해진 경로(예: /health)로 HTTP 요청을 보내고, 200 OK 응답이 오는지 확인합니다.

만약 응답이 없거나 에러가 나면 그 서버를 타겟에서 제외합니다. 코드 분석 - 헬스 체크 설정 위의 코드에서 health_check 블록을 자세히 살펴보겠습니다.

path = "/health"는 헬스 체크 요청을 보낼 경로입니다. 보통 서버에 /health 엔드포인트를 만들어서 간단히 "OK"를 반환하게 합니다.

interval = 30은 30초마다 체크한다는 의미입니다. timeout = 5는 5초 안에 응답이 와야 한다는 뜻입니다.

healthy_threshold = 2는 연속 2번 성공하면 건강한 상태로 판단합니다. unhealthy_threshold = 2는 연속 2번 실패하면 비정상 상태로 간주합니다.

matcher = "200"은 HTTP 상태 코드가 200일 때만 성공으로 봅니다. 만약 200, 201, 204를 모두 허용하고 싶다면 "200,201,204" 또는 "200-299"로 설정할 수 있습니다.

Deregistration Delay deregistration_delay = 30은 매우 중요한 설정입니다. 서버를 타겟 그룹에서 제거할 때, 즉시 제거하면 진행 중이던 요청이 실패할 수 있습니다.

그래서 일정 시간 동안 "배수(draining)" 상태로 둡니다. 새 요청은 받지 않지만, 기존 요청은 처리하게 합니다.

30초면 대부분의 HTTP 요청은 완료됩니다. 만약 장시간 처리하는 업로드나 다운로드가 있다면 이 값을 늘려야 합니다.

포트와 프로토콜 port = 3000은 타겟 서버가 3000번 포트에서 요청을 받는다는 의미입니다. Node.js Express 서버가 보통 3000번 포트를 사용하죠.

protocol = "HTTP"는 HTTP로 통신합니다. ALB와 타겟 간 통신도 HTTPS로 암호화하고 싶다면 "HTTPS"로 설정할 수 있습니다.

하지만 대부분 내부 통신이므로 HTTP를 사용합니다. 실무 활용 사례 한 금융 서비스 회사에서는 타겟 그룹을 두 개 운영합니다.

하나는 일반 사용자용, 다른 하나는 VIP 고객용입니다. VIP용 서버는 성능이 더 좋은 인스턴스를 사용하고, 별도의 타겟 그룹으로 관리합니다.

커머스 회사에서는 배포할 때 블루-그린 배포를 사용합니다. 새 버전 서버를 별도 타겟 그룹에 올리고, 헬스 체크가 성공하면 트래픽을 전환합니다.

문제가 있으면 즉시 롤백할 수 있습니다. 주의사항 초보자들이 자주 하는 실수는 헬스 체크 경로를 잘못 설정하는 것입니다.

서버에 /health 엔드포인트를 만들지 않았는데 헬스 체크 경로를 /health로 설정하면 모든 타겟이 unhealthy 상태가 됩니다. 또 다른 실수는 보안 그룹 설정입니다.

타겟 서버의 보안 그룹에서 ALB로부터의 트래픽을 허용하지 않으면 헬스 체크가 실패합니다. 정리 김개발 씨는 타겟 그룹을 생성하고, EC2 인스턴스를 등록했습니다.

몇 분 후 헬스 체크가 성공하고, ALB를 통해 정상적으로 접속할 수 있었습니다. "이제 서버가 죽어도 자동으로 다른 서버로 트래픽이 가겠네요!" 김개발 씨는 뿌듯했습니다.

실전 팁

💡 - /health 엔드포인트는 데이터베이스 연결도 체크하도록 구현하세요

  • deregistration_delay는 평균 응답 시간의 2-3배로 설정하세요
  • 타겟이 하나도 healthy하지 않으면 CloudWatch 알람을 설정하세요

4. ECS 서비스 연동

김개발 씨가 Docker 컨테이너로 애플리케이션을 배포하고 싶다고 말했습니다. 박시니어 씨가 "그럼 ECS를 사용하고, ALB와 연동하면 완벽해요"라고 제안했습니다.

하지만 ECS가 뭔지, 어떻게 연동하는지 막막했습니다.

**Amazon ECS(Elastic Container Service)**는 컨테이너 오케스트레이션 서비스입니다. Docker 컨테이너를 쉽게 배포하고 관리할 수 있습니다.

ECS 서비스에 ALB의 타겟 그룹을 연결하면 자동으로 컨테이너가 등록되고 제거됩니다. 컨테이너가 시작되면 자동으로 타겟에 추가되고, 종료되면 자동으로 제거됩니다.

다음 코드를 살펴봅시다.

// Terraform으로 ECS 서비스에 ALB 연동
resource "aws_ecs_service" "app" {
  name            = "my-app-service"
  cluster         = aws_ecs_cluster.main.id
  task_definition = aws_ecs_task_definition.app.arn
  desired_count   = 3
  launch_type     = "FARGATE"

  network_configuration {
    subnets          = [aws_subnet.private_a.id, aws_subnet.private_c.id]
    security_groups  = [aws_security_group.ecs_task.id]
    assign_public_ip = false
  }

  load_balancer {
    target_group_arn = aws_lb_target_group.app.arn
    container_name   = "my-app"
    container_port   = 3000
  }

  depends_on = [aws_lb_listener.http]
}

김개발 씨는 Docker를 사용해서 로컬에서 개발하고 있었습니다. 이제 이것을 AWS에서 운영하고 싶은데, EC2에 직접 Docker를 설치하는 것보다 더 나은 방법이 있을까요?

박시니어 씨가 ECS를 소개했습니다. "컨테이너 관리를 자동화해주는 서비스예요.

ALB와 연동하면 정말 편리합니다." ECS란 무엇인가? ECS는 쉽게 말하면 Docker 컨테이너를 위한 자동화된 관리자입니다. 여러분이 식당 주인이라고 상상해보세요.

손님이 많아지면 직원을 더 고용하고, 손님이 줄면 직원을 줄입니다. ECS도 똑같이 트래픽에 따라 컨테이너를 늘렸다 줄였다 합니다.

Fargate vs EC2 Launch Type ECS에는 두 가지 실행 방식이 있습니다. EC2 Launch Type은 여러분이 직접 EC2 인스턴스를 관리합니다.

인스턴스 위에 컨테이너가 실행됩니다. 비용을 최적화하고 싶거나, 특정 하드웨어 요구사항이 있을 때 사용합니다.

Fargate는 서버를 관리할 필요가 없습니다. AWS가 알아서 인프라를 관리해줍니다.

개발자는 컨테이너만 신경 쓰면 됩니다. 더 비싸지만 훨씬 편리합니다.

대부분의 스타트업은 Fargate를 선호합니다. 인프라 관리에 시간을 쓰느니 비즈니스 로직에 집중하는 게 낫기 때문입니다.

ECS 서비스 설정 desired_count = 3은 항상 3개의 컨테이너를 유지하라는 의미입니다. 하나가 죽으면 자동으로 새 컨테이너를 시작합니다.

network_configuration에서 프라이빗 서브넷을 지정했습니다. 컨테이너는 외부에 직접 노출되지 않고, ALB를 통해서만 접근 가능합니다.

이것이 보안상 안전한 구성입니다. assign_public_ip = false는 퍼블릭 IP를 할당하지 않습니다.

컨테이너가 인터넷에 접근해야 한다면 NAT Gateway를 통해야 합니다. ALB 연동의 핵심 load_balancer 블록이 가장 중요합니다.

target_group_arn으로 앞서 만든 타겟 그룹을 지정합니다. container_name은 태스크 정의에서 정의한 컨테이너 이름입니다.

container_port = 3000은 컨테이너가 3000번 포트에서 요청을 받는다는 뜻입니다. 이렇게 설정하면 마법처럼 자동으로 연동됩니다.

ECS가 새 컨테이너를 시작하면, 그 컨테이너의 IP를 타겟 그룹에 자동으로 등록합니다. 컨테이너가 종료되면 자동으로 제거합니다.

자동 확장과 축소 실무에서는 Auto Scaling을 함께 설정합니다. 트래픽이 많을 때는 컨테이너를 10개까지 늘리고, 새벽에는 2개로 줄입니다.

CPU 사용률이 70%를 넘으면 자동으로 컨테이너를 추가합니다. 이 모든 과정에서 ALB는 자동으로 새 컨테이너를 타겟에 추가하고, 헬스 체크가 성공하면 트래픽을 보내기 시작합니다.

Blue-Green 배포 ECS와 ALB를 활용하면 무중단 배포가 쉽습니다. 새 버전의 태스크 정의를 만들고, ECS 서비스를 업데이트합니다.

ECS가 새 컨테이너를 시작하고, 헬스 체크가 성공하면 ALB가 트래픽을 보냅니다. 이 과정에서 사용자는 아무것도 모릅니다.

서비스 중단이 없습니다. 문제가 발생하면?

이전 태스크 정의로 롤백하면 됩니다. 몇 분 안에 이전 상태로 돌아갑니다.

보안 그룹 구성 보안 그룹 설정이 매우 중요합니다. ALB의 보안 그룹은 인터넷(0.0.0.0/0)에서 80/443 포트를 허용합니다.

ECS 태스크의 보안 그룹은 ALB의 보안 그룹으로부터만 3000번 포트를 허용합니다. 이렇게 하면 컨테이너에 직접 접근할 수 없습니다.

모든 트래픽은 반드시 ALB를 거쳐야 합니다. 보안이 한층 강화됩니다.

실무 사례 한 스타트업은 ECS + ALB 조합으로 서버를 운영합니다. 평소에는 컨테이너 3개로 서비스하다가, TV 광고 시간대에는 자동으로 20개까지 늘어납니다.

광고가 끝나면 다시 3개로 줄어듭니다. 비용은 실제 사용한 만큼만 냅니다.

대형 플랫폼에서는 여러 마이크로서비스를 각각의 ECS 서비스로 운영합니다. 사용자 서비스, 주문 서비스, 결제 서비스가 각각 독립적으로 배포되고 확장됩니다.

하나의 ALB가 경로별로 다른 타겟 그룹으로 라우팅합니다. 주의사항 처음 설정할 때 가장 많이 하는 실수는 depends_on을 빼먹는 것입니다.

리스너가 생성되기 전에 ECS 서비스가 생성되면 에러가 발생합니다. 또 다른 실수는 컨테이너 포트와 타겟 그룹 포트를 다르게 설정하는 것입니다.

반드시 일치해야 합니다. 정리 김개발 씨는 ECS 서비스를 배포하고, ALB를 통해 접속해봤습니다.

컨테이너가 자동으로 타겟에 등록되고, 헬스 체크가 성공했습니다. "이제 배포할 때마다 수동으로 서버를 등록할 필요가 없겠네요!" ECS와 ALB의 조합은 현대적인 컨테이너 기반 애플리케이션의 표준입니다.

한 번 설정해두면 배포와 확장이 정말 쉬워집니다.

실전 팁

💡 - ECS 서비스 배포 시 deployment_minimum_healthy_percent를 50으로 설정하면 롤링 업데이트가 빨라집니다

  • CloudWatch Logs로 컨테이너 로그를 수집하도록 설정하세요
  • Task Definition에서 CPU와 메모리를 적절히 설정하여 비용을 최적화하세요

5. 헬스 체크 설정

김개발 씨가 배포를 했는데, 사용자들이 간헐적으로 에러를 겪는다고 불평했습니다. 로그를 보니 일부 컨테이너가 데이터베이스 연결에 실패했는데도 트래픽을 받고 있었습니다.

박시니어 씨가 "헬스 체크를 제대로 설정하지 않았군요"라고 지적했습니다.

헬스 체크는 서버가 정상적으로 요청을 처리할 수 있는지 주기적으로 확인하는 기능입니다. 단순히 서버가 살아있는지만 체크하는 것이 아니라, 실제로 서비스가 가능한 상태인지 검증해야 합니다.

데이터베이스 연결, 외부 API 연결 등 중요한 의존성을 함께 체크하는 것이 좋습니다. 적절한 임계값 설정으로 불필요한 재시작을 방지할 수 있습니다.

다음 코드를 살펴봅시다.

// Express.js 헬스 체크 엔드포인트 예제
import express from 'express';
import { Pool } from 'pg';

const app = express();
const db = new Pool({ /* DB 설정 */ });

// 간단한 헬스 체크 (권장하지 않음)
app.get('/health', (req, res) => {
  res.status(200).send('OK');
});

// 제대로 된 헬스 체크 (권장)
app.get('/health', async (req, res) => {
  try {
    // 데이터베이스 연결 확인
    await db.query('SELECT 1');

    // 추가 의존성 체크 (Redis, 외부 API 등)
    // await redis.ping();

    res.status(200).json({
      status: 'healthy',
      timestamp: new Date().toISOString(),
      uptime: process.uptime()
    });
  } catch (error) {
    res.status(503).json({
      status: 'unhealthy',
      error: error.message
    });
  }
});

app.listen(3000);

김개발 씨는 처음에 간단하게 /health 엔드포인트에서 "OK"만 반환하도록 만들었습니다. 서버가 실행 중이기만 하면 200 OK를 보냈습니다.

별 문제 없을 것 같았습니다. 하지만 실제 운영 중에 문제가 발생했습니다.

서버는 살아있지만 데이터베이스 연결이 끊긴 상태였습니다. 헬스 체크는 통과했지만, 실제 요청은 모두 실패했습니다.

박시니어 씨가 설명했습니다. "헬스 체크는 단순히 '살아있음'을 확인하는 게 아니에요.

'정상적으로 서비스할 수 있는 상태'를 확인해야 합니다." 헬스 체크의 진짜 목적 헬스 체크는 마치 비행기 이륙 전 점검과 같습니다. 조종사가 "비행기가 움직이네"만 확인하고 이륙하면 위험합니다.

연료는 충분한지, 엔진은 정상인지, 통신 장비는 작동하는지 모두 확인해야 합니다. 서버도 마찬가지입니다.

프로세스가 실행 중이라는 것만으로는 부족합니다. 데이터베이스에 연결할 수 있는지, 필수 환경 변수가 로드되었는지, 외부 API에 접근 가능한지 확인해야 합니다.

Shallow vs Deep 헬스 체크 헬스 체크에는 두 가지 접근 방식이 있습니다. Shallow 헬스 체크는 빠르게 "OK"만 반환합니다.

서버가 HTTP 요청을 받을 수 있다는 것만 확인합니다. 장점은 빠르고 가볍지만, 실제 문제를 놓칠 수 있습니다.

Deep 헬스 체크는 모든 의존성을 실제로 확인합니다. 데이터베이스에 쿼리를 실행하고, Redis에 핑을 보내고, S3 접근 권한을 확인합니다.

더 정확하지만 시간이 걸립니다. 실무에서는 두 가지를 적절히 혼합합니다.

ALB 헬스 체크는 가벼운 체크를 사용하고, 별도의 모니터링으로 깊은 체크를 합니다. 코드 분석 - 제대로 된 헬스 체크 위의 두 번째 헬스 체크 코드를 살펴봅시다.

await db.query('SELECT 1')로 실제로 데이터베이스에 쿼리를 실행합니다. 연결이 끊겼거나 타임아웃이 발생하면 에러가 throw됩니다.

catch 블록에서 503 상태 코드를 반환합니다. 503은 "Service Unavailable"을 의미합니다.

ALB는 이것을 보고 "이 서버는 지금 서비스할 수 없구나"라고 판단하고 트래픽을 보내지 않습니다. uptimetimestamp도 함께 반환합니다.

나중에 로그를 분석할 때 유용합니다. 타임아웃 설정의 중요성 헬스 체크에서 데이터베이스 쿼리가 너무 오래 걸리면 어떻게 될까요?

ALB의 헬스 체크 타임아웃이 5초인데, 데이터베이스 쿼리가 10초 걸린다면 항상 타임아웃으로 실패합니다. 설정을 잘못하면 정상적인 서버도 unhealthy로 판정됩니다.

따라서 헬스 체크용 쿼리는 가능한 한 빠르게 실행되어야 합니다. SELECT 1처럼 단순한 쿼리를 사용하는 이유입니다.

복잡한 JOIN 쿼리는 절대 사용하지 마세요. Healthy와 Unhealthy 임계값 ALB 타겟 그룹 설정에서 healthy_thresholdunhealthy_threshold가 중요합니다.

healthy_threshold = 2는 연속 2번 성공해야 healthy 상태가 된다는 뜻입니다. 한 번 성공했다고 바로 트래픽을 보내지 않습니다.

우연히 한 번 성공했을 수도 있기 때문입니다. unhealthy_threshold = 2는 연속 2번 실패해야 unhealthy 상태가 됩니다.

네트워크 지연으로 일시적으로 실패할 수 있으므로, 바로 제외하지 않습니다. 이 값들을 적절히 조정하면 불필요한 재시작을 줄일 수 있습니다.

인터벌과 타임아웃의 균형 interval = 30은 30초마다 체크합니다. 너무 짧으면 서버에 부담을 주고, 너무 길면 장애를 늦게 발견합니다.

대부분의 경우 30초가 적당합니다. 고가용성이 매우 중요한 서비스는 10초로 줄이기도 합니다.

반대로 헬스 체크가 무거운 경우 60초로 늘립니다. timeout = 5는 5초 안에 응답이 와야 합니다.

데이터베이스 쿼리 타임아웃을 3초로 설정했다면, 헬스 체크 타임아웃은 5초로 여유를 둡니다. 실무 사례 한 스타트업은 초기에 단순한 헬스 체크만 사용했습니다.

어느 날 RDS가 재시작되면서 모든 서버의 DB 연결이 끊겼습니다. 하지만 헬스 체크는 통과했고, 사용자들은 계속 에러를 겪었습니다.

이후 DB 연결을 확인하는 헬스 체크를 추가했습니다. 대형 플랫폼에서는 Graceful Shutdown을 구현합니다.

SIGTERM 신호를 받으면 헬스 체크가 즉시 실패하도록 만듭니다. ALB가 트래픽을 보내지 않게 하고, 기존 요청은 모두 처리한 후 종료합니다.

모니터링과 알람 헬스 체크 실패는 CloudWatch 메트릭으로 수집됩니다. UnHealthyHostCount 메트릭이 0보다 크면 알람을 보냅니다.

Slack으로 즉시 알림을 받아서 빠르게 대응할 수 있습니다. HealthyHostCount가 원하는 개수보다 적으면 경고를 보냅니다.

예를 들어 3개를 유지하려는데 2개만 healthy하면 문제가 있는 것입니다. 주의사항 헬스 체크 엔드포인트에 인증을 걸면 안 됩니다.

ALB는 토큰 없이 요청을 보내기 때문에 항상 실패합니다. 또 다른 실수는 헬스 체크에서 너무 많은 것을 확인하려는 것입니다.

외부 API를 10개나 호출하면 헬스 체크가 느려지고, 하나라도 실패하면 서버 전체가 unhealthy가 됩니다. 핵심 의존성만 확인하세요.

정리 김개발 씨는 헬스 체크를 제대로 구현했습니다. 데이터베이스 연결을 확인하고, 적절한 타임아웃을 설정했습니다.

이제 서버가 정말 문제 있을 때만 트래픽이 차단됩니다. "헬스 체크가 이렇게 중요한 줄 몰랐어요." 김개발 씨는 운영의 중요성을 깨달았습니다.

실전 팁

💡 - /health 엔드포인트는 인증을 요구하지 않도록 설정하세요

  • DB 쿼리는 간단한 SELECT 1로 충분합니다
  • 헬스 체크 실패 로그를 CloudWatch에 남겨서 원인 분석에 활용하세요

6. HTTPS 설정

김개발 씨가 서비스를 오픈하려는데, 브라우저에서 "안전하지 않은 사이트"라고 경고가 뜹니다. 박시니어 씨가 "HTTPS 설정을 안 했군요.

요즘은 HTTPS가 필수예요"라고 말했습니다. SSL 인증서는 어떻게 발급받고, ALB에는 어떻게 적용할까요?

HTTPS는 HTTP 통신을 암호화하여 보안을 강화하는 프로토콜입니다. ALB는 SSL/TLS 종료(termination) 기능을 제공하여 인증서 관리를 간편하게 해줍니다.

AWS Certificate Manager(ACM)로 무료 SSL 인증서를 발급받고, ALB 리스너에 연결하면 됩니다. HTTP는 자동으로 HTTPS로 리다이렉트하도록 설정하는 것이 좋습니다.

다음 코드를 살펴봅시다.

// Terraform으로 HTTPS 리스너 설정
resource "aws_lb_listener" "https" {
  load_balancer_arn = aws_lb.main.arn
  port              = "443"
  protocol          = "HTTPS"
  ssl_policy        = "ELBSecurityPolicy-TLS13-1-2-2021-06"
  certificate_arn   = aws_acm_certificate.main.arn

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

// HTTP를 HTTPS로 리다이렉트
resource "aws_lb_listener" "http" {
  load_balancer_arn = aws_lb.main.arn
  port              = "80"
  protocol          = "HTTP"

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

김개발 씨가 드디어 서비스를 공개하려고 URL을 공유했습니다. 하지만 동료들이 "브라우저에서 보안 경고가 뜬다"고 말했습니다.

Chrome에서는 "주의 요함"이라는 무서운 메시지가 나타났습니다. 박시니어 씨가 화면을 보더니 "아직 HTTP로 서비스하고 있네요.

2025년에 HTTP는 안 돼요"라고 말했습니다. 왜 HTTPS가 필수인가? HTTPS는 HTTP에 보안(Security) 레이어를 추가한 것입니다.

카페에서 공용 Wi-Fi를 사용한다고 상상해보세요. HTTP로 통신하면 누군가 중간에서 여러분의 비밀번호를 가로챌 수 있습니다.

마치 엽서로 비밀 편지를 보내는 것과 같습니다. HTTPS는 암호화된 봉투에 넣어서 보냅니다.

중간에 누가 가로채도 내용을 볼 수 없습니다. 사용자의 개인정보, 로그인 정보, 결제 정보를 보호합니다.

브라우저의 요구사항 Chrome, Safari, Firefox 같은 현대 브라우저는 HTTP 사이트를 "안전하지 않음"으로 표시합니다. 주소창에 자물쇠 아이콘이 없으면 사용자들이 불안해합니다.

더 중요한 것은 많은 기능이 HTTPS를 요구한다는 점입니다. 위치 정보, 카메라 접근, 푸시 알림 같은 기능은 HTTPS가 아니면 작동하지 않습니다.

Progressive Web App(PWA)도 HTTPS가 필수입니다. 검색 엔진도 HTTPS 사이트를 우대합니다.

Google은 HTTPS를 검색 순위 요소로 사용합니다. AWS Certificate Manager(ACM) 과거에는 SSL 인증서를 구매하고 갱신하는 것이 번거로웠습니다.

매년 수십만 원을 내고, 만료되기 전에 갱신해야 했습니다. AWS는 **ACM(AWS Certificate Manager)**을 통해 무료로 SSL 인증서를 제공합니다.

자동으로 갱신되므로 만료 걱정이 없습니다. ALB, CloudFront, API Gateway에서 바로 사용할 수 있습니다.

도메인 소유권만 확인하면 몇 분 안에 인증서를 발급받을 수 있습니다. DNS 검증이나 이메일 검증 중 하나를 선택하면 됩니다.

SSL/TLS 종료(Termination) ALB는 SSL/TLS 종료 기능을 제공합니다. 사용자는 HTTPS로 ALB에 접속합니다.

ALB가 SSL을 해독하고, 백엔드 서버에는 HTTP로 전달합니다. 백엔드 서버는 SSL 인증서를 관리할 필요가 없습니다.

훨씬 간단합니다. 물론 ALB와 백엔드 간에도 HTTPS를 사용할 수 있습니다.

보안이 매우 중요한 금융권에서는 종단 간 암호화(end-to-end encryption)를 사용합니다. 하지만 대부분의 경우 ALB에서 종료하는 것으로 충분합니다.

HTTPS 리스너 설정 위의 코드에서 HTTPS 리스너를 살펴봅시다. port = "443"은 HTTPS의 표준 포트입니다.

protocol = "HTTPS"로 설정하고, certificate_arn에 ACM 인증서의 ARN을 지정합니다. ssl_policy는 어떤 TLS 버전과 암호화 알고리즘을 사용할지 정의합니다.

ELBSecurityPolicy-TLS13-1-2-2021-06은 TLS 1.2와 1.3을 지원하는 최신 정책입니다. 보안과 호환성의 균형을 맞춥니다.

HTTP to HTTPS 리다이렉트 사용자가 http://example.com으로 접속하면 어떻게 될까요? HTTP 리스너에서 자동으로 https://example.com으로 리다이렉트합니다.

status_code = "HTTP_301"은 영구 이동을 의미합니다. 브라우저가 이 정보를 캐시해서 다음부터는 자동으로 HTTPS로 접속합니다.

이렇게 하면 사용자가 어떻게 접속하든 항상 HTTPS로 연결됩니다. 보안 경고를 볼 일이 없습니다.

다중 도메인과 와일드카드 인증서 하나의 ALB에 여러 도메인을 연결할 수 있습니다. example.com, www.example.com, api.example.com을 모두 같은 ALB에 연결할 수 있습니다.

각 도메인마다 인증서를 발급받거나, 와일드카드 인증서 *.example.com을 사용할 수 있습니다. SNI(Server Name Indication)를 활용하면 하나의 IP 주소로 여러 SSL 인증서를 제공할 수 있습니다.

도메인별로 다른 인증서를 사용할 수 있습니다. 실무 사례 한 스타트업은 처음에 Let's Encrypt로 EC2에 직접 인증서를 설치했습니다.

3개월마다 갱신해야 해서 번거로웠습니다. ALB와 ACM으로 전환하자 모든 것이 자동화되었습니다.

더 이상 만료 알람에 깜짝 놀랄 일이 없습니다. 대형 플랫폼에서는 HSTS(HTTP Strict Transport Security) 헤더를 추가합니다.

한 번 HTTPS로 접속하면, 브라우저가 이후 모든 요청을 강제로 HTTPS로 보냅니다. 중간자 공격을 더욱 효과적으로 방어합니다.

성능과 비용 HTTPS가 HTTP보다 느리지 않을까요? 과거에는 SSL 핸드셰이크로 인한 오버헤드가 있었습니다.

하지만 현대의 하드웨어와 TLS 1.3은 매우 빠릅니다. 체감할 수 있는 차이는 거의 없습니다.

ALB의 SSL 종료는 무료입니다. 추가 비용이 발생하지 않습니다.

ACM 인증서도 무료입니다. HTTPS를 사용하지 않을 이유가 없습니다.

주의사항 ACM 인증서는 리전별로 발급받습니다. ALB가 서울 리전에 있다면 인증서도 서울 리전에서 발급받아야 합니다.

CloudFront에서 사용하려면 버지니아(us-east-1) 리전에서 발급받아야 합니다. 도메인 검증이 완료되지 않으면 인증서가 "검증 대기 중" 상태로 남습니다.

DNS 레코드를 제대로 추가했는지 확인하세요. Route 53을 사용하면 자동으로 추가할 수 있습니다.

정리 김개발 씨는 ACM에서 인증서를 발급받고, ALB 리스너에 연결했습니다. HTTP는 HTTPS로 리다이렉트하도록 설정했습니다.

이제 브라우저 주소창에 자물쇠 아이콘이 나타납니다. "이제 사용자들이 안심하고 서비스를 이용할 수 있겠네요!" 김개발 씨는 뿌듯했습니다.

HTTPS는 더 이상 선택이 아닌 필수입니다. ALB와 ACM을 활용하면 복잡한 인증서 관리 없이 쉽게 HTTPS를 적용할 수 있습니다.

실전 팁

💡 - ACM 인증서는 자동 갱신되지만, 도메인 검증 레코드는 삭제하지 마세요

  • TLS 1.0/1.1은 보안상 취약하므로 최신 SSL Policy를 사용하세요
  • CloudWatch에서 SSL 핸드셰이크 에러를 모니터링하여 인증서 문제를 조기에 발견하세요

이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!

#AWS#ALB#LoadBalancer#ECS#TargetGroup

댓글 (0)

댓글을 작성하려면 로그인이 필요합니다.