블로그로 돌아가기
·9분 분량·productdevbook

macOS 네트워크 사용 데이터를 내보내는 방법

macOS 네트워크 사용 데이터를 내보내고 분석하는 방법입니다. 기본 명령어, 자주 쓰는 포맷, 유용한 한 줄 명령들을 정리했습니다.

  • Developer tools
  • macOS
  • Bandwidth
  • Tutorial

마침내 급증을 잡았습니다. 3일 동안 가정 인터넷 사용량이 무작위 시간에 점프하는 이유를 궁금해했고, 마침내 그것을 보기에 적절한 순간에 도구가 열려 있습니다. 이제 어떻게 하나요? 라이브 UI에서 이 데이터를 빼서, 분석하거나, 동료와 공유하거나, 서버 로그와 상관시킬 수 있는 무언가로 가져오고 싶습니다. macOS 네트워크 사용량을 내보내는 능력은 사람들이 깨닫는 것보다 더 중요하며, macOS는 어디를 봐야 하는지 알면 적절한 옵션을 가지고 있습니다.

이 글은 실용적인 경로를 안내합니다. 짧은 캡처를 위한 nettop -L, 시스템 측 네트워킹 이벤트를 위한 통합 로그, CSV를 위한 샘플링 스크립트, 그리고 ova가 디스크에 데이터를 어디에 저장하는지.

macOS 네트워크 사용량을 왜 내보내는가

몇 가지 실제 사례:

  • 이상 조사 — 새벽 3시에 2GB 업로드를 보았고, 밤 동안의 출처 프로세스를 그래프로 그리고 싶습니다.
  • 용량 계획 — 종량제 또는 한도 연결(Starlink Roam, 호텔 Wi-Fi, 모바일 테더링)에 있고 무엇을 켜둬도 안전한지 알고 싶습니다.
  • 성능 디버깅 — 서버 팀이 느린 요청이 언제 시작되었는지 묻고 있고, 클라이언트 측 네트워크 사용량을 그들의 서버 로그에 겹쳐 두고 싶습니다.
  • 프로젝트별 대역폭 예산 — 클라이언트에게 시간 단위로 청구하고 빌드 파이프라인이 어제 무엇을 업로드했는지 검증하고 싶습니다.
  • 호기심 — 그저 자신의 데이터를 보고 싶습니다.

이 모든 것에 대해, "활성 상태 보기를 열고 응시"하는 것은 부족합니다. 디스크에, 조작할 수 있는 형식으로 데이터가 필요합니다.

옵션 1: nettop 로그 모드

가장 간단한 내보내기 경로는 내장되어 있습니다. nettop -L <count><count> 샘플 동안 로그 모드로 실행되어 각 샘플을 텍스트 줄로 덤프하고 종료합니다. 열을 선택하는 -J와 간격을 설정하는 -s와 결합하면, 파일로 파이프할 수 있는 깨끗한 출력을 얻습니다.

nettop -L 600 -s 1 -P -J bytes_in,bytes_out,interface,state \
  > ~/Desktop/nettop-10min.txt

그것이 1초 간격의 600 샘플 — 10분의 캡처입니다. 각 샘플은 요청한 열로 모든 활성 프로세스를 나열합니다.

출력은 정확히 CSV가 아닙니다. 샘플당 헤더, 샘플 간의 빈 줄, 공백이 있는 프로세스 이름이 있습니다. 하지만 파싱 가능합니다. 짧은 awk 또는 Python 스크립트가 그것을 깨끗한 표로 바꿔 줍니다.

nettop 로깅의 한계

  • 실행 중일 때만 캡처합니다. 어제 무슨 일이 있었는지 알고 싶었다면 운이 없습니다.
  • 기본적으로 프로세스 시작 이후 누적을 보고합니다. 델타는 직접 계산해야 합니다.
  • 도우미 프로세스가 별도 행으로 보입니다(접기 없음).
  • 샘플 형식은 일급 CSV가 아닙니다. 파서를 작성할 것을 예상하세요.

특정 시간 창의 임시 캡처 — "GitHub에 푸시하려고 하니 그 주변의 5분을 캡처하자" — 에는 nettop -L이 좋습니다. 지속적인 데이터를 위해서는 다른 것이 필요합니다.

옵션 2: 통합 로그

macOS의 통합 로그는 네트워킹을 포함한 시스템 프레임워크의 구조화된 이벤트를 캡처합니다. CFNetwork(URLSession 계층)와 Network.framework는 모두 연결 수명 주기, TLS 핸드셰이크, 재시도, 실패에 대한 로그 줄을 방출합니다. 사후에 그것을 추출할 수 있습니다.

지금 무엇이 있는지 보려면, 지난 한 시간을 쿼리하세요.

