갑자기 꺼지는 PostgreSQL: OOM 킬러를 막는 메모리 설정의 비밀

대표 이미지

갑자기 꺼지는 PostgreSQL: OOM 킬러를 막는 메모리 설정의 비밀

리눅스 커널의 메모리 오버커밋 설정이 PostgreSQL의 안정성에 미치는 치명적인 영향과 이를 해결하기 위한 엄격한 메모리 관리 전략을 분석합니다.

데이터베이스 관리자가 가장 공포를 느끼는 순간은 예고 없이 서버가 다운되었을 때가 아니라, 원인을 알 수 없는 이유로 데이터베이스 프로세스가 갑자기 종료되었음을 발견했을 때입니다. 로그 파일에는 아무런 에러 메시지가 없는데, 시스템 로그(dmesg)를 확인하면 ‘Out of Memory: Kill process’라는 냉혹한 문구가 적혀 있습니다. 이것이 바로 리눅스 커널의 OOM(Out of Memory) 킬러가 작동한 결과입니다.

많은 엔지니어가 PostgreSQL의 shared_bufferswork_mem 설정을 최적화하는 데 집중하지만, 정작 그 기반이 되는 운영체제의 메모리 할당 방식인 ‘오버커밋(Overcommit)’ 설정은 간과하곤 합니다. 하지만 이 설정 하나가 고가용성 데이터베이스의 생존 여부를 결정짓습니다. 왜 리눅스는 멀쩡해 보이는 프로세스를 죽이는지, 그리고 왜 우리는 ‘엄격한 메모리 오버커밋’ 설정을 선택해야 하는지 깊이 있게 살펴보겠습니다.

리눅스 커널의 위험한 도박: 메모리 오버커밋

리눅스 커널은 기본적으로 ‘낙관적’입니다. 프로세스가 메모리를 요청할 때, 커널은 실제로 물리 메모리가 충분한지 즉시 확인하지 않고 일단 “알았어, 나중에 필요할 때 줄게”라고 약속하며 가상 메모리 주소만 할당합니다. 이를 메모리 오버커밋(Memory Overcommit)이라고 합니다.

이 방식의 논리는 간단합니다. 대부분의 프로세스는 요청한 메모리를 전부 사용하지 않는다는 점에 착안하여, 실제 물리 메모리보다 더 많은 양의 메모리를 할당함으로써 자원 효율성을 극대화하려는 것입니다. 하지만 PostgreSQL 같은 데이터베이스 시스템에서는 이 낙관주의가 재앙이 됩니다. PostgreSQL은 공유 메모리(Shared Memory)를 대량으로 사용하며, 예측 가능한 메모리 사용 패턴을 유지해야 하기 때문입니다.

만약 커널이 약속했던 메모리를 실제로 제공해야 하는 시점에 물리 메모리가 부족하다면, 커널은 시스템 전체의 붕괴를 막기 위해 가장 ‘적절한’ 희생양을 찾아 강제로 종료시킵니다. 이때 OOM 킬러의 타겟이 되기 쉬운 것이 바로 메모리를 많이 점유하고 있는 PostgreSQL 프로세스입니다.

왜 PostgreSQL은 OOM 킬러의 표적이 되는가?

PostgreSQL의 아키텍처는 프로세스 기반 모델입니다. 각 연결마다 새로운 프로세스가 생성되며, 이들은 shared_buffers라는 거대한 공유 메모리 영역을 공유합니다. 문제는 리눅스 커널이 OOM 상황에서 프로세스를 선택하는 기준입니다. 커널은 보통 메모리 사용량이 많으면서도 시스템에 가하는 영향이 크다고 판단되는 프로세스에 높은 점수(oom_score)를 부여합니다.

PostgreSQL 프로세스는 공유 메모리를 통해 엄청난 양의 데이터를 핸들링하므로, 커널의 눈에는 매우 ‘무거운’ 프로세스로 보입니다. 결과적으로 시스템에 메모리가 부족해지면, 커널은 데이터베이스의 핵심 프로세스를 죽여 메모리를 확보하려 합니다. 이는 단순한 서비스 중단을 넘어, 비정상 종료로 인한 복구(Recovery) 시간 증가와 데이터 정합성 확인이라는 추가적인 리스크를 초래합니다.

해결책: 엄격한 메모리 오버커밋(Strict Memory Overcommit)

이 문제를 근본적으로 해결하는 방법은 커널의 태도를 ‘낙관적’에서 ‘보수적’으로 바꾸는 것입니다. 리눅스의 vm.overcommit_memory 파라미터를 통해 이를 제어할 수 있습니다.

  • vm.overcommit_memory = 0 (Heuristic): 기본값입니다. 커널이 적당히 판단하여 오버커밋을 허용합니다. 예측 불가능하며 OOM 킬러가 언제 작동할지 모릅니다.
  • vm.overcommit_memory = 1 (Always): 항상 오버커밋을 허용합니다. 메모리가 완전히 고갈될 때까지 계속 할당하며, 결국 가장 처참한 OOM 상황을 맞이하게 됩니다.
  • vm.overcommit_memory = 2 (Strict): 엄격한 모드입니다. 커널이 overcommit_ratio에 의해 계산된 한도 이상의 메모리 할당 요청을 단호하게 거절합니다.

vm.overcommit_memory = 2 설정을 사용하면, 메모리가 부족할 때 커널이 프로세스를 죽이는 대신, 메모리 할당 요청(malloc) 자체를 실패하게 만듭니다. 데이터베이스 입장에서는 프로세스가 갑자기 죽는 것보다, 특정 쿼리가 ‘메모리 부족’ 에러를 내며 실패하는 것이 훨씬 안전합니다. 전자는 전체 시스템의 다운을 의미하지만, 후자는 단일 요청의 실패로 끝나기 때문입니다.

