서버 구성 · 8 min read · Jan 26, 2026

최대 성능을 위한 Apache 구성

Apache는 오픈 소스 HTTP 서버 구현입니다. 이는 인터넷에서 가장 인기 있는 웹 서버입니다. Netcraft에서 실시한 2005년 12월 웹 서버 조사 [

1

]에 따르면 인터넷의 약 70% 웹사이트가 Apache를 사용하고 있습니다.

1. Apache 서버 성능

Apache 서버 성능은 RAM, 더 빠른 CPU 등과 같은 추가 하드웨어 리소스를 추가하여 개선할 수 있습니다. 그러나 대부분의 경우 서버의 사용자 정의 구성을 통해 동일한 결과를 얻을 수 있습니다. 이 기사는 기존 하드웨어 리소스를 사용하여 Apache에서 최대 성능을 얻는 방법을 살펴봅니다. 특히 Linux 시스템에 대해 다룹니다. 물론 서버가 자주 스와핑되지 않도록 충분한 하드웨어 리소스, 특히 충분한 RAM이 있다고 가정합니다. 처음 두 섹션에서는 다양한 컴파일 시간 및 실행 시간 구성 옵션을 살펴봅니다. 실행 시간 섹션은 Apache가

prefork

MPM으로 컴파일되었다고 가정합니다. 다음으로 HTTP 압축 및 캐싱에 대해 논의합니다. 마지막으로 정적 및 동적 콘텐츠를 제공하기 위해 별도의 서버를 사용하는 방법에 대해 논의합니다. Apache 및 Linux를 컴파일하고 구성하는 기본 지식이 있다고 가정합니다.

2 컴파일 시간 구성 옵션

2.1 필요한 모듈만 로드하기:

Apache HTTP 서버는 관리자가 모듈 집합을 선택하여 서버에 포함할 기능을 선택할 수 있는 모듈식 프로그램입니다 [

2

]. 모듈은 httpd 바이너리에 정적으로 컴파일되거나 동적 공유 객체(DSO)로 컴파일될 수 있습니다. DSO 모듈은 서버가 빌드될 때 컴파일되거나 나중에 추가하기 위해

apxs

유틸리티를 사용할 수 있습니다. DSO 지원을 활성화하려면 mod_so 모듈이 Apache 코어에 정적으로 컴파일되어야 합니다.

필요한 모듈만 로드하여 Apache를 실행하십시오. 이렇게 하면 메모리 사용량이 줄어들고 서버 성능이 향상됩니다. 모듈을 정적으로 컴파일하면 동적으로 로드된 모듈을 지원하는 데 사용되는 RAM이 절약되지만, 모듈을 추가하거나 삭제할 때마다 Apache를 다시 컴파일해야 합니다. 이때 DSO 메커니즘이 유용합니다. mod_so 모듈이 정적으로 컴파일되면 httpd.conf 파일의 LoadModule 명령을 사용하여 다른 모듈을 추가하거나 삭제할 수 있습니다. 물론 서버가 빌드될 때 컴파일되지 않은 경우 apxs를 사용하여 모듈을 컴파일해야 합니다.

2.2 적절한 MPM 선택:

Apache 서버는 네트워크 포트에 바인딩하고 요청을 수락하며 요청을 처리할 자식 프로세스를 배포하는 책임이 있는 여러 개의 다중 처리 모듈(MPM)을 제공합니다 [

3

]. 한 번에 하나의 MPM만 서버에 로드될 수 있습니다.

MPM 선택은 OS가 스레드를 지원하는지, 사용 가능한 메모리 양, 확장성 대 안정성, 비스레드 안전한 서드파티 모듈 사용 여부 등 다양한 요인에 따라 달라집니다. Linux 시스템은 worker와 같은 스레드형 MPM 또는 prefork와 같은 비스레드형 MPM을 선택할 수 있습니다:

