우분투에서 메모리 누수가 발생하는 원인은 여러 가지가 있지만, 다행히 누수가 발생하면 그 증상은 비교적 뚜렷하게 나타납니다. 가장 큰 원인은 대개 버그가 있는 코드입니다. 프로그래머가 더 이상 필요하지 않은 메모리를 제대로 해제했는지 확인하지 못한 경우에 발생하기 때문입니다. 불안정한 패키지를 설치하거나 소스 코드를 직접 컴파일해 사용 중이라면 이런 이유로 메모리 누수를 겪고 있을 가능성이 높습니다. 실제로는 충분한 물리적 RAM을 장착하고 있음에도 소프트웨어 애플리케이션이 메모리 부족을 호소하기 시작한다면 메모리 누수를 의심해 볼 수 있습니다.
메모리 누수가 걱정된다면 터미널에서 free 명령어를 반복적으로 입력해 보세요. RAM 사용량이 급격히 늘어나는 것이 보인다면 이미 메모리 누수를 감지한 것입니다. 만약 터미널이나 가상 콘솔만 열려 있는 상태에서 "bash: Not enough Memory"와 같은 오류가 나타난다면, 거의 확실하게 메모리 누수 문제를 다루고 있는 것입니다. 일부 메모리 누수는 좀 더 미묘하게 나타나기도 하지만, 우분투와 다양한 파생 배포판에는 이러한 누수를 감지하는 데 도움이 되는 도구와 패키지들이 마련되어 있습니다.
우분투에서 메모리 누수 감지하기
메모리 누수를 감지하는 도구들은 주로 CLI(명령줄 인터페이스) 프롬프트 기반이므로 어떤 버전의 우분투에서 실행하든 상관없습니다. 일반 우분투의 Unity 터미널, 우분투 서버의 가상 콘솔, Lubuntu의 lxterm, Kubuntu의 Konsole, 심지어 Xubuntu의 Xfce 환경에서도 잘 작동합니다. sudo -s를 입력하고 비밀번호를 입력하는 간단한 작업부터 시작해 보세요.
올바르게 수행했다면 루트(root) 셸을 얻을 수 있지만, 이미 누수가 너무 심각해진 상태라면 메모리 오류가 발생할 수 있습니다. 루트 셸에 접근할 수 있다면 echo 3 > /proc/sys/vm/drop_caches를 입력하고 엔터 키를 누른 후 exit를 입력하세요. 그다음 free 또는 free -m을 다시 실행하여 메모리가 해제되었는지 확인합니다.
일부 개발자들은 추가적인 물리적 메모리가 필요할 때 캐시는 자동으로 플러시되어 회수되므로, 커널이 강제로 캐시를 비우게 하는 것은 의미가 없다고 주장합니다. 물론 캐시를 강제로 플러시하면 시스템 성능이 저하되지만, 이는 어디까지나 테스트 목적이라는 점을 기억하세요. 시스템을 재부팅하면 리눅스 커널은 원래 상태대로 메모리 캐시를 다시 구성합니다.
일부 사용자들은 cron이 주기적으로 실행하는 스크립트에 sync; sudo echo 3 > /proc/sys/vm/drop_caches 줄을 추가하는 방법을 권하기도 합니다. 하지만 이는 메모리 캐싱의 존재 이유 자체를 무색하게 만드는 행위입니다. 여유 메모리(free memory)란 단순히 사용되지 않는 RAM일 뿐이며, 그렇다는 것은 데이터를 훨씬 느린 전자기식 저장 장치(HDD)나 NAND 플래시에서 불러와야 한다는 의미입니다. 아무리 빠른 저장 장치라도 RAM보다는 느리기 때문에, 메모리 누수는 반드시 해결해야 하지만 최적화된 캐시 설정은 함부로 건드리지 않는 것이 좋습니다.
top 명령어로 문제 프로세스 찾기
컴퓨터를 사용하는 동안 주기적으로 발생하지만 특정 원인으로 좁혀지지 않는 지속적인 메모리 누수가 확인되었고, 여전히 CLI 접근이 가능하다면 top 명령어를 실행해 보세요. 실행 중인 프로세스 목록이 표시됩니다.
top 실행 시 비정상적인 오류가 발생한다면 busybox top을 입력하여 더 단순한 버전의 프로그램에 접근해 보세요. 목록이 표시되면 %MEM 또는 유사한 열을 확인하여 가장 많은 메모리를 할당받은 애플리케이션을 찾습니다. PID를 기록해 두었다가 해당 번호로 kill 명령을 내릴 수 있지만, 이는 단순히 애플리케이션을 강제 종료할 뿐입니다. 종료 후에도 해당 프로세스가 사용하던 메모리가 해제되지 않을 수 있지만, 시도해 볼 가치는 충분합니다.
많은 양의 메모리를 사용하는 애플리케이션을 발견했다면 q를 눌러 top을 종료한 후, 이전 화면에서 확인한 PID 번호로 kill #### 명령을 실행합니다. 단, 시스템 프로세스는 이 방법으로 종료해서는 안 되며, 저장하지 않은 작업이 있는 프로그램 역시 마찬가지입니다. Ctrl+Alt+Del 작업 관리자로 프로세스를 종료하는 것과 유사하게 생각하면 되며, 같은 용도로 활용할 수도 있습니다.
특정 프로그램에서 이러한 현상이 반복적으로 발생한다면, 향후 동일한 문제가 재발하지 않도록 해당 프로그램의 설정을 조정하여 예방할 수 있습니다. 물론 프로그램마다 필요한 조치는 다르며, 이는 단순히 메모리 누수를 감지하는 작업을 넘어선 영역입니다.
개발자를 위한 메모리 분석 도구
단순히 애플리케이션 문제를 해결하는 것을 넘어 실제로 코드를 작성하는 개발자라면 활용할 수 있는 몇 가지 추가 수단이 있습니다. 우분투와 그 파생 배포판은 프로그래밍용으로 membarrier, memusage, memusagestat C 루틴을 제공합니다.
man membarrier, man memusage 또는 man memusagestat 명령으로 이 중요한 루틴들에 대한 리눅스 프로그래머 매뉴얼 페이지를 확인할 수 있습니다. 새로운 우분투 버전이 출시되면서 라이브러리에 업데이트가 생기면 변경 사항이 항상 여기에 정리됩니다.
시각적인 자료가 필요하다면 memusagestat는 메모리 사용량을 PNG 파일로 저장하는 옵션도 제공합니다. 이 덕분에 유틸리티 개발자에게도 매력적인 기능인데, 이를 활용해 주기적으로 메모리 누수를 검사하는 애플리케이션을 만들 수 있기 때문입니다.
memprof 설치도 고려해 볼 만합니다. memprof는 메모리 사용량을 프로파일링하여 메모리 누수를 찾는 데 도움을 주는 도구입니다. 작성 중인 프로그램의 각 함수가 얼마나 많은 메모리를 할당하는지에 대한 프로필을 생성하며, 할당되었지만 더 이상 유효한 참조가 없는 메모리 블록을 찾기 위해 기존 메모리를 스캔할 수도 있습니다. 이는 표준 C 라이브러리의 메모리 할당 기능을 대체하기 위해 라이브러리를 사전 로드(pre-loading)하는 방식으로 동작합니다.
이 도구를 사용할 계획이라면 코드를 공개하기 전에 코드 시작 부분의 include memprof 줄을 반드시 제거하세요. 이는 누수 여부를 확인하기 위한 용도일 뿐이며, 코드를 패키징하여 저장소에 배포할 때 불필요한 의존성으로 남아서는 안 됩니다.
저자 소개
Kevin Arrows (케빈 애로우즈)
케빈 애로우즈는 10년 이상의 업계 경력을 보유한 베테랑 기술 전문가입니다. Microsoft Certified Technology Specialist(MCTS) 자격증을 보유하고 있으며, 최신 기술 동향을 끊임없이 학습하는 데 깊은 열정을 가지고 있습니다. 소프트웨어 개발, 사이버 보안, 클라우드 컴퓨팅 등 다양한 기술 분야의 주제에 대해 폭넓게 집필해 왔으며, 복잡한 기술 개념을 명확하고 간결하게 설명하는 능력으로 동료들의 인정과 존경을 받고 있습니다.