블로그 목록
Fundamentals30분 읽기

B-frame 완전정복 — 5 STEP으로 이해하는 '미래를 아는 인코더'

B-frame은 왜 미래를 알고 있는가? 인코더 버퍼링의 실체, STEP 1~5로 따라가는 인코딩 흐름, '기분 문자 메시지' 비유, I:P:B = 100:40:20 압축 효율, GOP 구조, 재배열 ≠ 끊김, 1시간 영화 28GB 절약의 수학적 근거, VOD ✅ / WebRTC ❌ 사용 범위에 Bonus로 'B-frame은 오디오와 관계 있나?'(Opus 블록, 립싱크 간접 경로)까지.

B-frameI-frameP-frameGOP인코더 버퍼DTSPTSH.264VODWebRTCOpus립싱크기초
목차(29개 항목)
  1. 먼저 — 왜 B-frame이 존재하는가? (목적: 압축률)
    1. 세 가지 프레임 타입 — 상대 용량 비교
    2. 기분을 문자로 보내는 비유
  2. STEP 1 — 카메라가 찍어서 버퍼에 쌓는다
  3. STEP 2 — 인코더가 B-frame 만들 때의 사고 과정
  4. STEP 3 — 인코더 처리 순서 (촬영 순서 ≠ 인코딩 순서)
  5. STEP 4 — 인코딩 지연의 정체
  6. STEP 5 — 디코더를 위한 전송 순서 재배열
    1. 디코더 입장에서 한 번 더
  7. 쉬운 비유로 다시 정리
  8. 실제 영상에서의 배치 — GOP 구조
  9. 언제 쓰는가 — 상황별 매핑
  10. 오해 풀기 — "재배열하면 디코더는 문제없는 거 아냐?"
    1. 1. 패킷 손실 → B-frame 참조 불가 (연쇄 손상)
    2. 2. 패킷 지연 (Jitter)
    3. 3. WebRTC가 B-frame을 안 쓰는 "진짜" 이유 — 2가지
    4. 4. 그럼 B-frame이 없어도 끊기는 이유는?
  11. 압축 효율 — 얼마나 차이나나
    1. 실전 수치 — 영화 한 편에서
  12. 최종 요약 — 4가지 역할
    1. 한 줄 결론
  13. Bonus — B-frame은 오디오와 관계가 있나?
    1. 결론: 없음
    2. 왜 오디오엔 B-frame이 없나 — 근본적 차이
    3. 오디오의 압축 방식은 따로
    4. 헷갈리는 지점: "오디오 프레임"이라는 말
    5. 오디오도 약간의 "의존성"은 있음
    6. 유일한 연결점 — 립싱크(A/V Sync)
    7. 한 줄 요약

"B-frame이 미래를 어떻게 알지?", "왜 전송 순서가 표시 순서랑 다르지?", "그럼 재배열하면 되니까 WebRTC에서도 써도 되는 거 아냐?". 이 세 질문은 영상 코덱을 처음 깊이 파고드는 사람이 반드시 부딪히는 지점입니다. 이 글은 B-frame을 5 STEP 비유 + 시각화로 끝까지 풀어보는 심화 가이드입니다.

앞선 글 두 편이 개념 기초(프레임의 모든 것)와 실무 코덱 선택(H.264 Profile·비트레이트)을 다뤘다면, 이 글은 B-frame 하나만 파고듭니다. 모든 설명은 비유 → 그림 → 메커니즘 순서입니다.


먼저 — 왜 B-frame이 존재하는가? (목적: 압축률)

같은 화질로 파일 크기를 줄이는 것이 목표입니다.

I-frame:  🖼️  완전한 그림 한 장 통째로 저장              → 용량 크다 (100%)
P-frame:  📝  이전 프레임 대비 달라진 부분만 저장          → 용량 중간 (~40%)
B-frame:  📝  이전과 이후 사이의 중간값만 저장            → 용량 제일 작다 (~20%)

앞뒤를 둘 다 알면 "중간은 이거야"라고 더 짧게 표현할 수 있습니다. 이게 B-frame이 가장 잘 압축되는 이유입니다.

세 가지 프레임 타입 — 상대 용량 비교

