블로그 목록
Fundamentals20분 읽기

프레임의 모든 것 — Interlaced / I·P·B-frame / GOP / PLI·FIR까지

아날로그 TV의 Interlaced 비월 주사에서 디지털 Progressive로, 720p의 p의 정체, I/P/B-frame 용량 차이(100:15:8), WebRTC가 I+P만 쓰는 구조적 이유, GOP 길이 트레이드오프, PLI/FIR RTCP 피드백 루프, B-frame의 양방향 참조 그물망이 장애 복구를 어렵게 만드는 방식, 전송 순서 ≠ 표시 순서로 발생하는 look-ahead 지연까지 다이어그램으로 정리.

InterlacedProgressiveI-frameP-frameB-frameGOPPLIFIRRTCPH.264WebRTC기초
목차(43개 항목)
  1. 1. 프레임이란? 그리고 Interlaced의 역사
    1. 아날로그 시대의 문제
    2. Interlaced (비월 주사)의 등장
    3. Progressive vs Interlaced
    4. 왜 "부드러워 보이는가"
    5. 현대는 왜 Progressive가 표준인가
  2. 2. 720p의 "p"의 정체
  3. 3. I / P / B-frame — 세 가지 프레임 타입
    1. I-frame (Intra-coded)
    2. P-frame (Predictive)
    3. I-frame vs P-frame — 실제로 뭐가 다른가
    4. B-frame (Bi-directional predictive)
    5. B-frame은 "미래"를 어떻게 아는가 — 가장 근본적인 질문
    6. 용량 비교 (대략)
    7. 한눈에 보는 프레임 타입별 의존성
  4. 4. WebRTC는 왜 대부분 P-frame만 쓰는가
    1. I-frame만 보내면 어떻게 될까
    2. 왜 B-frame도 안 쓰는가
    3. 결과: I + P 조합
    4. 전략 요약
  5. 5. GOP란 무엇인가
    1. GOP 길이와 I-frame 간격
    2. GOP 짧음 vs 김
    3. GOP 시각화
  6. 6. I-frame은 언제, 왜 새로 찍히는가
    1. 정기 I-frame
    2. 추가(동적) I-frame 트리거
  7. 7. PLI / FIR — RTCP 피드백 메시지
    1. PLI (Picture Loss Indication)
    2. FIR (Full Intra Request)
    3. 왜 필요한가
    4. 시각화 — RTCP 피드백 루프
    5. 언제 PLI 대신 FIR 쓰나
  8. 8. B-frame이 장애 복구를 어렵게 만드는 구조
    1. I + P만 있을 때 (WebRTC)
    2. B-frame이 섞일 때
  9. 9. 전송 순서 ≠ 표시 순서 — B-frame 지연의 정체
    1. 표시 순서 vs 전송 순서 — 시각화
    2. 순서 역전 예시
    3. 디코더 관점의 프로세스
    4. 실시간 통신에서의 영향
    5. Look-ahead 지연 시각화
  10. 정리

"프레임이 뭐예요?", "720p의 p가 뭐예요?", "I-frame은 뭐고 P-frame은 뭐예요?", "GOP는 왜 있어요?". 영상 품질 이슈를 조사할 때마다 이 질문들이 반복됩니다. 이 글은 영상이 픽셀 덩어리에서 네트워크를 타고 눈에 도달할 때까지 반드시 이해해야 할 개념들을, 현실 예시와 다이어그램으로 정리합니다.

구성:

  1. 프레임의 개념과 Interlaced(비월) vs Progressive(순차)
  2. 720p의 "p"의 정체
  3. I / P / B-frame
  4. WebRTC는 왜 대부분 P-frame만 쓰는가
  5. GOP란 무엇인가
  6. I-frame은 언제, 왜 새로 찍히는가
  7. PLI와 FIR — "키프레임 다시 주세요" RTCP 피드백
  8. B-frame이 장애 복구를 어렵게 만드는 구조
  9. 전송 순서 ≠ 표시 순서 — B-frame 지연의 정체

