개발이군고구마

Apache HTTPD 본문

Cloud Deploy

Apache HTTPD

김구황 2026. 4. 5. 20:36
728x90
Apache HTTPD 완전 정복 — EC2 웹서버 설정 가이드

Apache HTTPD, 정확히 무엇인가

"세계에서 가장 많이 쓰이는 웹 서버"라는 표현은 추상적. EC2 환경에서 실제로 어떤 역할을 하는지를 중심으로 이해하는 것이 핵심.

한 줄 정의
EC2의 80·443 포트를 열고, 외부에서 들어오는 모든 HTTP/HTTPS 요청을 가장 먼저 받아서 "어디로 보낼지"를 결정하는 프로세스.
🌐 브라우저 인터넷 HTTP 요청
요청 ──▶
APACHE · httpd 80 / 443 포트 점유 httpd.conf 참조 → 요청 목적지 결정 로깅 · SSL 처리
ProxyPass──▶
ALB /api/* → 백엔드
DocRoot ──▶
/var/www/html 정적 HTML 직접 응답
Rewrite──▶
S3 버킷 /static/* → 파일
EC2 Instance
Apache가 없으면 EC2는 그냥 켜져 있는 컴퓨터. Apache가 있어야 비로소 웹 서버.

EC2 내부에서 실제로 동작하는 프로세스

# EC2에 SSH 접속 후 프로세스 확인
$ ps aux | grep httpd

root    1234  httpd   ← 마스터 프로세스 (설정 로드, 워커 관리)
apache  1235  httpd   ← 워커 프로세스 (실제 요청 처리)
apache  1236  httpd
apache  1237  httpd
🚪
포트 점유

80·443 포트를 열고 외부 요청 수신

🗺️
라우팅 결정

URL 경로에 따라 ALB, S3, 로컬 파일로 분기

🔒
SSL/TLS 처리

HTTPS 인증서 관리 및 암복호화

📋
로깅

모든 요청·응답 기록 및 에러 추적

httpd.conf — 경비원의 근무 지침서

Apache는 스스로 판단하지 않음. httpd.conf에 적힌 내용 그대로만 행동. 지침서가 없으면 아무것도 못하고, 지침서가 잘못되면 엉뚱한 곳으로 요청을 보내거나 503 에러 반환.

비유
httpd.conf = 경비원 근무 지침서 (전체 규정집)
conf.d/*.conf = 서비스별 세부 업무 지침서 (실제 작업 파일)

RHEL / CentOS 계열 디렉토리 구조

/etc/httpd/
├── conf/
│   └── httpd.conf          ← 총괄 설정 (ServerRoot, Listen, User 등)
│
├── conf.d/               ← ★ 실제 작업 영역
│   ├── myapp.conf          ← 서비스 VirtualHost, ProxyPass 설정
│   ├── ssl.conf            ← HTTPS 인증서 설정
│   └── welcome.conf        ← 기본 웰컴 페이지 (보통 비활성화)
│
├── conf.modules.d/
│   ├── 00-base.conf        ← 기본 모듈 목록
│   └── 00-proxy.conf       ← ProxyPass 사용 시 필요한 모듈
│
└── logs/
    ├── access_log          ← 모든 요청 기록
    └── error_log           ← 에러 발생 기록

Debian / Ubuntu 계열 디렉토리 구조

/etc/apache2/
├── apache2.conf           ← 총괄 설정
│
├── sites-available/       ← 정의만 해두는 곳 (비활성)
│   ├── 000-default.conf
│   └── myapp.conf
│
├── sites-enabled/         ← 심볼릭 링크로 활성화된 설정
│   └── myapp.conf → ../sites-available/myapp.conf
│
├── mods-available/        ← 사용 가능한 모듈 목록
└── mods-enabled/          ← a2enmod 명령으로 활성화된 모듈
⚠️ RHEL vs Ubuntu — 이름만 다르고 소프트웨어는 동일
패키지 이름이 httpd(RHEL) vs apache2(Ubuntu)로 다를 뿐, 동작 원리와 설정 문법은 완전히 동일.
항목RHEL / CentOS (httpd)Ubuntu / Debian (apache2)
패키지 설치yum install httpdapt install apache2
서비스 시작systemctl start httpdsystemctl start apache2
메인 설정/etc/httpd/conf/httpd.conf/etc/apache2/apache2.conf
추가 설정conf.d/*.confsites-enabled/*.conf
모듈 활성화설정파일에 직접 LoadModule 작성a2enmod proxy 명령 사용
소프트웨어동일 — Apache HTTP Server 2.4

Apache → ALB : ProxyPass 설정

ProxyPass는 Apache가 받은 요청을 내부 또는 외부의 다른 서버로 투명하게 전달하는 디렉티브. 클라이언트는 ALB의 존재를 알지 못하고 Apache 하나와만 통신하는 것처럼 인식.

🌐 Browser GET /api/users ALB 존재 모름
HTTP──▶
🛡️ Apache httpd ProxyPass 매칭 /api → ALB 전달 요청 분기 결정
ProxyPass──▶
⚖️ ALB 로드밸런싱 → EC2 / ECS 트래픽 분산
──▶
⚙️ Backend Spring / Node 8080 port 비즈니스 처리

모듈 활성화 (설정 전 필수)

# RHEL/CentOS — /etc/httpd/conf.modules.d/00-proxy.conf 확인
LoadModule proxy_module        modules/mod_proxy.so
LoadModule proxy_http_module   modules/mod_proxy_http.so
LoadModule headers_module      modules/mod_headers.so

# Ubuntu/Debian — 명령어로 활성화
$ a2enmod proxy proxy_http headers

VirtualHost + ProxyPass 설정

/etc/httpd/conf.d/myapp.conf
<VirtualHost *:80>
    ServerName  www.example.com

    # ① 원본 Host 헤더를 백엔드에 그대로 전달
    ProxyPreserveHost  On

    # ② /api/* 요청을 ALB로 전달
    ProxyPass        /api  http://my-alb-1234.ap-northeast-2.elb.amazonaws.com/api
    ProxyPassReverse /api  http://my-alb-1234.ap-northeast-2.elb.amazonaws.com/api

    # ③ 클라이언트 실제 IP를 백엔드에 전달
    RequestHeader set X-Forwarded-For   "%{REMOTE_ADDR}s"
    RequestHeader set X-Forwarded-Proto "http"

    # ④ 나머지 경로는 로컬 파일 서빙
    DocumentRoot  /var/www/html

    ErrorLog   /var/log/httpd/error.log
    CustomLog  /var/log/httpd/access.log combined
</VirtualHost>
디렉티브역할
ProxyPass요청을 지정한 백엔드 URL로 포워딩
ProxyPassReverse백엔드의 리다이렉트 응답 Location 헤더를 Apache 주소로 재작성
ProxyPreserveHost On원본 도메인(Host 헤더) 유지. ALB 연결 시 권장
X-Forwarded-For백엔드가 클라이언트 실제 IP를 알 수 있도록 헤더 추가

Apache → S3 : ProxyPass vs RewriteRule

S3로 연결하는 방법은 두 가지. 목적에 따라 선택이 달라짐.

방법 A — ProxyPass (S3 URL 숨김, Apache가 중계)
Browser
──▶
Apache
ProxyPass──▶
S3 버킷(비공개 가능)
✅ S3 URL 노출 없음 ✅ 비공개 버킷 사용 가능 ⚠️ Apache가 모든 트래픽 중계
방법 B — RewriteRule 302 (브라우저가 S3로 직접 이동)
Browser
↓ ③ 직접 요청
① 요청──▶ ◀── ② 302
Apache302 응답
──▶
S3 버킷(퍼블릭 필요)
✅ Apache 부하 최소화 ✅ CDN 연계 최적 ⚠️ S3 퍼블릭 설정 필요

방법 A — ProxyPass

  • S3 URL 클라이언트에 미노출
  • 비공개(Private) S3 버킷 사용 가능
  • Apache가 모든 트래픽을 중계
  • 대용량 파일 시 Apache 부하 증가
  • ProxyPreserveHost Off 설정 필수

방법 B — RewriteRule (302)

  • S3 URL이 브라우저에 노출됨
  • S3 버킷이 퍼블릭이어야 함
  • Apache는 302만 응답, 부하 최소
  • 대용량 파일, CDN 연계에 최적
  • CloudFront 앞단 구성과 궁합 최적

방법 A — ProxyPass로 S3 연결

/etc/httpd/conf.d/myapp.conf
<VirtualHost *:80>
    ServerName  www.example.com

    # S3 연결 시 반드시 Off — On이면 S3가 Host 헤더를 인식 못해 403 발생
    ProxyPreserveHost  Off

    # /uploads/* → S3 비공개 버킷으로 프록시
    ProxyPass        /uploads  https://my-bucket.s3.ap-northeast-2.amazonaws.com/uploads
    ProxyPassReverse /uploads  https://my-bucket.s3.ap-northeast-2.amazonaws.com/uploads
</VirtualHost>
⚠️ S3 ProxyPass 필수 주의사항
ProxyPreserveHost Off 를 반드시 설정. On 상태로 요청 시 S3가 Host 헤더(www.example.com)를 인식하지 못해 403 AccessDenied 오류 발생.

방법 B — RewriteRule로 S3 리다이렉트

/etc/httpd/conf.d/myapp.conf
LoadModule rewrite_module modules/mod_rewrite.so

<VirtualHost *:80>
    ServerName  www.example.com
    RewriteEngine  On

    # /static/* → CloudFront(S3 앞단)로 302 리다이렉트
    RewriteRule ^/static/(.*)$ \
        https://d1234abcd.cloudfront.net/static/$1 [R=302,L]

    # /uploads/* → S3 퍼블릭 버킷으로 리다이렉트
    RewriteRule ^/uploads/(.*)$ \
        https://my-bucket.s3.ap-northeast-2.amazonaws.com/uploads/$1 [R=302,L]
</VirtualHost>
비교 항목ProxyPassRewriteRule (302)
S3 URL 노출❌ 숨김✅ 노출
Apache 부하높음 (트래픽 중계)낮음 (302만 응답)
S3 퍼블릭 설정불필요퍼블릭 필수
대용량 파일비추천추천
CDN 연계가능최적
적합한 케이스비공개 파일, URL 은닉이미지·동영상, CDN 활용

ALB + S3 통합 최종 설정 예시

/api는 ALB, /uploads는 S3 프록시, /static은 S3 리다이렉트, 나머지는 로컬 파일 서빙 — 실제 프로덕션에서 사용하는 전체 VirtualHost 구성.

🌐 Browser www.example.com :443
──▶
🛡️ Apache httpd
/api/* → ALB
/uploads/* → S3 Proxy
/static/* → S3 302
/* → /var/www/html
EC2 Instance
ProxyPass ──▶
⚖️ ALBBackend API 서버
ProxyPass ──▶
🗄️ S3 (Private)/uploads 비공개
Rewrite ──▶
☁️ CloudFrontS3 Public /static
DocRoot   ──▶
📄 /var/www/html로컬 정적 파일
/etc/httpd/conf.d/myapp.conf
LoadModule proxy_module        modules/mod_proxy.so
LoadModule proxy_http_module   modules/mod_proxy_http.so
LoadModule rewrite_module      modules/mod_rewrite.so
LoadModule headers_module      modules/mod_headers.so
LoadModule ssl_module          modules/mod_ssl.so

<VirtualHost *:443>
    ServerName  www.example.com

    # SSL 설정
    SSLEngine            on
    SSLCertificateFile    /etc/ssl/certs/example.crt
    SSLCertificateKeyFile /etc/ssl/private/example.key

    RewriteEngine  On

    # ── ① /static/* → CloudFront 302 리다이렉트 ────────────────
    RewriteRule ^/static/(.*)$ \
        https://d1234abcd.cloudfront.net/static/$1 [R=302,L]

    # ── ② /uploads/* → S3 비공개 버킷 ProxyPass ────────────────
    ProxyPreserveHost  Off   # S3 연결 시 Off 필수
    ProxyPass        /uploads  https://my-private.s3.ap-northeast-2.amazonaws.com/uploads
    ProxyPassReverse /uploads  https://my-private.s3.ap-northeast-2.amazonaws.com/uploads

    # ── ③ /api/* → ALB ProxyPass ────────────────────────────────
    ProxyPreserveHost  On   # ALB 연결 시 On 권장
    ProxyPass        /api  http://my-alb-xxxx.ap-northeast-2.elb.amazonaws.com/api
    ProxyPassReverse /api  http://my-alb-xxxx.ap-northeast-2.elb.amazonaws.com/api

    RequestHeader set X-Forwarded-Proto "https"
    RequestHeader set X-Forwarded-For   "%{REMOTE_ADDR}s"

    # ── ④ 나머지 → 로컬 파일 ────────────────────────────────────
    DocumentRoot  /var/www/html

    <Directory /var/www/html>
        Options   -Indexes
        AllowOverride None
        Require   all granted
    </Directory>

    ErrorLog   /var/log/httpd/error.log
    CustomLog  /var/log/httpd/access.log combined
</VirtualHost>

# HTTP → HTTPS 리다이렉트
<VirtualHost *:80>
    ServerName  www.example.com
    RewriteEngine  On
    RewriteRule  ^(.*)$  https://%{HTTP_HOST}$1  [R=301,L]
</VirtualHost>

설정 적용 및 검증

# 설정 문법 검사 (적용 전 반드시 실행)
$ httpd -t
Syntax OK

# 무중단 설정 반영 (권장)
$ systemctl reload httpd

# 완전 재시작
$ systemctl restart httpd

# 실시간 에러 로그 확인
$ tail -f /var/log/httpd/error.log

ASG 환경에서 httpd 설정 자동화

Auto Scaling Group(ASG)은 트래픽 변화에 따라 EC2를 자동으로 종료하고 새로 생성. 수동으로 conf 파일을 배포하면 새 인스턴스에는 설정이 없는 상태로 올라오므로, 설정 파일을 코드로 관리하고 인스턴스 생성 시 자동으로 주입하는 구조가 필수.

핵심 흐름 요약
Git 리포지토리에 conf 파일 관리 → CI/CD가 S3에 업로드 → ASG가 EC2 생성 시 UserData 스크립트 실행 → S3에서 conf 다운로드 → httpd 자동 시작
① Git Repo api.conf mobile.conf pc.conf conf 버전 관리
push──▶
② CI/CD GitHub Actions CodePipeline 등 자동 배포
upload──▶
③ S3 버킷 api/api.conf mobile/mobile.conf pc/pc.conf common/httpd.conf conf 중앙 저장소
Launch Template──▶
S3 pull──▶
④ ASG EC2 자동 생성
⑤ EC2 생성 UserData 실행
⑥ httpd 시작 conf 자동 적용 무상태 인스턴스

Git 리포지토리 — conf 파일 구조

서비스 유형(api, mobile, pc)별로 conf를 분리해서 관리. 각 Launch Template이 필요한 파일만 선택적으로 S3에서 가져옴.

httpd-configs/                  ← Git 리포지토리 루트
├── common/
│   ├── httpd.conf              ← 전체 공통 설정 (포트, 모듈, 로그)
│   └── ssl.conf               ← HTTPS 공통 설정
│
├── api/
│   └── api.conf               ← API 서버용 VirtualHost (ProxyPass → ALB-API)
│
├── mobile/
│   └── mobile.conf            ← 모바일 웹용 VirtualHost (ProxyPass → ALB-Mobile)
│
├── pc/
│   └── pc.conf                ← PC 웹용 VirtualHost (ProxyPass → ALB-PC)
│
└── scripts/
    └── upload-to-s3.sh        ← CI/CD에서 호출하는 S3 업로드 스크립트

CI/CD → S3 업로드 스크립트

scripts/upload-to-s3.sh
#!/bin/bash
# GitHub Actions / CodePipeline 등에서 호출
# conf 파일 전체를 S3에 동기화

BUCKET="my-httpd-configs"
REGION="ap-northeast-2"

# 변경된 파일만 동기화 (--delete: S3에서 삭제된 파일도 반영)
aws s3 sync ./ s3://$BUCKET/httpd/ \
    --region $REGION \
    --exclude "*.sh" \
    --exclude ".git/*" \
    --delete

echo "✅ conf 파일 S3 동기화 완료"

Launch Template — UserData 스크립트

ASG의 Launch Template에 UserData를 등록해두면, EC2가 생성될 때마다 자동으로 실행됨. APP_TYPE 환경변수 또는 태그를 통해 어느 conf를 내려받을지 결정.

Launch Template UserData — api 서버 예시
#!/bin/bash
# EC2 생성 시 자동 실행되는 UserData 스크립트
# 역할: S3에서 해당 서버 유형의 conf를 받아 httpd 설치 후 시작

## ① 변수 정의
APP_TYPE="api"           # api / mobile / pc — Launch Template마다 다르게 설정
BUCKET="my-httpd-configs"
REGION="ap-northeast-2"
CONF_DIR="/etc/httpd/conf.d"

## ② 패키지 업데이트 및 httpd 설치
yum update -y
yum install -y httpd mod_ssl

## ③ S3에서 공통 설정 다운로드
aws s3 cp s3://$BUCKET/httpd/common/httpd.conf /etc/httpd/conf/httpd.conf \
    --region $REGION
aws s3 cp s3://$BUCKET/httpd/common/ssl.conf $CONF_DIR/ssl.conf \
    --region $REGION

## ④ S3에서 서버 유형별 conf 다운로드
#   APP_TYPE=api   → api/api.conf 만 적용
#   APP_TYPE=mobile → mobile/mobile.conf 만 적용
#   APP_TYPE=pc    → pc/pc.conf 만 적용
aws s3 cp s3://$BUCKET/httpd/$APP_TYPE/$APP_TYPE.conf \
    $CONF_DIR/$APP_TYPE.conf \
    --region $REGION

## ⑤ 설정 문법 검사
httpd -t
if [ $? -ne 0 ]; then
    echo "❌ httpd 설정 오류 — 시작 중단" | logger
    exit 1
fi

## ⑥ httpd 시작 및 자동시작 등록
systemctl enable httpd
systemctl start  httpd

echo "✅ $APP_TYPE 서버 httpd 시작 완료" | logger
IAM Role 필수
EC2가 S3에서 conf를 다운로드하려면, Launch Template에 연결된 IAM Instance Profiles3:GetObject 권한이 있어야 함. 별도의 Access Key 없이 IAM Role로만 처리하는 것이 보안 모범 사례.

서비스별 conf 파일 예시

api/api.conf — API 서버 전용
<VirtualHost *:443>
    ServerName   api.example.com

    SSLEngine            on
    SSLCertificateFile    /etc/ssl/certs/example.crt
    SSLCertificateKeyFile /etc/ssl/private/example.key

    # API 트래픽 전체를 ALB-API로 프록시
    ProxyPreserveHost  On
    ProxyPass        /  http://api-alb-xxxx.ap-northeast-2.elb.amazonaws.com/
    ProxyPassReverse /  http://api-alb-xxxx.ap-northeast-2.elb.amazonaws.com/

    RequestHeader set X-Forwarded-Proto "https"
    ErrorLog  /var/log/httpd/api-error.log
    CustomLog /var/log/httpd/api-access.log combined
</VirtualHost>
mobile/mobile.conf — 모바일 웹 전용
<VirtualHost *:443>
    ServerName   m.example.com

    SSLEngine            on
    SSLCertificateFile    /etc/ssl/certs/example.crt
    SSLCertificateKeyFile /etc/ssl/private/example.key

    RewriteEngine  On
    # 정적 자산 → CloudFront
    RewriteRule ^/static/(.*)$ \
        https://mobile-cdn.cloudfront.net/static/$1 [R=302,L]

    # 모바일 앱 API → ALB-Mobile
    ProxyPreserveHost  On
    ProxyPass        /api  http://mobile-alb-xxxx.ap-northeast-2.elb.amazonaws.com/api
    ProxyPassReverse /api  http://mobile-alb-xxxx.ap-northeast-2.elb.amazonaws.com/api

    DocumentRoot /var/www/html/mobile
    ErrorLog  /var/log/httpd/mobile-error.log
    CustomLog /var/log/httpd/mobile-access.log combined
</VirtualHost>

ASG Launch Template — 서비스별 분리 구조

ASG-API Launch Template API
ASG-Mobile Launch Template Mobile
ASG-PC Launch Template PC
──▶ ──▶ ──▶
S3 conf-repo api/api.conf mobile/mobile.conf pc/pc.conf common/httpd.conf
UserData ──▶ UserData ──▶ UserData ──▶
EC2 × N (API) api.conf 적용
EC2 × N (Mobile) mobile.conf 적용
EC2 × N (PC) pc.conf 적용
이 구조의 핵심 이점
• conf 파일이 Git으로 버전 관리되므로 변경 이력 추적 및 롤백 가능
• ASG가 EC2를 몇 대 생성하든 항상 동일한 설정으로 올라옴 (불변 인프라)
• 서비스 유형별로 conf가 분리되어 있어 api만, 또는 mobile만 별도 배포 가능
• EC2 내부에 conf를 직접 수정하면 다음 Scale-in/out 시 사라지므로, 서버에서 직접 수정하는 습관은 금지
⚠️ UserData는 최초 1회만 실행
UserData 스크립트는 EC2 최초 부팅 시에만 실행됨. 이미 실행 중인 인스턴스에 conf를 변경하려면 S3 업데이트 후 인스턴스 교체(Refresh)가 필요. ASG의 "Instance Refresh" 기능을 사용하면 무중단으로 순차 교체 가능.

핵심 개념 요약

용어실제 의미
httpd (Apache)EC2에서 80/443 포트를 열고 요청을 수신하는 프로세스
httpd.confApache가 어떻게 동작할지 정의된 설정 파일 (근무 지침서)
conf.d/*.conf서비스별 세부 설정 파일. 실제 작업 대상
VirtualHost도메인별로 다른 설정을 적용하는 단위
ProxyPass요청을 ALB·S3 등 다른 서버로 투명하게 전달
ProxyPassReverse백엔드 리다이렉트 URL을 Apache 주소로 재작성
RewriteRuleURL 패턴 매칭 후 리다이렉트 또는 변환
mod_proxyProxyPass 기능을 사용하기 위한 Apache 모듈
ASG (Auto Scaling Group)트래픽에 따라 EC2를 자동 생성·종료하는 AWS 서비스
Launch TemplateASG가 EC2를 생성할 때 참조하는 인스턴스 설정 템플릿
UserDataEC2 최초 부팅 시 자동 실행되는 초기화 스크립트
Instance RefreshASG가 기존 인스턴스를 새 설정으로 순차적으로 무중단 교체하는 기능
ProxyPreserveHost 규칙 요약
ALB로 전달 시 → ProxyPreserveHost On — 원본 도메인 유지
S3로 전달 시 → ProxyPreserveHost Off — S3가 Host 헤더를 자체 처리
S3 연결 방식 선택 기준
S3 URL 숨기기 / 비공개 버킷 필요 → ProxyPass
대용량 파일 / CDN 연계 / Apache 부하 최소화 → RewriteRule (302)