Apache MPM 설정 간 차이와 최적화 전략

조회수: 0

Apache httpd를 튜닝할 때 가장 먼저 짚어야 하는 것이 MPM이다. MPM은 멀티 프로세싱 모듈의 줄임말로, 아파치가 요청을 처리하기 위해 프로세스와 스레드를 어떻게 배치할지 결정한다.

같은 하드웨어라도 어떤 MPM을 쓰느냐에 따라 동시 접속 한계가 크게 달라지고, 메모리 부족이나 문맥 전환 비용 등 병목 지점도 완전히 달라진다. 따라서 모듈만 끄고 켜는 수준의 튜닝보다 MPM부터 알맞게 고르는 것이 훨씬 효과적이다.

Apache MPM의 역할 이해

MPM은 크게 다음 두 가지를 정의한다.

  • 프로세스와 스레드 구조
  • 연결을 유지하고 재사용하는 방식

결국 MPM 선택은 다음 질문에 대한 답이다.

  • 동시 접속 수가 얼마나 필요한가
  • 요청당 처리 시간이 긴 편인가 짧은 편인가
  • 사용하는 모듈이 스레드 안전한가
  • 메모리 여유가 얼마나 되는가

이 질문에 따라 prefork worker event 중 하나를 고르고, 각 MPM에 맞는 디렉티브 값을 조정하는 식으로 튜닝이 진행된다.

prefork MPM의 구조와 특징

프로세스 기반 모델의 안정성과 한계

prefork는 아파치의 가장 전통적인 MPM이다. 구조는 단순하다.

  • 하나의 요청당 하나의 프로세스
  • 각 프로세스는 단일 스레드로 동작
  • 프로세스를 여러 개 미리 띄워 두고 요청을 분배

이 방식의 가장 큰 장점은 격리다. 각 요청이 별도의 프로세스로 처리되기 때문에, 스레드 안전하지 않은 모듈이나 오래된 라이브러리와도 잘 어울린다. 예전 mod php 환경에서 prefork가 사실상 기본 선택이었던 이유가 여기에 있다.

하지만 단점도 분명하다.

  • 동시 접속 수만큼 프로세스가 필요하므로 메모리 사용량이 크다
  • 문맥 전환 비용이 커져 고동시 환경에서 비효율적이다
  • 커넥션 유지 시간이 길수록 비활성 프로세스가 메모리를 점유하게 된다

즉 안정성과 호환성이 필요한 대신, 동시 접속이 폭발적으로 많은 환경에는 적합하지 않다.

prefork 환경에서의 기본 튜닝 포인트

prefork에서 중요한 디렉티브는 대략 다음과 같다.

  • StartServers
  • MinSpareServers
  • MaxSpareServers
  • MaxRequestWorkers 예전 이름은 MaxClients
  • MaxConnectionsPerChild 예전 이름은 MaxRequestsPerChild

실전에서는 서버 메모리를 기준으로 프로세스 하나가 대략 어느 정도 메모리를 쓰는지 확인한 뒤, MaxRequestWorkers의 안전한 상한을 계산하는 식으로 접근한다.

예를 들면 다음과 비슷한 값을 쓸 수 있다.

StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxRequestWorkers 150
MaxConnectionsPerChild 2000

숫자 자체가 정답은 아니고, 프로세스당 메모리 사용량과 서버 전체 메모리, 동시 접속 패턴을 바탕으로 조정하는 것이 핵심이다.

worker MPM의 구조와 특징

프로세스와 스레드를 혼합한 모델

worker는 하나의 프로세스 내에 여러 개의 스레드를 두어 요청을 처리하는 구조다. 요약하면 다음과 같다.

  • 프로세스는 비교적 적은 수
  • 각 프로세스 안에 여러 개의 워커 스레드
  • 요청은 스레드 단위로 처리

이 구조의 장점은 명확하다.

  • prefork보다 같은 메모리로 훨씬 많은 동시 접속 처리 가능
  • 문맥 전환 비용이 줄어들어 CPU 측면에서도 유리