I Intra-coded 독립 프레임 완전한 이미지를 통째로 저장. 다른 프레임 참조 없음. JPEG 한 장과 동일한 개념. 💾 상대 용량 크다 (100%) 키프레임 / 기준점 P Predictive 단방향 참조 이전 I 또는 P와 비교해 달라진 부분만 저장. "앞을 보고 예측" 💾 상대 용량 중간 (약 40%) 단방향 예측 B Bi-directional 양방향 참조 앞 프레임 + 뒤 프레임 둘 다 참조해서 차이만 저장. 가장 압축률 높음. 💾 상대 용량 작다 (약 20%) 양방향 예측

기분을 문자로 보내는 비유

친구한테 매일 기분을 숫자로 문자 보낸다고 생각해봅시다. 글자 수가 요금이라 최대한 짧게 보내고 싶습니다.

월요일 기분: 😊 100점
화요일 기분: 😐 150점
수요일 기분: 😄 200점

I-frame 방식 (매번 다 보냄):

월: "오늘 기분 100점"
화: "오늘 기분 150점"   ← 매번 처음부터 다 설명
수: "오늘 기분 200점"

→ 글자 수 많음.

P-frame 방식 (과거만 참조):

월: "오늘 기분 100점"               ← 기준점
화: "어제보다 50점 올랐어"          ← 어제만 참조
수: "어제보다 50점 올랐어"          ← 어제만 참조

→ 달라진 것만 보내니 짧아짐.

B-frame 방식 (과거+미래 참조):

월: "오늘 기분 100점"               ← 기준점
수: "월요일보다 100점 올랐어"       ← 수요일 먼저!
화: "월요일이랑 수요일 딱 중간"     ← 한 마디면 끝 🎯

화요일(150점)은 월요일(100점)과 수요일(200점)의 딱 중간값이니까 "중간"이라는 말 한마디로 완벽하게 전달됩니다. 이게 B-frame의 핵심 트릭입니다.


STEP 1 — 카메라가 찍어서 버퍼에 쌓는다

가장 헷갈리는 질문: B-frame은 "미래"를 어떻게 알지?

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

📷 카메라 🗂 인코더 버퍼 (임시 저장소) — 이미 찍힌 프레임들 🌅 t=0 🌄 t=1 🌃 t=2 🌉 t=3 핵심: "미래"는 사실 이미 찍힌 과거 30fps면 1초에 30장이 버퍼에 쌓입니다. 인코더가 t=1을 처리할 때 t=3은 이미 버퍼 속 현재 데이터일 뿐입니다. 시간 순서는 사용자 입장이지, 인코더에게는 그냥 "버퍼에 쌓인 데이터"일 뿐.

STEP 2 — 인코더가 B-frame 만들 때의 사고 과정

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

STEP 3 — 인코더 처리 순서 (촬영 순서 ≠ 인코딩 순서)

카메라는 t=0 → t=1 → t=2 → t=3 순서로 찍지만, 인코더는 다른 순서로 처리합니다.

t=0 → I-frame 키프레임 아무것도 참조 안 함. 화면 전체를 통째로 저장. 📦 용량 가장 큼 — 하지만 완전히 독립적 t=3 → P-frame 단방향 참조 t=0만 참조 → "t=0에서 뭐가 바뀌었나?" 만 저장. 📦 용량 중간 t=1 → B-frame 양방향 참조 ← 핵심! t=0(과거) + t=3(미래) 둘 다 참조해서 중간값 계산. ⏳ t=3이 버퍼에 쌓일 때까지 기다려야 함 = 인코딩 지연 📦 용량 중간 t=2 → B-frame 양방향 참조 마찬가지로 t=0 + t=3 둘 다 참조. 📦 용량 가장 작음 — 앞뒤를 다 알고 있으니 차이가 최소화

STEP 4 — 인코딩 지연의 정체

영상통화는 실시간입니다. 카메라가 t=1을 찍는 순간 바로 보내야 자연스럽습니다. 그런데 B-frame을 쓰면:

시각 t=0 t=1 t=2 t=3 카메라 촬영 📷 촬영 📷 촬영 📷 촬영 📷 촬영 t=1 인코딩 ⏳ 대기 ⏳ 대기 ✅ 인코딩 t=3이 찍힐 때까지 t=1은 인코딩 못 함 → "기다리는 시간" = 인코딩 지연 이게 바로 WebRTC(영상통화)에서 B-frame을 쓰지 않는 이유입니다.

STEP 5 — 디코더를 위한 전송 순서 재배열

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

🖥 화면 표시 순서 (시청자가 보는 순서) 표시 ① I t=0 표시 ② B t=1 표시 ③ B t=2 표시 ④ P t=3 📦 실제 전송 순서 (인코더가 재배열) 전송 ① I t=0 전송 ② P t=3 전송 ③ B t=1 전송 ④ B t=2 왜 P(t=3)을 B(t=1)보다 먼저 보내나? 디코더가 B(t=1)을 복원하려면 t=3이 필요하기 때문. → 디코더가 B(t=1)을 받을 때는 이미 I(t=0)과 P(t=3)을 둘 다 가진 상태 → 복원 가능 ✅

디코더 입장에서 한 번 더

❌ 잘못된 순서로 보내면:
받은 순서: I(0) → B(1) → B(2) → P(3)
디코더:    I(0) 디코딩 OK
           B(1) 디코딩 시도... "t=3이 없는데??" 💥 오류!

✅ 올바른 순서로 보내면:
받은 순서: I(0) → P(3) → B(1) → B(2)
디코더:    I(0) 디코딩 OK
           P(3) 디코딩 OK  ← B(1)보다 먼저 준비 완료
           B(1) 디코딩 OK  ← t=0, t=3 둘 다 있으니 계산 가능!
           B(2) 디코딩 OK

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

이것이 저장 컨테이너에서 **DTS (Decoding Timestamp)**와 **PTS (Presentation Timestamp)**가 다른 이유이기도 합니다.


쉬운 비유로 다시 정리

📸 I-Frame 사진 한 장을 통째로 찍는 것 "오늘 방 상태 전체 사진 찍어둠" 완전한 스냅샷 📝 P-Frame 어제랑 비교해서 바뀐 것만 메모 "책상 위 컵이 왼쪽으로 이동함" 변화만 기록 🔮 B-Frame 어제 + 내일 둘 다 보고 오늘을 역산 "중간쯤 있었겠지" 앞뒤 보간

실제 영상에서의 배치 — GOP 구조

B-frame은 단독으로 존재하지 않고, I와 P 사이에 규칙적으로 섞여 들어갑니다. 이 전체 패턴을 **GOP (Group of Pictures)**라고 부릅니다.

▶ 일반적인 GOP 패턴: I B B P B B P B B I ... I #1 B #2 B #3 P #4 B #5 B #6 P #7 B #8 B #9 💡 GOP: I-frame부터 다음 I-frame 전까지의 묶음. 보통 30~60 프레임마다 I-frame이 등장.

언제 쓰는가 — 상황별 매핑