1. 프레임이란? 그리고 Interlaced의 역사

TV 화면은 실제로는 정지 이미지(프레임)를 빠르게 연속으로 보여주는 것입니다. 초당 30장의 정지 이미지를 보여주면 사람 눈은 "움직임"으로 인식합니다. 이건 시각의 잔상 효과(persistence of vision) 덕분입니다.

아날로그 시대의 문제

옛날 아날로그 TV는 전송할 수 있는 대역폭이 제한적이었습니다.

  • 30fps → 그럭저럭 전송 가능
  • 60fps → 데이터 2배, 전송 불가
  • 30fps는 깜빡임(flicker)이 심해 눈이 피로

Interlaced (비월 주사)의 등장

"한 프레임을 두 번에 나눠서 보내자"는 해결책이 나왔습니다. 화면의 가로 주사선을 홀수 줄 / 짝수 줄로 나눕니다.

전체 프레임 (예: 480줄)
├── 홀수 줄: 1, 3, 5, 7, ..., 479  → Field 1 (1/60초에 전송)
└── 짝수 줄: 2, 4, 6, 8, ..., 480  → Field 2 (다음 1/60초에 전송)

시각화:

화면 한 장면:
━━━━━━━━━━━━━━━━━━━━━━━━━━━  ← 1번 줄
                              ← 2번 줄 (다음 field)
━━━━━━━━━━━━━━━━━━━━━━━━━━━  ← 3번 줄
                              ← 4번 줄
━━━━━━━━━━━━━━━━━━━━━━━━━━━  ← 5번 줄
...

Field 1에는 홀수 줄만 존재 → 1/60초 뒤 Field 2에 짝수 줄이 채워짐

Progressive vs Interlaced

Progressive (순차)Interlaced (비월)
방식한 프레임을 통째로 전송홀수/짝수 줄 번갈아 전송
초당 전송 횟수30회60회 (반쪽씩)
데이터량100%50%
움직임30fps60 field → 부드럽게 보임
정지 화면 화질선명깨끗 (두 field 합성)
움직이는 화면깔끔Comb 아티팩트 발생 가능

왜 "부드러워 보이는가"

사람 눈은 Field 1(홀수 줄)과 Field 2(짝수 줄)를 1/60초 간격으로 번갈아 보여주면 뇌가 이를 하나의 움직임으로 합쳐서 인식합니다. 실제 데이터는 30fps와 동일하지만, 움직임 감각은 60fps에 가까워집니다.

현대는 왜 Progressive가 표준인가

  • 디지털 전송은 대역폭 충분
  • LCD/OLED 모니터는 픽셀 전체를 한 번에 그림 (Interlaced를 재현하려면 디인터레이싱 처리 필요)
  • 스포츠처럼 빠른 움직임에서 Interlaced는 Comb 아티팩트 (머리카락 빗 모양 줄무늬)가 보임
  • WebRTC/스마트폰/웹캠은 전부 Progressive

2. 720p의 "p"의 정체

  • p = progressive
  • i = interlaced

숫자는 세로 픽셀 수(해상도의 높이)입니다.

표기해상도스캔 방식
720p1280 × 720Progressive
1080p1920 × 1080Progressive
1080i1920 × 1080Interlaced
2160p (4K UHD)3840 × 2160Progressive
4320p (8K)7680 × 4320Progressive

"숫자의 의미"는 세로 픽셀 수. 다른 해상도 표기(Full HD = 1080p, HD = 720p, UHD = 2160p)와 본질이 같고 "p"는 스캔 방식을 명시할 뿐입니다.


3. I / P / B-frame — 세 가지 프레임 타입

H.264/H.265 같은 비디오 코덱은 프레임 간 중복을 압축의 핵심 전략으로 씁니다. 배경이 거의 안 바뀌는 영상이라면 매 프레임마다 같은 픽셀을 반복 전송할 이유가 없습니다.

I-frame (Intra-coded)