Worker MPM은 여러 자식 프로세스를 사용합니다. 각 자식 내에서 다중 스레드이며 각 스레드는 단일 연결을 처리합니다. Worker는 빠르고 확장성이 뛰어나며 메모리 사용량이 상대적으로 낮습니다. 여러 프로세서에 잘 맞습니다. 반면에 worker는 결함이 있는 모듈에 대해 덜 관용적이며 결함이 있는 스레드는 자식 프로세스의 모든 스레드에 영향을 미칠 수 있습니다.

Prefork MPM은 여러 자식 프로세스를 사용하며 각 자식은 한 번에 하나의 연결을 처리합니다. Prefork는 단일 또는 이중 CPU 시스템에 잘 맞으며 속도는 worker와 비슷하고 결함이 있는 모듈 및 충돌하는 자식에 대해 높은 관용성을 보입니다. 그러나 메모리 사용량이 높고 더 많은 트래픽은 더 많은 메모리 사용으로 이어집니다.

3 실행 시간 구성 옵션

3.1 DNS 조회:

HostnameLookups 지시어는 DNS 조회를 활성화하여 IP 주소 대신 호스트 이름을 기록할 수 있도록 합니다. 이는 요청이 완료되기 전에 DNS 조회가 완료되어야 하므로 모든 요청에 지연을 추가합니다. HostnameLookups는 Apache 1.3 이상에서 기본적으로 꺼져 있습니다. 이를 꺼두고 logresolve와 같은 후처리 프로그램을 사용하여 Apache의 액세스 로그 파일에서 IP 주소를 해결하십시오. Logresolve는 Apache와 함께 제공됩니다.

Allow from 또는 Deny from 지시어를 사용할 때는 도메인 이름이나 호스트 이름 대신 IP 주소를 사용하십시오. 그렇지 않으면 도메인 이름이나 호스트 이름이 스푸핑되지 않도록 확인하기 위해 이중 DNS 조회가 수행됩니다.

3.2 AllowOverride:

AllowOverride가 ‘None’으로 설정되지 않은 경우 Apache는 방문하는 각 디렉토리에서 .htaccess 파일(AccessFileName 지시어에 지정됨)을 열려고 시도합니다. 예를 들어:

DocumentRoot /var/www/html  
   
 AllowOverride all  
 

/index.html에 대한 요청이 들어오면 Apache는 /.htaccess, /var/.htaccess, /var/www/.htaccess 및 /var/www/html/.htaccess를 열려고 시도합니다. 이러한 추가 파일 시스템 조회는 지연을 추가합니다. 특정 디렉토리에 .htaccess가 필요한 경우 해당 디렉토리에서만 활성화하십시오.

3.3 FollowSymLinks 및 SymLinksIfOwnerMatch:

FollowSymLinks 옵션이 설정된 경우 서버는 이 디렉토리의 심볼릭 링크를 따릅니다. SymLinksIfOwnerMatch가 설정된 경우 서버는 대상 파일이나 디렉토리가 링크와 동일한 사용자가 소유하는 경우에만 심볼릭 링크를 따릅니다.

SymLinksIfOwnerMatch가 설정된 경우 Apache는 링크와 대상 파일의 소유권이 일치하는지 확인하기 위해 추가 시스템 호출을 수행해야 합니다. FollowSymLinks가 설정되지 않은 경우에도 추가 시스템 호출이 필요합니다. 예를 들어:

 DocumentRoot /vaw/www/html   
    
 Options SymLinksIfOwnerMatch   
  

/index.html에 대한 요청이 들어오면 Apache는 /var, /var/www, /var/www/html 및 /var/www/html/index.html에 대해 lstat()를 수행합니다. 이러한 추가 시스템 호출은 지연을 추가합니다. lstat 결과는 캐시되지 않으므로 모든 요청에서 발생합니다.

최대 성능을 위해 모든 곳에서 FollowSymLinks를 설정하고 SymLinksIfOwnerMatch는 절대 설정하지 마십시오. 또는 특정 디렉토리에 SymLinksIfOwnerMatch가 필요한 경우 해당 디렉토리에서만 설정하십시오.