상황B-frame 사용?이유
영화·드라마 파일 (VOD)✅ 적극 사용용량 줄이는 게 최우선
유튜브 업로드✅ 사용저장 용량·스트리밍 대역폭 절약
블루레이·OTT 배포✅ 사용최대 압축률
영상통화 (WebRTC)❌ 안 씀인코딩 지연 + 패킷 손실 취약성
게임 스트리밍 (저지연)❌ 거의 안 씀지연 민감
RTMP 라이브 방송⚠️ 권고 안 함하류 WebRTC 변환 시 문제 (#26 참고)

오해 풀기 — "재배열하면 디코더는 문제없는 거 아냐?"

재배열은 "순서 문제"를 해결하는 것이고, 끊김은 "패킷 손실·지연 문제"라서 완전히 별개입니다.

1. 패킷 손실 → B-frame 참조 불가 (연쇄 손상)

전송: I → P → B₁ → B₂

근데 P가 네트워크에서 유실됨 💥

디코더: B₁ 받았는데... P가 없네?
        B₁은 P를 참조해야 복원 가능한데
        → B₁ 복원 불가 → B₂도 복원 불가
        → 화면 멈춤 / 깨짐

P 하나 날아가면 그걸 참조하는 B-frame 전부 연쇄 손상됩니다.

2. 패킷 지연 (Jitter)

정상:  I 도착 → P 도착 → B₁ 도착 (순서대로 빠르게)
현실:  I 도착 → P가 늦게 도착 (네트워크 혼잡)

디코더: B₁은 이미 받았는데 P가 아직 안 왔어
        재생 시간은 됐는데 복원 못 함
        → 화면 멈춤

3. WebRTC가 B-frame을 안 쓰는 "진짜" 이유 — 2가지

이유설명
인코딩 지연t=3을 기다려야 t=1 인코딩 가능 → 실시간 불가 (STEP 4)
패킷 손실 취약성B-frame은 참조 체인이 복잡 → 1개 손실 = 연쇄 손상

4. 그럼 B-frame이 없어도 끊기는 이유는?

I ← 이게 손실되면 최악
↓ 참조
P → 손실 시 이후 P들도 연쇄 손상
↓ 참조
P ...

I-frame이 날아가면 뒤따르는 P-frame 전부 복원 불가 → 다음 I-frame 올 때까지 화면 깨짐. 그래서 WebRTC는 PLI(Picture Loss Indication) 신호로 수신자가 송신자에게 "I-frame 다시 보내줘"라고 역방향 요청을 보냅니다. (#27에서 자세히)


압축 효율 — 얼마나 차이나나

같은 화질 기준 파일 크기 상대 비교:

구성파일 크기
I-frame만100% (기준)
I + P약 50%
I + P + B약 30%

실전 수치 — 영화 한 편에서

1920 × 1080 해상도 = 픽셀 약 2,073,600개
30fps = 초당 30장
1시간 영화 = 30 × 3600 = 108,000 프레임

P-frame 대비 B-frame이 픽셀 1개당 1 bit만 아껴도:
  2,073,600 픽셀 × 108,000 프레임 ≈ 2,240억 bit 절약
  ≈ 28 GB 절약 💾

2시간짜리 영화가 Blu-ray에서 4 GB vs 27 GB 차이를 만드는 것은 B-frame의 존재 유무 차이입니다. 이게 VOD 세계가 B-frame을 포기하지 않는 이유.


최종 요약 — 4가지 역할

🎥 인코더의 역할 버퍼에서 미래 프레임을 꺼내 B-frame 압축 후 순서 재배열해서 전송 📺 디코더의 역할 재배열된 순서로 받아서 참조 프레임 먼저 복원 → B-frame 복원 📦 B-frame 장점 앞뒤 둘 다 참조 → 차이 최소 압축률 최고 (VOD에 최적) B-frame 단점 미래 프레임 버퍼링 필요 실시간 스트리밍 부적합

한 줄 결론

B-frame은 저장 세계에서 "신의 도구", 실시간 세계에서 "독". 두 세계를 이어붙일 때만 문제가 된다.

두 세계를 이어붙이는 RTMP → WebRTC 같은 파이프라인을 다루신다면 #26에서 실제 PTS rollback 디버그 기록을 보시면 이 글의 모든 개념이 현장에서 어떻게 드러나는지 확인할 수 있습니다.


Bonus — B-frame은 오디오와 관계가 있나?

결론: 없음

B-frame은 비디오 전용 개념입니다. 오디오엔 애초에 그런 구조가 없어요. 헷갈리는 이유와 유일한 간접 연결점만 짚고 넘어갑니다.

왜 오디오엔 B-frame이 없나 — 근본적 차이

데이터 성격이 완전히 달라서입니다.

비디오의 특성

  • 한 프레임 = 수백만 픽셀의 2D 이미지
  • 연속된 프레임끼리 거의 똑같은 경우 많음 (배경 안 바뀌고 얼굴만 조금 움직임)
  • "이전 프레임 기준으로 변화량만" 표현하면 수백 배 압축 가능 → I/P/B 참조 구조가 효율적

오디오의 특성

  • 1 블록 = 20ms짜리 파형 (수백~수천 개 샘플)
  • 블록끼리 비슷해 보여도 주파수 분석하면 완전히 다름
  • "이전 블록 참조"로 얻을 이득이 적음 → 각 블록을 독립적으로 압축하는 게 표준
비디오 (I, P, B 프레임) I B B P B 각 프레임이 다른 종류, 서로 참조 프레임 하나 = 2D 이미지 (수백만 픽셀) 같은 화면의 반복 정보 많음 → 참조 압축 유리 프레임 크기: 수십 KB ~ 수백 KB 오디오 (균일한 샘플 블록) 20ms 20ms 20ms 20ms 20ms 20ms 모든 블록이 동등, 서로 독립 (대체로) 블록 하나 = 짧은 시간의 소리 파형 블록 크기: 수백 Byte ~ 수 KB 블록 간 참조 없음 → I/P/B 구분 불필요 B-frame은 비디오만의 개념 — 오디오는 애초에 그런 구조가 없음

오디오의 압축 방식은 따로

오디오 코덱(AAC, Opus, MP3)은 다른 기법으로 압축합니다:

  • 주파수 분석 (FFT/MDCT): 파형을 주파수별로 분해
  • 심리음향 모델: 사람 귀가 못 듣는 주파수 버림
  • 비트 할당: 중요한 주파수에 더 많은 비트

프레임 간 참조와는 완전히 다른 차원의 기술입니다.

헷갈리는 지점: "오디오 프레임"이라는 말

오디오에서도 "프레임"이라는 단어를 씁니다:

코덱프레임 정의
AAC1024 샘플 묶음
Opus2.5 / 5 / 10 / 20 / 40 / 60ms 중 하나
MP31152 샘플 묶음

이건 **"한 번에 압축/디코딩하는 단위"**라는 뜻이지, I/P/B 같은 참조 관계 타입이 아닙니다. 단어만 같고 의미가 다릅니다.

오디오도 약간의 "의존성"은 있음

일부 오디오 코덱엔 프레임 간 의존성이 약하게 존재합니다:

  • AAC LTP (Long Term Prediction): 이전 주기성 참조
  • Opus SILK 모드: 제한적 예측 코딩

단, B-frame과 달리 미래 프레임 참조는 안 하고, 참조 깊이가 얕아 실시간 지연이 거의 없습니다. Opus가 저지연 코덱으로 유명한 이유 중 하나.

유일한 연결점 — 립싱크(A/V Sync)

비디오와 오디오는 독립 인코딩되지만, 같이 재생돼야 하므로 연결점이 있습니다.

카메라 + 마이크 (원본 소스) 각자 독립적으로 인코딩 진행 비디오 인코더 (H.264, I/P/B 판단) 오디오 인코더 (Opus, 블록 단위) 먹서 (RTP 패킷화) — 타임스탬프 부여 각 패킷에 시간 정보 / 비디오 트랙 / 오디오 트랙 ← 여기서 두 트랙이 하나의 스트림으로 합쳐짐 디코더 측: 각자 디코딩 후 타임스탬프로 동기화 비디오 프레임과 오디오 블록을 같은 시각에 재생 B-frame이 오디오에 영향을 주는 간접 경로 비디오가 B-frame 때문에 지연 → 오디오는 먼저 도착 → 디코더가 '립싱크'를 위해 오디오 버퍼링 → 전체 재생 지연

비디오에 B-frame이 있으면:

  1. 비디오 디코딩이 미래 프레임 기다려서 지연
  2. 오디오는 먼저 도착
  3. 재생 플레이어가 립싱크 맞추려고 오디오를 인위적으로 지연
  4. 결과적으로 전체 지연 증가

B-frame이 오디오와 관계 있다고 할 수 있는 유일한 간접 경로입니다. 오디오 코덱 자체에는 영향 없음.

한 줄 요약

질문
오디오에 B-frame 있나?없음. 비디오 전용 개념
오디오 압축 방식은?주파수 분석 + 심리음향 모델 (완전 다른 접근)
관계가 아예 없나?코덱은 무관. 재생 타이밍(립싱크)에서만 간접 영향
실시간 음성 서비스는?Opus는 B-frame 이슈 없음. 비디오 함께 쓸 때만 신경

관련 글: 오디오 파이프라인 해부 · B-frame 완전정복 본편 · RTMP B-frame PTS rollback 트러블슈팅

© 2026 Frank Kim. All rights reserved.