log show --last 1h --predicate 'subsystem == "com.apple.CFNetwork"' \
  --info --debug

파일로 내보내려면:

log show --last 24h --predicate 'subsystem == "com.apple.CFNetwork"' \
  --style compact > ~/Desktop/cfnetwork-day.log

유용한 술어:

  • subsystem == "com.apple.CFNetwork" — URLSession 요청, TLS, 리디렉션
  • subsystem == "com.apple.network" — Network.framework 경로 변경, 연결 상태
  • process == "YourApp" — 한 앱으로 제한
  • eventMessage CONTAINS "443" — 로그 메시지 내부 텍스트 검색

통합 로그는 볼륨에 따라 대략 지난 며칠의 시스템 이벤트를 보관합니다. 바이트 회계를 위해 설계되지 않았습니다. 이벤트 감사를 위해 설계되었습니다. 하지만 질문이 "api.example.com에 대한 연결이 14:23에 실패했는가"라면, 통합 로그가 압니다.

log show 대 log stream

log show는 과거 로그를 읽습니다. log stream은 새 이벤트를 라이브로 지켜봅니다. 터미널을 실행한 채로 두고 이벤트가 일어날 때 지켜보고 싶을 때 log stream을 사용하세요.

log stream --predicate 'subsystem == "com.apple.network"' --level debug

회전 캡처를 추가하려면 >>로 파일에 파이프하세요.

옵션 3: 사용자 정의 샘플링 스크립트

대부분 사람들의 실제 목표 — 프로세스별 대역폭의 CSV 출력 — 을 원한다면, 20줄의 셸로 만들 수 있습니다. 아이디어: N초마다 폴링하고, 누적 바이트 수를 차이내고, CSV를 방출하세요.

#!/usr/bin/env bash
# 단순한 프로세스별 대역폭 샘플러.
INTERVAL=5
echo "timestamp,pid,process,delta_in,delta_out"
declare -A prev_in prev_out
while true; do
  ts=$(date +%s)
  while IFS=, read pid name in_bytes out_bytes; do
    pi=${prev_in[$pid]:-0}
    po=${prev_out[$pid]:-0}
    di=$((in_bytes - pi))
    do_=$((out_bytes - po))
    if (( di > 0 || do_ > 0 )); then
      echo "$ts,$pid,$name,$di,$do_"
    fi
    prev_in[$pid]=$in_bytes
    prev_out[$pid]=$out_bytes
  done < <(nettop -P -L 1 -J pid,interface,bytes_in,bytes_out 2>/dev/null \
            | awk 'NR>2 {print $2","$1","$3","$4}')
  sleep $INTERVAL
done

이는 스케치입니다 — 프로덕션 코드는 프로세스 종료, 도우미 프로세스 접기, 로그 회전, 그리고 nettop의 출력 형식이 파싱하기 짜증난다는 사실을 처리할 것입니다 — 하지만 모양을 보여줍니다. 샘플링하고, 차이내고, CSV를 방출합니다. 절전을 견디게 하고 싶다면 caffeinate 아래 또는 launchd 에이전트로 실행하세요.

ova 작동 모습 보기

한눈에 볼 수 있는 메뉴 바 대역폭 모니터 — 로컬, 서명, 약 3MB.

macOS용 다운로드

옵션 4: ova의 로컬 데이터베이스

목적에 맞게 만들어진 대역폭 모니터는 위 스크립트를 작성하는 것에서 구해 줍니다. ova는 다음에 SQLite 데이터베이스를 보관합니다.

~/Library/Application Support/ova/

내용은 UI에서 보는 것과 같은 시계열 데이터입니다. 약 1Hz로 샘플링된 앱별 들어오는 바이트와 나가는 바이트, 도우미 프로세스가 상위 앱 아래로 접힘. 로컬, 클라우드 동기화 없음, 텔레메트리 없음. 파일은 본인 것입니다.

SQLite이기 때문에, SQLite를 읽을 수 있는 어떤 것이든 그것을 읽을 수 있습니다. sqlite3 CLI, Python의 sqlite3 모듈, DB Browser for SQLite, 또는 DuckDB의 빠른 쿼리. 다음을 할 수 있습니다.

  • 한 명령으로 전체 기록을 CSV로 내보내기
  • 집계 실행("이번 주에 시간별로 어떤 앱이 가장 많은 대역폭을 사용했는가")
  • 자체 로그(빌드 파이프라인, 서버 접근 로그, 캘린더 이벤트)와 조인
  • 정상 백업 대상으로 백업

sqlite3을 사용한 일반적인 CSV 내보내기:

sqlite3 -header -csv \
  ~/Library/Application\ Support/ova/<file>.sqlite \
  "SELECT timestamp, app, bytes_in, bytes_out FROM samples \
   WHERE timestamp > strftime('%s','now','-7 days') \
   ORDER BY timestamp" > ~/Desktop/last-week.csv

실용적인 레시피, 조인, 프라이버시

CSV를 가지면 — 어떤 출처에서든 — 몇 가지 쿼리가 노력을 보상합니다.

주별 상위 앱

SELECT app,
       SUM(bytes_in) / (1024*1024) AS mb_down,
       SUM(bytes_out) / (1024*1024) AS mb_up
  FROM samples
 WHERE timestamp > strftime('%s','now','-7 days')
 GROUP BY app
 ORDER BY (mb_down + mb_up) DESC
 LIMIT 20;

거의 항상 명확한 이야기를 들려줍니다. 상위에 브라우저, 중간에 동기화 앱, 하단에 시스템 서비스.

시간별 히트맵

SELECT strftime('%H', timestamp, 'unixepoch', 'localtime') AS hour,
       SUM(bytes_in + bytes_out) / (1024*1024) AS mb
  FROM samples
 WHERE timestamp > strftime('%s','now','-30 days')
 GROUP BY hour
 ORDER BY hour;

트래픽이 언제 정점인지 보여줍니다. 대부분의 사람에게: 오전 9시, 오후 1시, 오후 4시, 밤새 클라우드 동기화의 긴 꼬리.

이상 감지

SELECT app,
       date(timestamp, 'unixepoch', 'localtime') AS day,
       SUM(bytes_out) / (1024*1024) AS mb_up
  FROM samples
 GROUP BY app, day
HAVING mb_up > 500
 ORDER BY mb_up DESC;

500MB 이상 업로드의 앱-일을 표시합니다. 한 줌은 정상입니다(네트워크 대상으로의 Time Machine, 사진 동기화, 큰 파일 전송). 익숙하지 않은 앱의 전체 목록은 조사할 만합니다.

로컬 SQLite 기록
ova는 약 1Hz로 앱별 대역폭을 샘플링하고 ~/Library/Application Support/ova/의 SQLite 파일에 저장합니다. 다른 데이터베이스에 사용할 같은 도구로 쿼리할 수 있습니다.

출처 결합

가장 강력한 워크플로는 한 번에 여러 출처를 사용합니다.

  • 바이트 회계를 위한 ova — 무엇이, 어떤 앱에 의해, 언제 사용되었는가
  • 이벤트를 위한 통합 로그 — 연결이 언제 시작, 실패, 재시도되었는가
  • 선을 위한 tcpdump — 무언가가 정말로 신비할 때

타임스탬프로 조인할 수 있습니다. ova가 새벽 3:14에 cloudd에 의한 200MB 업로드를 보여준다면, 통합 로그는 cloudd가 무엇을 동기화하고 있었는지 보여주고, (패킷 캡처가 실행 중이었다면) tcpdump는 그것이 iCloud였다는 것을 확인하는 목적지 IP 공간을 보여줍니다.

프라이버시에 대한 메모

네트워크 데이터를 내보내는 모든 것은 공유할 의도가 없는 정보를 누설할 수 있습니다. 호스트 이름, 통합 로그의 경로조차 어떤 서비스를 사용하는지 드러낼 수 있습니다. 동료에게 로그를 보내거나 채팅에 붙여넣기 전에:

  • 가정 네트워크를 식별하는 IP 주소를 제거
  • 개인 서비스를 드러내는 호스트 이름을 검열
  • 광고하지 않으려는 앱을 드러내는 프로세스 이름을 제거

이것이 또한 로컬 전용 도구가 중요한 이유입니다. ova는 데이터를 어디로도 보내지 않습니다 — 디스크에 머무릅니다. 무엇을 내보낼지는 본인의 결정입니다.

마무리

macOS 네트워크 사용 데이터를 내보내려면, 몇 가지 합리적인 경로가 있습니다. 짧은 캡처를 위한 nettop -L, 이벤트 감사를 위한 통합 로그, 완전한 제어를 위한 사용자 정의 샘플링 스크립트, 그리고 지속적인 앱별 회계를 위한 ova 같은 로컬 SQLite 기반 모니터. 이벤트가 필요한지 바이트가 필요한지, 그리고 얼마나 긴 창을 신경 쓰는지에 따라 고르세요.

지속적으로 캡처하고 나중에 쿼리할 수 있게 하는 적은 노력의 경로를 위해, ova를 설치하세요. 약 3MB, macOS 14+, Apple Silicon과 Intel, 약 1Hz로 샘플링. 데이터는 SQLite의 ~/Library/Application Support/ova/ 디렉토리에 살므로, 이미 알고 있는 어떤 분석 도구든 그것을 읽을 수 있습니다.