3.4 콘텐츠 협상:

빠른 응답을 위해 콘텐츠 협상을 피하십시오. 사이트에 콘텐츠 협상이 필요한 경우 Options MultiViews 지시어 대신 type-map 파일을 사용하십시오. MultiViews를 사용하면 Apache가 파일을 찾기 위해 디렉토리를 스캔해야 하므로 지연이 추가됩니다.

3.5 MaxClients:

MaxClients는 서버가 지원할 수 있는 최대 동시 요청 수에 대한 제한을 설정합니다. 이보다 많은 수의 자식 프로세스가 생성되지 않습니다. 새로운 연결이 대기열에 들어가서 결국 타임아웃되고 서버 리소스가 사용되지 않도록 너무 낮게 설정해서는 안 됩니다. 이를 너무 높게 설정하면 서버가 스와핑을 시작하고 응답 시간이 급격히 저하됩니다. MaxClients에 대한 적절한 값은 다음과 같이 계산할 수 있습니다: MaxClients = 웹 서버에 할당된 총 RAM / 최대 자식 프로세스 크기 —- [

4

]정적 파일을 제공하는 자식 프로세스 크기는 약 2-3M입니다. PHP와 같은 동적 콘텐츠의 경우 약 15M일 수 있습니다. 다음의 RSS 열은

"ps -ylC httpd --sort:rss"

Apache 프로세스의 비스왑 물리적 메모리 사용량을 킬로바이트 단위로 보여줍니다.

동시 사용자가 MaxClients보다 많으면 요청은 ListenBacklog 지시어를 기반으로 한 수치로 대기열에 쌓입니다. ServerLimit를 증가시켜 MaxClients를 256 이상으로 설정하십시오.

3.6 MinSpareServers, MaxSpareServers 및 StartServers:

MaxSpareServers 및 MinSpareServers는 요청을 기다리는 동안 유지할 자식 프로세스 수를 결정합니다. MinSpareServers가 너무 낮고 많은 요청이 들어오면 Apache는 요청을 처리하기 위해 추가 자식 프로세스를 생성해야 합니다. 자식 프로세스를 생성하는 것은 상대적으로 비용이 많이 듭니다. 서버가 자식 프로세스를 생성하는 데 바쁘면 클라이언트 요청을 즉시 처리할 수 없습니다. MaxSpareServers는 너무 높게 설정해서는 안 되며, 자식 프로세스가 리소스를 소비하므로 리소스 문제를 일으킬 수 있습니다.

MinSpareServers 및 MaxSpareServers를 조정하여 Apache가 초당 4개 이상의 자식 프로세스를 자주 생성하지 않도록 하십시오(아파치는 초당 최대 32개의 자식 프로세스를 생성할 수 있습니다). 초당 4개 이상의 자식이 생성되면 ErrorLog에 메시지가 기록됩니다.

StartServers 지시어는 시작 시 생성되는 자식 서버 프로세스의 수를 설정합니다. Apache는 MinSpareServers 설정에 도달할 때까지 자식 프로세스를 계속 생성합니다. 서버가 자주 재시작되지 않으면 성능에 큰 영향을 미치지 않습니다. 요청이 많고 Apache가 자주 재시작되는 경우 상대적으로 높은 값으로 설정하십시오.

3.7 MaxRequestsPerChild:

MaxRequestsPerChild 지시어는 개별 자식 서버 프로세스가 처리할 요청 수에 대한 제한을 설정합니다. MaxRequestsPerChild 요청 후 자식 프로세스는 종료됩니다. 기본적으로 0으로 설정되어 있어 자식 프로세스는 만료되지 않습니다. 몇 천으로 설정하는 것이 적절합니다. 이는 프로세스가 특정 수의 요청을 처리한 후 종료되므로 메모리 누수를 방지하는 데 도움이 될 수 있습니다. 너무 낮게 설정하지 마십시오. 새로운 프로세스를 생성하는 데는 오버헤드가 있습니다.

3.8 KeepAlive 및 KeepAliveTimeout:

KeepAlive 지시어는 동일한 TCP 연결을 통해 여러 요청을 보낼 수 있도록 합니다. 이는 이미지가 많은 HTML 페이지를 제공할 때 특히 유용합니다. KeepAlive가 꺼져 있으면 각 이미지에 대해 별도의 TCP 연결을 만들어야 합니다. TCP 연결을 설정하는 데 따른 오버헤드를 제거하려면 KeepAlive를 켜십시오.

KeepAliveTimeout은 다음 요청을 기다리는 시간을 결정합니다. 이를 낮은 값으로 설정하십시오. 아마도 2초에서 5초 사이가 적당합니다. 너무 높게 설정하면 자식 프로세스가 클라이언트를 기다리느라 묶여 있어 새로운 클라이언트를 제공하는 데 사용할 수 없습니다.

4 HTTP 압축 및 캐싱

HTTP 압축은 HTTP/1.1에서 완전히 지정됩니다. 서버는 클라이언트에게 전송되기 전에 응답 페이로드에 gzip 또는 deflate 인코딩 방법을 사용합니다. 클라이언트는 페이로드를 압축 해제합니다. 모든 주요 브라우저가 이를 지원하므로 클라이언트 측에 추가 소프트웨어를 설치할 필요가 없습니다. 압축을 사용하면 대역폭을 절약하고 응답 시간을 개선할 수 있으며, 연구에 따르면 평균 압축 이득은 75.2%입니다 [

5

]. Apache에서 HTTP 압축은

mod_deflate

모듈을 사용하여 활성화할 수 있습니다. 브라우저가 압축을 요청하는 경우에만 페이로드가 압축되며, 그렇지 않으면 압축되지 않은 콘텐츠가 제공됩니다. 압축 인식 브라우저는 HTTP 요청 헤더를 통해 압축된 콘텐츠를 선호한다고 서버에 알립니다 - “Accept-Encoding: gzip,deflate”. 그러면 서버는 압축된 페이로드와 함께 응답하고 응답 헤더는 다음과 같이 설정됩니다:

Content-Encoding:  
gzip

다음 예는 telnet을 사용하여 요청 및 응답 헤더를 보는 방법입니다:

bash-3.00$ telnet www.webperformance.org 80  
 Trying 24.60.234.27...  
 Connected to www.webperformance.org (24.60.234.27).  
 Escape character is '^]'.  
 HEAD / HTTP/1.1  
 Host: www.webperformance.org  
 Accept-Encoding: gzip,deflate  
   
 HTTP/1.1 200 OK  
 Date: Sat, 31 Dec 2005 02:29:22 GMT  
 Server: Apache/2.0  
 X-Powered-By: PHP/5.1.1  
 Cache-Control: max-age=0  
 Expires: Sat, 31 Dec 2005 02:29:22 GMT  
 Vary: Accept-Encoding  
 Content-Encoding: gzip  
 Content-Length: 20  
 Content-Type: text/html; charset=ISO-8859-1  
 

캐싱에서는 데이터의 복사본이 클라이언트 또는 프록시 서버에 저장되어 서버에서 자주 검색할 필요가 없습니다. 이는 대역폭을 절약하고 서버의 부하를 줄이며 지연을 감소시킵니다. 캐시 제어는 HTTP 헤더를 통해 수행됩니다. Apache에서는 이를

mod_expires

mod_headers

모듈을 통해 수행할 수 있습니다. 또한 서버 측 캐싱이 있으며, 자주 액세스되는 콘텐츠가 메모리에 저장되어 빠르게 제공될 수 있습니다. mod_cache 모듈은 서버 측 캐싱에 사용할 수 있으며, Apache 버전 2.2에서 프로덕션 안정적입니다.

5 정적 및 동적 콘텐츠를 위한 별도의 서버