실제 사례: 커널 버그와 설정의 충돌

이론적으로는 엄격한 오버커밋이 정답처럼 보이지만, 현실에서는 예상치 못한 변수가 존재합니다. 한 클라우드 서비스 제공업체는 모든 PostgreSQL 인스턴스에 vm.overcommit_memory = 2를 적용했다가 갑작스러운 서비스 장애를 겪었습니다. 원인은 PostgreSQL의 문제가 아니라 리눅스 커널의 아주 작은 버그였습니다.

특정 커널 버전에서 메모리 할당 요청 시 계산 로직에 오류가 발생하여, 실제 물리 메모리가 충분함에도 불구하고 커널이 할당을 거부하는 현상이 발견된 것입니다. 단 한 글자의 코드 오류가 엄격한 메모리 정책과 결합하자, 데이터베이스가 정상적인 상황에서도 실행되지 않는 상황이 벌어졌습니다. 결국 해당 업체는 커널 패치가 이루어질 때까지 일시적으로 설정을 되돌려야 했습니다. 이는 시스템 최적화가 단순히 설정값을 바꾸는 것이 아니라, 커널 버전과 하드웨어 특성을 모두 고려해야 하는 정밀한 작업임을 보여줍니다.

기술적 장단점 비교

구분 낙관적 오버커밋 (Mode 0) 엄격한 오버커밋 (Mode 2)
메모리 활용도 매우 높음 (가상 메모리 적극 활용) 보수적 (실제 가용량 내에서만 할당)
장애 형태 OOM 킬러에 의한 프로세스 강제 종료 메모리 할당 실패 에러 (malloc failure)
시스템 안정성 불안정 (예측 불가능한 다운타임) 안정적 (부분적 실패로 영향 최소화)
관리 복잡도 낮음 (기본 설정 사용) 높음 (정확한 ratio 계산 필요)

실무자를 위한 단계별 액션 가이드

지금 운영 중인 PostgreSQL 서버의 안정성을 높이고 싶다면 다음 단계를 따라 설정을 검토하십시오.

  • 현재 설정 확인: sysctl vm.overcommit_memory 명령어를 통해 현재 모드를 확인하십시오. 0이라면 OOM 킬러의 위험에 노출되어 있는 상태입니다.
  • 메모리 한도 계산: vm.overcommit_ratio 값을 확인하십시오. 기본값은 보통 50%입니다. CommitLimit = (RAM * ratio / 100) + Swap 공식으로 계산된 한도가 PostgreSQL의 shared_buffers와 최대 연결 수 기준 work_mem 합계보다 충분히 큰지 계산해야 합니다.
  • 단계적 적용: 운영 환경에 바로 적용하기 전, 스테이징 환경에서 vm.overcommit_memory = 2로 변경하고 부하 테스트를 수행하십시오. 특히 메모리 집약적인 복잡한 조인(Join) 쿼리가 실패하지 않는지 확인해야 합니다.
  • 모니터링 강화: /proc/meminfoCommitLimitCommitted_AS 값을 모니터링하여, 실제 할당된 메모리가 한계치에 얼마나 근접했는지 추적하십시오.

결론: 예측 가능성이 안정성을 만든다

인프라 엔지니어링의 핵심은 ‘최대 성능’이 아니라 ‘예측 가능한 성능’을 만드는 것입니다. 리눅스 커널의 기본 설정은 범용적인 사용성을 위해 설계되었지만, PostgreSQL과 같은 전문 데이터베이스 시스템에는 오히려 독이 될 수 있습니다.

엄격한 메모리 오버커밋 설정은 시스템의 자원 활용도를 약간 낮출 수 있지만, 대신 ‘갑작스러운 죽음’이라는 최악의 시나리오를 제거해 줍니다. 프로세스가 죽어 전체 서비스가 마비되는 것보다, 일부 쿼리가 실패하여 사용자에게 에러 메시지를 보여주는 것이 비즈니스 관점에서 훨씬 통제 가능한 리스크입니다. 지금 바로 여러분의 커널 설정을 점검하고, 데이터베이스에 예측 가능한 환경을 제공하십시오.

FAQ

PostgreSQL and the OOM Killer: Why We Use Strict Memory Overcommit의 핵심 쟁점은 무엇인가요?

핵심 문제 정의, 비용 구조, 실제 적용 방법, 리스크를 함께 봐야 합니다.

PostgreSQL and the OOM Killer: Why We Use Strict Memory Overcommit를 바로 도입해도 되나요?

작은 범위에서 실험하고 데이터를 확인한 뒤 단계적으로 확대하는 편이 안전합니다.

실무에서 가장 먼저 확인할 것은 무엇인가요?

목표 지표, 대상 사용자, 예산 범위, 운영 책임자를 먼저 명확히 해야 합니다.

법률이나 정책 이슈도 함께 봐야 하나요?

네. 데이터 수집 방식, 플랫폼 정책, 개인정보 관련 제한을 반드시 점검해야 합니다.

성과를 어떻게 측정하면 좋나요?

비용, 전환율, 클릭률, 운영 공수, 재사용 가능성 같은 지표를 함께 보는 것이 좋습니다.

관련 글 추천

  • https://infobuza.com/2026/04/29/20260429-jjffuc/
  • https://infobuza.com/2026/04/29/20260429-c1xlz1/

지금 바로 시작할 수 있는 실무 액션

  • 현재 팀의 AI 활용 범위와 검증 절차를 먼저 문서화합니다.
  • 작은 파일럿 프로젝트로 KPI를 정하고 2~4주 단위로 검증합니다.
  • 보안, 품질, 리뷰 기준을 자동화 도구와 함께 연결합니다.

보조 이미지 1

보조 이미지 2

댓글 남기기