콘텐츠로 이동

로그 스트리밍과 -f 옵션

11/12(목)

한 줄 요약: 로그 명령의 -f는 follow(따라가기)다. 지금까지 쌓인 로그를 보여 주고 끝내지 않고, 새 줄이 생길 때마다 계속 이어서 보여 준다. 멈출 때는 Ctrl+C. 배포 직후나 재현 테스트를 실시간으로 볼 때 쓴다.

📍 만난 상황

  • 2026-11-12 17:40 — 젬마 어시스턴트 실패 원인을 분석하던 중이었다(→ 작업 4). 직전에 "mvp(hub-dev) 어시스턴트에 젬마로 대시보드·앱 요청을 보내는 테스트를 백그라운드에서 돌리고 있고, 끝나면 결과를 정리하겠다"는 안내를 들었다.
  • 그 사이 로그 명령에 붙는 -f가 무슨 뜻인지 물었다.
  • 답은 테스트 결과 정리(4번 중 1번만 성공)로 넘어가서 -f 설명은 받지 못했다. 이 파일이 그 빈칸을 채운다. → 그날 일지

🧩 쉽게 말하면

CCTV를 떠올리면 된다. -f 없이 보면 녹화본을 처음부터 지금까지 재생하고 끝난다.

-f를 붙이면 녹화본 끝까지 본 다음 실시간 화면으로 넘어가 계속 보여 준다. 끄기 전까지 안 끝난다.

-f가 없으면 새 로그를 볼 때마다 명령을 다시 쳐야 하고, 이미 본 줄이 매번 처음부터 다시 쏟아진다.

📖 제대로 알기

용어

  • 로그(log): 프로그램이 한 일을 시간순으로 한 줄씩 남긴 기록. 파일에 쓰거나 표준 출력(stdout: 프로그램이 화면으로 내보내는 출력)으로 내보낸다.
  • 스트리밍(streaming): 끝이 정해지지 않은 데이터를 생기는 대로 흘려보내는 방식.
  • -f / --follow: 출력을 끝내지 않고 새 내용을 계속 따라가라는 옵션.
  • Ctrl+C: 터미널에서 실행 중인 명령을 멈추는 키. 로그 보기만 멈추고, 앱은 그대로 돈다.

도구별 -f

명령 무엇을 따라가나 같이 쓰는 옵션
tail -f 파일 파일 끝에 붙는 줄 -n 50, -F
kubectl logs -f 파드 컨테이너 표준 출력 --tail, --since, -c
docker logs -f 컨테이너 컨테이너 표준 출력 --tail, --since
journalctl -f 리눅스 서비스 로그 -u 서비스이름

같이 알아 둘 옵션

  • --tail=50(tail은 -n 50): 처음에 마지막 50줄만 보여 준다.
  • --since=10m: 최근 10분 것만 보여 준다.
  • --previous(-p): 재시작되기 전 컨테이너의 로그. 앱이 죽은 이유를 볼 때.
  • -c 이름: 파드 안에 컨테이너가 여럿일 때 하나를 고른다.
  • -F(tail): 파일이 지워지고 새로 생겨도(로그 회전) 다시 열어서 계속 따라간다.

⚙️ 어떻게 동작하나

tail -f의 경우: 1. 파일 끝에서 10줄(기본값)을 출력한다. 2. 어디까지 읽었는지 위치를 기억한다. 3. 파일이 커지면 새로 붙은 부분만 읽어 출력한다. 운영체제의 변경 알림을 받거나 짧은 간격으로 확인한다. 4. Ctrl+C를 누를 때까지 3을 반복한다.

kubectl logs -f는 한 단계 더 거친다. 내 컴퓨터가 클러스터에 연결을 열어 둔 채 새 줄을 받아 온다.

sequenceDiagram
  participant U as 내 터미널
  participant API as API 서버
  participant K as 노드의 kubelet
  participant C as 컨테이너 로그
  U->>API: kubectl logs -f 요청
  API->>K: 로그 스트림 요청
  K->>C: 로그 끝을 따라 읽기
  C-->>K: 새 줄
  K-->>API: 새 줄 전달
  API-->>U: 화면에 출력
kubelet(각 노드에서 컨테이너를 관리하는 프로그램)이 로그 파일을 따라 읽고, API 서버를 거쳐 내 터미널까지 흘려보낸다. 연결은 Ctrl+C나 파드 종료 때까지 유지된다.