동적 콘텐츠를 제공하는 Apache 프로세스는 약 3M에서 20M의 RAM을 사용합니다. 이는 제공하는 콘텐츠에 맞춰 증가하며 프로세스가 종료될 때까지 감소하지 않습니다. 예를 들어, Apache 프로세스가 동적 콘텐츠를 제공하기 위해 20M로 증가했다고 가정해 보겠습니다. 요청을 완료한 후에는 다른 요청을 제공할 수 있습니다. 이미지 요청이 들어오면 이 20M 프로세스가 정적 콘텐츠를 제공하고, 이는 1M 프로세스에서도 제공될 수 있습니다. 메모리가 비효율적으로 사용됩니다.

최소한의 모듈이 정적으로 컴파일된 작은 Apache를 프론트엔드 서버로 사용하여 정적 콘텐츠를 제공합니다. 동적 콘텐츠에 대한 요청은 모든 필요한 모듈로 컴파일된 무거운 Apache로 전달됩니다. 가벼운 프론트엔드 서버를 사용하면 정적 콘텐츠가 빠르게 제공되며 메모리 사용량이 적고 동적 콘텐츠만 무거운 서버로 전달됩니다.

요청 전달은 mod_proxy 및 rewrite_module 모듈을 사용하여 수행할 수 있습니다. 예를 들어, 포트 80에서 수신 대기하는 경량 Apache 서버와 포트 8088에서 수신 대기하는 무거운 Apache가 있다고 가정해 보겠습니다. 그러면 경량 Apache에서 다음 구성을 사용하여 이미지 요청을 제외한 모든 요청을 무거운 서버로 전달할 수 있습니다.

ProxyPassReverse / http://%{HTTP_HOST}:8088/  
 RewriteEngine on                                             ---- [9]  
 RewriteCond   %{REQUEST_URI} !.*\.(gif|png|jpg)$  
 RewriteRule ^/(.*) http://%{HTTP_HOST}:8088/$1 [P]

이미지를 제외한 모든 요청이 백엔드 서버로 프록시됩니다. 응답은 프론트엔드 서버에서 수신되고 클라이언트에 공급됩니다. 클라이언트 입장에서는 모든 응답이 단일 서버에서 오는 것처럼 보입니다.

6 결론

최대 성능을 위한 Apache 구성은 까다롭고, 확고한 규칙이 없습니다. 웹 서버 요구 사항을 이해하고 다양한 사용 가능한 옵션을 실험하십시오. 성능을 측정하기 위해 ab 및 httperf와 같은 도구를 사용하십시오. tux, thttpd와 같은 경량 서버를 프론트엔드 서버로 사용할 수도 있습니다. 데이터베이스 서버를 사용하는 경우 병목 현상이 발생하지 않도록 최적화되어 있는지 확인하십시오. MySQL의 경우 mtop을 사용하여 느린 쿼리를 모니터링할 수 있습니다. PHP 스크립트의 성능은 Turck MMCache와 같은 PHP 캐싱 제품을 사용하여 개선할 수 있습니다. 이는 PHP 스크립트를 컴파일된 상태로 캐시하여 컴파일로 인한 오버헤드를 제거합니다.

참고 문헌

1 http://news.netcraft.com/archives/web_server_survey.html

2 http://httpd.apache.org/docs/2.2/dso.html

3 http://httpd.apache.org/docs/2.2/mpm.html

4 http://modperlbook.org/html/ch11_01.html

5 http://www.speedupyoursite.com/18/18-2t.html

6 http://www.xs4all.nl/~thomas/apachecon/PerformanceTuning.html

7 http://www.onlamp.com/pub/a/onlamp/2004/02/05/lamp_tuning.html

8 http://httpd.apache.org/docs/2.2/misc/perf-tuning.html

9 Linux Server Hacks by Rob Flickenger

작가 소개: Vishnu Ram은 IIT Madras에서 통신 시스템으로 MTech를 취득했습니다. 그는 2003년에 Bobcares에 합류했으며 그 이후로 Poornam에서 일하고 있습니다.

Share: X/Twitter LinkedIn

새 게시물을 받은 편지함에서 받기

스팸은 없습니다. 언제든지 구독 해지 가능합니다.