"Intra" = 독립적. 자기 자신만으로 완전히 디코딩 가능한 프레임입니다. JPEG 이미지 하나 수준의 용량.

  • 다른 프레임을 참조하지 않음
  • 용량이 큼 (full image)
  • 새 시청자가 합류하면 I-frame부터 봐야 영상 시작 가능
I-frame은 스스로 완결된 이미지:
┌──────────────────────┐
│  [전체 픽셀 데이터]   │ ← 이것만 받아도 복원 가능
└──────────────────────┘

P-frame (Predictive)

**이전 I 또는 P 프레임과의 차분(delta)**만 전송. "배경은 동일, 얼굴만 조금 움직임" → 움직인 부분의 정보만 보냄.

P-frame = 이전 프레임 + "이만큼 바뀜" 정보

이전 P-frame:                  현재 P-frame:
┌──────────────────────┐      ┌──────────────────────┐
│                      │      │                      │
│    ● ← 얼굴 위치      │  →  │      ● ← 얼굴 이동    │
│                      │      │                      │
│   [배경 동일]         │      │   [배경 동일, 안 보냄] │
└──────────────────────┘      └──────────────────────┘

전송되는 것:
  "얼굴 영역이 오른쪽으로 5픽셀 이동했음" + 잔차(residual)
  → 데이터 매우 작음

I-frame vs P-frame — 실제로 뭐가 다른가

예시: 사람이 오른쪽으로 살짝 움직이는 영상 I-frame (완전한 그림) t=0 (I-frame 내용) 데이터에 담긴 것 • 모든 픽셀의 색깔 정보 • "(0,0)은 회색, (1,0)도 회색, (112,85)는 주황…" • 배경 + 얼굴 + 몸 전부 • 용량: 큼 (예: 100 KB) P-frame (변화량만) t=1 (변화) 데이터에 담긴 것 • "사람을 오른쪽으로 10 픽셀 이동" • 배경은 언급 없음 (안 바뀜) • 변화량(delta) + 잔차(residual)만 지시 • 용량: 작음 (예: 10 KB, 약 1/10)

핵심 차이:

I-frameP-frame
담는 것절대값 — 전체 픽셀 색깔변화량 — 이전 대비 delta
지시 방식"이 장면을 이렇게 그려라""이전 프레임에서 이만큼만 바꿔라"
비유그림을 처음부터 다 그리기수정 지시서
용량크다 (예: 100 KB)작다 (예: 10 KB, ~1/10)

그래서 용량 차이가 큰 겁니다. P-frame은 "바뀐 부분만" 담으니까 훨씬 작음.

B-frame (Bi-directional predictive)

이전과 이후 프레임 둘 다 참조합니다. 가장 작지만, 디코딩 시점에 미래 프레임이 먼저 도착해 있어야 합니다.

B-frame은 "미래"를 어떻게 아는가 — 가장 근본적인 질문

가장 헷갈리는 지점입니다. 답이 의외로 간단합니다.

답: 인코더는 미래를 알고 있습니다. 왜냐하면 이미 다 찍혔으니까.

인코더 관점 — 미래를 안다

카메라는 계속 프레임을 찍어서 **버퍼(임시 저장소)**에 쌓습니다. 30fps면 1초에 30장이 버퍼에 쌓입니다.

인코더는 이 버퍼를 보면서 작업합니다:

"지금 t=1을 인코딩해야 함. B-frame으로 만들 거야"
"그럼 t=0(과거)과 t=3(미래) 둘 다 참조해야 해"
"t=3? 아, 버퍼에 이미 있네. 카메라가 진작 찍었으니까"  ← 핵심
"둘을 비교해서 중간값 계산 → B-frame 완성"

**인코더 입장에서는 미래도 과거도 다 "이미 찍힌 프레임"**입니다. 시간 순서는 사용자 입장이지, 인코더 입장에서는 그냥 "버퍼에 쌓인 데이터들"일 뿐입니다.

카메라 → 버퍼 (이미 쌓인 프레임들) I t=0 B₁ t=1 B₂ t=2 P t=3 ← 인코더가 접근 가능 인코더 사고 과정 "t=1을 B-frame으로 만들자 → t=3이 필요해 → 버퍼에 이미 있네 → 둘 비교해서 중간값 계산"