🧪 예시

  • 예시 1 · 일상에 빗대어: 가게 CCTV가 오전 9시부터 켜져 있고 지금은 17:40이다.
  • -f 없이: 9시~17:40 녹화를 다 재생하고 끝난다.
  • --tail=20 -f: 마지막 20장면만 보여 주고, 그 뒤로 실시간 화면을 계속 띄운다.
  • --since=10m: 17:30~17:40 녹화만 재생하고 끝난다.

  • 예시 2 · 실제로는: 어시스턴트에 테스트 요청을 보내며 로그를 보는 경우다.

    kubectl logs -n <네임스페이스> deploy/<어시스턴트> --tail=50 -f
    kubectl logs -n <네임스페이스> deploy/<어시스턴트> --since=10m | grep 422
    kubectl logs -n <네임스페이스> <파드> --previous
    tail -F run.log
    
    ① 마지막 50줄부터 보여 주고 실시간으로 계속 따라간다. 다른 창에서 요청을 보내면 오류가 바로 뜬다. ② -f 없이 최근 10분만 잘라 422가 들어간 줄만 고른다. 끝나는 명령이라 결과를 정리하기 좋다. ③ 파드가 재시작됐을 때, 죽기 직전 로그를 본다. ④ 테스트 스크립트가 쓰는 결과 파일을 따라간다. 파일이 새로 만들어져도 놓치지 않는다.

⚖️ 비교 · 흔한 오해

명령 동작 끝나나
logs 쌓인 로그 전체 출력 바로 끝남
logs --tail=50 마지막 50줄 출력 바로 끝남
logs -f 출력 후 새 줄 계속 Ctrl+C까지 안 끝남
  • 오해 1: "-f는 force(강제)" → 로그 명령에서는 follow다.
  • 왜 헷갈리기 쉽나: rm -f, git push -f처럼 자주 보는 -f는 force다. 같은 글자라도 명령마다 뜻이 다르다. 헷갈리면 명령 --help로 확인한다.
  • 오해 2: "명령이 멈췄다(먹통)" → 새 줄을 기다리는 중이다. 앱에 요청이 없으면 화면이 조용할 뿐이다.
  • 오해 3: "Ctrl+C를 누르면 앱도 꺼진다" → 로그 보기만 멈춘다.
  • 오해 4: "-f는 새 줄만 보여 준다" → kubectl logs -f는 기존 로그를 전부 먼저 쏟고 나서 따라간다. 오래 돈 파드면 --tail을 같이 붙인다.

🛠️ 실무에서는

  • 쓸 때: 배포 직후 앱이 잘 뜨는지, 요청을 보내며 오류가 나는지 실시간으로 볼 때.
  • 피할 때: 스크립트·자동화 안에서. -f는 끝나지 않아 다음 단계로 못 넘어간다. 이때는 --since·--tail로 끝나는 명령을 쓴다.
  • 오래전 장애는 -f가 아니라 --since나 로그 수집 시스템에서 찾는다. 파드가 사라지면 그 로그도 사라진다.
  • 안 보일 때 먼저 볼 것
  • 파드 안 컨테이너가 여럿인가? → -c로 지정.
  • 파드가 재시작됐나? → --previous.
  • 파드가 여러 개인가? → deploy/이름은 그중 하나만 보여 준다. -l 라벨 --prefix로 여럿을 함께 본다.
  • grep을 붙였더니 늦게 뜨나? → grep --line-buffered로 바로바로 내보내게 한다.

❓ 자주 묻는 질문

  • Q. -f를 켜 둔 동안 파드가 죽으면? A. 연결이 끊기고 명령이 끝난다. 새 파드로 다시 실행하고, 죽은 이유는 --previous로 본다.
  • Q. tail -f와 tail -F는 뭐가 다른가? A. -f는 처음 연 파일만 따라간다. -F는 파일이 바뀌어도(로그 회전) 같은 이름의 새 파일을 다시 연다.
  • Q. 시간도 같이 보고 싶으면? A. kubectl logs --timestamps를 붙이면 줄마다 시각이 붙는다.

🔭 더 깊이 보기

📚 참고 자료

  • kubectl 치트 시트 (Kubernetes 한국어 문서) — "파드와 상호작용" 부분의 kubectl logs -f·--previous 예시 · 링크
  • tail invocation (GNU coreutils 매뉴얼, 영문) — -f와 -F의 정확한 차이 · 링크
  • docker container logs (Docker 공식 문서, 영문) — --follow, --tail, --since 옵션 · 링크

🗓️ 이력

  • 2026-11-12: 로그 명령의 -f 뜻을 물었으나 답이 테스트 결과로 넘어가 설명을 받지 못함 → 일지

🕸️ 연결된 주제