์๋ฐ์คํฌ๋ฆฝํธ ์ดํฐ๋ ์ดํฐ ํฌํผ๊ฐ ์คํธ๋ฆฌ๋ฐ ๋ฐ์ดํฐ ์ฒ๋ฆฌ์์ ๋ฆฌ์์ค ๊ด๋ฆฌ๋ฅผ ์ด๋ป๊ฒ ํฅ์์ํค๋์ง ์์๋ณด์ธ์. ํจ์จ์ ์ด๊ณ ํ์ฅ ๊ฐ๋ฅํ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ํ ์ต์ ํ ๊ธฐ๋ฒ์ ๋ฐฐ์๋๋ค.
์๋ฐ์คํฌ๋ฆฝํธ ์ดํฐ๋ ์ดํฐ ํฌํผ ๋ฆฌ์์ค ๊ด๋ฆฌ: ์คํธ๋ฆผ ๋ฆฌ์์ค ์ต์ ํ
ํ๋ ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ๋ฐ์์๋ ๋ฐ์ดํฐ ์คํธ๋ฆผ์ ๋ค๋ฃจ๋ ์ผ์ด ๋น๋ฒํฉ๋๋ค. ๋์ฉ๋ ํ์ผ์ ์ฒ๋ฆฌํ๋ , ์ค์๊ฐ ๋ฐ์ดํฐ ํผ๋๋ฅผ ๋ค๋ฃจ๋ , API ์๋ต์ ๊ด๋ฆฌํ๋ , ์คํธ๋ฆผ ์ฒ๋ฆฌ ์ค ๋ฆฌ์์ค๋ฅผ ํจ์จ์ ์ผ๋ก ๊ด๋ฆฌํ๋ ๊ฒ์ ์ฑ๋ฅ๊ณผ ํ์ฅ์ฑ์ ๋งค์ฐ ์ค์ํฉ๋๋ค. ES2015์ ๋์ ๋๊ณ ๋น๋๊ธฐ ์ดํฐ๋ ์ดํฐ์ ์ ๋๋ ์ดํฐ๋ก ํฅ์๋ ์ดํฐ๋ ์ดํฐ ํฌํผ๋ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํ ๊ฐ๋ ฅํ ๋๊ตฌ๋ฅผ ์ ๊ณตํฉ๋๋ค.
์ดํฐ๋ ์ดํฐ์ ์ ๋๋ ์ดํฐ ์ดํดํ๊ธฐ
๋ฆฌ์์ค ๊ด๋ฆฌ์ ๋ํด ์์๋ณด๊ธฐ ์ ์, ์ดํฐ๋ ์ดํฐ์ ์ ๋๋ ์ดํฐ์ ๋ํด ๊ฐ๋จํ ๋ณต์ตํด ๋ณด๊ฒ ์ต๋๋ค.
์ดํฐ๋ ์ดํฐ๋ ์ํ์ค๋ฅผ ์ ์ํ๊ณ ๊ทธ ํญ๋ชฉ์ ํ ๋ฒ์ ํ๋์ฉ ์ ๊ทผํ๋ ๋ฉ์๋๋ฅผ ๊ฐ์ง ๊ฐ์ฒด์
๋๋ค. ์ด๋ ์ดํฐ๋ ์ดํฐ ํ๋กํ ์ฝ์ ๋ฐ๋ฅด๋ฉฐ, ์ด ํ๋กํ ์ฝ์ next() ๋ฉ์๋๋ฅผ ์๊ตฌํฉ๋๋ค. ์ด ๋ฉ์๋๋ value(์ํ์ค์ ๋ค์ ํญ๋ชฉ)์ done(์ํ์ค๊ฐ ์๋ฃ๋์๋์ง ์ฌ๋ถ๋ฅผ ๋ํ๋ด๋ ๋ถ๋ฆฌ์ธ ๊ฐ)์ด๋ผ๋ ๋ ๊ฐ์ง ์์ฑ์ ๊ฐ์ง ๊ฐ์ฒด๋ฅผ ๋ฐํํฉ๋๋ค.
์ ๋๋ ์ดํฐ๋ ์ผ์ ์ค์งํ๊ณ ์ฌ๊ฐํ ์ ์๋ ํน๋ณํ ํจ์๋ก, ์๊ฐ์ ๋ฐ๋ผ ์ผ๋ จ์ ๊ฐ์ ์์ฑํ ์ ์์ต๋๋ค. yield ํค์๋๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ์ ๋ฐํํ๊ณ ์คํ์ ์ผ์ ์ค์งํฉ๋๋ค. ์ ๋๋ ์ดํฐ์ next() ๋ฉ์๋๊ฐ ๋ค์ ํธ์ถ๋๋ฉด, ์คํ์ ์ค๋จ๋ ์ง์ ๋ถํฐ ์ฌ๊ฐ๋ฉ๋๋ค.
์์ :
function* numberGenerator(limit) {
for (let i = 0; i <= limit; i++) {
yield i;
}
}
const generator = numberGenerator(3);
console.log(generator.next()); // Output: { value: 0, done: false }
console.log(generator.next()); // Output: { value: 1, done: false }
console.log(generator.next()); // Output: { value: 2, done: false }
console.log(generator.next()); // Output: { value: 3, done: false }
console.log(generator.next()); // Output: { value: undefined, done: true }
์ดํฐ๋ ์ดํฐ ํฌํผ: ์คํธ๋ฆผ ์ฒ๋ฆฌ ๋จ์ํ
์ดํฐ๋ ์ดํฐ ํฌํผ๋ (๋๊ธฐ ๋ฐ ๋น๋๊ธฐ) ์ดํฐ๋ ์ดํฐ ํ๋กํ ํ์ ์์ ์ฌ์ฉํ ์ ์๋ ๋ฉ์๋์ ๋๋ค. ์ด๋ฅผ ํตํด ์ดํฐ๋ ์ดํฐ์ ๋ํ ์ผ๋ฐ์ ์ธ ์์ ์ ๊ฐ๊ฒฐํ๊ณ ์ ์ธ์ ์ธ ๋ฐฉ์์ผ๋ก ์ํํ ์ ์์ต๋๋ค. ์ด๋ฌํ ์์ ์๋ ๋งคํ, ํํฐ๋ง, ๋ฆฌ๋์ฑ ๋ฑ์ด ํฌํจ๋ฉ๋๋ค.
์ฃผ์ ์ดํฐ๋ ์ดํฐ ํฌํผ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
map(): ๊ฐ ์ดํฐ๋ ์ดํฐ ์์๋ฅผ ๋ณํํฉ๋๋ค.filter(): ์กฐ๊ฑด์ ๋ง์กฑํ๋ ์์๋ฅผ ์ ํํฉ๋๋ค.reduce(): ์์๋ค์ ๋จ์ผ ๊ฐ์ผ๋ก ๋์ ํฉ๋๋ค.take(): ์ดํฐ๋ ์ดํฐ์ ์ฒซ N๊ฐ ์์๋ฅผ ๊ฐ์ ธ์ต๋๋ค.drop(): ์ดํฐ๋ ์ดํฐ์ ์ฒซ N๊ฐ ์์๋ฅผ ๊ฑด๋๋๋๋ค.forEach(): ๊ฐ ์์์ ๋ํด ์ ๊ณต๋ ํจ์๋ฅผ ํ ๋ฒ์ฉ ์คํํฉ๋๋ค.toArray(): ๋ชจ๋ ์์๋ฅผ ๋ฐฐ์ด๋ก ์์งํฉ๋๋ค.
์๋ฐํ ๋งํด *์ดํฐ๋ ์ดํฐ*์ ๋ฉ์๋๊ฐ ์๋๋ผ ๊ธฐ๋ณธ *์ดํฐ๋ฌ๋ธ*์ ๋ฉ์๋์ด๊ธฐ ๋๋ฌธ์ ๊ธฐ์ ์ ์ผ๋ก *์ดํฐ๋ ์ดํฐ* ํฌํผ๋ ์๋์ง๋ง, Array.from()๊ณผ ๊ฐ์ ๋ฐฐ์ด ๋ฉ์๋๋ ์คํ๋ ๋ ๋ฌธ๋ฒ(...)๋ ์ดํฐ๋ ์ดํฐ๋ฅผ ๋ฐฐ์ด๋ก ๋ณํํ์ฌ ์ถ๊ฐ ์ฒ๋ฆฌ๋ฅผ ํ๋ ๋ฐ ํจ๊ณผ์ ์ผ๋ก ์ฌ์ฉ๋ ์ ์์ต๋๋ค. ๋ค๋ง ์ด ๊ฒฝ์ฐ ๋ชจ๋ ์์๋ฅผ ํ ๋ฒ์ ๋ฉ๋ชจ๋ฆฌ์ ๋ก๋ํด์ผ ํ๋ค๋ ์ ์ ์ธ์งํด์ผ ํฉ๋๋ค.
์ด๋ฌํ ํฌํผ๋ค์ ๋ ํจ์์ ์ด๊ณ ๊ฐ๋ ์ฑ ๋์ ์คํ์ผ์ ์คํธ๋ฆผ ์ฒ๋ฆฌ๋ฅผ ๊ฐ๋ฅํ๊ฒ ํฉ๋๋ค.
์คํธ๋ฆผ ์ฒ๋ฆฌ์์์ ๋ฆฌ์์ค ๊ด๋ฆฌ ๊ณผ์
๋ฐ์ดํฐ ์คํธ๋ฆผ์ ๋ค๋ฃฐ ๋, ๋ช ๊ฐ์ง ๋ฆฌ์์ค ๊ด๋ฆฌ ๊ณผ์ ๊ฐ ๋ฐ์ํฉ๋๋ค:
- ๋ฉ๋ชจ๋ฆฌ ์๋น: ๋์ฉ๋ ์คํธ๋ฆผ์ ์ฒ๋ฆฌํ ๋ ์ ์คํ๊ฒ ๋ค๋ฃจ์ง ์์ผ๋ฉด ๊ณผ๋ํ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ์ผ๋ก ์ด์ด์ง ์ ์์ต๋๋ค. ์ ์ฒด ์คํธ๋ฆผ์ ๋ฉ๋ชจ๋ฆฌ์ ๋ก๋ํ ํ ์ฒ๋ฆฌํ๋ ๊ฒ์ ์ข ์ข ๋นํ์ค์ ์ ๋๋ค.
- ํ์ผ ํธ๋ค: ํ์ผ์์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ ๋ ๋ฆฌ์์ค ๋์๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด ํ์ผ ํธ๋ค์ ์ ์ ํ๊ฒ ๋ซ๋ ๊ฒ์ด ํ์์ ์ ๋๋ค.
- ๋คํธ์ํฌ ์ฐ๊ฒฐ: ํ์ผ ํธ๋ค๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก, ๋ฆฌ์์ค๋ฅผ ํด์ ํ๊ณ ์ฐ๊ฒฐ ๊ณ ๊ฐ์ ๋ฐฉ์งํ๊ธฐ ์ํด ๋คํธ์ํฌ ์ฐ๊ฒฐ์ ๋ซ์์ผ ํฉ๋๋ค. ์ด๋ API๋ ์น ์์ผ์ผ๋ก ์์ ํ ๋ ํนํ ์ค์ํฉ๋๋ค.
- ๋์์ฑ: ๋์ ์คํธ๋ฆผ์ด๋ ๋ณ๋ ฌ ์ฒ๋ฆฌ๋ฅผ ๊ด๋ฆฌํ๋ฉด ๋ฆฌ์์ค ๊ด๋ฆฌ๊ฐ ๋ณต์กํด์ง ์ ์์ผ๋ฉฐ, ์ ์คํ ๋๊ธฐํ์ ์กฐ์จ์ด ํ์ํฉ๋๋ค.
- ์ค๋ฅ ์ฒ๋ฆฌ: ์คํธ๋ฆผ ์ฒ๋ฆฌ ์ค ์๊ธฐ์น ์์ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ฉด, ์ ์ ํ๊ฒ ์ฒ๋ฆฌ๋์ง ์์ ๊ฒฝ์ฐ ๋ฆฌ์์ค๊ฐ ์ผ๊ด์ฑ ์๋ ์ํ๋ก ๋จ์ ์ ์์ต๋๋ค. ์ ์ ํ ์ ๋ฆฌ๋ฅผ ๋ณด์ฅํ๊ธฐ ์ํด ๊ฐ๋ ฅํ ์ค๋ฅ ์ฒ๋ฆฌ๊ฐ ์ค์ํฉ๋๋ค.
์ดํฐ๋ ์ดํฐ ํฌํผ์ ๋ค๋ฅธ ์๋ฐ์คํฌ๋ฆฝํธ ๊ธฐ์ ์ ์ฌ์ฉํ์ฌ ์ด๋ฌํ ๊ณผ์ ๋ฅผ ํด๊ฒฐํ๋ ์ ๋ต์ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
์คํธ๋ฆผ ๋ฆฌ์์ค ์ต์ ํ ์ ๋ต
1. ์ง์ฐ ํ๊ฐ์ ์ ๋๋ ์ดํฐ
์ ๋๋ ์ดํฐ๋ ์ง์ฐ ํ๊ฐ(lazy evaluation)๋ฅผ ๊ฐ๋ฅํ๊ฒ ํ๋๋ฐ, ์ด๋ ๊ฐ์ด ํ์ํ ๋๋ง ์์ฑ๋๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค. ์ด๋ ๋์ฉ๋ ์คํธ๋ฆผ์ผ๋ก ์์ ํ ๋ ๋ฉ๋ชจ๋ฆฌ ์๋น๋ฅผ ํฌ๊ฒ ์ค์ผ ์ ์์ต๋๋ค. ์ดํฐ๋ ์ดํฐ ํฌํผ์ ๊ฒฐํฉํ๋ฉด ํ์์ ๋ฐ๋ผ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๋ ํจ์จ์ ์ธ ํ์ดํ๋ผ์ธ์ ๋ง๋ค ์ ์์ต๋๋ค.
์์ : ๋์ฉ๋ CSV ํ์ผ ์ฒ๋ฆฌ (Node.js ํ๊ฒฝ):
const fs = require('fs');
const readline = require('readline');
async function* csvLineGenerator(filePath) {
const fileStream = fs.createReadStream(filePath);
const rl = readline.createInterface({
input: fileStream,
crlfDelay: Infinity
});
try {
for await (const line of rl) {
yield line;
}
} finally {
// Ensure the file stream is closed, even in case of errors
fileStream.close();
}
}
async function processCSV(filePath) {
const lines = csvLineGenerator(filePath);
let processedCount = 0;
for await (const line of lines) {
// Process each line without loading the entire file into memory
const data = line.split(',');
console.log(`Processing: ${data[0]}`);
processedCount++;
// Simulate some processing delay
await new Promise(resolve => setTimeout(resolve, 10)); // Simulate I/O or CPU work
}
console.log(`Processed ${processedCount} lines.`);
}
// Example Usage
const filePath = 'large_data.csv'; // Replace with your actual file path
processCSV(filePath).catch(err => console.error("Error processing CSV:", err));
์ค๋ช :
csvLineGeneratorํจ์๋fs.createReadStream๊ณผreadline.createInterface๋ฅผ ์ฌ์ฉํ์ฌ CSV ํ์ผ์ ํ ์ค์ฉ ์ฝ์ต๋๋ค.yieldํค์๋๋ ๊ฐ ์ค์ด ์ฝํ ๋๋ง๋ค ํด๋น ์ค์ ๋ฐํํ๋ฉฐ, ๋ค์ ์ค์ด ์์ฒญ๋ ๋๊น์ง ์ ๋๋ ์ดํฐ๋ฅผ ์ผ์ ์ค์งํฉ๋๋ค.processCSVํจ์๋for await...of๋ฃจํ๋ฅผ ์ฌ์ฉํ์ฌ ์ค์ ๋ฐ๋ณตํ๋ฉฐ, ์ ์ฒด ํ์ผ์ ๋ฉ๋ชจ๋ฆฌ์ ๋ก๋ํ์ง ์๊ณ ๊ฐ ์ค์ ์ฒ๋ฆฌํฉ๋๋ค.- ์ ๋๋ ์ดํฐ์
finally๋ธ๋ก์ ์ฒ๋ฆฌ ์ค ์ค๋ฅ๊ฐ ๋ฐ์ํ๋๋ผ๋ ํ์ผ ์คํธ๋ฆผ์ด ๋ซํ๋๋ก ๋ณด์ฅํฉ๋๋ค. ์ด๋ ๋ฆฌ์์ค ๊ด๋ฆฌ์ *๋งค์ฐ ์ค์*ํฉ๋๋ค.fileStream.close()๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฆฌ์์ค๋ฅผ ๋ช ์์ ์ผ๋ก ์ ์ดํ ์ ์์ต๋๋ค. - ์ง์ฐ ํ๊ฐ์ ์ค์์ฑ์ ๊ธฐ์ฌํ๋ ์ค์ I/O ๋๋ CPU ๋ฐ์ด๋ ์์ ์ ๋ํ๋ด๊ธฐ ์ํด `setTimeout`์ ์ฌ์ฉํ ์๋ฎฌ๋ ์ด์ ๋ ์ฒ๋ฆฌ ์ง์ฐ์ด ํฌํจ๋์์ต๋๋ค.
2. ๋น๋๊ธฐ ์ดํฐ๋ ์ดํฐ
๋น๋๊ธฐ ์ดํฐ๋ ์ดํฐ(async iterators)๋ API ์๋ํฌ์ธํธ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฟผ๋ฆฌ์ ๊ฐ์ ๋น๋๊ธฐ ๋ฐ์ดํฐ ์์ค๋ก ์์ ํ๋๋ก ์ค๊ณ๋์์ต๋๋ค. ๋ฐ์ดํฐ๊ฐ ์ฌ์ฉ ๊ฐ๋ฅํด์ง๋ ๋๋ก ์ฒ๋ฆฌํ ์ ์๊ฒ ํ์ฌ ๋ธ๋กํน ์์ ์ ๋ฐฉ์งํ๊ณ ์๋ต์ฑ์ ํฅ์์ํต๋๋ค.
์์ : ๋น๋๊ธฐ ์ดํฐ๋ ์ดํฐ๋ฅผ ์ฌ์ฉํ์ฌ API์์ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ:
async function* apiDataGenerator(url) {
let page = 1;
while (true) {
const response = await fetch(`${url}?page=${page}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
if (data.length === 0) {
break; // No more data
}
for (const item of data) {
yield item;
}
page++;
// Simulate rate limiting to avoid overwhelming the server
await new Promise(resolve => setTimeout(resolve, 500));
}
}
async function processAPIdata(url) {
const dataStream = apiDataGenerator(url);
try {
for await (const item of dataStream) {
console.log("Processing item:", item);
// Process the item
}
} catch (error) {
console.error("Error processing API data:", error);
}
}
// Example usage
const apiUrl = 'https://example.com/api/data'; // Replace with your actual API endpoint
processAPIdata(apiUrl).catch(err => console.error("Overall error:", err));
์ค๋ช :
apiDataGeneratorํจ์๋ API ์๋ํฌ์ธํธ์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ฉฐ, ๊ฒฐ๊ณผ๋ฅผ ํ์ด์ง๋ค์ด์ ํฉ๋๋ค.awaitํค์๋๋ ๊ฐ API ์์ฒญ์ด ์๋ฃ๋ ํ ๋ค์ ์์ฒญ์ด ์ด๋ฃจ์ด์ง๋๋ก ๋ณด์ฅํฉ๋๋ค.yieldํค์๋๋ ๊ฐ ํญ๋ชฉ์ด ๊ฐ์ ธ์์ง ๋๋ง๋ค ๋ฐํํ๋ฉฐ, ๋ค์ ํญ๋ชฉ์ด ์์ฒญ๋ ๋๊น์ง ์ ๋๋ ์ดํฐ๋ฅผ ์ผ์ ์ค์งํฉ๋๋ค.- ์ฑ๊ณต์ ์ด์ง ์์ HTTP ์๋ต์ ํ์ธํ๊ธฐ ์ํด ์ค๋ฅ ์ฒ๋ฆฌ๊ฐ ํตํฉ๋์ด ์์ต๋๋ค.
- API ์๋ฒ์ ๊ณผ๋ถํ๊ฐ ๊ฑธ๋ฆฌ๋ ๊ฒ์ ๋ฐฉ์งํ๊ธฐ ์ํด
setTimeout์ ์ฌ์ฉํ์ฌ ์๋ ์ ํ์ ์๋ฎฌ๋ ์ด์ ํฉ๋๋ค. ์ด๋ API ํตํฉ์ *๋ชจ๋ฒ ์ฌ๋ก*์ ๋๋ค. - ์ด ์์ ์์๋ ๋คํธ์ํฌ ์ฐ๊ฒฐ์ด
fetchAPI์ ์ํด ์์์ ์ผ๋ก ๊ด๋ฆฌ๋๋ค๋ ์ ์ ์ ์ํ์ธ์. ๋ ๋ณต์กํ ์๋๋ฆฌ์ค(์: ์๊ตฌ์ ์ธ ์น ์์ผ ์ฌ์ฉ)์์๋ ๋ช ์์ ์ธ ์ฐ๊ฒฐ ๊ด๋ฆฌ๊ฐ ํ์ํ ์ ์์ต๋๋ค.
3. ๋์์ฑ ์ ํ
์คํธ๋ฆผ์ ๋์์ ์ฒ๋ฆฌํ ๋ ๋ฆฌ์์ค ๊ณผ๋ถํ๋ฅผ ํผํ๊ธฐ ์ํด ๋์ ์์ ์๋ฅผ ์ ํํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค. ์ธ๋งํฌ์ด๋ ์์ ํ์ ๊ฐ์ ๊ธฐ์ ์ ์ฌ์ฉํ์ฌ ๋์์ฑ์ ์ ์ดํ ์ ์์ต๋๋ค.
์์ : ์ธ๋งํฌ์ด๋ก ๋์์ฑ ์ ํํ๊ธฐ:
class Semaphore {
constructor(max) {
this.max = max;
this.count = 0;
this.waiting = [];
}
async acquire() {
if (this.count < this.max) {
this.count++;
return;
}
return new Promise(resolve => {
this.waiting.push(resolve);
});
}
release() {
this.count--;
if (this.waiting.length > 0) {
const resolve = this.waiting.shift();
resolve();
this.count++; // Increment the count back up for the released task
}
}
}
async function processItem(item, semaphore) {
await semaphore.acquire();
try {
console.log(`Processing item: ${item}`);
// Simulate some asynchronous operation
await new Promise(resolve => setTimeout(resolve, 200));
console.log(`Finished processing item: ${item}`);
} finally {
semaphore.release();
}
}
async function processStream(data, concurrency) {
const semaphore = new Semaphore(concurrency);
const promises = data.map(async item => {
await processItem(item, semaphore);
});
await Promise.all(promises);
console.log("All items processed.");
}
// Example usage
const data = Array.from({ length: 10 }, (_, i) => i + 1);
const concurrencyLevel = 3;
processStream(data, concurrencyLevel).catch(err => console.error("Error processing stream:", err));
์ค๋ช :
Semaphoreํด๋์ค๋ ๋์ ์์ ์๋ฅผ ์ ํํฉ๋๋ค.acquire()๋ฉ์๋๋ ํ๊ฐ๋ฅผ ๋ฐ์ ์ ์์ ๋๊น์ง ๋ธ๋กํนํฉ๋๋ค.release()๋ฉ์๋๋ ํ๊ฐ๋ฅผ ํด์ ํ์ฌ ๋ค๋ฅธ ์์ ์ด ์งํ๋ ์ ์๋๋ก ํฉ๋๋ค.processItem()ํจ์๋ ํญ๋ชฉ์ ์ฒ๋ฆฌํ๊ธฐ ์ ์ ํ๊ฐ๋ฅผ ํ๋ํ๊ณ ์ฒ๋ฆฌ ํ์ ํด์ ํฉ๋๋ค.finally๋ธ๋ก์ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋๋ผ๋ ํด์ ๋ฅผ *๋ณด์ฅ*ํฉ๋๋ค.processStream()ํจ์๋ ์ง์ ๋ ๋์์ฑ ์์ค์ผ๋ก ๋ฐ์ดํฐ ์คํธ๋ฆผ์ ์ฒ๋ฆฌํฉ๋๋ค.- ์ด ์์ ๋ ๋น๋๊ธฐ ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋์์ ๋ฆฌ์์ค ์ฌ์ฉ์ ์ ์ดํ๊ธฐ ์ํ ์ผ๋ฐ์ ์ธ ํจํด์ ๋ณด์ฌ์ค๋๋ค.
4. ์ค๋ฅ ์ฒ๋ฆฌ ๋ฐ ๋ฆฌ์์ค ์ ๋ฆฌ
๊ฐ๋ ฅํ ์ค๋ฅ ์ฒ๋ฆฌ๋ ์ค๋ฅ ๋ฐ์ ์ ๋ฆฌ์์ค๊ฐ ์ ๋๋ก ์ ๋ฆฌ๋๋๋ก ํ๋ ๋ฐ ํ์์ ์
๋๋ค. try...catch...finally ๋ธ๋ก์ ์ฌ์ฉํ์ฌ ์์ธ๋ฅผ ์ฒ๋ฆฌํ๊ณ finally ๋ธ๋ก์์ ๋ฆฌ์์ค๋ฅผ ํด์ ํ์ธ์. finally ๋ธ๋ก์ ์์ธ ๋ฐ์ ์ฌ๋ถ์ ๊ด๊ณ์์ด *ํญ์* ์คํ๋ฉ๋๋ค.
์์ : try...catch...finally๋ก ๋ฆฌ์์ค ์ ๋ฆฌ ๋ณด์ฅํ๊ธฐ:
const fs = require('fs');
async function processFile(filePath) {
let fileHandle = null;
try {
fileHandle = await fs.promises.open(filePath, 'r');
const stream = fileHandle.createReadStream();
for await (const chunk of stream) {
console.log(`Processing chunk: ${chunk.toString()}`);
// Process the chunk
}
} catch (error) {
console.error(`Error processing file: ${error}`);
// Handle the error
} finally {
if (fileHandle) {
try {
await fileHandle.close();
console.log('File handle closed successfully.');
} catch (closeError) {
console.error('Error closing file handle:', closeError);
}
}
}
}
// Example usage
const filePath = 'data.txt'; // Replace with your actual file path
// Create a dummy file for testing
fs.writeFileSync(filePath, 'This is some sample data.\nWith multiple lines.');
processFile(filePath).catch(err => console.error("Overall error:", err));
์ค๋ช :
processFile()ํจ์๋ ํ์ผ์ ์ด๊ณ , ๋ด์ฉ์ ์ฝ๊ณ , ๊ฐ ์ฒญํฌ๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค.try...catch...finally๋ธ๋ก์ ์ฒ๋ฆฌ ์ค ์ค๋ฅ๊ฐ ๋ฐ์ํ๋๋ผ๋ ํ์ผ ํธ๋ค์ด ๋ซํ๋๋ก ๋ณด์ฅํฉ๋๋ค.finally๋ธ๋ก์ ํ์ผ ํธ๋ค์ด ์ด๋ ค ์๋์ง ํ์ธํ๊ณ ํ์ํ ๊ฒฝ์ฐ ๋ซ์ต๋๋ค. ๋ํ ๋ซ๋ ์์ ์์ฒด์์ ๋ฐ์ํ ์ ์๋ ์ ์ฌ์ ์ค๋ฅ๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํด ์์ฒดtry...catch๋ธ๋ก์ ํฌํจํฉ๋๋ค. ์ด ์ค์ฒฉ๋ ์ค๋ฅ ์ฒ๋ฆฌ๋ ์ ๋ฆฌ ์์ ์ด ๊ฒฌ๊ณ ํ๊ฒ ์ด๋ฃจ์ด์ง๋๋ก ํ๋ ๋ฐ ์ค์ํฉ๋๋ค.- ์ด ์์ ๋ ๋ฆฌ์์ค ๋์๋ฅผ ๋ฐฉ์งํ๊ณ ์ ํ๋ฆฌ์ผ์ด์ ์ ์์ ์ฑ์ ๋ณด์ฅํ๊ธฐ ์ํ ์ ์์ ์ธ ๋ฆฌ์์ค ์ ๋ฆฌ์ ์ค์์ฑ์ ๋ณด์ฌ์ค๋๋ค.
5. ๋ณํ ์คํธ๋ฆผ ์ฌ์ฉํ๊ธฐ
๋ณํ ์คํธ๋ฆผ์ ์ฌ์ฉํ๋ฉด ๋ฐ์ดํฐ๊ฐ ์คํธ๋ฆผ์ ํต๊ณผํ ๋ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ์ฌ ํ ํ์์์ ๋ค๋ฅธ ํ์์ผ๋ก ๋ณํํ ์ ์์ต๋๋ค. ์์ถ, ์ํธํ ๋๋ ๋ฐ์ดํฐ ์ ํจ์ฑ ๊ฒ์ฌ์ ๊ฐ์ ์์ ์ ํนํ ์ ์ฉํฉ๋๋ค.
์์ : zlib์ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ ์คํธ๋ฆผ ์์ถํ๊ธฐ (Node.js ํ๊ฒฝ):
const fs = require('fs');
const zlib = require('zlib');
const { pipeline } = require('stream');
const { promisify } = require('util');
const pipe = promisify(pipeline);
async function compressFile(inputPath, outputPath) {
const gzip = zlib.createGzip();
const source = fs.createReadStream(inputPath);
const destination = fs.createWriteStream(outputPath);
try {
await pipe(source, gzip, destination);
console.log('Compression completed.');
} catch (err) {
console.error('An error occurred during compression:', err);
}
}
// Example Usage
const inputFilePath = 'large_input.txt';
const outputFilePath = 'large_input.txt.gz';
// Create a large dummy file for testing
const largeData = Array.from({ length: 1000000 }, (_, i) => `Line ${i}\n`).join('');
fs.writeFileSync(inputFilePath, largeData);
compressFile(inputFilePath, outputFilePath).catch(err => console.error("Overall error:", err));
์ค๋ช :
compressFile()ํจ์๋zlib.createGzip()์ ์ฌ์ฉํ์ฌ gzip ์์ถ ์คํธ๋ฆผ์ ์์ฑํฉ๋๋ค.pipeline()ํจ์๋ ์์ค ์คํธ๋ฆผ(์ ๋ ฅ ํ์ผ), ๋ณํ ์คํธ๋ฆผ(gzip ์์ถ), ๋์ ์คํธ๋ฆผ(์ถ๋ ฅ ํ์ผ)์ ์ฐ๊ฒฐํฉ๋๋ค. ์ด๋ ์คํธ๋ฆผ ๊ด๋ฆฌ์ ์ค๋ฅ ์ ํ๋ฅผ ๋จ์ํํฉ๋๋ค.- ์์ถ ๊ณผ์ ์์ ๋ฐ์ํ๋ ๋ชจ๋ ์ค๋ฅ๋ฅผ ํฌ์ฐฉํ๊ธฐ ์ํด ์ค๋ฅ ์ฒ๋ฆฌ๊ฐ ํตํฉ๋์ด ์์ต๋๋ค.
- ๋ณํ ์คํธ๋ฆผ์ ๋ชจ๋์์ ํจ์จ์ ์ธ ๋ฐฉ์์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๋ ๊ฐ๋ ฅํ ๋ฐฉ๋ฒ์ ๋๋ค.
pipelineํจ์๋ ํ๋ก์ธ์ค ์ค ์ค๋ฅ๊ฐ ๋ฐ์ํ ๊ฒฝ์ฐ ์ ์ ํ ์ ๋ฆฌ(์คํธ๋ฆผ ๋ซ๊ธฐ)๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค. ์ด๋ ์๋ ์คํธ๋ฆผ ํ์ดํ์ ๋นํด ์ค๋ฅ ์ฒ๋ฆฌ๋ฅผ ์๋นํ ๋จ์ํํฉ๋๋ค.
์๋ฐ์คํฌ๋ฆฝํธ ์คํธ๋ฆผ ๋ฆฌ์์ค ์ต์ ํ๋ฅผ ์ํ ๋ชจ๋ฒ ์ฌ๋ก
- ์ง์ฐ ํ๊ฐ ์ฌ์ฉ: ์ ๋๋ ์ดํฐ์ ๋น๋๊ธฐ ์ดํฐ๋ ์ดํฐ๋ฅผ ์ฌ์ฉํ์ฌ ํ์์ ๋ฐ๋ผ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๊ณ ๋ฉ๋ชจ๋ฆฌ ์๋น๋ฅผ ์ต์ํํ์ธ์.
- ๋์์ฑ ์ ํ: ๋ฆฌ์์ค ๊ณผ๋ถํ๋ฅผ ํผํ๊ธฐ ์ํด ๋์ ์์ ์๋ฅผ ์ ์ดํ์ธ์.
- ์ ์์ ์ธ ์ค๋ฅ ์ฒ๋ฆฌ:
try...catch...finally๋ธ๋ก์ ์ฌ์ฉํ์ฌ ์์ธ๋ฅผ ์ฒ๋ฆฌํ๊ณ ์ ์ ํ ๋ฆฌ์์ค ์ ๋ฆฌ๋ฅผ ๋ณด์ฅํ์ธ์. - ๋ช ์์ ์ผ๋ก ๋ฆฌ์์ค ๋ซ๊ธฐ: ํ์ผ ํธ๋ค, ๋คํธ์ํฌ ์ฐ๊ฒฐ ๋ฐ ๊ธฐํ ๋ฆฌ์์ค๊ฐ ๋ ์ด์ ํ์ํ์ง ์์ ๋ ๋ซํ๋๋ก ํ์ธ์.
- ๋ฆฌ์์ค ์ฌ์ฉ๋ ๋ชจ๋ํฐ๋ง: ๋๊ตฌ๋ฅผ ์ฌ์ฉํ์ฌ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋, CPU ์ฌ์ฉ๋ ๋ฐ ๊ธฐํ ๋ฆฌ์์ค ๋ฉํธ๋ฆญ์ ๋ชจ๋ํฐ๋งํ์ฌ ์ ์ฌ์ ์ธ ๋ณ๋ชฉ ํ์์ ์๋ณํ์ธ์.
- ์ฌ๋ฐ๋ฅธ ๋๊ตฌ ์ ํ: ํน์ ์คํธ๋ฆผ ์ฒ๋ฆฌ ์๊ตฌ์ ๋ง๋ ์ ์ ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ํ๋ ์์ํฌ๋ฅผ ์ ํํ์ธ์. ์๋ฅผ ๋ค์ด, ๋ ๊ณ ๊ธ ์คํธ๋ฆผ ์กฐ์ ๊ธฐ๋ฅ์ ์ํด Highland.js๋ RxJS์ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฌ์ฉ์ ๊ณ ๋ คํด ๋ณด์ธ์.
- ์ญ์(Backpressure) ๊ณ ๋ ค: ์์ฐ์๊ฐ ์๋น์๋ณด๋ค ํจ์ฌ ๋น ๋ฅธ ์คํธ๋ฆผ์ผ๋ก ์์ ํ ๋, ์๋น์๊ฐ ์๋๋นํ๋ ๊ฒ์ ๋ฐฉ์งํ๊ธฐ ์ํด ์ญ์ ๋ฉ์ปค๋์ฆ์ ๊ตฌํํ์ธ์. ์ฌ๊ธฐ์๋ ๋ฐ์ดํฐ ๋ฒํผ๋ง์ด๋ ๋ฐ์ํ ์คํธ๋ฆผ๊ณผ ๊ฐ์ ๊ธฐ์ ์ฌ์ฉ์ด ํฌํจ๋ ์ ์์ต๋๋ค.
- ์ฝ๋ ํ๋กํ์ผ๋ง: ํ๋กํ์ผ๋ง ๋๊ตฌ๋ฅผ ์ฌ์ฉํ์ฌ ์คํธ๋ฆผ ์ฒ๋ฆฌ ํ์ดํ๋ผ์ธ์ ์ฑ๋ฅ ๋ณ๋ชฉ ํ์์ ์๋ณํ์ธ์. ์ด๋ ์ฝ๋๋ฅผ ์ต๋ ํจ์จ๋ก ์ต์ ํํ๋ ๋ฐ ๋์์ด ๋ ์ ์์ต๋๋ค.
- ๋จ์ ํ ์คํธ ์์ฑ: ์คํธ๋ฆผ ์ฒ๋ฆฌ ์ฝ๋๋ฅผ ์ฒ ์ ํ ํ ์คํธํ์ฌ ์ค๋ฅ ์กฐ๊ฑด์ ํฌํจํ ๋ค์ํ ์๋๋ฆฌ์ค๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ ์ฒ๋ฆฌํ๋์ง ํ์ธํ์ธ์.
- ์ฝ๋ ๋ฌธ์ํ: ์คํธ๋ฆผ ์ฒ๋ฆฌ ๋ก์ง์ ๋ช ํํ๊ฒ ๋ฌธ์ํํ์ฌ ๋ค๋ฅธ ์ฌ๋๋ค(๊ทธ๋ฆฌ๊ณ ๋ฏธ๋์ ์์ )์ด ์ดํดํ๊ณ ์ ์ง ๊ด๋ฆฌํ๊ธฐ ์ฝ๋๋ก ๋ง๋์ธ์.
๊ฒฐ๋ก
ํจ์จ์ ์ธ ๋ฆฌ์์ค ๊ด๋ฆฌ๋ ๋ฐ์ดํฐ ์คํธ๋ฆผ์ ์ฒ๋ฆฌํ๋ ํ์ฅ ๊ฐ๋ฅํ๊ณ ์ฑ๋ฅ์ด ๋ฐ์ด๋ ์๋ฐ์คํฌ๋ฆฝํธ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ๋ ๋ฐ ๋งค์ฐ ์ค์ํฉ๋๋ค. ์ดํฐ๋ ์ดํฐ ํฌํผ, ์ ๋๋ ์ดํฐ, ๋น๋๊ธฐ ์ดํฐ๋ ์ดํฐ ๋ฐ ๊ธฐํ ๊ธฐ์ ์ ํ์ฉํ์ฌ ๋ฉ๋ชจ๋ฆฌ ์๋น๋ฅผ ์ต์ํํ๊ณ , ๋ฆฌ์์ค ๋์๋ฅผ ๋ฐฉ์งํ๋ฉฐ, ์ค๋ฅ๋ฅผ ์ ์์ ์ผ๋ก ์ฒ๋ฆฌํ๋ ๊ฐ๋ ฅํ๊ณ ํจ์จ์ ์ธ ์คํธ๋ฆผ ์ฒ๋ฆฌ ํ์ดํ๋ผ์ธ์ ๋ง๋ค ์ ์์ต๋๋ค. ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ฆฌ์์ค ์ฌ์ฉ๋์ ๋ชจ๋ํฐ๋งํ๊ณ ์ฝ๋๋ฅผ ํ๋กํ์ผ๋งํ์ฌ ์ ์ฌ์ ์ธ ๋ณ๋ชฉ ํ์์ ์๋ณํ๊ณ ์ฑ๋ฅ์ ์ต์ ํํ๋ ๊ฒ์ ์์ง ๋ง์ธ์. ์ ๊ณต๋ ์์ ๋ Node.js์ ๋ธ๋ผ์ฐ์ ํ๊ฒฝ ๋ชจ๋์์ ์ด๋ฌํ ๊ฐ๋ ์ ์ค์ ์ ์ธ ์ ์ฉ์ ๋ณด์ฌ์ฃผ๋ฏ๋ก, ๊ด๋ฒ์ํ ์ค์ ์๋๋ฆฌ์ค์ ์ด๋ฌํ ๊ธฐ์ ์ ์ ์ฉํ ์ ์์ต๋๋ค.