13년차의 서버실

서버, 인프라, 홈랩 기술 블로그

[태그:] 성능 모니터링

  • [Linux] ext4 디스크 I/O 성능 저하 원인 분석 및 진단 방법

    [Linux] ext4 디스크 I/O 성능 저하 원인 분석 및 진단 방법

    [Linux] ext4 디스크 I/O 성능 저하 원인 분석 및 진단 방법

    안녕하세요, 13년차 서버실 지킴이입니다. 🤓

    어느 날 갑자기 서버가 느려졌는데, CPU나 메모리 사용량은 평온하고 네트워크 트래픽도 평소와 다를 바 없을 때, 문득 이런 생각이 들지 않으세요? “혹시 ext4의 디스크 I/O 문제인가?” 네, 정확한 추측일 수도 있어요. 리눅스 서버에서 가장 흔하게 사용되는 파일시스템인 ext4에서 성능 저하가 벌어지면 정말 당황스럽죠. 특히 서비스 운영 중이라면 심장이 덜컥 내려앉을 겁니다.

    저도 홈랩에서 이것저것 실험하다가 갑자기 디스크 읽기/쓰기 속도가 확 떨어져서 며칠 밤낮을 삽질했던 경험이 있거든요. 처음엔 설정 문제인가 싶었는데, 알고 보니 ext4 파일시스템 자체의 특성이나 잘못된 마운트 옵션, 혹은 숨겨진 병목 때문이었더라고요. 그래서 오늘은 ext4 디스크 I/O 성능 저하의 원인을 파헤치고, 어떻게 진단하고 해결할 수 있는지 제 경험을 바탕으로 솔직하게 풀어보려 합니다. 함께 리눅스 디스크 I/O 문제를 해결해 봅시다! 💡

    리눅스 서버의 ext4 파일시스템 I/O 흐름 및 잠재적 병목 지점 개요 다이어그램

    ext4 파일시스템과 디스크 I/O, 대체 뭐가 문제일까요? 🤔

    먼저, 기본적인 개념부터 짚고 넘어갈게요. 디스크 I/O(Input/Output)는 말 그대로 디스크에 데이터를 쓰고(write) 읽는(read) 작업을 말합니다. 서버 애플리케이션의 응답 속도는 이 디스크 I/O 성능에 크게 좌우되죠. 웹 서버의 로그 기록, 데이터베이스의 쿼리 처리, 캐시 파일 저장 등 거의 모든 작업이 디스크 I/O를 수반하거든요.

    ext4는 리눅스에서 가장 널리 사용되는 저널링 파일시스템(Journaling Filesystem)입니다. 저널링 덕분에 시스템 크래시(crash) 시 데이터 일관성(data consistency)을 보장하는 강력한 장점이 있지만, 이 저널링 과정 자체가 때로는 I/O 성능 오버헤드(overhead)로 작용할 수 있어요. 쉽게 말해, 데이터를 변경하기 전에 먼저 변경 내용을 저널(journal)이라는 특별한 영역에 기록하고 나서 실제 데이터 영역에 쓰는 방식이라, 안정성은 높지만 그만큼 추가적인 디스크 작업이 필요하다는 거죠.

    ext4의 성능에 영향을 미치는 주요 요소는 다음과 같습니다:

    • 저널링 모드 (Journaling Mode): data=journal, data=ordered, data=writeback 등 모드에 따라 데이터 안정성과 성능이 달라집니다.
    • 블록 사이즈 (Block Size): 파일시스템 생성 시 지정하는 데이터 처리 단위로, 작은 파일이 많으면 작은 블록 사이즈가, 큰 파일이 많으면 큰 블록 사이즈가 유리할 수 있습니다.
    • 마운트 옵션 (Mount Options): noatime, discard, barrier=0 등 다양한 옵션으로 성능을 튜닝할 수 있습니다.
    • 디스크 자체 성능: HDD냐 SSD냐, RAID 구성이냐 등 물리적인 디스크의 스펙도 중요하죠.
    • 파일 단편화 (Fragmentation): 파일이 디스크 여러 곳에 흩어져 저장되면 읽기/쓰기 성능이 저하됩니다.

    실전! ext4 디스크 I/O 성능 진단 도구 활용법 🛠️

    자, 이제 실제로 서버에서 디스크 I/O 병목을 어떻게 찾아내는지 알아볼 차례입니다. 리눅스에는 정말 유용한 도구들이 많아요. 제가 즐겨 쓰는 몇 가지를 소개합니다.

    1. iostat: 시스템 전체 디스크 I/O 통계

    iostat은 시스템 전체의 디스크 I/O 통계를 실시간으로 보여주는 강력한 도구예요. 특정 디스크의 사용률, 큐 길이, 응답 시간 등을 한눈에 파악할 수 있거든요.

    # iostat -x 1 5
    # -x: 확장 통계 정보 출력 (extended statistics)
    # 1: 1초 간격으로
    # 5: 5번 반복 출력
    
    Linux 5.15.0-78-generic (my-server) 	08/20/2023 	_x86_64_ 	(8 CPU)
    
    avg-cpu:  %user   %nice %system %iowait  %steal   %idle
               1.20    0.00    0.80    0.10    0.00   97.90
    
    Device             r/s   w/s   rkB/s   wkB/s  avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
    sda               0.10  0.00    2.00    0.00     40.00     0.00    0.20    0.20    0.00   0.20   0.00
    sdb               0.00  0.00    0.00    0.00      0.00     0.00    0.00    0.00    0.00   0.00   0.00
    

    여기서 봐야 할 핵심 지표들은 다음과 같습니다:

    • %util: 디스크 사용률입니다. 100%에 가깝다면 디스크가 항상 바쁘다는 뜻인데, 성능 병목의 강력한 신호일 수 있어요. (⚠️ 단, 고성능 NVMe SSD의 경우 100%에 가까워도 실제 성능은 좋을 수 있으니 다른 지표와 함께 봐야 합니다!)
    • avgqu-sz (Average Queue Size): 디스크 I/O 요청 큐의 평균 길이입니다. 이 값이 지속적으로 높다면 디스크가 요청을 처리하지 못하고 대기 중인 작업이 많다는 뜻이에요. 보통 1 이상이면 주의 깊게 봐야 합니다.
    • await (Average Wait Time): I/O 요청이 디스크에서 처리되기까지 걸리는 평균 시간(밀리초)입니다. 큐에서 대기하는 시간까지 포함하므로, 이 값이 높으면 응답성이 떨어진다는 의미죠.
    • svctm (Average Service Time): I/O 요청이 디스크 컨트롤러에 의해 실제로 처리되는 평균 시간(밀리초)입니다. await과 svctm의 차이가 크다면, 큐에서 대기하는 시간이 길다는 의미로 해석할 수 있어요.

    2. sar -d: 상세 디스크 활동 통계

    sar는 시스템 활동 리포트(System Activity Reporter)의 약자로, CPU, 메모리, 네트워크 등 다양한 시스템 통계를 기록하고 분석할 수 있습니다. 디스크 I/O를 보려면 -d 옵션을 사용하면 되죠.

    # sar -d 1 5
    # -d: 디스크 활동 통계 출력
    # 1: 1초 간격으로
    # 5: 5번 반복 출력
    
    Linux 5.15.0-78-generic (my-server) 	08/20/2023 	_x86_64_ 	(8 CPU)
    
    02:30:01 PM   DEV       tps  rd_sec/s  wr_sec/s  avgrq-sz  avgqu-sz  await  svctm  %util
    02:30:02 PM   sda      0.10      2.00      0.00     40.00      0.00   0.20   0.20   0.00
    02:30:02 PM   sdb      0.00      0.00      0.00      0.00      0.00   0.00   0.00   0.00
    

    iostat과 비슷한 지표들을 제공하지만, sar는 기록된 데이터를 나중에 분석할 때 유용해요. 특히 tps (초당 전송 수), rd_sec/s (초당 읽기 섹터 수), wr_sec/s (초당 쓰기 섹터 수)를 통해 디스크의 처리량(throughput)을 가늠해볼 수 있습니다. sar는 sysstat 패키지에 포함되어 있으니, 설치되어 있지 않다면 sudo apt install sysstat (Debian/Ubuntu) 또는 sudo yum install sysstat (CentOS/RHEL)로 설치해 주세요.

    3. iotop: 프로세스별 디스크 I/O 사용량

    시스템 전체나 특정 디스크의 I/O 통계를 봤는데, 어떤 프로세스가 디스크를 많이 쓰고 있는지 궁금할 때가 있습니다. 이럴 땐 iotop이 아주 유용해요. 마치 top 명령어처럼 프로세스별 I/O 사용량을 실시간으로 보여주거든요.

    # iotop
    # -o: 현재 I/O를 사용하는 프로세스만 표시
    # -P: 프로세스만 표시 (스레드 제외)
    
    Total DISK READ :       0.00 B/s | Total DISK WRITE :       0.00 B/s
    Actual DISK READ:       0.00 B/s | Actual DISK WRITE:       0.00 B/s
      TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN     IO>    COMMAND
        1 be/4 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % init
        2 be/4 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % [kthreadd]
      ...
    

    iotop을 실행하면 어떤 프로세스가 디스크를 가장 많이 쓰고 있는지 바로 알 수 있어요. IO> 컬럼을 통해 I/O 대기(wait) 상태를 파악할 수 있고, 이를 통해 특정 애플리케이션이나 서비스가 디스크 병목을 유발하는 주범인지 쉽게 찾아낼 수 있습니다. 💡

    iotop 명령어로 확인하는 프로세스별 디스크 I/O 사용량

    iotop 명령어를 통해 실시간 프로세스별 디스크 I/O 사용량을 확인하는 모습

    ⚠️ 삽질 경험담: ext4 마운트 옵션과 저널링의 함정

    제가 가장 많이 삽질했던 부분 중 하나가 바로 ext4의 마운트 옵션(Mount Options)과 저널링(Journaling)이었습니다. 단순히 디스크를 마운트할 때 아무 생각 없이 기본값으로 쓰다가 나중에 피를 본 적이 많거든요. 특히 작은 파일을 빈번하게 읽고 쓰는 웹 서버나 캐시 서버에서 이런 문제가 자주 발생하더라고요.

    1. atime 업데이트 오버헤드

    기본적으로 리눅스 파일시스템은 파일에 접근(access)할 때마다 atime(access time)을 업데이트합니다. 이게 참 좋은 기능이지만, 문제는 파일에 접근할 때마다 디스크 쓰기 작업이 발생한다는 거예요. 즉, 읽기 작업인데도 쓰기 I/O가 발생해 성능 저하를 일으킬 수 있어요. 그래서 저는 특별한 이유가 없다면 noatime 옵션을 즐겨 사용합니다.

    # /etc/fstab 파일 예시
    UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx /data ext4 defaults,noatime,errors=remount-ro 0 1
    
    # 변경 후 적용
    sudo mount -o remount /data
    

    noatime은 atime 업데이트를 완전히 비활성화합니다. 만약 atime 정보가 필요하지만 I/O 오버헤드를 줄이고 싶다면 relatime 옵션을 사용할 수도 있어요. relatime은 마지막 접근 시간이 마지막 변경 시간(mtime)보다 오래되었을 때만 atime을 업데이트합니다. 대부분의 경우 relatime으로도 충분하고, 극단적인 성능이 필요하면 noatime을 사용하죠.

    2. 저널링 모드 선택

    앞서 설명했듯이, ext4는 저널링 모드에 따라 성능과 데이터 안정성이 달라집니다. 주요 모드는 세 가지입니다.

    • data=journal: 데이터와 메타데이터(metadata) 모두 저널에 기록합니다. 가장 안전하지만, 가장 느려요. 데이터 일관성이 최우선인 경우에만 고려해볼 만합니다.
    • data=ordered (기본값): 메타데이터만 저널에 기록하고, 데이터는 메타데이터가 커밋(commit)되기 전에 디스크에 쓰여지도록 보장합니다. 안정성과 성능의 균형이 좋아서 대부분의 경우에 적합하죠.
    • data=writeback: 메타데이터만 저널에 기록하고, 데이터는 저널링되지 않습니다. 가장 빠르지만, 시스템 크래시 시 데이터 손실 위험이 있어요. 캐시 디스크나 로그 디스크처럼 데이터 손실이 치명적이지 않은 경우에 고려할 수 있습니다.

    저널링 모드 변경은 파일시스템 생성 시 또는 tune2fs 명령으로 변경 가능하지만, 마운트 옵션으로도 지정할 수 있어요. 예를 들어, 성능을 최우선으로 한다면:

    # /etc/fstab 파일 예시
    UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx /cache ext4 defaults,noatime,data=writeback 0 2
    
    # 변경 후 적용
    sudo mount -o remount /cache
    

    ⚠️ data=writeback은 데이터 손실 위험이 있으니 신중하게 사용하세요!

    3. 그 외 유용한 마운트 옵션

    몇 가지 더 유용한 옵션들을 표로 정리해봤습니다.

    옵션 설명 효과 주의사항
    noatime 파일 접근 시간(atime) 업데이트 비활성화 읽기 I/O 발생 시 쓰기 I/O 감소 atime 정보가 필요한 애플리케이션에 문제 발생 가능
    relatime mtime보다 오래된 atime만 업데이트 noatime과 atime 업데이트의 절충안 대부분의 경우 noatime 대신 사용 권장
    data=writeback 데이터 저널링 비활성화 가장 빠른 쓰기 성능 시스템 크래시 시 데이터 손실 위험
    barrier=0 디스크 쓰기 배리어(write barrier) 비활성화 일부 환경에서 쓰기 성능 향상 RAID 컨트롤러 또는 가상 환경에서 데이터 손실 위험 증가, 신중히 사용
    discard TRIM 명령 활성화 (SSD에 유용) SSD 성능 유지 및 수명 연장 지속적인 TRIM으로 인한 오버헤드 발생 가능 (주기적인 fstrim 권장)
    ext4 마운트 옵션별 성능 및 데이터 안정성 비교 인포그래픽

    ext4 마운트 옵션별 성능 및 데이터 안정성 비교

    ✅ 검증 및 결과 확인: 성능 개선을 눈으로 확인하기!

    마운트 옵션을 변경했거나, 문제가 되는 프로세스를 해결했다면, 이제 정말로 성능이 개선되었는지 확인해야겠죠? 저는 주로 iostat이나 sar로 다시 한번 지표를 확인해요. 특히 await, avgqu-sz, %util 값이 어떻게 변했는지 집중해서 봅니다.

    • await 값이 5ms 미만으로 꾸준히 유지된다면 양호한 수준입니다. 10ms 이상으로 지속된다면 여전히 I/O 병목이 있을 가능성이 높아요.
    • avgqu-sz 값이 1 이하로 떨어졌는지 확인해요. 이 값이 높으면 I/O 요청이 계속 밀리고 있다는 뜻이거든요.
    • %util은 무조건 낮다고 좋은 건 아니지만, 과도하게 높으면서 다른 지표들(await, avgqu-sz)도 높다면 문제가 있다는 신호예요.

    만약 특정 애플리케이션의 성능 저하가 문제였다면, 해당 애플리케이션의 응답 시간(response time)이나 처리량(throughput) 지표를 직접 확인하는 것이 가장 정확해요. 예를 들어, 데이터베이스 쿼리 속도가 빨라졌는지, 웹 페이지 로딩 시간이 단축되었는지 등을 측정해보는 거죠. 저는 Grafana와 Prometheus를 활용해서 I/O 지표를 시각화해서 보곤 하는데, 이렇게 하면 변화 추이를 한눈에 파악하기 정말 편하더라고요. 🎉

    Grafana 대시보드에서 디스크 I/O 성능 개선 추이를 시각적으로 확인하는 예시

    마무리: 나의 ext4는 어떤 길을 가야 할까? 🚀

    ext4 디스크 I/O 성능 문제는 정말 흔하고, 처음엔 막막하게 느껴질 수 있어요. 하지만 iostat, sar, iotop 같은 도구들을 활용해서 정확한 원인을 파악하고, 적절한 마운트 옵션 튜닝이나 저널링 모드 변경을 통해 충분히 해결할 수 있습니다.

    결론적으로, “내 ext4는 어떤 설정이 최적일까?”라는 질문에 대한 답은 “어떤 데이터를, 어떻게 사용하는지에 따라 다르다”는 거예요.

    • 만약 데이터 일관성과 안전성이 최우선이라면, data=ordered (기본값)를 유지하고, noatime보다는 relatime을 고려하는 것이 좋습니다.
    • 로그 파일이나 캐시처럼 데이터 손실에 비교적 관대한 환경에서 최고의 쓰기 성능을 원한다면, data=writeback과 noatime 조합을 신중하게 테스트해볼 수 있습니다. 하지만 이 경우 백업 전략을 더욱 철저히 해야겠죠.
    • SSD를 사용 중이라면, discard 옵션을 사용하거나 주기적으로 fstrim 명령을 실행하여 성능을 유지하는 것이 좋아요.

    이번 글이 여러분의 ext4 성능 문제 해결에 작은 도움이 되었기를 바랍니다. 다음번에는 파일 단편화(fragmentation) 문제를 깊이 다루거나, 더 나아가 ZFS나 Btrfs 같은 다른 파일시스템의 성능 튜닝에 대해서도 이야기해볼까 합니다. 궁금한 점이 있다면 언제든 댓글로 남겨주세요! 저의 삽질 경험이 또 다른 글이 될 수 있으니까요. 😉

  • [Linux] Linux 커널 vRAM 성능 개선: zswap·zram·PSI 가이드

    [Linux] Linux 커널 vRAM 성능 개선: zswap·zram·PSI 가이드

    Linux 커널 vRAM 성능 개선: zswap·zram·PSI 모니터링 가이드

    Linux 커널 vRAM 성능이라는 표현은 늘 헷갈리더라고요. GPU VRAM 얘기로 흘러가기도 하고, 어떤 분은 swap만 떠올리시죠. 이 글에서는 후자, 그러니까 메모리 압박이 왔을 때 커널이 어떤 계층으로 시간을 벌고 그 대가를 CPU·RAM·I/O 어디에 치르는지를 다룹니다. 홈랩에서 VM 밀도를 올리다 보면 메모리 사용률보다 stall이 먼저 서비스 응답을 무너뜨리는 경우가 꽤 자주 보입니다. 그래서 저는 이제 swappiness부터 만지지 않습니다. 먼저 압박이 어디서 발생하는지 보고, 그다음에 zswap인지 zram인지, 마지막으로 정책값을 조정합니다.

    이 주제가 실무에서 어려운 이유도 여기 있습니다. 기능이 많아서라기보다, 증상은 비슷한데 원인은 다를 때가 많기 때문입니다. SwapUsed가 늘어도 괜찮은 경우가 있고, free 메모리가 남아 보이는데도 reclaim이 꼬여 tail latency가 튀는 경우도 있거든요. 그래서 이 글은 정의 설명보다 관측 순서, 선택 기준, 실패 모드의 근본 원인에 초점을 맞춰 정리해보겠습니다.

    Linux 커널 vRAM 성능, PSI, zswap, zram, swap 디스크의 관계를 한눈에 보여주는 개요 이미지입니다.

    1. Linux 커널 vRAM 성능에서 말하는 vRAM의 정체

    운영 현장에서 말하는 vRAM은 공식 커널 용어가 아닙니다. 보통은 디스크 swap에 닿기 전에 메모리 압박을 완충하는 계층을 묶어 부를 때가 많습니다. 이름보다 중요한 건 계층의 위치입니다.

    • swap: 최종 퇴로입니다. 느린 디스크라면 여기서 지연이 바로 드러납니다.
    • zswap: 기존 swap 앞단에 붙는 압축 캐시입니다. 페이지를 바로 디스크로 내보내지 않고 RAM 안의 압축 풀에 잠깐 머물게 합니다.
    • zram: RAM 안에 만드는 압축 블록 디바이스입니다. 그 장치를 swap으로 써서 디스크 접근을 줄이거나 늦춥니다.
    • PSI: 메모리 부족 여부 자체보다, 그 부족이 실제로 태스크를 얼마나 멈추게 했는지 보여줍니다.

    제 판단 기준은 단순합니다. 문제는 메모리 사용량이 아니라 stall의 비용입니다. 페이지 캐시를 적극적으로 쓰는 서버는 메모리가 꽉 차도 정상일 수 있습니다. 반대로 reclaim scan이 많이 돌고 swap I/O가 겹치면 사용자는 CPU나 디스크 수치보다 먼저 응답 지연으로 체감합니다.

    2. Linux 커널 vRAM 성능 모니터링은 사용률보다 압박 형태가 먼저입니다

    대시보드를 열기 전에 커널 기본 인터페이스부터 보는 편이 훨씬 정확합니다. 아래 다섯 군데만 읽어도 방향이 꽤 선명해집니다.

    1. /proc/pressure/memory: 메모리 때문에 작업이 멈춘 시간 비율
    2. /proc/vmstat: pswpin, pswpout, pgscan, pgsteal 같은 reclaim 흔적
    3. /proc/meminfo: MemAvailable, SwapFree 등 현재 상태
    4. /sys/module/zswap/parameters/*: zswap 활성화 여부와 정책값
    5. /sys/block/zram0/*: zram 압축 효율, I/O 이상 징후, 메모리 오버헤드

    아래 명령 정도만 확인해도 1차 진단은 충분합니다.

    uname -r
    cat /proc/pressure/memory
    grep -E 'MemTotal|MemAvailable|SwapTotal|SwapFree' /proc/meminfo
    grep -E 'pswpin|pswpout|pgscan|pgsteal|pgfault|pgmajfault' /proc/vmstat
    vmstat 1 10

    해석은 사용률 표보다 훨씬 냉정하게 하셔야 합니다.

    • memory full이 부하 시 계속 상승: 시스템 전체가 메모리 때문에 전진하지 못하는 상태에 가깝습니다. 단순 부족이라기보다 thrashing 징후로 보는 편이 맞습니다.
    • pgscan은 큰데 pgsteal이 기대만큼 따라오지 않음: 회수 후보는 많이 뒤지는데 건질 게 적다는 뜻입니다.
    • pswpout 증가 + I/O 대기 증가: 디스크 swap 비용이 사용자 지연으로 번질 가능성이 큽니다.
    • SwapUsed 증가만 있고 PSI는 낮음: 꼭 나쁜 신호는 아닙니다. 커널이 완충 계층을 잘 쓰는 상황일 수도 있습니다.

    실제로 자주 보는 시나리오도 이렇습니다. VM 호스트에서 야간 백업과 압축 작업이 겹치면 free 메모리는 아직 남아 보이는데 memory full이 먼저 튑니다. 이유는 단순 메모리 부족이 아니라 익명 메모리와 캐시가 동시에 압박받으면서 reclaim과 writeback이 서로 발목을 잡기 때문입니다. 이때 swappiness만 낮추면 해결되기보다, 익명 메모리를 디스크로 더 늦게 밀어 결국 stall이 더 커질 때도 많습니다.

    3. zswap과 zram은 비슷해 보여도 선택 기준이 다릅니다

    둘 다 압축을 쓰지만, 운영 관점에서는 거의 다른 도구에 가깝습니다. 차이는 기존 swap 경로를 유지하느냐, RAM을 swap 장치로 재구성하느냐에 있습니다.

    옵션 동작 방식 이럴 때 우선 검토 피해야 할 경우 운영 포인트
    swap only 디스크 swap만 사용 구조 단순성이 더 중요할 때, 메모리 압박이 드물 때 느린 스토리지, burst성 메모리 압박이 잦을 때 PSI와 swap I/O 상관관계 확인이 핵심입니다
    zswap swap 직전 페이지를 RAM 압축 풀에 저장 기존 swap은 유지하되 디스크 쓰기를 줄이고 싶을 때, VM 호스트나 일반 서버 CPU가 이미 바쁘고 압축 이득이 낮은 워크로드 compressor, max_pool_percent, accept_threshold_percent, shrinker_enabled를 같이 봅니다
    zram RAM 기반 압축 블록 디바이스를 swap으로 사용 디스크가 약한 미니 PC, 홈랩, 엣지 노드, 임시 burst 흡수가 필요할 때 RAM 자체가 너무 타이트하고 압축률이 낮은 워크로드 comp_algorithm, disksize, mm_stat, mem_used_total, huge_pages를 봅니다

    제 경험상 판단은 이렇게 가져가면 덜 틀립니다. 디스크 swap은 이미 있고 운영 변경 폭을 작게 가져가야 한다면 zswap, 디스크 병목이 뚜렷하거나 swap 장치를 RAM 안에 고립시키는 편이 낫다면 zram입니다. 둘을 동시에 쓸 수도 있지만, 처음부터 같이 만지면 원인 분리가 어려워집니다.

    4. zswap은 기존 swap 경로를 보존하면서 지연을 깎을 때 유리합니다

    운영 서버에서 먼저 검토하는 쪽은 대체로 zswap입니다. swap 체인을 갈아엎지 않고도 디스크 write pressure를 줄일 수 있기 때문이죠. 특히 SSD swap이 있는 VM 호스트나 컨테이너 밀도가 높은 서버에서 접근성이 좋습니다. 다만 배포판 기본값과 커널 설정에 따라 일부 파라미터 노출 여부가 다를 수 있으니, 먼저 파일 존재 여부부터 확인하는 게 안전합니다.

    # 현재 상태 확인
    cat /sys/module/zswap/parameters/enabled
    cat /sys/module/zswap/parameters/compressor
    cat /sys/module/zswap/parameters/max_pool_percent
    cat /sys/module/zswap/parameters/accept_threshold_percent
    cat /sys/module/zswap/parameters/shrinker_enabled
    
    # 런타임 조정 예시
    sudo sh -c 'echo 1 > /sys/module/zswap/parameters/enabled'
    sudo sh -c 'echo lzo > /sys/module/zswap/parameters/compressor'
    sudo sh -c 'echo 20 > /sys/module/zswap/parameters/max_pool_percent'
    sudo sh -c 'echo 80 > /sys/module/zswap/parameters/accept_threshold_percent'
    sudo sh -c 'echo Y > /sys/module/zswap/parameters/shrinker_enabled'

    각 값은 이렇게 해석하시면 됩니다.

    • compressor: 압축률보다 CPU 비용 대비 전체 지연 관점으로 봐야 합니다. CPU 여유가 적은 노드에서는 조금 덜 압축돼도 빠른 알고리즘이 낫습니다.
    • max_pool_percent: 풀이 커지면 디스크 쓰기는 줄어들 수 있지만 RAM 경쟁이 심해질 수 있습니다.
    • accept_threshold_percent: 풀이 한 번 가득 찬 뒤 언제 다시 페이지를 받기 시작할지 정합니다.
    • shrinker_enabled: 차가운 페이지가 zswap에 오래 쌓이는 환경에서는 메모리를 되돌리는 데 도움이 됩니다.

    여기서 흔한 실패는 세 가지입니다. 첫째, 압축 풀이 성능 향상 수단이 아니라 메모리 은닉 수단으로만 쓰이는 경우입니다. 둘째, CPU가 이미 꽉 찬 노드에서 무거운 압축기를 쓰는 경우입니다. 셋째, writeback을 막아놓고 store failure가 반복되는 경우입니다. 이때는 압축되지 않는 페이지를 계속 거절하면서 reclaim 효율이 떨어질 수 있습니다.

    swappiness도 같은 맥락에서 봐야 합니다. 예전처럼 무조건 낮출 값은 아닙니다. 커널 문서 기준으로 vm.swappiness는 0~200 범위를 쓰며, zram이나 zswap 같은 in-memory swap에서는 100을 넘는 값도 검토할 수 있습니다. 즉, 아래 예시는 출발점일 뿐이고 정답처럼 고정하시면 안 됩니다.

    # 현재 정책 확인
    sysctl vm.swappiness
    cat /proc/sys/vm/swappiness
    
    # 실험용 런타임 변경
    sudo sysctl -w vm.swappiness=100
    
    # 영구 반영 예시
    sudo tee /etc/sysctl.d/99-vm-tuning.conf >/dev/null <<'EOF'
    vm.swappiness = 100
    EOF
    sudo sysctl --system

    권고를 짧게 정리하면 이렇습니다. zswap을 켰다면 swappiness를 너무 낮게 고정하지 말고, PSI와 pswpout 패턴을 보면서 다시 잡으세요. 디스크 swap만 있는 서버에서 쓰던 감각을 그대로 가져오면 의외로 손해를 봅니다.

    Linux 커널 vRAM 성능 개선을 위한 zswap 설정과 PSI 모니터링 이미지

    zswap 활성화, compressor 선택, max_pool_percent 조정, PSI 관측 흐름을 함께 보여주는 구성 이미지입니다.

    5. zram은 느린 디스크를 우회할 때 강하지만 RAM 예산 관리가 더 까다롭습니다

    zram은 홈랩이나 저전력 노드에서 체감이 큰 편입니다. 이거 잘 맞으면 진짜 편하더라고요. 다만 장점이 분명한 만큼 함정도 분명합니다. 디스크 I/O를 아끼는 대신 RAM과 CPU를 더 정교하게 써야 한다는 점입니다. 그래서 저는 zram을 켤 때 늘 압축 이득과 메타데이터·단편화 오버헤드를 같이 봅니다.

    # 새 장치 초기화 전에는 comp_algorithm을 먼저 고릅니다.
    sudo modprobe zram num_devices=1
    cat /sys/block/zram0/comp_algorithm
    sudo sh -c 'echo lz4 > /sys/block/zram0/comp_algorithm'
    
    # 크기를 정한 뒤 swap으로 만듭니다.
    sudo sh -c 'echo 8G > /sys/block/zram0/disksize'
    sudo mkswap /dev/zram0
    sudo swapon -p 100 /dev/zram0
    
    # 상태 확인
    zramctl
    cat /sys/block/zram0/mm_stat
    cat /sys/block/zram0/io_stat

    여기서 놓치기 쉬운 실무 포인트가 있습니다.

    • comp_algorithm은 장치 초기화 뒤에는 변경할 수 없습니다. 이미 disksize를 설정했다면 순서를 다시 잡아야 합니다.
    • disksize는 실제 메모리 사용량이 아닙니다. 논리 크기일 뿐이고, 실제 소비는 mm_stat와 mem_used_total을 같이 봐야 감이 옵니다.
    • 우선순위(swapon -p)를 안 잡으면 기대와 다른 swap 경로로 흘러갈 수 있습니다.

    mm_stat는 꼭 읽어보셔야 합니다.

    • orig_data_size: 원본 데이터 크기
    • compr_data_size: 압축 후 데이터 크기
    • mem_used_total: 실제로 zram이 먹는 메모리. 메타데이터와 단편화 비용이 반영됩니다
    • huge_pages: 압축 이득이 낮은 페이지 수를 가늠할 때 참고할 수 있는 값입니다

    판단법은 단순합니다. orig_data_size 대비 compr_data_size가 의미 있게 줄고, 그에 비해 mem_used_total이 과하게 불어나지 않으면 성공에 가깝습니다. 반대로 huge_pages가 계속 늘면 이 워크로드는 압축 친화적이지 않을 가능성이 큽니다. 그 상태에서 zram 크기만 키우면 메모리 버퍼를 늘린 게 아니라 비효율을 키운 것에 가까워집니다.

    zram을 피하는 편이 나은 경우도 분명합니다. 메모리 자체가 매우 타이트하고, 워크로드가 이미 CPU를 바쁘게 쓰며, 페이지 내용이 압축에 잘 안 걸리는 경우입니다. 이런 노드는 오히려 작은 zswap + 보수적 swappiness가 덜 흔들릴 때가 있습니다.

    6. 트러블슈팅은 증상이 아니라 원인 축으로 봐야 빨리 풀립니다

    제가 실무에서 가장 많이 헷갈렸던 지점도 여기였습니다. 겉으로는 다 메모리 문제처럼 보이는데, 실제로 손대야 할 축이 다르거든요.

    • PSI avg10만 보고 안심: 짧은 spike는 평균보다 total 증가와 순간 지연에서 먼저 드러납니다.
    • swap 사용량 증가를 실패로 해석: swap을 얼마나 썼는지가 아니라, 그 결과로 stall이 줄었는지를 봐야 합니다.
    • zswap 파라미터가 안 보임: 커널 설정, 배포판 기본값, 부팅 옵션 차이일 수 있습니다.
    • zram이 있는데 체감 개선이 없음: 압축률 부족, huge_pages 증가, 우선순위 misconfig, 또는 실제 병목이 메모리보다 CPU일 수 있습니다.
    • writeback을 막았더니 오히려 느려짐: 압축 불가 페이지가 반복 거절되며 reclaim만 더 많이 돌기 때문입니다.

    컨테이너 환경에서는 시스템 평균만 봐서는 자주 틀립니다. 어떤 워크로드 하나가 압박을 만들고 있는데 전체 노드는 멀쩡해 보일 수 있거든요. 그래서 cgroup v2 파일을 같이 읽는 편이 좋습니다. 다만 memory.zswap.* 계열은 비교적 최신 커널과 해당 기능 지원이 필요하니, 파일이 없으면 기능 미지원부터 의심하세요.

    CG=/sys/fs/cgroup/my-workload
    cat $CG/memory.pressure
    cat $CG/memory.current
    cat $CG/memory.high
    cat $CG/memory.swap.max
    cat $CG/memory.zswap.current
    cat $CG/memory.zswap.max
    cat $CG/memory.zswap.writeback

    이 파일들의 조합이 중요한 이유는 시스템 전체 메모리 정책과 워크로드별 완충 정책이 서로 다를 수 있기 때문입니다.

    • memory.high: OOM 전에 압박을 일찍 걸어 reclaim을 유도합니다.
    • memory.swap.max: cgroup 단위 swap 허용 범위를 제한합니다.
    • memory.zswap.max: zswap 사용량의 상한입니다.
    • memory.zswap.writeback: 0으로 두면 zswap writeback과 store failure에 따른 swapout 경로를 막습니다. 대신 반복 거절이 생기면 reclaim 효율이 무너질 수 있습니다.

    권하는 방식은 시스템 전체 평균 대신 문제가 되는 cgroup의 memory.pressure와 zswap 사용량을 같이 보는 것입니다. 멀티테넌트 환경에서는 전체 PSI보다 특정 서비스 cgroup의 압박이 장애와 더 직접적으로 연결될 때가 많습니다.

    7. 검증은 swap 숫자가 아니라 지연 구조가 바뀌었는지로 끝냅니다

    설정 적용 후에 보는 순서도 정해두는 편이 좋습니다. 안 그러면 우연한 캐시 상태를 개선으로 착각하기 쉽습니다.

    1. 부하 전후 /proc/pressure/memory의 some, full, total 비교
    2. /proc/vmstat에서 pswpout, pgscan, pgsteal 패턴 비교
    3. zram이면 mm_stat에서 압축 이득과 실제 메모리 사용량 확인
    4. zswap이면 pool 크기 정책과 cgroup별 사용량, writeback 정책 확인
    5. 마지막으로 애플리케이션 지연 로그나 요청 처리 시간과 맞춰 보기

    좋은 방향의 신호는 대체로 이렇습니다.

    • 메모리 PSI의 full 증가 속도가 둔화됩니다.
    • swap activity가 남아 있어도 응답 지연의 튐이 줄어듭니다.
    • zram의 compr_data_size가 의미 있게 작고, mem_used_total이 통제됩니다.
    • 특정 cgroup의 압박이 다른 워크로드로 덜 번집니다.

    반대로 실패 신호도 분명합니다. swap은 줄었는데 PSI가 그대로 높다, zram 사용량은 늘었는데 huge_pages도 함께 오른다, writeback을 막은 뒤 reclaim scan만 폭증한다. 이런 경우는 설정을 더 밀어붙일 게 아니라, 선택 자체를 다시 봐야 합니다.

    Linux 커널 vRAM 성능 개선 결과를 보여주는 PSI와 zram zswap 대시보드 이미지

    메모리 PSI, swap activity, zram 압축 효율, cgroup 단위 메모리 압박 개선 결과를 시각화한 대시보드 이미지입니다.

    8. 운영 판단을 바로 내릴 수 있게 시나리오별로 끊어보겠습니다

    Q1. swappiness는 낮을수록 좋은가요?

    그렇게 보면 자주 틀립니다. 디스크 swap만 주로 쓰는 서버라면 낮은 값이 도움이 될 수 있습니다. 하지만 zswap이나 zram처럼 메모리 안쪽에 완충 계층이 있을 때는 너무 낮은 값이 익명 메모리를 오래 붙잡아 reclaim 비용을 키울 수 있습니다. 실무에서는 결국 사용률이 아니라 PSI와 지연으로 판단하는 게 덜 틀립니다.

    Q2. zswap과 zram 중 무엇부터 볼까요?

    운영 변경 폭을 작게 가져가야 하는 일반 서버, VM 호스트, SSD swap 환경이면 zswap부터 보시면 됩니다. 디스크가 약한 미니 PC, 홈랩, 엣지 노드라면 zram이 먼저입니다. 둘 다 가능해도 처음엔 한 단계씩 바꾸세요. 그래야 어느 계층이 실제 이득을 냈는지 분리해서 볼 수 있습니다.

    Q3. 컨테이너 환경에서는 무엇이 가장 중요할까요?

    노드 평균보다 cgroup별 pressure와 상한입니다. memory.high, memory.swap.max, memory.zswap.max, memory.zswap.writeback를 같이 보셔야 합니다. 평균이 멀쩡해도 특정 서비스 하나만 느려지는 이유가 여기서 자주 나옵니다.

    Q4. 언제 쓰지 말아야 하나요?

    CPU가 이미 바쁘고, 압축률이 낮고, 메모리 예산도 빠듯한 노드에서는 과한 압축 계층이 손해일 수 있습니다. 이런 경우는 zram을 크게 잡기보다, zswap을 보수적으로 두거나 메모리 상한 정책부터 정리하는 편이 낫습니다.

    Linux 커널 vRAM 성능 선택 기준을 정리한 zswap zram 비교 인포그래픽

    zswap과 zram의 선택 기준, Linux 커널 vRAM 성능 모니터링 체크포인트, 상황별 추천안을 정리한 요약 이미지입니다.

    실무 권고를 딱 잘라 정리하면 이렇습니다.

    • SSD swap이 있고 서버 역할이 많은 시스템: zswap부터 켜고, compressor와 max_pool_percent를 보수적으로 시작한 뒤 PSI와 pswpout으로 확인하세요.
    • 저전력 홈랩, 미니 PC, 느린 디스크: zram swap을 우선 검토하세요. 다만 mm_stat에서 mem_used_total과 huge_pages를 꼭 같이 보셔야 합니다.
    • 컨테이너 밀도가 높은 환경: 시스템 전체 평균보다 memory.pressure, memory.high, memory.swap.max, memory.zswap.*를 우선 보세요.
    • CPU 여유가 적은 노드: 압축률보다 압축 비용을 먼저 계산하세요. 디스크 I/O 절감이 CPU 손실을 상쇄하지 못하면 방향을 다시 잡아야 합니다.

    제가 이 주제에서 끝까지 붙드는 한 문장은 이것입니다. Linux 커널 vRAM 성능 개선은 swap 숫자 줄이기 게임이 아니라, stall이 발생하는 위치를 바꾸고 그 비용을 통제하는 작업이라는 점입니다. 그래서 설정값 자체보다 PSI, reclaim 흔적, cgroup 경계, 압축 계층의 실제 이득이 더 중요합니다.

    관련 글도 함께 보면 이해가 빨라집니다. 예를 들어 Linux 메모리 관리, 커널 튜닝, 성능 모니터링 주제를 내부 문서로 이어두면 운영 기준을 잡는 데 도움이 됩니다. 한 줄 추천으로 마무리하면, 범용 서버는 zswap부터, 느린 디스크 노드는 zram부터, 멀티테넌트 환경은 cgroup pressure부터 보시면 됩니다. 그다음에야 swappiness가 의미를 갖습니다.

  • [Cloud] Sentry vs Elastic APM: 클라우드 환경 에러 및 성능 모니터링 솔루션 비교 분석

    [Cloud] Sentry vs Elastic APM: 클라우드 환경 에러 및 성능 모니터링 솔루션 비교 분석

    [인프라] Sentry vs Elastic APM 비교 분석

    Sentry Elastic APM 비교를 고민하시는 분들은 보통 비슷한 시점에 막히더라고요. 서비스는 클라우드에 올렸는데, 장애는 간헐적으로 터지고, CPU나 응답 시간도 오락가락하고, 로그만 봐서는 도대체 어디서부터 추적해야 할지 감이 안 오는 순간이 있습니다. 저도 홈랩이랑 실서비스 비슷한 테스트 환경에서 이것저것 붙여보면서 꽤 삽질했었는데요. 결론부터 말씀드리면 Sentry와 Elastic APM은 겹치는 영역이 있지만 출발점이 꽤 다릅니다. 하나는 에러 트래킹(Error Tracking, 예외 중심 추적)에 강하고, 다른 하나는 APM(Application Performance Monitoring, 애플리케이션 성능 모니터링)과 관측성(Observability, 시스템 상태를 추론하는 능력) 전체 흐름에 더 가깝습니다.

    그래서 오늘은 마케팅 문구 말고, 실제 운영자 시점에서 어떤 팀에 뭐가 더 맞는지 차근차근 정리해보겠습니다. 클라우드 모니터링을 처음 붙이는 분도 이해할 수 있게 풀어볼게요.

    Sentry Elastic APM 비교를 위한 클라우드 모니터링 아키텍처 다이어그램

    애플리케이션, SDK/Agent, 수집 서버, 대시보드까지 이어지는 전체 흐름을 한눈에 보여주는 비교용 다이어그램입니다.

    Sentry와 Elastic APM, 쉽게 말해 뭐가 다른가요?

    쉽게 말해 Sentry는 에러가 났을 때 개발자가 바로 달려가게 만드는 도구에 가깝고, Elastic APM은 서비스가 느려지거나 병목이 생길 때 시스템 전체 문맥을 보게 해주는 도구에 가깝습니다.

    • Sentry: 예외(Exception, 런타임 오류), 스택 트레이스(Stack Trace, 오류 호출 경로), 릴리스 추적(Release Tracking, 배포 버전별 상태) 쪽이 직관적입니다.
    • Elastic APM: 트랜잭션(Transaction, 요청 단위 처리 흐름), 스팬(Span, 세부 작업 구간), 인프라 메트릭(Metrics, CPU/메모리 같은 수치), 로그 연계가 자연스럽습니다.

    처음엔 저도 둘 다 비슷해 보였거든요. 근데 실제로 써보니까 질문 자체가 달라집니다.

    1. Sentry를 볼 때는 “왜 이 에러가 났지?”를 먼저 묻게 됩니다.
    2. Elastic APM을 볼 때는 “왜 이 요청이 느리지?” 또는 “어느 서비스 구간이 병목이지?”를 먼저 보게 됩니다.

    여기서 중요한 포인트! 장애 대응의 시작점이 예외냐, 성능 저하냐에 따라 체감 가치가 꽤 달라집니다.

    클라우드 모니터링 관점에서 보는 핵심 차이

    항목 Sentry Elastic APM
    주력 영역 에러 트래킹, 이슈 그룹화, 릴리스 단위 추적 성능 모니터링, 분산 추적, 로그/메트릭 연계
    초기 진입 난이도 상대적으로 빠름 구성 요소를 이해해야 해서 더 복합적일 수 있음
    개발자 체감 예외 발생 시 원인 파악이 빠름 느린 쿼리, 외부 호출, 서비스 병목 분석에 강함
    운영자 체감 애플리케이션 오류 집중 애플리케이션과 인프라를 함께 보기 좋음
    적합한 팀 작은 팀, 앱/웹 중심 팀, 빠른 에러 대응이 필요한 팀 Elastic Stack을 이미 쓰는 팀, 관측성 통합이 중요한 팀
    확장성 관점 이슈 기반 운영에 편함 로그, 메트릭, 트레이스 통합 설계에 유리

    제가 직접 해보니, 팀에 로그 플랫폼이 이미 있느냐가 생각보다 큽니다. 이미 Elasticsearch(엘라스틱서치, 검색/분석 엔진)와 Kibana(키바나, 시각화 대시보드)를 쓰고 있다면 Elastic APM 쪽이 훨씬 자연스럽게 이어집니다. 반대로 그런 기반이 없고 일단 에러부터 빨리 잡아야 한다면 Sentry가 체감 속도가 빠르더라고요.

    Sentry가 잘 맞는 상황

    Sentry는 특히 이런 상황에서 강합니다.

    • 배포 직후 특정 버전에서 에러가 급증하는지 빠르게 보고 싶을 때
    • 프론트엔드와 백엔드 예외를 한 번에 추적하고 싶을 때
    • 개발자가 스택 트레이스와 컨텍스트만 보고 바로 수정 포인트를 잡아야 할 때
    • 소규모 팀에서 운영 복잡도를 크게 늘리지 않고 에러 트래킹을 붙이고 싶을 때

    실제로 써보니까 Sentry는 “이 에러가 몇 명에게 영향을 줬는가”, “어느 릴리스 이후 시작됐는가” 같은 질문에 답하기 좋았습니다. 특히 이슈 그룹화(Issue Grouping, 같은 유형 오류 묶기)가 잘 되면 알림 피로도도 꽤 줄어듭니다.

    Elastic APM이 빛나는 상황

    Elastic APM은 다음처럼 전체 흐름을 보려는 팀에 잘 맞습니다.

    • 마이크로서비스(Microservices, 기능별로 쪼갠 서비스 구조) 환경에서 요청 경로를 따라가야 할 때
    • 애플리케이션 성능 문제와 인프라 메트릭을 같이 보고 싶을 때
    • 로그, 메트릭, 트레이스를 한 플랫폼에서 묶어 보고 싶을 때
    • 운영팀과 개발팀이 같은 관측성 도구를 공유해야 할 때

    이쪽은 처음엔 좀 묵직합니다. 저도 처음엔 “이걸 다 연결해야 하나?” 싶었는데, 한 번 구조가 잡히면 장점이 확실합니다. 예를 들어 API 응답이 느릴 때, 단순히 느리다는 사실만 보는 게 아니라 DB 쿼리, 외부 HTTP 호출, 특정 서비스 구간까지 내려가서 볼 수 있거든요. 이거 진짜 편하더라고요.

    실전 구현: Python 앱에 둘 다 붙여보기

    비교는 결국 손에 붙여봐야 감이 옵니다. 여기서는 가장 단순한 예제로 Flask(플라스크, Python 웹 프레임워크) 기준으로 보여드릴게요. 실제 서비스에서는 환경 변수로 키를 분리하고, 운영/스테이징 환경을 나눠서 쓰시는 걸 권장합니다.

    1. Sentry SDK 연결

    pip install flask sentry-sdk
    import os
    from flask import Flask
    import sentry_sdk
    from sentry_sdk.integrations.flask import FlaskIntegration
    
    sentry_sdk.init(
        dsn=os.environ.get("SENTRY_DSN"),
        integrations=[FlaskIntegration()],
        traces_sample_rate=0.1,
        send_default_pii=False,
    )
    
    app = Flask(__name__)
    
    @app.route("/")
    def index():
        return {"status": "ok"}
    
    @app.route("/error")
    def error():
        raise RuntimeError("sentry test error")

    여기서 dsn은 Sentry 프로젝트에서 발급받는 연결 정보입니다. traces_sample_rate는 성능 이벤트 샘플링 비율인데요. 무조건 높게 두기보다 트래픽 규모를 보고 잡는 게 좋습니다.

    2. Elastic APM Agent 연결

    pip install flask elastic-apm
    import os
    from flask import Flask
    from elasticapm.contrib.flask import ElasticAPM
    
    app = Flask(__name__)
    app.config["ELASTIC_APM"] = {
        "SERVICE_NAME": "demo-flask-app",
        "SECRET_TOKEN": os.environ.get("ELASTIC_APM_SECRET_TOKEN"),
        "SERVER_URL": os.environ.get("ELASTIC_APM_SERVER_URL"),
        "ENVIRONMENT": os.environ.get("APP_ENV", "production"),
    }
    
    apm = ElasticAPM(app)
    
    @app.route("/")
    def index():
        return {"status": "ok"}
    
    @app.route("/slow")
    def slow():
        import time
        time.sleep(1.2)
        return {"status": "slow"}

    Elastic APM은 보통 APM Server 또는 Elastic Cloud 쪽 엔드포인트로 데이터를 보냅니다. 서비스 이름을 어떻게 나누느냐가 꽤 중요하더라고요. 나중에 대시보드에서 서비스별로 분리해서 보게 되기 때문입니다.

    3. 컨테이너 환경 변수 분리

    services:
      app:
        image: my-flask-app:latest
        environment:
          SENTRY_DSN: "${SENTRY_DSN}"
          ELASTIC_APM_SERVER_URL: "${ELASTIC_APM_SERVER_URL}"
          ELASTIC_APM_SECRET_TOKEN: "${ELASTIC_APM_SECRET_TOKEN}"
          APP_ENV: "production"
        ports:
          - "8000:8000"

    클라우드 환경에서는 Kubernetes(쿠버네티스, 컨테이너 오케스트레이션)나 ECS 같은 플랫폼에서도 같은 원칙입니다. 민감한 값은 Secret으로 빼고, 서비스명과 환경명은 일관되게 가져가세요.

    Sentry Elastic APM 비교용 Flask 연동 구성 다이어그램

    실전 구현 단계에서 앱 코드, 환경 변수, 외부 모니터링 서비스가 어떻게 연결되는지 보여주는 구성 이미지입니다.

    ⚠️ 실제로 자주 겪는 문제와 트러블슈팅

    여기서부터가 진짜 운영 팁입니다. 문서만 보면 금방 붙을 것 같았는데, 저는 여기서 삽질 좀 했습니다 ㅎㅎ

    에러는 들어오는데 성능 데이터가 비어 있는 경우

    • Sentry에서는 트레이싱 샘플링 설정이 너무 낮거나 꺼져 있는지 확인합니다.
    • Elastic APM에서는 Agent 설정은 되었는데 서버 URL 또는 인증 토큰이 맞지 않는 경우가 많습니다.
    • 프록시(Proxy, 중간 전달 장비)나 보안 그룹 때문에 수집 엔드포인트로 아웃바운드가 막힌 경우도 자주 있습니다.

    서비스 이름이 제각각 찍히는 경우

    이건 운영하면서 은근 치명적입니다. 배포마다 이름이 달라지면 대시보드가 찢어집니다. service name 규칙을 미리 정해두세요. 예를 들면 team-service-env 같은 형태로요.

    알림이 너무 많이 오는 경우

    Sentry는 같은 유형의 예외를 얼마나 잘 묶어주느냐가 중요하고, Elastic APM은 임계값(Threshold, 경고 기준치) 설계를 잘해야 합니다. 처음부터 모든 알림을 켜면 금방 무뎌집니다. 저도 초반엔 메신저가 울리기만 하고 아무도 안 보는 상태가 됐었거든요.

    개인정보와 민감정보 유출 위험

    가장 조심해야 할 부분입니다. 에러 이벤트나 트레이스에 요청 본문, 헤더, 사용자 식별값이 섞여 들어갈 수 있습니다. 그래서 기본값을 그대로 믿지 말고 다음 원칙을 꼭 적용하세요.

    1. 민감한 필드는 수집 전에 마스킹(Masking, 값 가리기)합니다.
    2. PII(개인식별정보) 전송 여부를 명시적으로 검토합니다.
    3. 운영 환경과 개발 환경의 수집 범위를 분리합니다.

    검증: 붙인 뒤 무엇을 확인해야 하나요?

    연동이 끝났다고 바로 끝은 아닙니다. 최소한 아래 시나리오는 확인해보셔야 합니다.

    1. Sentry 검증: 테스트 예외를 한 번 발생시켜 이슈가 생성되는지 확인합니다.
    2. Elastic APM 검증: 응답이 느린 엔드포인트를 호출해 트랜잭션과 스팬이 보이는지 확인합니다.
    3. 배포 검증: 새 릴리스 이후 에러 추세가 구분되는지 확인합니다.
    4. 알림 검증: 실제로 필요한 채널로 경고가 가는지 확인합니다.
    curl http://localhost:8000/error
    curl http://localhost:8000/slow

    제가 실제로 써보니까, 검증할 때는 일부러 실패를 만들어보는 게 제일 확실합니다. 정상 상태만 보면 연동이 된 것처럼 보이는데, 막상 장애가 터지면 필요한 필드가 빠져 있는 경우가 있거든요. 드디어 됐다! 싶어서 넘겼다가 나중에 다시 뜯어보는 경우, 정말 많습니다.

    Sentry Elastic APM 비교 결과를 보여주는 에러 및 성능 대시보드 이미지

    하나는 에러 중심, 다른 하나는 성능 흐름 중심이라는 차이를 직관적으로 보여주는 결과 화면 예시입니다.

    어떤 팀이 무엇을 선택하면 좋을까?

    상황 추천 방향
    스타트업/소규모 서비스, 장애 원인 파악이 급함 Sentry 우선
    Elastic Stack을 이미 운영 중 Elastic APM 우선
    프론트엔드 예외와 백엔드 예외를 빠르게 모으고 싶음 Sentry 적합
    로그, 메트릭, 트레이스를 한곳에서 보고 싶음 Elastic APM 적합
    멀티서비스 병목 분석이 중요함 Elastic APM 쪽이 유리
    배포 후 에러 급증 여부를 빠르게 추적해야 함 Sentry 체감이 좋음

    사실 둘 중 하나만 절대 정답이라고 보긴 어렵습니다. 팀의 현재 성숙도와 운영 방식이 더 중요합니다. 로그 플랫폼이 아직 없고 개발자 중심으로 빠르게 대응해야 한다면 Sentry가 훨씬 덜 부담스럽습니다. 반대로 이미 Elastic 기반 운영 체계가 있다면 Elastic APM은 확장성이 좋습니다.

    자주 묻는 질문 정리

    Q. 둘 다 같이 써도 되나요?

    네, 가능합니다. 실제로 에러 트래킹은 Sentry, 통합 관측성은 Elastic APM으로 나눠 가져가는 팀도 있습니다. 다만 데이터 중복과 운영 포인트 증가를 감안하셔야 합니다.

    Q. 클라우드 모니터링 입문자는 무엇부터 시작할까요?

    개인적으로는 장애를 빨리 잡는 경험을 먼저 만드는 걸 추천합니다. 그래서 입문자는 Sentry 같은 에러 중심 도구부터 시작하고, 이후에 성능 모니터링과 분산 추적으로 넓히는 흐름이 덜 헷갈립니다.

    Q. Elastic APM은 언제 더 빛나나요?

    서비스가 여러 개로 나뉘고, 느려지는 구간이 앱 코드인지 DB인지 외부 API인지 구분이 안 될 때요. 그때부터는 트레이스 기반 분석 가치가 확 올라갑니다.

    Sentry Elastic APM 비교와 선택 기준을 정리한 인포그래픽

    팀 규모, 운영 방식, 분석 목적에 따라 어떤 도구가 더 맞는지 빠르게 판단할 수 있도록 요약한 비교 인포그래픽입니다.

    마무리: 결국 질문은 도구가 아니라 운영 방식입니다

    Sentry Elastic APM 비교를 한 줄로 줄이면 이렇습니다. Sentry는 에러 대응의 속도를 높여주고, Elastic APM은 성능과 구조를 읽는 시야를 넓혀줍니다.

    저도 처음엔 “둘 중 뭐가 더 좋지?”만 붙잡고 있었는데, 실제로 써보니까 질문을 바꿔야 하더라고요. 우리 팀은 지금 무엇이 더 아픈가? 에러 원인 파악이 급한지, 아니면 서비스 전체 병목과 클라우드 모니터링 체계를 정리해야 하는지가 먼저입니다.

    혹시 지금 막 APM 솔루션 도입을 검토 중이시라면, 제 추천은 이렇습니다. 작게 붙이고, 일부러 장애를 내보고, 대시보드와 알림이 실제 운영에 도움이 되는지 먼저 확인하세요. 그 다음에 범위를 넓히는 게 훨씬 덜 고생합니다.

    다음 글에서는 OpenTelemetry(OpenTelemetry, 관측성 데이터 수집 표준) 기준으로 Sentry와 Elastic 계열 도구를 어떻게 같이 엮을 수 있는지도 다뤄볼 예정입니다. 이전 글에서 로그 수집 파이프라인 정리한 내용과도 이어보시면 도움이 될 겁니다. 🎉

  • [Cloud] New Relic 사용 후기: 1년 APM 운영하며 배운 성능 모니터링 실전 경험

    [Cloud] New Relic 사용 후기: 1년 APM 운영하며 배운 성능 모니터링 실전 경험

    New Relic 사용 후기: 1년 APM 운영하며 배운 성능 모니터링 실전 경험

    New Relic 사용 후기를 찾는 분들은 대개 비슷한 시점에 오시더라고요. 서비스가 어느 정도 커졌는데, 장애는 꼭 새벽에 터지고, CPU나 메모리만 봐서는 원인을 못 찾겠고, 개발팀이랑 인프라팀이 서로 “어디서 느린 거지?” 하고 로그만 뒤집는 상황 말입니다. 저도 13년차 인프라 엔지니어로 일하면서 이런 구간을 여러 번 겪었고, 실제로 지난 1년 동안 New Relic을 운영 환경에 붙여 보면서 APM(Application Performance Monitoring, 애플리케이션 성능 관리)이 왜 필요한지 몸으로 배웠거든요.

    처음엔 솔직히 “모니터링 툴이 다 거기서 거기 아닌가?” 싶었는데요. 실제로 써보니까 New Relic은 단순히 그래프 예쁘게 보여주는 도구라기보다, 문제를 좁혀 가는 순서 자체를 바꿔 주는 도구에 가깝더라고요. 이번 글에서는 화려한 성공담보다는, 제가 직접 해보니 좋았던 점과 불편했던 점, 그리고 삽질했던 포인트까지 같이 정리해보겠습니다.

    New Relic 사용 후기와 함께 보는 전체 서비스 모니터링 아키텍처 이미지

    애플리케이션, 데이터베이스, 외부 API, 사용자 요청 흐름 위에 New Relic이 어떻게 관측 지점을 만드는지 보여주는 개요 이미지입니다.

    1. APM이 필요했던 이유: 성능 모니터링의 빈칸

    예전에는 Node Exporter나 cAdvisor 같은 인프라 지표 위주로 많이 봤습니다. 물론 그것만으로도 기본 체력은 확인할 수 있죠. 그런데 실제 장애 대응에서는 그다음 질문이 꼭 나옵니다. “그래서 어느 요청이 느렸고, 어떤 쿼리가 문제였고, 외부 호출 중 어디서 시간이 새는 건데?” 여기서부터 일반적인 서버 모니터링과 애플리케이션 성능 관리가 갈립니다.

    쉽게 말해 인프라 모니터링은 서버가 아픈지를 보는 거고, APM은 서비스 요청이 어디서 아픈지를 보여주는 쪽입니다. CPU 40%인데 사용자는 느리다고 할 수 있거든요. 저도 처음엔 이 간극이 좀 답답했습니다. 특히 마이크로서비스처럼 서비스가 여러 개로 나뉘면, 한 군데만 봐서는 절대 안 보입니다.

    • 인프라 지표: CPU, 메모리, 디스크, 네트워크 중심
    • APM 및 성능 모니터링: 트랜잭션 응답 시간, 에러율, 외부 호출, DB 쿼리, 분산 추적 중심
    • 운영 관점 핵심: “서버 상태”보다 “사용자 경험”에 더 가깝게 본다는 점

    2. New Relic 사용 후기를 시작하기 전에: 핵심 개념

    New Relic은 애플리케이션 안에 에이전트(agent)를 심거나 연동해서 요청 흐름과 성능 데이터를 수집하고 분석하는 플랫폼입니다. 처음 접하면 메뉴가 많아서 조금 압도적이긴 한데요. 저도 처음엔 “이게 뭔가” 싶었는데 하루 이틀 만져보니 핵심은 의외로 단순했습니다.

    1. 애플리케이션에 에이전트를 붙입니다.
    2. 트래픽이 들어오면 트랜잭션 단위로 데이터를 수집합니다.
    3. 응답 시간, 에러, 외부 호출, 데이터베이스 구간을 나눠 보여줍니다.
    4. 이상 징후가 보이면 알림(alert)과 대시보드로 추적합니다.

    여기서 중요한 포인트! New Relic 사용 후기를 읽을 때 꼭 봐야 할 건 “기능이 많다”가 아니라, 문제 분석 시간이 실제로 줄었는가입니다. 저한테는 이게 가장 컸습니다. 예전에는 로그를 먼저 보고 추측했는데, New Relic을 붙인 뒤에는 느린 엔드포인트부터 보고 그다음 로그를 보는 순서로 바뀌었습니다.

    항목 인프라 모니터링 New Relic APM
    관점 서버/컨테이너 상태 요청과 코드 실행 흐름
    주요 질문 서버가 바쁜가? 왜 이 요청이 느린가?
    장애 대응 자원 병목 추정 문제 지점 구간화
    협업 효과 인프라팀 중심 개발팀-운영팀 공통 언어 제공

    3. 실전 적용: New Relic 도입 시작하기

    실전에서는 거창하게 시작하지 않는 게 중요합니다. 처음부터 모든 서비스에 다 붙이려 하면 운영팀이 먼저 지칩니다 ㅎㅎ 저는 트래픽이 많고 문의가 자주 들어오던 핵심 API부터 시작했습니다.

    3-1. 애플리케이션 연결 전 체크 포인트

    • 어떤 서비스가 가장 중요한지 우선순위를 정합니다.
    • 운영 환경 변수 관리 방식을 먼저 정리합니다.
    • 로그, 메트릭, 트레이스 중 무엇을 먼저 볼지 결정합니다.
    • 알림을 누구에게 어떤 채널로 보낼지 정합니다.

    3-2. Docker 환경에서 기본 연결 예시

    아래는 개념적으로 가장 많이 쓰는 방식입니다. 실제 변수명이나 연동 방식은 언어와 런타임에 따라 조금씩 다를 수 있으니, 운영 중인 스택에 맞춰 공식 문서를 같이 보시는 게 좋습니다.

    export NEW_RELIC_LICENSE_KEY="YOUR_LICENSE_KEY"
    export NEW_RELIC_APP_NAME="my-production-api"
    export NEW_RELIC_ENVIRONMENT="production"
    
    docker run -d \
      --name my-api \
      -e NEW_RELIC_LICENSE_KEY="$NEW_RELIC_LICENSE_KEY" \
      -e NEW_RELIC_APP_NAME="$NEW_RELIC_APP_NAME" \
      -e NEW_RELIC_ENVIRONMENT="$NEW_RELIC_ENVIRONMENT" \
      my-api-image:latest

    쿠버네티스(Kubernetes, 컨테이너 오케스트레이션) 환경이라면 보통 Secret과 Deployment에 나눠 넣게 됩니다.

    apiVersion: v1
    kind: Secret
    metadata:
      name: newrelic-secret
    type: Opaque
    stringData:
      NEW_RELIC_LICENSE_KEY: "YOUR_LICENSE_KEY"
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: my-api
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: my-api
      template:
        metadata:
          labels:
            app: my-api
        spec:
          containers:
            - name: my-api
              image: my-api:latest
              env:
                - name: NEW_RELIC_LICENSE_KEY
                  valueFrom:
                    secretKeyRef:
                      name: newrelic-secret
                      key: NEW_RELIC_LICENSE_KEY
                - name: NEW_RELIC_APP_NAME
                  value: "my-production-api"
                - name: NEW_RELIC_ENVIRONMENT
                  value: "production"

    이 단계에서 제가 느낀 건 하나였습니다. 성능 모니터링 도입 자체는 생각보다 어렵지 않은데, 이름 규칙과 태깅 전략을 대충 잡으면 나중에 대시보드가 금방 지저분해진다는 점입니다. 서비스명, 환경명, 팀 구분 태그는 초반에 깔끔하게 맞춰두는 게 좋습니다.

    컨테이너 기반 서비스에 New Relic 환경 변수와 에이전트가 연결되는 흐름을 보여주는 구성 다이어그램입니다.

    4. 실제로 가장 많이 본 화면: 성능 모니터링의 3대 지표

    New Relic을 1년 정도 쓰면서 가장 자주 본 건 화려한 종합 대시보드가 아니라, 결국 느린 트랜잭션 상세 화면이었습니다. 장애나 성능 저하가 오면 순서는 거의 비슷했습니다.

    1. 응답 시간이 튄 시간대를 확인합니다.
    2. 어떤 엔드포인트가 느렸는지 봅니다.
    3. DB(Database, 데이터베이스) 구간인지, 외부 API 호출인지 나눕니다.
    4. 필요하면 로그와 애플리케이션 코드로 내려갑니다.

    예를 들어 API 평균 응답 시간이 갑자기 늘었는데 CPU는 멀쩡한 경우가 있었거든요. 처음엔 애플리케이션 내부 로직 문제인 줄 알았습니다. 근데 실제로 써보니까 외부 결제 API 호출 구간이 길어지고 있더라고요. 만약 APM이 없었다면 앱 서버 스케일 아웃부터 했을 수도 있습니다. 그런 의미에서 New Relic은 문제 해결의 방향을 틀리지 않게 해주는 장치였습니다.

    이 부분이 바로 제가 말하고 싶은 New Relic 사용 후기의 핵심입니다. 대시보드가 예쁜 것보다, 장애 대응에서 잘못된 가설을 빨리 버리게 해주는 게 훨씬 중요합니다.

    5. ⚠️ 1년 쓰면서 겪은 성능 모니터링의 실제 어려움

    좋은 얘기만 하면 블로그 글이 너무 광고 같잖아요. 실제 운영에서는 분명히 아쉬운 점도 있었습니다. 저도 삽질 좀 했습니다 ㅎㅎ

    5-1. 데이터가 많아지면 처음엔 어디를 봐야 할지 헷갈립니다

    메뉴가 다양하고 기능도 넓어서, 초반에는 오히려 “뭘 봐야 하지?” 상태가 옵니다. 이건 도구의 문제라기보다 온보딩 문제에 가깝더라고요.

    해결법: 처음부터 모든 기능을 다 보지 말고 아래 4가지만 먼저 익히는 게 좋았습니다.

    • APM 서비스 목록
    • 트랜잭션 응답 시간
    • 에러율
    • 알림 조건(Alert Condition)

    5-2. 에이전트만 붙였다고 끝이 아닙니다

    간혹 “붙였는데 데이터가 생각보다 의미가 없다”는 경우가 있습니다. 이유는 보통 서비스명 혼선, 환경 태그 누락, 로그와 추적의 연결 부족이더라고요.

    kubectl get pods -n production
    kubectl describe deployment my-api -n production
    kubectl logs deploy/my-api -n production --tail=200

    이런 기본 점검을 통해 환경 변수가 빠졌는지, 배포가 꼬였는지 먼저 확인했습니다. 은근히 단순한 실수가 많습니다.

    5-3. 경고 임계치(alert threshold)를 너무 예민하게 잡으면 피로해집니다

    이건 정말 많이 겪었습니다. 처음엔 에러율이나 응답 시간을 민감하게 잡아야 잘 잡히는 줄 알았거든요. 근데 새벽에 의미 없는 알림이 반복되면 팀이 결국 무시하게 됩니다. 그러면 진짜 장애 때도 놓치게 되죠.

    해결법: 비즈니스 영향이 있는 지표부터 우선순위를 줬습니다. 예를 들면 핵심 API 응답 시간, 결제 실패율, 로그인 오류율처럼요.

    5-4. 로그만 믿던 습관을 버리는 데 시간이 걸렸습니다

    이건 도구보다 사람의 습관 문제였어요. 저도 처음엔 장애 나면 바로 로그부터 열었는데, 나중엔 APM에서 느린 구간을 먼저 확인한 뒤 로그를 보는 방식이 훨씬 빨랐습니다. 혹시 지금도 로그 검색부터 시작하고 계신다면, 이 순서 한번 바꿔보세요. 생각보다 체감이 큽니다.

    New Relic 사용 후기에서 다루는 응답 시간과 에러율 분석 대시보드 이미지

    트랜잭션 분석 화면에서 병목 구간과 에러 추세를 확인하는 모습을 시각화한 이미지입니다.

    6. 검증: 1년 New Relic 운영으로 실제 어떻게 바뀌었나

    수치를 지어내서 말하고 싶지는 않습니다. 다만 운영 체감은 분명했습니다. 가장 큰 변화는 문제 확인까지 걸리는 시간이 줄었다는 점이었습니다. 예전에는 느리다는 제보가 오면 서버 지표, 로드밸런서, 로그, DB를 순서 없이 왔다 갔다 했는데요. New Relic을 붙인 뒤에는 병목 후보를 먼저 좁힌 뒤 확인하는 흐름이 자리 잡았습니다.

    • 장애 대응 회의에서 추측성 발언이 줄었습니다.
    • 개발팀과 운영팀이 같은 화면을 보고 이야기하게 됐습니다.
    • “서버는 안 바쁜데 왜 느리지?” 같은 상황에서 방향을 빨리 잡았습니다.
    • 릴리스 직후 성능 변화도 이전보다 빨리 감지했습니다.

    특히 애플리케이션 성능 관리가 필요한 팀이라면, 배포 직후의 미묘한 성능 저하를 잡는 데 도움이 됩니다. 장애가 아니라서 그냥 지나칠 수 있는 수준의 지연도 추세로 보면 보이거든요. 이건 나중에 큰 장애를 막는 데 꽤 중요했습니다.

    # 배포 직후 기본 확인 루틴 예시
    kubectl rollout status deployment/my-api -n production
    kubectl top pods -n production
    kubectl logs deploy/my-api -n production --since=10m

    그리고 New Relic 화면에서 같은 시간대의 응답 시간과 에러율을 같이 보면, 배포 영향인지 외부 의존성 문제인지 감이 빨리 옵니다. 드디어 됐다! 싶은 순간이 이런 데서 나오더라고요.

    7. New Relic 도입이 잘 맞는 경우와 기대를 버려야 할 부분

    모든 도구가 그렇듯 New Relic도 만능은 아닙니다. 그래서 기대치를 현실적으로 잡는 게 중요합니다.

    잘 맞는 경우 주의할 점
    여러 서비스가 연결된 구조 단일 정적 서비스만 운영하면 체감이 작을 수 있음
    개발팀과 운영팀이 함께 장애 대응 팀 내 공통 해석 기준이 없으면 화면만 늘어남
    배포 후 성능 영향 확인이 중요 알림 설계를 대충 하면 노이즈가 많아짐
    DB, 외부 API 병목이 자주 발생 에이전트 연결만으로 모든 원인이 자동 설명되진 않음

    즉, New Relic 사용 후기를 한 줄로 요약하면 이렇습니다. 문제를 자동으로 해결해주진 않지만, 문제를 훨씬 빨리 이해하게 해줍니다. 이 차이가 운영에서는 꽤 큽니다.

    New Relic 사용 후기 기반의 도입 전후 문제 해결 흐름 비교 인포그래픽

    도입 전후의 장애 대응 방식, 협업 흐름, 분석 속도 차이를 한눈에 보여주는 비교 이미지입니다.

    8. 정리: APM과 성능 모니터링의 현실적 결론

    1년 정도 운영하면서 느낀 결론은 분명합니다. 성능 모니터링은 단순히 그래프를 쌓는 작업이 아니라, 장애 대응의 사고방식을 바꾸는 작업이었습니다. 저도 처음엔 기능이 많아서 약간 부담스러웠는데, 실제로 써보니까 핵심은 복잡하지 않았습니다. 중요한 서비스부터 작게 시작하고, 알림을 다듬고, 팀이 같은 지표를 보게 만드는 것. 결국 이 세 가지가 제일 중요하더라고요.

    혹시 지금 APM 도입을 고민 중이시라면, 처음부터 거창하게 가지 마세요. 가장 느리다고 의심되는 API 하나, 에러가 자주 나는 서비스 하나부터 붙여보시면 됩니다. 그리고 인프라 지표와 애플리케이션 지표를 분리해서 보지 말고 함께 보셔야 합니다. 그 순간부터 운영이 꽤 달라집니다.

    다음 글에서는 로그(Log, 애플리케이션 기록)와 트레이스(Trace, 요청 흐름 추적)를 같이 볼 때 어떤 식으로 운영 효율이 올라가는지 정리해보려고 합니다. 이전 글에서 다뤘던 Kubernetes 리소스 관찰 전략과도 연결되는 내용이라, 같이 보시면 더 이해가 잘 되실 겁니다.

    자주 묻는 질문

    • Q. New Relic은 인프라 모니터링만으로 대체 가능한가요?
      A. 어렵습니다. 인프라 지표는 서버 상태를, APM은 요청 흐름과 병목 지점을 보여주기 때문에 역할이 다릅니다.
    • Q. 성능 모니터링 도입 초반에 가장 중요한 설정은 뭔가요?
      A. 서비스 이름 규칙, 환경 구분, 핵심 알림 조건입니다. 이 세 가지가 엉키면 나중에 데이터 해석이 힘들어집니다.
    • Q. 개발팀 없이 운영팀만 써도 효과가 있나요?
      A. 있습니다. 다만 코드 레벨 원인 분석까지 빨리 가려면 개발팀과 같은 화면을 보며 협업하는 편이 훨씬 좋습니다.