그래서 인코딩 지연이 생긴다

근데 이게 문제입니다. 영상통화는 실시간인데:

B-frame을 쓰려면:
  인코더가 t=1을 받고도 "아직 인코딩 안 함"
  t=2도 받고도 "아직"
  t=3이 찍힐 때까지 기다림
  그제야 t=3 인코딩 → 이어서 t=1, t=2 인코딩

→ "기다리는 시간" = 인코딩 지연

이게 WebRTC가 B-frame을 쓰지 않는 두 번째 이유입니다:

어느 쪽 지연인가원인
1번째 이유디코딩 지연 (수신측)B-frame 디코딩하려면 미래 P-frame 대기
2번째 이유인코딩 지연 (송신측)인코더가 미래 프레임이 쌓일 때까지 기다림

디코더 관점 — 미래 모름, 재배열로 해결

디코더는 네트워크에서 도착하는 순서대로만 받을 수 있습니다. 그래서 인코더가 일부러 순서를 바꿔서 보냅니다:

카메라가 찍은 순서 (= 표시 순서):  I → B₁ → B₂ → P
네트워크로 보내는 순서:             I → P 먼저 → B₁ → B₂

이러면 디코더가 B₁을 받는 시점에는 이미 I와 P를 둘 다 가지고 있음 → 참조 가능 → B₁ 디코딩 OK.

결론: "디코더가 미래를 계산하는 게 아니라, 인코더가 미래를 미리 봐서 계산해놓고 순서를 재배열한 것."

표시 순서:    I₁   B   B   P₁   B   B   P₂
              ↑   ↑↓  ↑↓   ↑  ↑↓  ↑↓   ↑
              │   참조│    │  참조│    │
              └─양방향┘    └─양방향┘

B-frame은 과거 I/P와 미래 I/P 둘 다 봄
→ 가장 잘 압축됨
→ 대신 "미래"를 기다려야 하므로 지연 발생

용량 비교 (대략)

프레임 타입상대 용량특징
I-frame100Full image, 재시작 지점
P-frame10~20앞만 참조, 선형 의존
B-frame5~10양방향 참조, 최고 압축률

한눈에 보는 프레임 타입별 의존성

I-frame 독립, 용량 큼 I 참조 없음 P-frame 과거만 참조 I P 한 방향 의존 B-frame 과거 + 미래 참조 I B P 양방향 의존

핵심: WebRTC = I + P만 사용 (B는 look-ahead 지연 발생). 실시간 대화를 위해 미래 프레임 대기 불가.


4. WebRTC는 왜 대부분 P-frame만 쓰는가

I-frame만 보내면 어떻게 될까

모든 프레임을 I-frame으로 보내면:

720p @ 30fps 가정:
  I-frame 하나: ≈ 50 KB (JPEG 수준)
  초당 30장: 1,500 KB/s = 12 Mbps
  
실제 필요 비트레이트의 ~6~8배
→ 네트워크 감당 불가

왜 B-frame도 안 쓰는가

B-frame을 쓰면 압축은 더 잘 되지만:

  • 디코더가 "미래 프레임"을 기다리는 지연 발생 (look-ahead)
  • 참조 관계가 양방향 그물망 → 패킷 하나 유실되면 영향 범위 폭증
  • RTP는 PTS 단일 타임스탬프 모델 → B-frame의 DTS/PTS 분리와 충돌

이건 별도 글에서 자세히 다뤘습니다 → RTMP 라이브 송출의 B-frame이 만든 PTS rollback

결과: I + P 조합

WebRTC 스트림의 전형적 구성:

[I  P  P  P  P  P  P  P  P  P  P  P  P  P  P] [I  P  P  P  P  P  P ...
  └──── 약 2초 (60 frames) ────────────────┘   └──── 다음 GOP ────...

I-frame: 드물게 (재시작/복구 기준점)
P-frame: 대부분 (직전 프레임과의 차분)
B-frame: 거의 없음

전략 요약

  • I-frame을 너무 자주 → 대역폭 폭증
  • I-frame을 너무 드물게 → 조인/복구 느림
  • 2초 전후의 GOP가 실시간성과 효율의 타협점

5. GOP란 무엇인가

🌱 처음부터 — fps가 뭐지? "2초마다 I-frame"이 무슨 뜻이지?

fps = frames per second = 초당 프레임 수. 영상은 사실 정지 이미지(프레임)를 빠르게 연속으로 보여주는 것입니다. 애니메이션 원리와 같습니다.

  • 영화: 24fps (초당 24장)
  • TV / YouTube: 30fps
  • 게임: 60fps, 120fps (더 부드러움)
  • 화상회의: 보통 30fps

"2초마다 I-frame"의 뜻:

30fps = 1초에 30 프레임
2초 = 60 프레임
→ 60 프레임에 한 번씩 I-frame 하나
→ 나머지 59개는 P-frame
→ 이 60 프레임 묶음 = GOP 1개

왜 2초?

  • 너무 짧으면 (1초 이하) → I-frame 자주 찍혀서 대역폭 낭비
  • 너무 길면 (5초 이상) → 손실 복구·신규 참여자 합류가 느림
  • 2초가 실시간 통신의 sweet spot

GOP = Group of Pictures. I-frame에서 다음 I-frame 직전까지의 프레임 묶음입니다.

[I  P  P  P  P  P  P  P  P  P  P  P  P  P  P]  [I  P  P  P  P  P  P  P  P  P  P  P  P  P  P]
 └────────── GOP 1 (15 frames) ────────────┘    └────────── GOP 2 ──────────────────────┘

GOP 길이와 I-frame 간격

30fps 기준:

GOP 길이I-frame 간격용도
301초마다저지연 실시간 (빠른 복구, 대역폭 많이 씀)
602초마다WebRTC 일반 기본값
1505초마다저지연 LL-HLS 등
30010초마다VOD 스타일 (최대 압축 효율)

GOP 짧음 vs 김

GOP 짧으면:

  • 새 참여자 조인 빠름 (곧 다음 I-frame 옴)
  • 패킷 유실 시 복구 빠름
  • 대역폭 많이 씀 (I-frame 자주 반복)

GOP 길면:

  • 대역폭 절약 (I-frame 드묾)
  • 조인/복구 느림
  • 장기 재생에는 유리

GOP 시각화

GOP = 30 (1초 간격):
t=0   t=1   t=2   t=3   t=4   t=5 (초)
 I-----I-----I-----I-----I-----I    ← 많은 재진입 지점

GOP = 300 (10초 간격):
t=0             t=10            t=20
 I─────────────I───────────────I    ← 재진입 거의 없음
                                      새 시청자는 최대 10초 대기

WebRTC는 실시간성이 중요하니 보통 2초 GOP가 표준입니다.


6. I-frame은 언제, 왜 새로 찍히는가

"2초마다 I-frame"이 기본값이지만, 실제로는 훨씬 자주 찍힙니다. 이유:

정기 I-frame

GOP 설정에 따라 주기적으로. 예: GOP 60 + 30fps → 2초마다.

추가(동적) I-frame 트리거

① 수신자가 PLI/FIR 요청
   "프레임 손실됨, 키프레임 다시 보내줘"
   → 송신자: 즉시 I-frame 삽입

② 장면 전환(scene change) 감지
   "카메라가 완전히 다른 장면으로 바뀜"
   → P-frame으로는 차분이 너무 커서 효율 떨어짐
   → 인코더가 자발적으로 I-frame 삽입

③ 새 참여자 합류
   "이 사람은 이전 프레임 없음, I-frame부터 필요"
   → 서버가 PLI 요청 → 송신자가 I-frame 삽입

④ 네트워크 상태 급변
   → 인코더가 재시작 기준점 확보를 위해 I-frame 삽입

"정기 + 필요할 때 수시" 구조입니다.


7. PLI / FIR — RTCP 피드백 메시지

🌱 처음부터 — PLI가 대체 뭐예요?

영상통화 상황을 상상해보세요. 상대방이 비디오를 계속 보내는 중. 어느 순간 인터넷이 불안해서 비디오 패킷 하나가 사라졌습니다. 내 화면이 깨집니다. 어떻게 복구할까요?

평소의 방향:

Sender → (비디오 RTP) → Receiver

문제 발생 시 수신자가 거꾸로 요청:

Sender ← (RTCP PLI: "I-frame 다시 보내줘") ← Receiver

PLI = Picture Loss Indication ("그림 손실 알림"). 수신자가 송신자에게 "방금 거 깨졌어, 재시작 기준점(I-frame) 보내줘" 하고 역방향 신호를 보내는 것입니다.

  • 평소엔 송신자 → 수신자로 한쪽 방향
  • 깨졌을 때만 수신자 → 송신자로 구조 요청
  • 송신자는 즉시 I-frame 생성 → 재전송
  • 수신자는 새 I-frame 받으면 다시 정상 재생

이게 RTCP (RTP Control Protocol)가 하는 일의 핵심입니다. 미디어 전송은 RTP, 피드백·제어는 RTCP.

둘 다 "키프레임 다시 보내줘" 요청. WebRTC/RTP 스택의 RTCP feedback 메시지입니다.

PLI (Picture Loss Indication)

  • RFC 4585 정의
  • "프레임 손실됨, 키프레임 보내줘"
  • 가벼운 요청 (일반 손실 복구용)

FIR (Full Intra Request)

  • RFC 5104 정의
  • "무조건 지금 키프레임 보내"
  • 강한 요청 (새 참여자 합류, 스트림 재시작, 서버가 결정적으로 I-frame 필요할 때)

왜 필요한가

UDP 기반 WebRTC는 패킷 유실이 정상 범위에 있습니다. P-frame 하나 잃으면 그 뒤의 모든 P-frame이 줄줄이 망가짐 (참조 체인).

정상 시나리오:
  I → P → P → P → P → P → P → P (잘 재생)

손실 시나리오:
  I → P → P → [P 유실] → P? → P? → P? → P? (깨짐)
                        └── 뒤로 다 박살
                        ↓
                  수신자: "PLI 보냄"
                        ↓
                  송신자: I 즉시 전송
                        ↓
  I → P → P → P  (다시 정상)

시각화 — RTCP 피드백 루프

  Sender                                Receiver
    │                                     │
    ├── RTP (P-frame seq=100) ───────────▶│
    ├── RTP (P-frame seq=101) ───────────▶│
    ├── RTP (P-frame seq=102) ─X          │    ← 유실
    ├── RTP (P-frame seq=103) ───────────▶│    ← 참조할 102 없어서 깨짐
    │                                     │
    │                                     │ 수신자: 손실 감지
    │◀── RTCP PLI (keyframe 요청) ────────┤
    │                                     │
    │   "즉시 I-frame 찍어!"              │
    ├── RTP (I-frame seq=110) ───────────▶│   ← 복구됨
    ├── RTP (P-frame seq=111) ───────────▶│
    │                                     │

언제 PLI 대신 FIR 쓰나

상황적절한 요청
일반 패킷 유실 복구PLI
새 참여자 합류 (MCU/SFU가 보냄)FIR
녹화 시작 시점 기준 확보FIR
코덱/스트림 재협상 직후FIR

8. B-frame이 장애 복구를 어렵게 만드는 구조

I + P만 있을 때와 B가 섞였을 때의 차이입니다.

I + P만 있을 때 (WebRTC)

전송 순서:   I₁  P₁  P₂  P₃  P₄  P₅  P₆  I₂
디코딩 순서: I₁  P₁  P₂  P₃  P₄  P₅  P₆  I₂
             (전송 순서 = 디코딩 순서, 동일)

의존성:
  I₁ ← P₁ ← P₂ ← P₃ ← P₄ ← P₅ ← P₆
  (단방향 선형 체인)

P₃ 손실 시:
  → P₄, P₅, P₆ 디코딩 불가 (줄줄이)
  → 해결: PLI 요청 → I₂ 받으면 복구
  → 구조가 단순, 복구 판단 쉬움

B-frame이 섞일 때

표시 순서:    I₁  B₁  B₂  P₁  B₃  B₄  P₂
              (사용자가 보는 순서)

전송 순서:    I₁  P₁  B₁  B₂  P₂  B₃  B₄
              (디코더가 받는 순서 — 다름!)
              ↑    ↑   ↑
              B₁을 디코딩하려면 I₁과 P₁ 둘 다 필요
              그래서 P₁을 B₁보다 먼저 보냄

의존성:
  I₁ ──→ P₁ ──→ P₂
   │  ↘  │  ↘   │
   ↓   ↘ ↓   ↘  ↓
   B₁    B₂   B₃   B₄
   (양방향 그물망)

P₁ 손실 시:
  → B₁, B₂ 디코딩 불가 (P₁ 참조)
  → P₂도 디코딩 불가 (P₁ 체인)
  → B₃, B₄도 디코딩 불가 (P₂ 참조)
  → 전부 박살
  → "어디부터 어디까지 버려야 하는가" 판단 복잡
  → 게다가 전송 순서 ≠ 표시 순서라 타이밍 조정도 복잡

결론: B-frame은 장애 영향 범위가 커지고 복구 경로가 복잡해집니다. 이것이 WebRTC가 B-frame을 피하는 구조적 이유 중 하나입니다.


9. 전송 순서 ≠ 표시 순서 — B-frame 지연의 정체

B-frame이 포함되면 디코더가 프레임을 받는 순서화면에 보여줘야 하는 순서가 달라집니다.

🌱 왜 순서가 달라져야만 하나? — 보간(interpolation) 비유

영화 필름을 보세요. 사용자는 시간 순서대로 봅니다: 0초 → 1초 → 2초 → 3초. 당연합니다.

그런데 B-frame은 **"과거와 미래의 중간값을 보간(interpolate)하는 프레임"**입니다.

예를 들어 t=1의 B₁ 프레임이 담고 있는 건:

"t=0의 I 프레임과 t=3의 P 프레임을 보고, 그 사이 중간값으로 나를 그려라"

B₁ 자체에는 완전한 그림이 없습니다. I와 P가 둘 다 있어야 B₁을 그릴 수 있습니다.

그래서 어떻게 되냐면:

  • 사용자가 보는 순서 (당연한 시간 순서): I → B₁ → B₂ → P
  • 네트워크로 보내는 순서 (디코더가 계산 가능한 순서): I → P 먼저 → B₁ → B₂

P를 보낼 때: "I만 참조하면 되니까 바로 그릴 수 있음" ✓ B₁을 보낼 때: "I와 P가 필요한데 P는 이미 보냈음" ✓

디코더는 받은 순서대로 처리합니다. P를 못 받았으면 B₁을 계산할 방법이 없습니다. 그래서 인코더가 일부러 P를 B보다 먼저 보내는 것. 이게 "표시 순서 ≠ 전송 순서"의 뜻입니다.

표시 순서 vs 전송 순서 — 시각화

표시 순서 (사용자가 보는 순서) I t=0 B₁ t=1 B₂ t=2 P t=3 전송 순서 (네트워크 도착 순서) I P B₁ B₂ P 먼저 받아야 B₁, B₂ 디코딩 가능 P 받은 시점 ~ B₁ 표시 시점 = look-ahead 지연 실시간 대화에서 치명적 WebRTC는 이 구조를 피함 전송 순서 = 디코딩 순서 = 표시 순서 (I + P만). 한 프레임 받으면 즉시 표시 가능.

순서 역전 예시

표시 순서 (사용자가 보는 순서):
  프레임 번호:   0   1   2   3
  타입:         I   B   B   P
  PTS (표시):    0  33  66  99 ms

B₁은 I(과거, 프레임 0)와 P(미래, 프레임 3) 둘 다 참조
B₂도 마찬가지

전송 순서 (디코더가 받는 순서):
  타입:         I   P   B₁  B₂
  DTS (디코딩):  0  33  66  99 ms
  PTS (표시):    0  99  33  66 ms
                    ↑   ↑   ↑
                    PTS가 뒤로 갔다가 앞으로 갔다가

디코더 관점의 프로세스

t=0   I 받음 → 바로 디코딩 → 화면에 I 표시 (정상)

t=33  P 받음 → 디코딩 가능
             → 근데 B₁, B₂가 먼저 표시되어야 함
             → 디코딩만 하고 화면 표시 대기

t=66  B₁ 받음 → I와 P 다 있으니 B₁ 디코딩 → 화면에 B₁ 표시

t=99  B₂ 받음 → B₂ 디코딩 → 화면에 B₂ 표시

t=132 드디어 P를 화면에 표시

P를 먼저 받고도 화면에 띄우지 못하고 기다리는 시간 — 이것이 B-frame 지연의 본질입니다.

실시간 통신에서의 영향

지연 예산 비교:

WebRTC 목표: end-to-end 200~500ms

B-frame 2개 + 30fps 가정:
  look-ahead 지연 = 2 × (1/30) × 1000 ≈ 67ms 추가

B-frame 4개:
  look-ahead 지연 = 133ms 추가

대화형 통신에서 100ms 추가 지연은 체감상 "턱턱 끊기는" 느낌

이것이 WebRTC, 라이브 인터랙션, 원격회의에서 B-frame을 쓰지 않는 구조적 이유입니다 (스펙상 "금지"가 아니라, 구현 선택으로 사실상 거의 배제).

Look-ahead 지연 시각화

B-frame 없음 (WebRTC 기본):

송출 ──→ 인코딩 ──→ 전송 ──→ 수신 ──→ 디코딩 ──→ 표시
 0ms    10ms      80ms    90ms    100ms    105ms
                                             ↑
                                         총 지연 ~105ms

B-frame 포함 (VOD/방송):

송출 ──→ 인코딩 ──→ 전송 ──→ 수신 ──→ 디코딩 ──→ [B 참조용 미래 프레임 대기] ──→ 표시
 0ms    10ms      80ms    90ms    100ms       +67ms (B-frame 2개)          172ms
                                                                            ↑
                                                                      총 지연 ~172ms

VOD에서는 175ms 지연이 문제 없지만, 실시간 통신에서는 체감 가능한 격차입니다.


정리

  • 프레임은 정지 이미지의 연속이고, 시각의 잔상 효과가 "움직임"을 만든다
  • Interlaced는 아날로그 시대 대역폭 절약 기법, 현대는 Progressive가 표준
  • "720p"의 p = progressive, 숫자는 세로 픽셀 수
  • I-frame(독립 완결) / P-frame(이전 참조, 차분) / B-frame(양방향 참조, 최고 압축)
  • WebRTC는 I-frame 비용과 B-frame 복잡도 사이에서 I + P 조합을 채택
  • GOP = I-frame 간격, WebRTC는 보통 2초
  • I-frame은 정기 생성 + PLI/FIR 요청 시 + 장면 전환 + 신규 참여자 합류 시도 추가 생성
  • PLI는 일반 손실 복구, FIR는 무조건 키프레임 요청
  • B-frame은 참조 체인이 그물망이라 장애 영향 범위와 복구 복잡도가 폭증
  • B-frame은 디코더에 look-ahead 지연을 강요 — 실시간 통신에서 치명적

다음 글에서는 H.264 프로파일, x264 인코더 옵션, 하드웨어 인코더, 비트레이트 계산을 다룹니다. 이 글이 "왜 WebRTC가 이렇게 생겼는가"에 대한 개념 기초라면, 다음 글은 "실무에서 어떻게 설정해야 하는가"의 현장 지침입니다.

© 2026 Frank Kim. All rights reserved.