์๋ฐ์คํฌ๋ฆฝํธ์ Web Streams API๋ฅผ ํตํด ํจ์จ์ ์ธ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ํ์ดํ๋ผ์ธ์ ๊ตฌ์ถํ๋ ๋ฐฉ๋ฒ์ ์์๋ณด์ธ์. ์คํธ๋ฆผ์ ํ์ฉํ์ฌ ์ฑ๋ฅ๊ณผ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ๋ฅผ ์ต์ ํํ ์ ์์ต๋๋ค.
Web Streams API: JavaScript์์์ ํจ์จ์ ์ธ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ํ์ดํ๋ผ์ธ
Web Streams API๋ JavaScript์์ ์คํธ๋ฆฌ๋ฐ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํ ๊ฐ๋ ฅํ ๋ฉ์ปค๋์ฆ์ ์ ๊ณตํ์ฌ ํจ์จ์ ์ด๊ณ ๋ฐ์์ฑ์ด ๋ฐ์ด๋ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฐ๋ฅํ๊ฒ ํฉ๋๋ค. ์ ์ฒด ๋ฐ์ดํฐ์ ์ ํ ๋ฒ์ ๋ฉ๋ชจ๋ฆฌ์ ๋ก๋ํ๋ ๋์ , ์คํธ๋ฆผ์ ์ฌ์ฉํ๋ฉด ๋ฐ์ดํฐ๋ฅผ ์ ์ง์ ์ผ๋ก ์ฒ๋ฆฌํ์ฌ ๋ฉ๋ชจ๋ฆฌ ์๋น๋ฅผ ์ค์ด๊ณ ์ฑ๋ฅ์ ํฅ์์ํฌ ์ ์์ต๋๋ค. ์ด๋ ํนํ ๋์ฉ๋ ํ์ผ, ๋คํธ์ํฌ ์์ฒญ ๋๋ ์ค์๊ฐ ๋ฐ์ดํฐ ํผ๋๋ฅผ ๋ค๋ฃฐ ๋ ์ ์ฉํฉ๋๋ค.
์น ์คํธ๋ฆผ(Web Streams)์ด๋ ๋ฌด์์ธ๊ฐ?
ํต์ฌ์ ์ผ๋ก Web Streams API๋ ์ธ ๊ฐ์ง ์ฃผ์ ์ ํ์ ์คํธ๋ฆผ์ ์ ๊ณตํฉ๋๋ค:
- ReadableStream: ํ์ผ, ๋คํธ์ํฌ ์ฐ๊ฒฐ ๋๋ ์์ฑ๋ ๋ฐ์ดํฐ์ ๊ฐ์ ๋ฐ์ดํฐ ์์ค๋ฅผ ๋ํ๋ ๋๋ค.
- WritableStream: ํ์ผ, ๋คํธ์ํฌ ์ฐ๊ฒฐ ๋๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๊ฐ์ ๋ฐ์ดํฐ์ ๋์์ ๋ํ๋ ๋๋ค.
- TransformStream: ReadableStream๊ณผ WritableStream ์ฌ์ด์ ๋ณํ ํ์ดํ๋ผ์ธ์ ๋ํ๋ ๋๋ค. ๋ฐ์ดํฐ๊ฐ ์คํธ๋ฆผ์ ํตํด ํ๋ฅผ ๋ ๋ฐ์ดํฐ๋ฅผ ์์ ํ๊ฑฐ๋ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
์ด๋ฌํ ์คํธ๋ฆผ ์ ํ๋ค์ ํจ๊ป ์๋ํ์ฌ ํจ์จ์ ์ธ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ํ์ดํ๋ผ์ธ์ ๋ง๋ญ๋๋ค. ๋ฐ์ดํฐ๋ ReadableStream์์ ์์ํ์ฌ ์ ํ์ ์ธ TransformStream์ ๊ฑฐ์ณ ์ต์ข ์ ์ผ๋ก WritableStream์ผ๋ก ํ๋ฆ ๋๋ค.
์ฃผ์ ๊ฐ๋ ๋ฐ ์ฉ์ด
- ์ฒญํฌ(Chunks): ๋ฐ์ดํฐ๋ ์ฒญํฌ๋ผ๊ณ ๋ถ๋ฆฌ๋ ๊ฐ๋ณ ๋จ์๋ก ์ฒ๋ฆฌ๋ฉ๋๋ค. ์ฒญํฌ๋ ๋ฌธ์์ด, ์ซ์ ๋๋ ๊ฐ์ฒด์ ๊ฐ์ ๋ชจ๋ JavaScript ๊ฐ์ด ๋ ์ ์์ต๋๋ค.
- ์ปจํธ๋กค๋ฌ(Controllers): ๊ฐ ์คํธ๋ฆผ ์ ํ์๋ ์คํธ๋ฆผ์ ๊ด๋ฆฌํ๊ธฐ ์ํ ๋ฉ์๋๋ฅผ ์ ๊ณตํ๋ ํด๋น ์ปจํธ๋กค๋ฌ ๊ฐ์ฒด๊ฐ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ReadableStreamController๋ ์คํธ๋ฆผ์ ๋ฐ์ดํฐ๋ฅผ ์ถ๊ฐ(enqueue)ํ ์ ์๊ฒ ํ๊ณ , WritableStreamController๋ ๋ค์ด์ค๋ ์ฒญํฌ๋ฅผ ์ฒ๋ฆฌํ ์ ์๊ฒ ํฉ๋๋ค.
- ํ์ดํ(Pipes): ์คํธ๋ฆผ์
pipeTo()
๋ฐpipeThrough()
๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ํจ๊ป ์ฐ๊ฒฐ๋ ์ ์์ต๋๋ค.pipeTo()
๋ ReadableStream์ WritableStream์ ์ฐ๊ฒฐํ๊ณ ,pipeThrough()
๋ ReadableStream์ TransformStream์ ์ฐ๊ฒฐํ ๋ค์ WritableStream์ ์ฐ๊ฒฐํฉ๋๋ค. - ์ญ์๋ ฅ(Backpressure): ์๋น์๊ฐ ์์ฐ์์๊ฒ ๋ ์ด์ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ ์ค๋น๊ฐ ๋์ง ์์์์ ์๋ฆด ์ ์๋ ๋ฉ์ปค๋์ฆ์ ๋๋ค. ์ด๋ ์๋น์๊ฐ ๊ณผ๋ถํ๋๋ ๊ฒ์ ๋ฐฉ์งํ๊ณ ๋ฐ์ดํฐ๊ฐ ์ง์ ๊ฐ๋ฅํ ์๋๋ก ์ฒ๋ฆฌ๋๋๋ก ๋ณด์ฅํฉ๋๋ค.
ReadableStream ์์ฑํ๊ธฐ
ReadableStream()
์์ฑ์๋ฅผ ์ฌ์ฉํ์ฌ ReadableStream์ ์์ฑํ ์ ์์ต๋๋ค. ์ด ์์ฑ์๋ ์คํธ๋ฆผ์ ๋์์ ์ ์ดํ๊ธฐ ์ํ ์ฌ๋ฌ ๋ฉ์๋๋ฅผ ์ ์ํ ์ ์๋ ๊ฐ์ฒด๋ฅผ ์ธ์๋ก ๋ฐ์ต๋๋ค. ์ด ์ค ๊ฐ์ฅ ์ค์ํ ๊ฒ์ ์คํธ๋ฆผ์ด ์์ฑ๋ ๋ ํธ์ถ๋๋ start()
๋ฉ์๋์ ์คํธ๋ฆผ์ด ๋ ๋ง์ ๋ฐ์ดํฐ๋ฅผ ํ์๋ก ํ ๋ ํธ์ถ๋๋ pull()
๋ฉ์๋์
๋๋ค.
๋ค์์ ์ซ์ ์ํ์ค๋ฅผ ์์ฑํ๋ ReadableStream์ ๋ง๋๋ ์์ ์ ๋๋ค:
const readableStream = new ReadableStream({
start(controller) {
let counter = 0;
function push() {
if (counter >= 10) {
controller.close();
return;
}
controller.enqueue(counter++);
setTimeout(push, 100);
}
push();
},
});
์ด ์์ ์์ start()
๋ฉ์๋๋ ์นด์ดํฐ๋ฅผ ์ด๊ธฐํํ๊ณ , ์คํธ๋ฆผ์ ์ซ์๋ฅผ ์ถ๊ฐ(enqueue)ํ ๋ค์ ์งง์ ์ง์ฐ ํ ์์ ์ ๋ค์ ํธ์ถํ๋ push()
ํจ์๋ฅผ ์ ์ํฉ๋๋ค. ์นด์ดํฐ๊ฐ 10์ ๋๋ฌํ๋ฉด controller.close()
๋ฉ์๋๊ฐ ํธ์ถ๋์ด ์คํธ๋ฆผ์ด ์ข
๋ฃ๋์์์ ์๋ฆฝ๋๋ค.
ReadableStream ์๋นํ๊ธฐ
ReadableStream์์ ๋ฐ์ดํฐ๋ฅผ ์๋นํ๋ ค๋ฉด ReadableStreamDefaultReader
๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. ๋ฆฌ๋(reader)๋ ์คํธ๋ฆผ์์ ์ฒญํฌ๋ฅผ ์ฝ๊ธฐ ์ํ ๋ฉ์๋๋ฅผ ์ ๊ณตํฉ๋๋ค. ์ด ์ค ๊ฐ์ฅ ์ค์ํ ๊ฒ์ read()
๋ฉ์๋๋ก, ๋ฐ์ดํฐ ์ฒญํฌ์ ์คํธ๋ฆผ ์ข
๋ฃ ์ฌ๋ถ๋ฅผ ๋ํ๋ด๋ ํ๋๊ทธ๊ฐ ํฌํจ๋ ๊ฐ์ฒด๋ก ํด์(resolve)๋๋ ํ๋ก๋ฏธ์ค(promise)๋ฅผ ๋ฐํํฉ๋๋ค.
๋ค์์ ์ด์ ์์ ์์ ์์ฑ๋ ReadableStream์์ ๋ฐ์ดํฐ๋ฅผ ์๋นํ๋ ์์ ์ ๋๋ค:
const reader = readableStream.getReader();
async function read() {
const { done, value } = await reader.read();
if (done) {
console.log('์คํธ๋ฆผ ์๋ฃ');
return;
}
console.log('์์ :', value);
read();
}
read();
์ด ์์ ์์ read()
ํจ์๋ ์คํธ๋ฆผ์์ ์ฒญํฌ๋ฅผ ์ฝ๊ณ ์ฝ์์ ๊ธฐ๋กํ ๋ค์, ์คํธ๋ฆผ์ด ๋๋ ๋๊น์ง ์์ ์ ๋ค์ ํธ์ถํฉ๋๋ค.
WritableStream ์์ฑํ๊ธฐ
WritableStream()
์์ฑ์๋ฅผ ์ฌ์ฉํ์ฌ WritableStream์ ์์ฑํ ์ ์์ต๋๋ค. ์ด ์์ฑ์๋ ์คํธ๋ฆผ์ ๋์์ ์ ์ดํ๊ธฐ ์ํ ์ฌ๋ฌ ๋ฉ์๋๋ฅผ ์ ์ํ ์ ์๋ ๊ฐ์ฒด๋ฅผ ์ธ์๋ก ๋ฐ์ต๋๋ค. ์ด ์ค ๊ฐ์ฅ ์ค์ํ ๊ฒ์ ๋ฐ์ดํฐ ์ฒญํฌ๋ฅผ ์ธ ์ค๋น๊ฐ ๋์์ ๋ ํธ์ถ๋๋ write()
๋ฉ์๋, ์คํธ๋ฆผ์ด ๋ซํ ๋ ํธ์ถ๋๋ close()
๋ฉ์๋, ๊ทธ๋ฆฌ๊ณ ์คํธ๋ฆผ์ด ์ค๋จ๋ ๋ ํธ์ถ๋๋ abort()
๋ฉ์๋์
๋๋ค.
๋ค์์ ๊ฐ ๋ฐ์ดํฐ ์ฒญํฌ๋ฅผ ์ฝ์์ ๊ธฐ๋กํ๋ WritableStream์ ๋ง๋๋ ์์ ์ ๋๋ค:
const writableStream = new WritableStream({
write(chunk) {
console.log('์ฐ๊ธฐ:', chunk);
return Promise.resolve(); // ์ฑ๊ณต ํ์
},
close() {
console.log('์คํธ๋ฆผ ๋ซํ');
},
abort(err) {
console.error('์คํธ๋ฆผ ์ค๋จ๋จ:', err);
},
});
์ด ์์ ์์ write()
๋ฉ์๋๋ ์ฒญํฌ๋ฅผ ์ฝ์์ ๊ธฐ๋กํ๊ณ ์ฒญํฌ๊ฐ ์ฑ๊ณต์ ์ผ๋ก ๊ธฐ๋ก๋์์ ๋ ํด์(resolve)๋๋ ํ๋ก๋ฏธ์ค(promise)๋ฅผ ๋ฐํํฉ๋๋ค. close()
๋ฐ abort()
๋ฉ์๋๋ ๊ฐ๊ฐ ์คํธ๋ฆผ์ด ๋ซํ๊ฑฐ๋ ์ค๋จ๋ ๋ ์ฝ์์ ๋ฉ์์ง๋ฅผ ๊ธฐ๋กํฉ๋๋ค.
WritableStream์ ์ฐ๊ธฐ
WritableStream์ ๋ฐ์ดํฐ๋ฅผ ์ฐ๋ ค๋ฉด WritableStreamDefaultWriter
๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. ๋ผ์ดํฐ(writer)๋ ์คํธ๋ฆผ์ ์ฒญํฌ๋ฅผ ์ฐ๊ธฐ ์ํ ๋ฉ์๋๋ฅผ ์ ๊ณตํฉ๋๋ค. ์ด ์ค ๊ฐ์ฅ ์ค์ํ ๊ฒ์ write()
๋ฉ์๋๋ก, ๋ฐ์ดํฐ ์ฒญํฌ๋ฅผ ์ธ์๋ก ๋ฐ๊ณ ์ฒญํฌ๊ฐ ์ฑ๊ณต์ ์ผ๋ก ๊ธฐ๋ก๋์์ ๋ ํด์(resolve)๋๋ ํ๋ก๋ฏธ์ค(promise)๋ฅผ ๋ฐํํฉ๋๋ค.
๋ค์์ ์ด์ ์์ ์์ ์์ฑ๋ WritableStream์ ๋ฐ์ดํฐ๋ฅผ ์ฐ๋ ์์ ์ ๋๋ค:
const writer = writableStream.getWriter();
async function writeData() {
await writer.write('Hello, world!');
await writer.close();
}
writeData();
์ด ์์ ์์ writeData()
ํจ์๋ "Hello, world!" ๋ฌธ์์ด์ ์คํธ๋ฆผ์ ์ด ๋ค์ ์คํธ๋ฆผ์ ๋ซ์ต๋๋ค.
TransformStream ์์ฑํ๊ธฐ
TransformStream()
์์ฑ์๋ฅผ ์ฌ์ฉํ์ฌ TransformStream์ ์์ฑํ ์ ์์ต๋๋ค. ์ด ์์ฑ์๋ ์คํธ๋ฆผ์ ๋์์ ์ ์ดํ๊ธฐ ์ํ ์ฌ๋ฌ ๋ฉ์๋๋ฅผ ์ ์ํ ์ ์๋ ๊ฐ์ฒด๋ฅผ ์ธ์๋ก ๋ฐ์ต๋๋ค. ์ด ์ค ๊ฐ์ฅ ์ค์ํ ๊ฒ์ ๋ฐ์ดํฐ ์ฒญํฌ๋ฅผ ๋ณํํ ์ค๋น๊ฐ ๋์์ ๋ ํธ์ถ๋๋ transform()
๋ฉ์๋์ ์คํธ๋ฆผ์ด ๋ซํ ๋ ํธ์ถ๋๋ flush()
๋ฉ์๋์
๋๋ค.
๋ค์์ ๊ฐ ๋ฐ์ดํฐ ์ฒญํฌ๋ฅผ ๋๋ฌธ์๋ก ๋ณํํ๋ TransformStream์ ๋ง๋๋ ์์ ์ ๋๋ค:
const transformStream = new TransformStream({
transform(chunk, controller) {
controller.enqueue(chunk.toUpperCase());
},
flush(controller) {
// ์ ํ ์ฌํญ: ์คํธ๋ฆผ์ด ๋ซํ ๋ ์ต์ข
์์
์ ์ํํฉ๋๋ค
},
});
์ด ์์ ์์ transform()
๋ฉ์๋๋ ์ฒญํฌ๋ฅผ ๋๋ฌธ์๋ก ๋ณํํ๊ณ ์ปจํธ๋กค๋ฌ์ ํ์ ์ถ๊ฐ(enqueue)ํฉ๋๋ค. flush()
๋ฉ์๋๋ ์คํธ๋ฆผ์ด ๋ซํ ๋ ํธ์ถ๋๋ฉฐ ์ต์ข
์์
์ ์ํํ๋ ๋ฐ ์ฌ์ฉํ ์ ์์ต๋๋ค.
ํ์ดํ๋ผ์ธ์์ TransformStream ์ฌ์ฉํ๊ธฐ
TransformStream์ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ํ์ดํ๋ผ์ธ์ ๋ง๋ค๊ธฐ ์ํด ํจ๊ป ์ฐ๊ฒฐ๋ ๋ ๊ฐ์ฅ ์ ์ฉํฉ๋๋ค. pipeThrough()
๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ReadableStream์ TransformStream์ ์ฐ๊ฒฐํ ๋ค์ WritableStream์ ์ฐ๊ฒฐํ ์ ์์ต๋๋ค.
๋ค์์ ReadableStream์์ ๋ฐ์ดํฐ๋ฅผ ์ฝ๊ณ , TransformStream์ ์ฌ์ฉํ์ฌ ๋๋ฌธ์๋ก ๋ณํํ ๋ค์, WritableStream์ ์ฐ๋ ํ์ดํ๋ผ์ธ์ ๋ง๋๋ ์์ ์ ๋๋ค:
const readableStream = new ReadableStream({
start(controller) {
controller.enqueue('hello');
controller.enqueue('world');
controller.close();
},
});
const transformStream = new TransformStream({
transform(chunk, controller) {
controller.enqueue(chunk.toUpperCase());
},
});
const writableStream = new WritableStream({
write(chunk) {
console.log('์ฐ๊ธฐ:', chunk);
return Promise.resolve();
},
});
readableStream.pipeThrough(transformStream).pipeTo(writableStream);
์ด ์์ ์์ pipeThrough()
๋ฉ์๋๋ readableStream
์ transformStream
์ ์ฐ๊ฒฐํ๊ณ , ๊ทธ ๋ค์ pipeTo()
๋ฉ์๋๊ฐ transformStream
์ writableStream
์ ์ฐ๊ฒฐํฉ๋๋ค. ๋ฐ์ดํฐ๋ ReadableStream์์ ์์ํ์ฌ TransformStream(์ฌ๊ธฐ์ ๋๋ฌธ์๋ก ๋ณํ๋จ)์ ๊ฑฐ์ณ WritableStream(์ฌ๊ธฐ์ ์ฝ์์ ๊ธฐ๋ก๋จ)์ผ๋ก ํ๋ฆ
๋๋ค.
์ญ์๋ ฅ(Backpressure)
์ญ์๋ ฅ์ ๋น ๋ฅธ ์์ฐ์๊ฐ ๋๋ฆฐ ์๋น์๋ฅผ ์๋ํ๋ ๊ฒ์ ๋ฐฉ์งํ๋ Web Streams์ ์ค์ํ ๋ฉ์ปค๋์ฆ์ ๋๋ค. ์๋น์๊ฐ ๋ฐ์ดํฐ ์์ฐ ์๋๋ฅผ ๋ฐ๋ผ๊ฐ ์ ์์ ๋, ์์ฐ์์๊ฒ ์๋๋ฅผ ๋ฆ์ถ๋ผ๊ณ ์ ํธ๋ฅผ ๋ณด๋ผ ์ ์์ต๋๋ค. ์ด๋ ์คํธ๋ฆผ์ ์ปจํธ๋กค๋ฌ์ ๋ฆฌ๋/๋ผ์ดํฐ ๊ฐ์ฒด๋ฅผ ํตํด ์ด๋ฃจ์ด์ง๋๋ค.
ReadableStream์ ๋ด๋ถ ํ๊ฐ ๊ฐ๋ ์ฐจ๋ฉด, ํ์ ๊ณต๊ฐ์ด ์๊ธธ ๋๊น์ง pull()
๋ฉ์๋๊ฐ ํธ์ถ๋์ง ์์ต๋๋ค. ๋ง์ฐฌ๊ฐ์ง๋ก WritableStream์ write()
๋ฉ์๋๋ ์คํธ๋ฆผ์ด ๋ ๋ง์ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ ์ค๋น๊ฐ ๋์์ ๋๋ง ํด์(resolve)๋๋ ํ๋ก๋ฏธ์ค(promise)๋ฅผ ๋ฐํํ ์ ์์ต๋๋ค.
์ญ์๋ ฅ์ ์ ์ ํ ์ฒ๋ฆฌํจ์ผ๋ก์จ ๋ค์ํ ๋ฐ์ดํฐ ์๋๋ฅผ ๋ค๋ฃฐ ๋์๋ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ํ์ดํ๋ผ์ธ์ด ๊ฒฌ๊ณ ํ๊ณ ํจ์จ์ ์ผ๋ก ์๋ํ๋๋ก ๋ณด์ฅํ ์ ์์ต๋๋ค.
์ฌ์ฉ ์ฌ๋ก ๋ฐ ์์
1. ๋์ฉ๋ ํ์ผ ์ฒ๋ฆฌ
Web Streams API๋ ๋์ฉ๋ ํ์ผ์ ๋ฉ๋ชจ๋ฆฌ์ ์ ๋ถ ๋ก๋ํ์ง ์๊ณ ์ฒ๋ฆฌํ๋ ๋ฐ ์ด์์ ์ ๋๋ค. ํ์ผ์ ์ฒญํฌ ๋จ์๋ก ์ฝ๊ณ , ๊ฐ ์ฒญํฌ๋ฅผ ์ฒ๋ฆฌํ ๋ค์, ๊ฒฐ๊ณผ๋ฅผ ๋ค๋ฅธ ํ์ผ์ด๋ ์คํธ๋ฆผ์ ์ธ ์ ์์ต๋๋ค.
async function processFile(inputFile, outputFile) {
const readableStream = fs.createReadStream(inputFile).pipeThrough(new TextDecoderStream());
const writableStream = fs.createWriteStream(outputFile).pipeThrough(new TextEncoderStream());
const transformStream = new TransformStream({
transform(chunk, controller) {
// ์์: ๊ฐ ์ค์ ๋๋ฌธ์๋ก ๋ณํ
const lines = chunk.split('\n');
lines.forEach(line => controller.enqueue(line.toUpperCase() + '\n'));
}
});
await readableStream.pipeThrough(transformStream).pipeTo(writableStream);
console.log('ํ์ผ ์ฒ๋ฆฌ ์๋ฃ!');
}
// ์ฌ์ฉ ์์ (Node.js ํ์)
// const fs = require('fs');
// processFile('input.txt', 'output.txt');
2. ๋คํธ์ํฌ ์์ฒญ ์ฒ๋ฆฌ
Web Streams API๋ฅผ ์ฌ์ฉํ์ฌ API ์๋ต์ด๋ ์๋ฒ-์ ์ก ์ด๋ฒคํธ(server-sent events)์ ๊ฐ์ ๋คํธ์ํฌ ์์ฒญ์์ ์์ ๋ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค. ์ด๋ฅผ ํตํด ์ ์ฒด ์๋ต์ด ๋ค์ด๋ก๋๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ์ง ์๊ณ ๋ฐ์ดํฐ๊ฐ ๋์ฐฉํ๋ ์ฆ์ ์ฒ๋ฆฌ๋ฅผ ์์ํ ์ ์์ต๋๋ค.
async function fetchAndProcessData(url) {
const response = await fetch(url);
const reader = response.body.getReader();
const decoder = new TextDecoder();
try {
while (true) {
const { done, value } = await reader.read();
if (done) {
break;
}
const text = decoder.decode(value);
// ์์ ๋ ๋ฐ์ดํฐ ์ฒ๋ฆฌ
console.log('์์ :', text);
}
} catch (error) {
console.error('์คํธ๋ฆผ ์ฝ๊ธฐ ์ค๋ฅ:', error);
} finally {
reader.releaseLock();
}
}
// ์ฌ์ฉ ์์
// fetchAndProcessData('https://example.com/api/data');
3. ์ค์๊ฐ ๋ฐ์ดํฐ ํผ๋
์น ์คํธ๋ฆผ์ ์ฃผ๊ฐ๋ ์ผ์ ํ๋ ๊ฐ๊ณผ ๊ฐ์ ์ค์๊ฐ ๋ฐ์ดํฐ ํผ๋๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐ์๋ ์ ํฉํฉ๋๋ค. ReadableStream์ ๋ฐ์ดํฐ ์์ค์ ์ฐ๊ฒฐํ๊ณ ๋ค์ด์ค๋ ๋ฐ์ดํฐ๋ฅผ ๋์ฐฉํ๋ ๋๋ก ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
// ์์: ์ค์๊ฐ ๋ฐ์ดํฐ ํผ๋ ์๋ฎฌ๋ ์ด์
const readableStream = new ReadableStream({
start(controller) {
let intervalId = setInterval(() => {
const data = Math.random(); // ์ผ์ ํ๋
๊ฐ ์๋ฎฌ๋ ์ด์
controller.enqueue(`๋ฐ์ดํฐ: ${data.toFixed(2)}`);
}, 1000);
this.cancel = () => {
clearInterval(intervalId);
controller.close();
};
},
cancel() {
this.cancel();
}
});
const reader = readableStream.getReader();
async function readStream() {
try {
while (true) {
const { done, value } = await reader.read();
if (done) {
console.log('์คํธ๋ฆผ ๋ซํ.');
break;
}
console.log('์์ :', value);
}
} catch (error) {
console.error('์คํธ๋ฆผ ์ฝ๊ธฐ ์ค๋ฅ:', error);
} finally {
reader.releaseLock();
}
}
readStream();
// 10์ด ํ ์คํธ๋ฆผ ์ค์ง
setTimeout(() => {readableStream.cancel()}, 10000);
Web Streams API ์ฌ์ฉ์ ์ด์
- ์ฑ๋ฅ ํฅ์: ๋ฐ์ดํฐ๋ฅผ ์ ์ง์ ์ผ๋ก ์ฒ๋ฆฌํ์ฌ ๋ฉ๋ชจ๋ฆฌ ์๋น๋ฅผ ์ค์ด๊ณ ๋ฐ์์ฑ์ ๊ฐ์ ํฉ๋๋ค.
- ํฅ์๋ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ: ์ ์ฒด ๋ฐ์ดํฐ์ ์ ๋ฉ๋ชจ๋ฆฌ์ ๋ก๋ํ๋ ๊ฒ์ ํผํ๋ฉฐ, ํนํ ๋์ฉ๋ ํ์ผ์ด๋ ๋คํธ์ํฌ ์คํธ๋ฆผ์ ์ ์ฉํฉ๋๋ค.
- ๋ ๋์ ์ฌ์ฉ์ ๊ฒฝํ: ๋ฐ์ดํฐ ์ฒ๋ฆฌ ๋ฐ ํ์๋ฅผ ๋ ๋นจ๋ฆฌ ์์ํ์ฌ ๋ ์ํธ์์ฉ์ ์ด๊ณ ๋ฐ์์ฑ์ด ์ข์ ์ฌ์ฉ์ ๊ฒฝํ์ ์ ๊ณตํฉ๋๋ค.
- ๋จ์ํ๋ ๋ฐ์ดํฐ ์ฒ๋ฆฌ: TransformStream์ ์ฌ์ฉํ์ฌ ๋ชจ๋์์ด๊ณ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ํ์ดํ๋ผ์ธ์ ๋ง๋ญ๋๋ค.
- ์ญ์๋ ฅ ์ง์: ๋ค์ํ ๋ฐ์ดํฐ ์๋๋ฅผ ์ฒ๋ฆฌํ๊ณ ์๋น์๊ฐ ๊ณผ๋ถํ๋๋ ๊ฒ์ ๋ฐฉ์งํฉ๋๋ค.
๊ณ ๋ ค ์ฌํญ ๋ฐ ๋ชจ๋ฒ ์ฌ๋ก
- ์ค๋ฅ ์ฒ๋ฆฌ: ์คํธ๋ฆผ ์ค๋ฅ๋ฅผ ์ ์์ ์ผ๋ก ์ฒ๋ฆฌํ๊ณ ์๊ธฐ์น ์์ ์ ํ๋ฆฌ์ผ์ด์ ๋์์ ๋ฐฉ์งํ๊ธฐ ์ํด ๊ฐ๋ ฅํ ์ค๋ฅ ์ฒ๋ฆฌ ๋ก์ง์ ๊ตฌํํด์ผ ํฉ๋๋ค.
- ๋ฆฌ์์ค ๊ด๋ฆฌ: ๋ฉ๋ชจ๋ฆฌ ๋์๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด ์คํธ๋ฆผ์ด ๋ ์ด์ ํ์ํ์ง ์์ ๋ ๋ฆฌ์์ค๋ฅผ ์ ์ ํ ํด์ ํด์ผ ํฉ๋๋ค.
reader.releaseLock()
์ ์ฌ์ฉํ๊ณ ์คํธ๋ฆผ์ด ์ ์ ํ ๋ ๋ซํ๊ฑฐ๋ ์ค๋จ๋๋๋ก ํด์ผ ํฉ๋๋ค. - ์ธ์ฝ๋ฉ ๋ฐ ๋์ฝ๋ฉ: ํ
์คํธ ๊ธฐ๋ฐ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ ๋๋
TextEncoderStream
๊ณผTextDecoderStream
์ ์ฌ์ฉํ์ฌ ์ฌ๋ฐ๋ฅธ ๋ฌธ์ ์ธ์ฝ๋ฉ์ ๋ณด์ฅํด์ผ ํฉ๋๋ค. - ๋ธ๋ผ์ฐ์ ํธํ์ฑ: Web Streams API๋ฅผ ์ฌ์ฉํ๊ธฐ ์ ์ ๋ธ๋ผ์ฐ์ ํธํ์ฑ์ ํ์ธํ๊ณ , ๊ตฌํ ๋ธ๋ผ์ฐ์ ๋ฅผ ์ํด ํด๋ฆฌํ(polyfill) ์ฌ์ฉ์ ๊ณ ๋ คํด์ผ ํฉ๋๋ค.
- ํ ์คํธ: ๋ฐ์ดํฐ ์ฒ๋ฆฌ ํ์ดํ๋ผ์ธ์ด ๋ค์ํ ์กฐ๊ฑด์์ ์ฌ๋ฐ๋ฅด๊ฒ ์๋ํ๋์ง ์ฒ ์ ํ ํ ์คํธํด์ผ ํฉ๋๋ค.
๊ฒฐ๋ก
Web Streams API๋ JavaScript์์ ์คํธ๋ฆฌ๋ฐ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๋ ๊ฐ๋ ฅํ๊ณ ํจ์จ์ ์ธ ๋ฐฉ๋ฒ์ ์ ๊ณตํฉ๋๋ค. ํต์ฌ ๊ฐ๋ ์ ์ดํดํ๊ณ ๋ค์ํ ์คํธ๋ฆผ ์ ํ์ ํ์ฉํจ์ผ๋ก์จ, ๋์ฉ๋ ํ์ผ, ๋คํธ์ํฌ ์์ฒญ ๋ฐ ์ค์๊ฐ ๋ฐ์ดํฐ ํผ๋๋ฅผ ์ฝ๊ฒ ์ฒ๋ฆฌํ ์ ์๋ ๊ฒฌ๊ณ ํ๊ณ ๋ฐ์์ฑ์ด ๋ฐ์ด๋ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ง๋ค ์ ์์ต๋๋ค. ์ญ์๋ ฅ์ ๊ตฌํํ๊ณ ์ค๋ฅ ์ฒ๋ฆฌ ๋ฐ ๋ฆฌ์์ค ๊ด๋ฆฌ์ ๋ํ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ๋ฐ๋ฅด๋ฉด ๋ฐ์ดํฐ ์ฒ๋ฆฌ ํ์ดํ๋ผ์ธ์ ์ ๋ขฐ์ฑ๊ณผ ์ฑ๋ฅ์ ๋ณด์ฅํ ์ ์์ต๋๋ค. ์น ์ ํ๋ฆฌ์ผ์ด์ ์ด ๊ณ์ ๋ฐ์ ํ๊ณ ์ ์ ๋ ๋ณต์กํ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํจ์ ๋ฐ๋ผ Web Streams API๋ ์ ์ธ๊ณ ๊ฐ๋ฐ์๋ค์๊ฒ ํ์์ ์ธ ๋๊ตฌ๊ฐ ๋ ๊ฒ์ ๋๋ค.