WebCodecsλ₯Ό μ¬μ©νμ¬ μΉ μ ν리μΌμ΄μ μμ κ²¬κ³ ν λΉλμ€ λ° μ€λμ€ λκΈ°νλ₯Ό λ¬μ±νκΈ° μν ν¬κ΄μ μΈ κ°μ΄λ. λ€μν νλ«νΌμμ μνν μ¬μμ μν κΈ°μ μ μΈλΆ μ¬ν, κ³Όμ , λͺ¨λ² μ¬λ‘λ₯Ό λ€λ£Ήλλ€.
νλ‘ νΈμλ WebCodecs νλ μ λ μ΄νΈ λκΈ°ν: λΉλμ€-μ€λμ€ μ±ν¬ κ΄λ¦¬ λ§μ€ν°νκΈ°
WebCodecs APIλ μΉ λΈλΌμ°μ λ΄μμ μ§μ λ―Έλμ΄ μΈμ½λ© λ° λμ½λ©μ λν μ λ‘ μλ μ μ΄ κΈ°λ₯μ μ 곡ν©λλ€. μ΄ κ°λ ₯ν κΈ°λ₯μ κ³ κΈ λΉλμ€ λ° μ€λμ€ μ²λ¦¬, μ μ§μ° μ€νΈλ¦¬λ°, λ§μΆ€ν λ―Έλμ΄ μ ν리μΌμ΄μ μ μν κΈ°νλ₯Ό μ΄μ΄μ€λλ€. νμ§λ§ κ°λ ₯ν νμλ ν° μ± μμ΄ λ°λ¦ λλ€. νΉν νλ μ λ μ΄νΈ μΌκ΄μ±κ³Ό κ°μ λΉλμ€ λ° μ€λμ€ λκΈ°νλ₯Ό κ΄λ¦¬νλ κ²μ μννκ³ μ λ¬Έμ μΈ μ¬μ©μ κ²½νμ 보μ₯νκΈ° μν μ€μν κ³Όμ κ° λ©λλ€.
κ³Όμ μ΄ν΄νκΈ°: λκΈ°νκ° μ€μν μ΄μ
λͺ¨λ λΉλμ€ μ ν리μΌμ΄μ μμ λΉλμ€μ μ€λμ€ μ€νΈλ¦Ό κ°μ μνν μ‘°νλ λ§€μ° μ€μν©λλ€. μ΄ μ€νΈλ¦Όλ€μ΄ λκΈ°νλμ§ μμΌλ©΄ μμ²μλ λμ λκ³ μ€λ§μ€λ¬μ΄ λ¬Έμ λ₯Ό κ²½ννκ² λ©λλ€:
- 립μ±ν¬ μ€λ₯: μΊλ¦ν°μ μ λͺ¨μμ΄ λ§νλ λ¨μ΄μ μΌμΉνμ§ μλ νμ.
- μ€λμ€ λ리ννΈ: μ€λμ€κ° λΉλμ€λ³΄λ€ μ μ°¨ λ€μ²μ§κ±°λ μμκ°λ νμ.
- λκΉ λλ λΆμμ ν μ¬μ: μΌκ΄λμ§ μμ νλ μ λ μ΄νΈλ‘ μΈν΄ λΉλμ€κ° λΆμμ νκ² λ³΄μ΄λ νμ.
μ΄λ¬ν λ¬Έμ λ€μ μμ² κ²½νμ μ¬κ°νκ² μ ν΄ν μ μμΌλ©°, νΉν νμ νμ, μ¨λΌμΈ κ²μ, μ€μκ° μ€νΈλ¦¬λ°κ³Ό κ°μ μΈν°λν°λΈ μ ν리μΌμ΄μ μμλ λμ± κ·Έλ μ΅λλ€. μλ²½ν λκΈ°νλ₯Ό λ¬μ±νλ κ²μ λ€μκ³Ό κ°μ λ€μν μμΈμΌλ‘ μΈν΄ μ§μμ μΈ μΈμμ λλ€:
- κ°λ³μ μΈ λ€νΈμν¬ μ‘°κ±΄: λ€νΈμν¬ μ§μ° μκ° λ° λμν λ³λμ λΉλμ€ λ° μ€λμ€ ν¨ν·μ λμ°© μκ°μ μν₯μ μ€ μ μμ΅λλ€.
- λμ½λ© λ° μΈμ½λ© μ€λ²ν€λ: λ―Έλμ΄λ₯Ό λμ½λ©νκ³ μΈμ½λ©νλ λ° νμν μ²λ¦¬ μκ°μ μ¬μ©λ μ₯μΉ λ° μ½λ±μ λ°λΌ λ¬λΌμ§ μ μμ΅λλ€.
- ν΄λ λ리ννΈ: λ―Έλμ΄ νμ΄νλΌμΈμ κ΄λ ¨λ μ¬λ¬ μ₯μΉ(μ: μλ², λΈλΌμ°μ , μ€λμ€ μΆλ ₯ μ₯μΉ)μ ν΄λμ΄ μλ²½νκ² λκΈ°νλμ§ μμ μ μμ΅λλ€.
- μ μν λΉνΈλ μ΄νΈ(ABR): ABR μκ³ λ¦¬μ¦μμ λ€λ₯Έ νμ§ μμ€ κ°μ μ νν λ μ μ€νκ² μ²λ¦¬νμ§ μμΌλ©΄ λκΈ°ν λ¬Έμ κ° λ°μν μ μμ΅λλ€.
WebCodecsμ μν
WebCodecsλ μλ°μ€ν¬λ¦½νΈμμ μ΄λ¬ν κ³Όμ λ€μ μ§μ μ²λ¦¬νκΈ° μν κ΅¬μ± μμλ₯Ό μ 곡ν©λλ€. μ΄λ κ°λ³ λΉλμ€ νλ μκ³Ό μ€λμ€ μ²ν¬λ₯Ό μΈμ½λ©νκ³ λμ½λ©νκΈ° μν μ μμ€ APIλ₯Ό λ ΈμΆνμ¬ κ°λ°μκ° λ―Έλμ΄ νμ΄νλΌμΈμ μΈλ°νκ² μ μ΄ν μ μλλ‘ ν©λλ€.
WebCodecsκ° λκΈ°ν κ³Όμ λ₯Ό ν΄κ²°νλ λ° λμμ΄ λλ λ°©λ²μ λ€μκ³Ό κ°μ΅λλ€:
- μ νν νμμ€ν¬ν μ μ΄: λμ½λ©λ κ° λΉλμ€ νλ μκ³Ό μ€λμ€ μ²ν¬μλ μ°κ΄λ νμμ€ν¬νκ° μμ΄, κ°λ°μκ° κ° λ―Έλμ΄ μμμ νλ μ ν μ΄μ μκ°μ μΆμ ν μ μμ΅λλ€.
- λ§μΆ€ν μ¬μ μ€μΌμ€λ§: WebCodecsλ λ―Έλμ΄κ° λ λλ§λλ λ°©μμ μ§μ νμ§ μμ΅λλ€. κ°λ°μλ νμμ€ν¬νλ₯Ό κΈ°λ°μΌλ‘ λΉλμ€ νλ μκ³Ό μ€λμ€ μ²ν¬κ° μ νν μκ°μ νμλλλ‘ λ§μΆ€ν μ¬μ μ€μΌμ€λ§ λ‘μ§μ ꡬνν μ μμ΅λλ€.
- μΈμ½λ©λ λ°μ΄ν°μ μ§μ μ κ·Ό: WebCodecsλ μΈμ½λ©λ λ°μ΄ν°λ₯Ό μ‘°μν μ μκ² νμ¬, λκΈ°ν μ€λ₯λ₯Ό 보μνκΈ° μν νλ μ λλ‘μ΄λ μ€λμ€ μ€νΈλ μΉκ³Ό κ°μ κ³ κΈ κΈ°μ μ μ¬μ©ν μ μκ² ν©λλ€.
ν΅μ¬ κ°λ : νμμ€ν¬ν, νλ μ λ μ΄νΈ, ν΄λ λ리ννΈ
νμμ€ν¬ν
νμμ€ν¬νλ λͺ¨λ λκΈ°ν μ λ΅μ κΈ°μ΄μ λλ€. WebCodecsμμ κ° `VideoFrame` λ° `AudioData` κ°μ²΄λ ν΄λΉ λ―Έλμ΄ μμμ μλλ νλ μ ν μ΄μ μκ°μ λ§μ΄ν¬λ‘μ΄ λ¨μλ‘ λνλ΄λ `timestamp` μμ±μ κ°μ§λλ€. μ΄λ¬ν νμμ€ν¬νμ μΆμ²μ μλ―Έλ₯Ό μ΄ν΄νλ κ²μ΄ μ€μν©λλ€.
μλ₯Ό λ€μ΄, λΉλμ€ μ€νΈλ¦Όμμ νμμ€ν¬νλ μΌλ°μ μΌλ‘ λΉλμ€ μμμ κΈ°μ€μΌλ‘ νλ μμ΄ νμλμ΄μΌ νλ μλλ μκ°μ λνλ λλ€. λ§μ°¬κ°μ§λ‘, μ€λμ€ νμμ€ν¬νλ μ€λμ€ μ€νΈλ¦Όμ μμμ κΈ°μ€μΌλ‘ μ€λμ€ λ°μ΄ν°μ μμ μκ°μ λνλ λλ€. μ€λμ€μ λΉλμ€ νμμ€ν¬νλ₯Ό μ ννκ² λΉκ΅νκΈ° μν΄μλ μΌκ΄λ νμλΌμΈμ μ μ§νλ κ²μ΄ μ€μν©λλ€.
μ격 μλ²λ‘λΆν° λΉλμ€ λ° μ€λμ€ λ°μ΄ν°λ₯Ό μμ νλ μλ리μ€λ₯Ό μκ°ν΄ 보μμμ€. μ΄μμ μΌλ‘ μλ²λ λ μ€νΈλ¦Όμ λν΄ μΌκ΄λκ³ μ νν νμμ€ν¬νλ₯Ό μμ±ν μ± μμ΄ μμ΄μΌ ν©λλ€. μλ²κ° νμμ€ν¬νλ₯Ό μ 곡νμ§ μκ±°λ μ λ’°ν μ μλ κ²½μ°, λ°μ΄ν° λμ°© μκ°μ κΈ°λ°μΌλ‘ μ체 νμμ€ν¬ν λ©μ»€λμ¦μ ꡬνν΄μΌ ν μλ μμ΅λλ€.
νλ μ λ μ΄νΈ
νλ μ λ μ΄νΈλ μ΄λΉ νμλλ λΉλμ€ νλ μμ μ(FPS)λ₯Ό μλ―Έν©λλ€. μΌκ΄λ νλ μ λ μ΄νΈλ₯Ό μ μ§νλ κ²μ μνν λΉλμ€ μ¬μμ νμμ μ λλ€. WebCodecsμμλ μΈμ½λ© λ° λμ½λ© μ€μ νλ μ λ μ΄νΈμ μν₯μ μ€ μ μμ΅λλ€. μ½λ± κ΅¬μ± κ°μ²΄λ₯Ό ν΅ν΄ μνλ νλ μ λ μ΄νΈλ₯Ό μ€μ ν μ μμ΅λλ€. κ·Έλ¬λ μ€μ νλ μ λ μ΄νΈλ λΉλμ€ μ½ν μΈ μ 볡μ‘μ±κ³Ό μ₯μΉμ μ²λ¦¬ λ₯λ ₯μ λ°λΌ λ¬λΌμ§ μ μμ΅λλ€.
λΉλμ€λ₯Ό λμ½λ©ν λ κ° νλ μμ μ€μ λμ½λ© μκ°μ μΆμ νλ κ²μ΄ νμμ μ λλ€. νλ μ λμ½λ©μ μμλ³΄λ€ μ€λ 걸리λ κ²½μ°, μΌκ΄λ μ¬μ μλλ₯Ό μ μ§νκΈ° μν΄ νμ νλ μμ λλ‘ν΄μΌ ν μλ μμ΅λλ€. μ΄λ μμ νλ μ ν μ΄μ μκ°(νλ μ λ μ΄νΈ κΈ°λ°)κ³Ό μ€μ λμ½λ© μκ°μ λΉκ΅νμ¬ νλ μμ νμν μ§ λλ λλ‘ν μ§λ₯Ό κ²°μ νλ κ³Όμ μ ν¬ν¨ν©λλ€.
ν΄λ λ리ννΈ
ν΄λ λ리ννΈλ μλ‘ λ€λ₯Έ μ₯μΉλ νλ‘μΈμ€ κ°μ ν΄λμ΄ μ μ°¨μ μΌλ‘ λ¬λΌμ§λ νμμ μλ―Έν©λλ€. λ―Έλμ΄ μ¬μμ λ§₯λ½μμ ν΄λ λ리ννΈλ μκ°μ΄ μ§λ¨μ λ°λΌ μ€λμ€μ λΉλμ€κ° μ μ°¨μ μΌλ‘ λκΈ°νλμ§ μκ² λ§λ€ μ μμ΅λλ€. μ΄λ μ€λμ€ λ° λΉλμ€ λμ½λκ° μ½κ° λ€λ₯Έ ν΄λμ κΈ°λ°μΌλ‘ μλν μ μκΈ° λλ¬Έμ λλ€. ν΄λ λ리ννΈλ₯Ό λ°©μ§νλ €λ©΄ λ리ννΈλ₯Ό 보μνκΈ° μν΄ μ£ΌκΈ°μ μΌλ‘ μ¬μ μλλ₯Ό μ‘°μ νλ λκΈ°ν λ©μ»€λμ¦μ ꡬννλ κ²μ΄ μ€μν©λλ€.
μΌλ°μ μΈ κΈ°μ μ€ νλλ μ€λμ€μ λΉλμ€ νμμ€ν¬ν κ°μ μ°¨μ΄λ₯Ό λͺ¨λν°λ§νκ³ κ·Έμ λ°λΌ μ€λμ€ μ¬μ μλλ₯Ό μ‘°μ νλ κ²μ λλ€. μλ₯Ό λ€μ΄, μ€λμ€κ° μ§μμ μΌλ‘ λΉλμ€λ³΄λ€ μμκ°λ κ²½μ°, μ€λμ€ μ¬μ μλλ₯Ό μ½κ° λ¦μΆμ΄ λ€μ λκΈ°νν μ μμ΅λλ€. λ°λλ‘, μ€λμ€κ° λΉλμ€λ³΄λ€ λ€μ²μ§λ κ²½μ°, μ€λμ€ μ¬μ μλλ₯Ό μ½κ° λμΌ μ μμ΅λλ€.
WebCodecsλ‘ νλ μ λ μ΄νΈ λκΈ°ν ꡬννκΈ°: λ¨κ³λ³ κ°μ΄λ
λ€μμ WebCodecsλ₯Ό μ¬μ©νμ¬ κ²¬κ³ ν νλ μ λ μ΄νΈ λκΈ°νλ₯Ό ꡬννλ λ°©λ²μ λν μ€μ©μ μΈ κ°μ΄λμ λλ€:
- λΉλμ€ λ° μ€λμ€ λμ½λ μ΄κΈ°ν:
λ¨Όμ , νμν μ½λ± ꡬμ±μ μ 곡νμ¬ `VideoDecoder` λ° `AudioDecoder`μ μΈμ€ν΄μ€λ₯Ό μμ±ν©λλ€. λΉλμ€ λμ½λμ ꡬμ±λ νλ μ λ μ΄νΈκ° λΉλμ€ μ€νΈλ¦Όμ μμ νλ μ λ μ΄νΈμ μΌμΉνλμ§ νμΈνμμμ€.
```javascript const videoDecoder = new VideoDecoder({ config: { codec: 'avc1.42E01E', // μ: H.264 Baseline Profile codedWidth: 640, codedHeight: 480, framerate: 30, }, error: (e) => console.error('Video decoder error:', e), output: (frame) => { // λμ½λ©λ λΉλμ€ νλ μ μ²λ¦¬ (4λ¨κ³ μ°Έμ‘°) handleDecodedVideoFrame(frame); }, }); const audioDecoder = new AudioDecoder({ config: { codec: 'opus', sampleRate: 48000, numberOfChannels: 2, }, error: (e) => console.error('Audio decoder error:', e), output: (audioData) => { // λμ½λ©λ μ€λμ€ λ°μ΄ν° μ²λ¦¬ (5λ¨κ³ μ°Έμ‘°) handleDecodedAudioData(audioData); }, }); ``` - μΈμ½λ©λ λ―Έλμ΄ λ°μ΄ν° μμ :
μμ€(μ: λ€νΈμν¬ μ€νΈλ¦Ό, νμΌ)λ‘λΆν° μΈμ½λ©λ λΉλμ€ λ° μ€λμ€ λ°μ΄ν°λ₯Ό μ»μ΅λλ€. μ΄ λ°μ΄ν°λ μΌλ°μ μΌλ‘ `EncodedVideoChunk` λ° `EncodedAudioChunk` κ°μ²΄ ννμΌ κ²μ λλ€.
```javascript // μ: WebSocketμΌλ‘λΆν° μΈμ½λ©λ λΉλμ€ λ° μ€λμ€ μ²ν¬ μμ socket.addEventListener('message', (event) => { const data = new Uint8Array(event.data); if (isVideoChunk(data)) { const chunk = new EncodedVideoChunk({ type: 'key', timestamp: getVideoTimestamp(data), data: data.slice(getVideoDataOffset(data)), }); videoDecoder.decode(chunk); } else if (isAudioChunk(data)) { const chunk = new EncodedAudioChunk({ type: 'key', timestamp: getAudioTimestamp(data), data: data.slice(getAudioDataOffset(data)), }); audioDecoder.decode(chunk); } }); ``` - λ―Έλμ΄ λ°μ΄ν° λμ½λ©:
`decode()` λ©μλλ₯Ό μ¬μ©νμ¬ μΈμ½λ©λ λΉλμ€ λ° μ€λμ€ μ²ν¬λ₯Ό κ° λμ½λμ 곡κΈν©λλ€. λμ½λλ λΉλκΈ°μ μΌλ‘ λ°μ΄ν°λ₯Ό μ²λ¦¬νκ³ κ΅¬μ±λ μΆλ ₯ νΈλ€λ¬λ₯Ό ν΅ν΄ λμ½λ©λ νλ μ λ° μ€λμ€ λ°μ΄ν°λ₯Ό μΆλ ₯ν©λλ€.
- λμ½λ©λ λΉλμ€ νλ μ μ²λ¦¬:
λΉλμ€ λμ½λμ μΆλ ₯ νΈλ€λ¬λ `VideoFrame` κ°μ²΄λ₯Ό λ°μ΅λλ€. μ¬κΈ°κ° ν΅μ¬ νλ μ λ μ΄νΈ λκΈ°ν λ‘μ§μ ꡬννλ κ³³μ λλ€. ꡬμ±λ νλ μ λ μ΄νΈλ₯Ό κΈ°λ°μΌλ‘ κ° νλ μμ μμ νλ μ ν μ΄μ μκ°μ μΆμ νμμμ€. μμ νλ μ ν μ΄μ μκ°κ³Ό νλ μμ΄ μ€μ λ‘ λμ½λ©λ μκ° μ¬μ΄μ μ°¨μ΄λ₯Ό κ³μ°ν©λλ€. μ°¨μ΄κ° νΉμ μκ³κ°μ μ΄κ³Όνλ©΄ λκΉμ λ°©μ§νκΈ° μν΄ νλ μμ λλ‘νλ κ²μ κ³ λ €νμμμ€.
```javascript let lastVideoTimestamp = 0; const frameInterval = 1000 / 30; // 30 FPSμ λν μμ κ°κ²© function handleDecodedVideoFrame(frame) { const now = performance.now(); const expectedTimestamp = lastVideoTimestamp + frameInterval; const delay = now - expectedTimestamp; if (delay > 2 * frameInterval) { // νλ μμ΄ μλΉν μ§μ°λμμΌλ―λ‘ λλ‘ν¨ frame.close(); console.warn('μ§μ°λ λΉλμ€ νλ μμ λλ‘ν©λλ€'); } else { // νλ μμ νμν¨ (μ: μΊλ²μ€μ 그리기) presentVideoFrame(frame); } lastVideoTimestamp = now; } function presentVideoFrame(frame) { const canvas = document.getElementById('video-canvas'); const ctx = canvas.getContext('2d'); ctx.drawImage(frame, 0, 0, canvas.width, canvas.height); frame.close(); // νλ μμ 리μμ€ ν΄μ } ``` - λμ½λ©λ μ€λμ€ λ°μ΄ν° μ²λ¦¬:
μ€λμ€ λμ½λμ μΆλ ₯ νΈλ€λ¬λ `AudioData` κ°μ²΄λ₯Ό λ°μ΅λλ€. λΉλμ€ νλ μκ³Ό μ μ¬νκ², κ° μ€λμ€ μ²ν¬μ μμ νλ μ ν μ΄μ μκ°μ μΆμ ν©λλ€. `AudioContext`λ₯Ό μ¬μ©νμ¬ μ€λμ€ λ°μ΄ν°μ μ¬μμ μμ½ν©λλ€. `AudioContext`μ μ¬μ μλλ₯Ό μ‘°μ νμ¬ ν΄λ λ리ννΈλ₯Ό 보μνκ³ λΉλμ€ μ€νΈλ¦Όκ³Όμ λκΈ°νλ₯Ό μ μ§ν μ μμ΅λλ€.
```javascript const audioContext = new AudioContext(); let lastAudioTimestamp = 0; function handleDecodedAudioData(audioData) { const audioBuffer = audioContext.createBuffer( audioData.numberOfChannels, audioData.numberOfFrames, audioData.sampleRate ); for (let channel = 0; channel < audioData.numberOfChannels; channel++) { const channelData = audioBuffer.getChannelData(channel); audioData.copyTo(channelData, { planeIndex: channel }); } const source = audioContext.createBufferSource(); source.buffer = audioBuffer; source.connect(audioContext.destination); source.start(audioContext.currentTime + (audioData.timestamp - lastAudioTimestamp) / 1000000); lastAudioTimestamp = audioData.timestamp; } ``` - ν΄λ λ리ννΈ λ³΄μ ꡬν:
νκ· μ€λμ€μ λΉλμ€ νμμ€ν¬ν κ°μ μ°¨μ΄λ₯Ό μ£ΌκΈ°μ μΌλ‘ λͺ¨λν°λ§ν©λλ€. μκ°μ΄ μ§λ¨μ λ°λΌ μ°¨μ΄κ° μ§μμ μΌλ‘ μ¦κ°νκ±°λ κ°μνλ κ²½μ°, μ€λμ€ μ¬μ μλλ₯Ό μ‘°μ νμ¬ ν΄λ λ리ννΈλ₯Ό 보μν©λλ€. μ€λμ€ μ¬μμ κΈκ²©ν λ³νλ₯Ό νΌνκΈ° μν΄ μμ μ‘°μ κ³μλ₯Ό μ¬μ©νμμμ€.
```javascript let audioVideoTimestampDifference = 0; let timestampSamples = []; const MAX_TIMESTAMP_SAMPLES = 100; function updateAudioVideoTimestampDifference(audioTimestamp, videoTimestamp) { const difference = audioTimestamp - videoTimestamp; timestampSamples.push(difference); if (timestampSamples.length > MAX_TIMESTAMP_SAMPLES) { timestampSamples.shift(); } audioVideoTimestampDifference = timestampSamples.reduce((a, b) => a + b, 0) / timestampSamples.length; // νκ· μ°¨μ΄μ κΈ°λ°νμ¬ μ€λμ€ μ¬μ μλ μ‘°μ const playbackRateAdjustment = 1 + (audioVideoTimestampDifference / 1000000000); // μμ μ‘°μ κ³μ audioContext.playbackRate.value = playbackRateAdjustment; } ```
λκΈ°νλ₯Ό μν κ³ κΈ κΈ°μ
νλ μ λλ‘ λ° μ€λμ€ μ€νΈλ μΉ
λκΈ°ν μ€λ₯κ° μ¬κ°ν κ²½μ°, νλ μ λλ‘ λ° μ€λμ€ μ€νΈλ μΉμ μ¬μ©νμ¬ λ³΄μ ν μ μμ΅λλ€. νλ μ λλ‘μ λΉλμ€λ₯Ό μ€λμ€μ λκΈ°ν μνλ‘ μ μ§νκΈ° μν΄ λΉλμ€ νλ μμ 건λλ°λ κ²μ ν¬ν¨ν©λλ€. μ€λμ€ μ€νΈλ μΉμ λΉλμ€μ μΌμΉμν€κΈ° μν΄ μ€λμ€ μ¬μμ μ½κ° λΉ λ₯΄κ² νκ±°λ λλ¦¬κ² νλ κ²μ ν¬ν¨ν©λλ€. κ·Έλ¬λ μ΄λ¬ν κΈ°μ μ λμ λλ μν°ν©νΈλ₯Ό μ λ°ν μ μμΌλ―λ‘ λλ¬Όκ² μ¬μ©ν΄μΌ ν©λλ€.
μ μν λΉνΈλ μ΄νΈ(ABR) κ³ λ €μ¬ν
μ μν λΉνΈλ μ΄νΈ μ€νΈλ¦¬λ°μ μ¬μ©ν λ, λ€λ₯Έ νμ§ μμ€ κ°μ μ ννλ©΄ λκΈ°ν λ¬Έμ κ° λ°μν μ μμ΅λλ€. νμμ€ν¬νκ° λ€λ₯Έ νμ§ μμ€ κ°μ μΌκ΄μ±μ΄ μλμ§ νμΈνμμμ€. νμ§ μμ€μ μ νν λ μνν λκΈ°νλ₯Ό 보μ₯νκΈ° μν΄ μ¬μ μμΉλ₯Ό μ½κ° μ‘°μ ν΄μΌ ν μλ μμ΅λλ€.
λμ½λ©μ μν μ컀 μ€λ λ
λΉλμ€ λ° μ€λμ€ λμ½λ©μ νΉν κ³ ν΄μλ μ½ν μΈ μ κ²½μ° κ³μ° μ§μ½μ μΌ μ μμ΅λλ€. λ©μΈ μ€λ λλ₯Ό μ°¨λ¨νκ³ UI μ§μ°μ μ λ°νλ κ²μ νΌνκΈ° μν΄ λμ½λ© νλ‘μΈμ€λ₯Ό μ컀 μ€λ λλ‘ μ€νλ‘λνλ κ²μ κ³ λ €νμμμ€. μ΄λ₯Ό ν΅ν΄ λμ½λ©μ΄ λ°±κ·ΈλΌμ΄λμμ λ°μνμ¬ λ©μΈ μ€λ λκ° UI μ λ°μ΄νΈ λ° κΈ°ν μμ μ μ²λ¦¬ν μ μλλ‘ ν΄μ€λλ€.
ν μ€νΈ λ° λλ²κΉ
λ€λ₯Έ μ₯μΉ λ° λ€νΈμν¬ μ‘°κ±΄μμ κ²¬κ³ ν λκΈ°νλ₯Ό 보μ₯νκΈ° μν΄ μ² μ ν ν μ€νΈκ° νμμ μ λλ€. λ€μν ν μ€νΈ λΉλμ€ λ° μ€λμ€ μ€νΈλ¦Όμ μ¬μ©νμ¬ λκΈ°ν λ‘μ§μ μ±λ₯μ νκ°νμμμ€. 립μ±ν¬ μ€λ₯, μ€λμ€ λ리ννΈ λ° λκΉ μλ μ¬μμ μΈμ¬ν μ£Όμλ₯Ό κΈ°μΈμ΄μμμ€.
λκΈ°ν λ¬Έμ λ₯Ό λλ²κΉ νλ κ²μ μ΄λ €μΈ μ μμ΅λλ€. λ‘κΉ λ° μ±λ₯ λͺ¨λν°λ§ λꡬλ₯Ό μ¬μ©νμ¬ λΉλμ€ νλ μ λ° μ€λμ€ μ²ν¬μ νμμ€ν¬ν, λμ½λ© μκ° λ° μ€λμ€ μ¬μ μλλ₯Ό μΆμ νμμμ€. μ΄ μ 보λ λκΈ°ν μ€λ₯μ κ·Όλ³Έ μμΈμ μλ³νλ λ° λμμ΄ λ μ μμ΅λλ€.
WebCodecs ꡬνμ μν μ μμ κ³ λ €μ¬ν
κ΅μ ν(i18n)
WebCodecsλ‘ μΉ μ ν리μΌμ΄μ μ κ°λ°ν λ, μ μΈκ³ μ¬μ©μλ₯Ό λ§μ‘±μν€κΈ° μν κ΅μ ν μΈ‘λ©΄μ κ³ λ €νμμμ€. μ¬κΈ°μλ λ€μμ΄ ν¬ν¨λ©λλ€:
- μΈμ΄ μ§μ: ν μ€νΈ λ° μ€λμ€ μ½ν μΈ λ₯Ό ν¬ν¨νμ¬ μ ν리μΌμ΄μ μ΄ μ¬λ¬ μΈμ΄λ₯Ό μ§μνλλ‘ νμμμ€.
- μλ§ λ° μΊ‘μ : λ λμ μ¬μ©μμΈ΅μ΄ λΉλμ€ μ½ν μΈ μ μ κ·Όν μ μλλ‘ λ€λ₯Έ μΈμ΄λ‘ λ μλ§ λ° μΊ‘μ μ μ§μνμμμ€.
- λ¬Έμ μΈμ½λ©: λ€λ₯Έ μΈμ΄μ λ¬Έμλ₯Ό μ¬λ°λ₯΄κ² μ²λ¦¬νκΈ° μν΄ UTF-8 μΈμ½λ©μ μ¬μ©νμμμ€.
μ κ·Όμ±(a11y)
μ κ·Όμ±μ μ₯μ κ° μλ μ¬λλ€μ΄ μΉ μ ν리μΌμ΄μ μ μ¬μ©ν μ μλλ‘ νλ λ° μ€μν©λλ€. WebCodecsλ₯Ό ꡬνν λ μ ν리μΌμ΄μ μ΄ μΉ μ½ν μΈ μ κ·Όμ± κ°μ΄λλΌμΈ(WCAG)κ³Ό κ°μ μ κ·Όμ± μ§μΉ¨μ μ€μνλλ‘ νμμμ€. μ¬κΈ°μλ λ€μμ΄ ν¬ν¨λ©λλ€:
- ν€λ³΄λ νμ: μ ν리μΌμ΄μ μ λͺ¨λ μνΈμμ© μμκ° ν€λ³΄λλ₯Ό μ¬μ©νμ¬ μ κ·Όν μ μλλ‘ νμμμ€.
- μ€ν¬λ¦° 리λ νΈνμ±: μκ° μ₯μ κ° μλ μ¬λλ€μ΄ μ¬μ©νλ μ€ν¬λ¦° 리λμ μ ν리μΌμ΄μ μ΄ νΈνλλλ‘ νμμμ€.
- μμ λλΉ: μ μλ ₯ μ¬μ©μκ° μ½ν μΈ λ₯Ό μ½μ μ μλλ‘ ν μ€νΈμ λ°°κ²½ κ°μ μΆ©λΆν μμ λλΉλ₯Ό μ¬μ©νμμμ€.
λ€μν μ₯μΉλ₯Ό μν μ±λ₯ μ΅μ ν
μΉ μ ν리μΌμ΄μ μ κ³ κΈ λ°μ€ν¬ν±λΆν° μ μ¬μ λͺ¨λ°μΌ μ₯μΉμ μ΄λ₯΄κΈ°κΉμ§ λ€μν μ₯μΉμμ μ μλν΄μΌ ν©λλ€. WebCodecsλ₯Ό ꡬνν λ, λ€λ₯Έ μ₯μΉμμ μνν μ¬μ©μ κ²½νμ 보μ₯νκΈ° μν΄ μ½λλ₯Ό μ±λ₯μ λ§κ² μ΅μ ννμμμ€. μ¬κΈ°μλ λ€μμ΄ ν¬ν¨λ©λλ€:
- μ½λ± μ ν: λμ μ₯μΉ λ° λ€νΈμν¬ μ‘°κ±΄μ λ°λΌ μ μ ν μ½λ±μ μ ννμμμ€. μΌλΆ μ½λ±μ λ€λ₯Έ μ½λ±λ³΄λ€ κ³μ° ν¨μ¨μ±μ΄ λ λμ΅λλ€.
- ν΄μλ μ€μΌμΌλ§: μ₯μΉμ νλ©΄ ν¬κΈ° λ° μ²λ¦¬ λ₯λ ₯μ λ°λΌ λΉλμ€ ν΄μλλ₯Ό μ‘°μ νμμμ€.
- λ©λͺ¨λ¦¬ κ΄λ¦¬: λ©λͺ¨λ¦¬ λμ λ° μ±λ₯ λ¬Έμ λ₯Ό νΌνκΈ° μν΄ λ©λͺ¨λ¦¬λ₯Ό ν¨μ¨μ μΌλ‘ κ΄λ¦¬νμμμ€.
κ²°λ‘
WebCodecsλ₯Ό μ¬μ©νμ¬ κ²¬κ³ ν λΉλμ€ λ° μ€λμ€ λκΈ°νλ₯Ό λ¬μ±νλ €λ©΄ μ μ€ν κ³ν, ꡬν λ° ν μ€νΈκ° νμν©λλ€. νμμ€ν¬ν, νλ μ λ μ΄νΈ, ν΄λ λ리ννΈμ ν΅μ¬ κ°λ μ μ΄ν΄νκ³ μ΄ κΈ°μ¬μμ μ€λͺ ν λ¨κ³λ³ κ°μ΄λλ₯Ό λ°λ₯΄λ©΄, λ€μν νλ«νΌκ³Ό μ μΈκ³ μ¬μ©μλ₯Ό μν΄ μννκ³ μ λ¬Έμ μΈ λ―Έλμ΄ μ¬μ κ²½νμ μ 곡νλ μΉ μ ν리μΌμ΄μ μ ꡬμΆν μ μμ΅λλ€. μ§μ μΌλ‘ ν¬μ©μ μ΄κ³ μ¬μ©μ μΉνμ μΈ μ ν리μΌμ΄μ μ λ§λ€κΈ° μν΄ κ΅μ ν, μ κ·Όμ± λ° μ±λ₯ μ΅μ νλ₯Ό κ³ λ €νλ κ²μ μμ§ λ§μμμ€. WebCodecsμ νμ λ°μλ€μ¬ λΈλΌμ°μ μμ λ―Έλμ΄ μ²λ¦¬λ₯Ό μν μλ‘μ΄ κ°λ₯μ±μ μ΄μ΄λ³΄μΈμ!