다만 모든 모듈과 코드가 스레드 안전해야 한다는 제약이 있다. 최근에는 대부분의 표준 모듈이 스레드 안전을 고려하지만, 오래된 서드파티 모듈과 함께 쓰이는 환경에서는 검증이 필요하다.

worker 환경에서의 주요 디렉티브

worker에서는 다음과 같은 설정을 주로 조정한다.

  • StartServers
  • ThreadsPerChild
  • MaxRequestWorkers
  • MaxConnectionsPerChild

예제로 많이 쓰는 형태는 다음과 비슷하다.

StartServers 2
ThreadsPerChild 25
MaxRequestWorkers 150
MaxConnectionsPerChild 2000

이 설정의 의미를 해석해 보면

  • 프로세스는 최소 2개
  • 각 프로세스마다 스레드 25개
  • 총 동시 처리 스레드 수 150개
    이 정도의 그림이 된다.

ThreadsPerChild와 StartServers를 곱한 값이 MaxRequestWorkers 이상이 되도록 조합하는 것이 일반적이며, 실제 동시 접속 목표와 메모리 상황을 동시에 고려해야 한다.

event MPM의 구조와 특징

keep alive 연결 최적화에 특화된 모델

event MPM은 worker를 기반으로 하면서 keep alive 연결을 더 효율적으로 처리하도록 개선된 모델이다. 특징을 정리하면 다음과 같다.

  • 실제 요청 처리를 담당하는 스레드와 keep alive 유지만 담당하는 스레드를 분리
  • 요청이 없는 keep alive 상태에서는 무거운 스레드를 점유하지 않음
  • 동시 접속 수가 매우 많고 keep alive 비율이 높은 환경에 유리

요청 처리 시간이 짧고, 클라이언트와의 연결 유지 시간이 상대적으로 긴 웹 서비스에서 특히 효과적이다. 최근 배포판에서 기본 MPM으로 event가 선택되는 경우가 많아진 이유이기도 하다.

event 환경에서의 설정 방향

event도 worker와 비슷한 디렉티브를 사용하지만, 내부적으로 연결 관리 방식이 다르다.

일반적인 예시는 다음과 비슷하다.

StartServers 2
ThreadsPerChild 50
MaxRequestWorkers 300
MaxConnectionsPerChild 4000

동시에 많은 클라이언트를 상대하지만 각 요청이 짧게 끝나는 정적 파일 제공이나 리버스 프록시 구성에서 잘 어울리는 패턴이다. keep alive 시간을 너무 길게 잡으면 불필요한 연결 유지가 늘어나므로, 타임아웃 설정과 함께 조정하는 것이 중요하다.

워크로드 유형별 MPM 선택 가이드

레거시 mod php 기반 환경

아직도 mod php로 PHP를 직접 구동하는 경우라면 스레드 안전성 문제로 prefork를 선택하는 경우가 많다.

이런 환경에서의 기본 전략은 다음과 같다.

  • prefork 사용
  • PHP 자체의 메모리 사용량을 최대한 줄이기
  • MaxRequestWorkers를 여유 있게 잡고, 메모리 부족이 발생하지 않도록 추적

다만 가능하다면 php fpm과 리버스 프록시 구조로 마이그레이션한 뒤 event MPM을 사용하는 방향이 중장기적으로 더 유연하다.

리버스 프록시와 정적 파일 서비스 중심 환경

리버스 프록시로 백엔드 여러 대를 뒤에 두고, 프론트에서 정적 파일과 SSL 종료를 담당하는 구조라면 event MPM이 거의 정석에 가깝다.

  • keep alive 활용을 통해 커넥션 재사용 극대화
  • event의 비블로킹 방식으로 더 많은 동시 접속 처리
  • 필요하다면 HTTP 압축과 캐시를 함께 적용

worker도 나쁘지 않지만, 최신 배포판과 모듈 호환성을 고려하면 event를 우선 검토하는 편이 좋다.

내부 관리용 저부하 서비스

동시 접속이 많지 않은 내부 관리용 서비스라면 MPM 선택이 성능에 미치는 영향이 상대적으로 작다. 이럴 때는 유지 보수 편의성이 더 중요하다.

  • 이미 안정적으로 운영 중인 MPM이 있다면 그대로 유지
  • 새로 구축하는 경우라면 event를 기본으로 고려
  • 모듈 호환성 문제가 있으면 worker로 한 단계 후퇴

즉 성능보다는 운영 안정성과 팀의 익숙함을 기준으로 선택해도 무방하다.

MPM 튜닝 절차와 실전 팁

단계별 튜닝 절차

실제 환경에서 MPM을 최적화할 때는 다음 순서를 추천할 수 있다.

첫째 현재 워크로드 파악

  • 동시 접속 수의 대략적인 범위
  • 요청당 평균 처리 시간
  • keep alive 비율과 타임아웃

둘째 MPM 후보 선정

  • 레거시 모듈 여부
  • 스레드 안전성 요구 사항

셋째 초깃값 설정

  • 메모리와 CPU 코어 수를 기준으로 MaxRequestWorkers를 안전하게 설정
  • 프로세스와 스레드 개수 비율 결정

넷째 부하 테스트와 모니터링

  • 단 성능 시험 툴로 동시 접속을 단계적으로 늘려 보며 응답 시간과 에러율 확인
  • 프로세스당 메모리 사용량과 CPU 로드를 함께 관찰

다섯째 운영 환경에 반영

  • 설정 변경 후 실제 트래픽에서 지표를 모니터링하며 추가 조정

이 과정을 반복하면서 서버 자원과 요구 성능 사이의 균형점을 맞추는 것이 핵심이다.

모니터링 시 꼭 보는 지표

MPM 튜닝 결과를 검증할 때는 다음과 같은 지표를 함께 보는 것이 좋다.

  • 전체 프로세스 수와 스레드 수
  • 프로세스당 메모리 사용량
  • 평균 응답 시간과 p95 p99 같은 지연 구간
  • 동시 접속 수 변화에 따른 에러율

이 지표들을 모니터링 시스템이나 아파치 상태 페이지를 통해 확인하면서, 설정 변경 전후를 비교하면 감으로만 튜닝하는 것을 피할 수 있다.

운영 환경에서의 체크리스트

실 서비스에 MPM 변경 또는 튜닝을 적용하기 전에 다음 질문들을 체크해 보자.

  • 사용하는 모든 모듈이 스레드 안전한지 확인했는가
  • 예상 최대 동시 접속 수와 그때의 메모리 사용량을 계산해 봤는가
  • 부하 테스트를 별도 환경에서 먼저 돌려봤는가
  • 롤백 플랜을 준비해 두었는가
  • 변경 사항을 팀원들과 공유하고 점검 시간대를 조정했는가

이 기본적인 체크만 지켜도 MPM 변경으로 인해 발생할 수 있는 대형 장애를 상당 부분 예방할 수 있다.

마무리 정리

Apache MPM은 웹 서버의 동시 처리 구조를 결정하는 핵심 설정이다.

prefork는 안정성과 호환성을, worker는 스레드 기반 효율을, event는 keep alive가 많은 환경에서의 대규모 동시 접속을 강점으로 가진다. 어느 하나가 절대적으로 우월하기보다는, 현재 워크로드와 모듈 구성, 메모리 여유를 기준으로 적합한 조합을 선택해야 한다.

새 시스템을 설계하거나 기존 환경을 개선할 계획이 있다면, 모듈만 조정하기 전에 먼저 MPM 선택과 기본 디렉티브부터 점검해 보자. 같은 하드웨어로도 훨씬 여유 있는 동시 접속 처리와 안정성을 끌어내는 가장 손쉬운 출발점이 될 수 있다.