๋ช ์์ ๋ฆฌ์์ค ๊ด๋ฆฌ๋ก JavaScript ์ ํ๋ฆฌ์ผ์ด์ ์ ์์ ์ฑ๊ณผ ์ฑ๋ฅ์ ํฅ์์ํค๋ ๋ฐฉ๋ฒ์ ๋ฐฐ์ฐ์ธ์. 'using' ์ ์ธ, WeakRef ๋ฑ์ ์ฌ์ฉํ ์๋ ์ ๋ฆฌ ๊ธฐ์ ๋ก ๊ฐ๋ ฅํ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ์ธ์.
JavaScript ๋ช ์์ ๋ฆฌ์์ค ๊ด๋ฆฌ: ์ ๋ฆฌ ์๋ํ ๋ง์คํฐํ๊ธฐ
JavaScript ๊ฐ๋ฐ ์ธ๊ณ์์ ํจ์จ์ ์ธ ๋ฆฌ์์ค ๊ด๋ฆฌ๋ ๊ฒฌ๊ณ ํ๊ณ ์ฑ๋ฅ ์ข์ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ๋ ๋ฐ ๋งค์ฐ ์ค์ํฉ๋๋ค. JavaScript์ ๊ฐ๋น์ง ์ปฌ๋ ํฐ(GC)๋ ๋ ์ด์ ์ ๊ทผํ ์ ์๋ ๊ฐ์ฒด๊ฐ ์ฐจ์งํ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์๋์ผ๋ก ํ์ํ์ง๋ง, GC์๋ง ์์กดํ๋ฉด ์์ธก ๋ถ๊ฐ๋ฅํ ๋์๊ณผ ๋ฆฌ์์ค ๋์๋ก ์ด์ด์ง ์ ์์ต๋๋ค. ๋ฐ๋ก ์ด ์ง์ ์์ ๋ช ์์ ๋ฆฌ์์ค ๊ด๋ฆฌ๊ฐ ํ์ํฉ๋๋ค. ๋ช ์์ ๋ฆฌ์์ค ๊ด๋ฆฌ๋ ๊ฐ๋ฐ์์๊ฒ ๋ฆฌ์์ค์ ์๋ช ์ฃผ๊ธฐ์ ๋ํ ๋ ํฐ ์ ์ด๊ถ์ ๋ถ์ฌํ์ฌ ์๊ธฐ์ ์ ํ ์ ๋ฆฌ๋ฅผ ๋ณด์ฅํ๊ณ ์ ์ฌ์ ์ธ ๋ฌธ์ ๋ฅผ ์๋ฐฉํฉ๋๋ค.
๋ช ์์ ๋ฆฌ์์ค ๊ด๋ฆฌ์ ํ์์ฑ ์ดํดํ๊ธฐ
JavaScript์ ๊ฐ๋น์ง ์ปฌ๋ ์ ์ ๊ฐ๋ ฅํ ๋ฉ์ปค๋์ฆ์ด์ง๋ง, ํญ์ ๊ฒฐ์ ์ ์ธ ๊ฒ์ ์๋๋๋ค. GC๋ ์ฃผ๊ธฐ์ ์ผ๋ก ์คํ๋๋ฉฐ, ์ ํํ ์คํ ์์ ์ ์์ธกํ ์ ์์ต๋๋ค. ์ด๋ ๋ค์๊ณผ ๊ฐ์ด ์ ์ํ๊ฒ ํด์ ํด์ผ ํ๋ ๋ฆฌ์์ค๋ฅผ ๋ค๋ฃฐ ๋ ๋ฌธ์ ๋ฅผ ์ผ์ผํฌ ์ ์์ต๋๋ค:
- ํ์ผ ํธ๋ค: ํ์ผ ํธ๋ค์ ์ด์ด๋๋ฉด ์์คํ ๋ฆฌ์์ค๋ฅผ ๊ณ ๊ฐ์ํค๊ณ ๋ค๋ฅธ ํ๋ก์ธ์ค๊ฐ ํ์ผ์ ์ ๊ทผํ๋ ๊ฒ์ ๋ง์ ์ ์์ต๋๋ค.
- ๋คํธ์ํฌ ์ฐ๊ฒฐ: ๋ซํ์ง ์์ ๋คํธ์ํฌ ์ฐ๊ฒฐ์ ์๋ฒ ๋ฆฌ์์ค๋ฅผ ์๋ชจํ๊ณ ์ฐ๊ฒฐ ์ค๋ฅ๋ก ์ด์ด์ง ์ ์์ต๋๋ค.
- ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ: ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ์ ๋๋ฌด ์ค๋ ์ ์งํ๋ฉด ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ฆฌ์์ค์ ๋ถ๋ด์ ์ฃผ๊ณ ์ฟผ๋ฆฌ ์ฑ๋ฅ์ ์ ํ์ํฌ ์ ์์ต๋๋ค.
- ์ด๋ฒคํธ ๋ฆฌ์ค๋: ์ด๋ฒคํธ ๋ฆฌ์ค๋๋ฅผ ์ ๊ฑฐํ์ง ์์ผ๋ฉด ๋ฉ๋ชจ๋ฆฌ ๋์์ ์๊ธฐ์น ์์ ๋์์ด ๋ฐ์ํ ์ ์์ต๋๋ค.
- ํ์ด๋จธ: ์ทจ์๋์ง ์์ ํ์ด๋จธ๋ ๋ฌดํ์ ๊ณ์ ์คํ๋์ด ๋ฆฌ์์ค๋ฅผ ์๋ชจํ๊ณ ์ ์ฌ์ ์ผ๋ก ์ค๋ฅ๋ฅผ ์ผ์ผํฌ ์ ์์ต๋๋ค.
- ์ธ๋ถ ํ๋ก์ธ์ค: ์์ ํ๋ก์ธ์ค๋ฅผ ์์ํ ๋ ํ์ผ ๋์คํฌ๋ฆฝํฐ์ ๊ฐ์ ๋ฆฌ์์ค๋ ๋ช ์์ ์ธ ์ ๋ฆฌ๊ฐ ํ์ํ ์ ์์ต๋๋ค.
๋ช ์์ ๋ฆฌ์์ค ๊ด๋ฆฌ๋ ๊ฐ๋น์ง ์ปฌ๋ ํฐ ์คํ ์์ ๊ณผ ๊ด๊ณ์์ด ์ด๋ฌํ ๋ฆฌ์์ค๊ฐ ์ ์ํ๊ฒ ํด์ ๋๋๋ก ๋ณด์ฅํ๋ ๋ฐฉ๋ฒ์ ์ ๊ณตํฉ๋๋ค. ์ด๋ฅผ ํตํด ๊ฐ๋ฐ์๋ ๋ฆฌ์์ค๊ฐ ๋ ์ด์ ํ์ํ์ง ์์ ๋ ์คํ๋ ์ ๋ฆฌ ๋ก์ง์ ์ ์ํ์ฌ ๋ฆฌ์์ค ๋์๋ฅผ ๋ฐฉ์งํ๊ณ ์ ํ๋ฆฌ์ผ์ด์ ์์ ์ฑ์ ํฅ์์ํฌ ์ ์์ต๋๋ค.
๋ฆฌ์์ค ๊ด๋ฆฌ์ ์ ํต์ ์ธ ์ ๊ทผ ๋ฐฉ์
์ต์ ๋ช ์์ ๋ฆฌ์์ค ๊ด๋ฆฌ ๊ธฐ๋ฅ์ด ๋ฑ์ฅํ๊ธฐ ์ ์ ๊ฐ๋ฐ์๋ค์ JavaScript์์ ๋ฆฌ์์ค๋ฅผ ๊ด๋ฆฌํ๊ธฐ ์ํด ๋ช ๊ฐ์ง ์ผ๋ฐ์ ์ธ ๊ธฐ์ ์ ์์กดํ์ต๋๋ค:
1. try...finally
๋ธ๋ก
try...finally
๋ธ๋ก์ try
๋ธ๋ก์์ ์์ธ ๋ฐ์ ์ฌ๋ถ์ ๊ด๊ณ์์ด finally
๋ธ๋ก์ ์ฝ๋ ์คํ์ ๋ณด์ฅํ๋ ๊ธฐ๋ณธ์ ์ธ ์ ์ด ํ๋ฆ ๊ตฌ์กฐ์
๋๋ค. ์ด๋ก ์ธํด ์ ๋ฆฌ ์ฝ๋๊ฐ ํญ์ ์คํ๋๋๋ก ํ๋ ์ ๋ขฐํ ์ ์๋ ๋ฐฉ๋ฒ์
๋๋ค.
์์ :
function processFile(filePath) {
let fileHandle;
try {
fileHandle = fs.openSync(filePath, 'r');
// ํ์ผ ์ฒ๋ฆฌ
const data = fs.readFileSync(fileHandle);
console.log(data.toString());
} finally {
if (fileHandle) {
fs.closeSync(fileHandle);
console.log('ํ์ผ ํธ๋ค์ด ๋ซํ์ต๋๋ค.');
}
}
}
์ด ์์ ์์ finally
๋ธ๋ก์ ํ์ผ ์ฒ๋ฆฌ ์ค ์ค๋ฅ๊ฐ ๋ฐ์ํ๋๋ผ๋ ํ์ผ ํธ๋ค์ด ๋ซํ๋๋ก ๋ณด์ฅํฉ๋๋ค. ํจ๊ณผ์ ์ด๊ธด ํ์ง๋ง, try...finally
๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ํนํ ์ฌ๋ฌ ๋ฆฌ์์ค๋ฅผ ๋ค๋ฃฐ ๋ ์ฅํฉํ๊ณ ๋ฐ๋ณต์ ์ผ ์ ์์ต๋๋ค.
2. dispose
๋๋ close
๋ฉ์๋ ๊ตฌํ
๋ ๋ค๋ฅธ ์ผ๋ฐ์ ์ธ ์ ๊ทผ ๋ฐฉ์์ ๋ฆฌ์์ค๋ฅผ ๊ด๋ฆฌํ๋ ๊ฐ์ฒด์ dispose
๋๋ close
๋ฉ์๋๋ฅผ ์ ์ํ๋ ๊ฒ์
๋๋ค. ์ด ๋ฉ์๋๋ ๋ฆฌ์์ค์ ๋ํ ์ ๋ฆฌ ๋ก์ง์ ์บก์ํํฉ๋๋ค.
์์ :
class DatabaseConnection {
constructor(connectionString) {
this.connection = connectToDatabase(connectionString);
}
query(sql) {
return this.connection.query(sql);
}
close() {
this.connection.close();
console.log('๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ์ด ๋ซํ์ต๋๋ค.');
}
}
// ์ฌ์ฉ ์:
const db = new DatabaseConnection('your_connection_string');
try {
const results = db.query('SELECT * FROM users');
console.log(results);
} finally {
db.close();
}
์ด ์ ๊ทผ ๋ฐฉ์์ ๋ฆฌ์์ค๋ฅผ ๊ด๋ฆฌํ๋ ๋ช
ํํ๊ณ ์บก์ํ๋ ๋ฐฉ๋ฒ์ ์ ๊ณตํฉ๋๋ค. ๊ทธ๋ฌ๋ ์ด๋ ๊ฐ๋ฐ์๊ฐ ๋ฆฌ์์ค๊ฐ ๋ ์ด์ ํ์ํ์ง ์์ ๋ dispose
๋๋ close
๋ฉ์๋๋ฅผ ํธ์ถํ๋ ๊ฒ์ ๊ธฐ์ตํด์ผ ํ๋ค๋ ์ ์ ์์กดํฉ๋๋ค. ๋ง์ฝ ๋ฉ์๋๊ฐ ํธ์ถ๋์ง ์์ผ๋ฉด ๋ฆฌ์์ค๋ ๊ณ์ ์ด๋ ค ์๊ฒ ๋์ด ์ ์ฌ์ ์ผ๋ก ๋ฆฌ์์ค ๋์๋ก ์ด์ด์ง ์ ์์ต๋๋ค.
์ต์ ๋ช ์์ ๋ฆฌ์์ค ๊ด๋ฆฌ ๊ธฐ๋ฅ
์ต์ JavaScript๋ ๋ฆฌ์์ค ๊ด๋ฆฌ๋ฅผ ๋จ์ํํ๊ณ ์๋ํํ์ฌ ๊ฒฌ๊ณ ํ๊ณ ์ ๋ขฐํ ์ ์๋ ์ฝ๋๋ฅผ ๋ ์ฝ๊ฒ ์์ฑํ ์ ์๋๋ก ํ๋ ๋ช ๊ฐ์ง ๊ธฐ๋ฅ์ ๋์ ํ์ต๋๋ค. ์ด๋ฌํ ๊ธฐ๋ฅ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
1. using
์ ์ธ
using
์ ์ธ์ JavaScript์ ์๋ก์ด ๊ธฐ๋ฅ(์ต์ ๋ฒ์ ์ Node.js ๋ฐ ๋ธ๋ผ์ฐ์ ์์ ์ฌ์ฉ ๊ฐ๋ฅ)์ผ๋ก, ๋ฆฌ์์ค๋ฅผ ์ ์ธ์ ์ผ๋ก ๊ด๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ์ ๊ณตํฉ๋๋ค. ์ด๋ ๊ฐ์ฒด๊ฐ ์ค์ฝํ๋ฅผ ๋ฒ์ด๋ ๋ ์๋์ผ๋ก ํด๋น ๊ฐ์ฒด์ Symbol.dispose
๋๋ Symbol.asyncDispose
๋ฉ์๋๋ฅผ ํธ์ถํฉ๋๋ค.
using
์ ์ธ์ ์ฌ์ฉํ๋ ค๋ฉด ๊ฐ์ฒด๋ Symbol.dispose
(๋๊ธฐ์ ์ ๋ฆฌ์ฉ) ๋๋ Symbol.asyncDispose
(๋น๋๊ธฐ์ ์ ๋ฆฌ์ฉ) ๋ฉ์๋๋ฅผ ๊ตฌํํด์ผ ํฉ๋๋ค. ์ด ๋ฉ์๋๋ค์ ๋ฆฌ์์ค์ ๋ํ ์ ๋ฆฌ ๋ก์ง์ ํฌํจํฉ๋๋ค.
์์ (๋๊ธฐ์ ์ ๋ฆฌ):
class FileWrapper {
constructor(filePath) {
this.filePath = filePath;
this.fileHandle = fs.openSync(filePath, 'r+');
}
[Symbol.dispose]() {
fs.closeSync(this.fileHandle);
console.log(`${this.filePath}์ ํ์ผ ํธ๋ค์ด ๋ซํ์ต๋๋ค`);
}
read() {
return fs.readFileSync(this.fileHandle).toString();
}
}
{
using file = new FileWrapper('my_file.txt');
console.log(file.read());
// 'file'์ด ์ค์ฝํ๋ฅผ ๋ฒ์ด๋ ๋ ํ์ผ ํธ๋ค์ด ์๋์ผ๋ก ๋ซํ๋๋ค.
}
์ด ์์ ์์ using
์ ์ธ์ file
๊ฐ์ฒด๊ฐ ์ค์ฝํ๋ฅผ ๋ฒ์ด๋ ๋ ํ์ผ ํธ๋ค์ด ์๋์ผ๋ก ๋ซํ๋๋ก ๋ณด์ฅํฉ๋๋ค. Symbol.dispose
๋ฉ์๋๊ฐ ์๋ฌต์ ์ผ๋ก ํธ์ถ๋์ด ์๋ ์ ๋ฆฌ ์ฝ๋๊ฐ ํ์ ์๊ฒ ๋ฉ๋๋ค. ์ค์ฝํ๋ ์ค๊ดํธ {}๋ก ์์ฑ๋ฉ๋๋ค. ์ค์ฝํ๊ฐ ์์ฑ๋์ง ์์ผ๋ฉด `file` ๊ฐ์ฒด๋ ๊ณ์ ์กด์ฌํ๊ฒ ๋ฉ๋๋ค.
์์ (๋น๋๊ธฐ์ ์ ๋ฆฌ):
const fsPromises = require('fs').promises;
class AsyncFileWrapper {
constructor(filePath) {
this.filePath = filePath;
this.fileHandle = null;
}
async open() {
this.fileHandle = await fsPromises.open(this.filePath, 'r+');
}
async [Symbol.asyncDispose]() {
if (this.fileHandle) {
await this.fileHandle.close();
console.log(`${this.filePath}์ ๋น๋๊ธฐ ํ์ผ ํธ๋ค์ด ๋ซํ์ต๋๋ค`);
}
}
async read() {
const buffer = await fsPromises.readFile(this.fileHandle);
return buffer.toString();
}
}
async function main() {
{
const file = new AsyncFileWrapper('my_async_file.txt');
await file.open();
using a = file; // ๋น๋๊ธฐ ์ปจํ
์คํธ๊ฐ ํ์ํฉ๋๋ค.
console.log(await file.read());
// 'file'์ด ์ค์ฝํ๋ฅผ ๋ฒ์ด๋ ๋ ํ์ผ ํธ๋ค์ด ๋น๋๊ธฐ์ ์ผ๋ก ์๋์ผ๋ก ๋ซํ๋๋ค.
}
}
main();
์ด ์์ ๋ Symbol.asyncDispose
๋ฉ์๋๋ฅผ ์ฌ์ฉํ ๋น๋๊ธฐ์ ์ ๋ฆฌ๋ฅผ ๋ณด์ฌ์ค๋๋ค. using
์ ์ธ์ ๋ค์์ผ๋ก ์งํํ๊ธฐ ์ ์ ๋น๋๊ธฐ ์ ๋ฆฌ ์์
์ ์๋ฃ๋ฅผ ์๋์ผ๋ก ๊ธฐ๋ค๋ฆฝ๋๋ค.
2. WeakRef
์ FinalizationRegistry
WeakRef
์ FinalizationRegistry
๋ ๊ฐ์ฒด ์๋ฉธ์ ์ถ์ ํ๊ณ ๊ฐ์ฒด๊ฐ ๊ฐ๋น์ง ์ปฌ๋ ์
๋ ๋ ์ ๋ฆฌ ์์
์ ์ํํ๋ ๋ฉ์ปค๋์ฆ์ ์ ๊ณตํ๊ธฐ ์ํด ํจ๊ป ์๋ํ๋ ๋ ๊ฐ์ง ๊ฐ๋ ฅํ ๊ธฐ๋ฅ์
๋๋ค.
WeakRef
:WeakRef
๋ ๊ฐ๋ฆฌํค๋ ๊ฐ์ฒด๋ฅผ ๊ฐ๋น์ง ์ปฌ๋ ํฐ๊ฐ ํ์ํ๋ ๊ฒ์ ๋ง์ง ์๋ ํน๋ณํ ์ ํ์ ์ฐธ์กฐ์ ๋๋ค. ๊ฐ์ฒด๊ฐ ๊ฐ๋น์ง ์ปฌ๋ ์ ๋๋ฉดWeakRef
๋ ๋น๊ฒ ๋ฉ๋๋ค.FinalizationRegistry
:FinalizationRegistry
๋ ๊ฐ์ฒด๊ฐ ๊ฐ๋น์ง ์ปฌ๋ ์ ๋ ๋ ์คํ๋ ์ฝ๋ฐฑ ํจ์๋ฅผ ๋ฑ๋กํ ์ ์๊ฒ ํด์ฃผ๋ ๋ ์ง์คํธ๋ฆฌ์ ๋๋ค. ์ฝ๋ฐฑ ํจ์๋ ๊ฐ์ฒด๋ฅผ ๋ฑ๋กํ ๋ ์ ๊ณตํ ํ ํฐ๊ณผ ํจ๊ป ํธ์ถ๋ฉ๋๋ค.
์ด๋ฌํ ๊ธฐ๋ฅ๋ค์ ๊ฐ์ฒด์ ์๋ช ์ฃผ๊ธฐ๋ฅผ ์ง์ ์ ์ดํ ์ ์๋ ์ธ๋ถ ์์คํ ์ด๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ๊ด๋ฆฌํ๋ ๋ฆฌ์์ค๋ฅผ ๋ค๋ฃฐ ๋ ํนํ ์ ์ฉํฉ๋๋ค.
์์ :
let registry = new FinalizationRegistry(
(heldValue) => {
console.log(heldValue, '์ ๋ฆฌ ์ค');
// ์ฌ๊ธฐ์ ์ ๋ฆฌ ์์
์ ์ํํฉ๋๋ค
}
);
let obj = {};
registry.register(obj, '์ด๋ค ๊ฐ');
obj = null;
// obj๊ฐ ๊ฐ๋น์ง ์ปฌ๋ ์
๋ ๋ FinalizationRegistry์ ์ฝ๋ฐฑ์ด ์คํ๋ฉ๋๋ค.
์ด ์์ ์์ FinalizationRegistry
๋ obj
๊ฐ์ฒด๊ฐ ๊ฐ๋น์ง ์ปฌ๋ ์
๋ ๋ ์คํ๋ ์ฝ๋ฐฑ ํจ์๋ฅผ ๋ฑ๋กํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. ์ฝ๋ฐฑ ํจ์๋ ํ ํฐ '์ด๋ค ๊ฐ'
์ ๋ฐ์ผ๋ฉฐ, ์ด๋ ์ ๋ฆฌ๋๋ ๊ฐ์ฒด๋ฅผ ์๋ณํ๋ ๋ฐ ์ฌ์ฉ๋ ์ ์์ต๋๋ค. obj = null;
์งํ์ ์ฝ๋ฐฑ์ด ์คํ๋๋ค๋ ๋ณด์ฅ์ ์์ต๋๋ค. ๊ฐ๋น์ง ์ปฌ๋ ํฐ๊ฐ ์ ๋ฆฌํ ์ค๋น๊ฐ ๋์์ ๋๋ฅผ ๊ฒฐ์ ํฉ๋๋ค.
์ธ๋ถ ๋ฆฌ์์ค๋ฅผ ์ฌ์ฉํ ์ค์ ์์ :
class ExternalResource {
constructor() {
this.id = generateUniqueId();
// allocateExternalResource๊ฐ ์ธ๋ถ ์์คํ
์์ ๋ฆฌ์์ค๋ฅผ ํ ๋นํ๋ค๊ณ ๊ฐ์
allocateExternalResource(this.id);
console.log(`ID๊ฐ ${this.id}์ธ ์ธ๋ถ ๋ฆฌ์์ค ํ ๋น๋จ`);
}
cleanup() {
// freeExternalResource๊ฐ ์ธ๋ถ ์์คํ
์์ ๋ฆฌ์์ค๋ฅผ ํด์ ํ๋ค๊ณ ๊ฐ์
freeExternalResource(this.id);
console.log(`ID๊ฐ ${this.id}์ธ ์ธ๋ถ ๋ฆฌ์์ค ํด์ ๋จ`);
}
}
const finalizationRegistry = new FinalizationRegistry((resourceId) => {
console.log(`ID๊ฐ ${resourceId}์ธ ์ธ๋ถ ๋ฆฌ์์ค ์ ๋ฆฌ ์ค`);
freeExternalResource(resourceId);
});
let resource = new ExternalResource();
finalizationRegistry.register(resource, resource.id);
resource = null; // ์ด์ ๋ฆฌ์์ค๋ ๊ฐ๋น์ง ์ปฌ๋ ์
๋์์ด ๋ฉ๋๋ค.
// ์ ์ ํ, finalization registry๊ฐ ์ ๋ฆฌ ์ฝ๋ฐฑ์ ์คํํ ๊ฒ์
๋๋ค.
3. ๋น๋๊ธฐ ์ดํฐ๋ ์ดํฐ์ Symbol.asyncDispose
๋น๋๊ธฐ ์ดํฐ๋ ์ดํฐ๋ ๋ช ์์ ๋ฆฌ์์ค ๊ด๋ฆฌ์ ์ด์ ์ ๋๋ฆด ์ ์์ต๋๋ค. ๋น๋๊ธฐ ์ดํฐ๋ ์ดํฐ๊ฐ ๋ฆฌ์์ค(์: ์คํธ๋ฆผ)๋ฅผ ๋ณด์ ํ๊ณ ์์ ๋, ๋ฐ๋ณต์ด ์๋ฃ๋๊ฑฐ๋ ์กฐ๊ธฐ์ ์ข ๋ฃ๋ ๋ ํด๋น ๋ฆฌ์์ค๊ฐ ํด์ ๋๋๋ก ๋ณด์ฅํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค.
๋น๋๊ธฐ ์ดํฐ๋ ์ดํฐ์ Symbol.asyncDispose
๋ฅผ ๊ตฌํํ์ฌ ์ ๋ฆฌ๋ฅผ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค:
class AsyncResourceIterator {
constructor(filePath) {
this.filePath = filePath;
this.fileHandle = null;
this.iterator = null;
}
async open() {
const fsPromises = require('fs').promises;
this.fileHandle = await fsPromises.open(this.filePath, 'r');
this.iterator = this.#createIterator();
return this;
}
async *#createIterator() {
const fsPromises = require('fs').promises;
const stream = this.fileHandle.readableWebStream();
const reader = stream.getReader();
try {
while (true) {
const { done, value } = await reader.read();
if (done) break;
yield new TextDecoder().decode(value);
}
} finally {
reader.releaseLock();
}
}
async [Symbol.asyncDispose]() {
if (this.fileHandle) {
await this.fileHandle.close();
console.log(`๋น๋๊ธฐ ์ดํฐ๋ ์ดํฐ๊ฐ ํ์ผ ๋ซ์: ${this.filePath}`);
}
}
[Symbol.asyncIterator]() {
return this.iterator;
}
}
async function processFile(filePath) {
const resourceIterator = new AsyncResourceIterator(filePath);
await resourceIterator.open();
try {
using fileIterator = resourceIterator;
for await (const chunk of fileIterator) {
console.log(chunk);
}
// ํ์ผ์ด ์ฌ๊ธฐ์ ์๋์ผ๋ก ํ๊ธฐ(dispose)๋ฉ๋๋ค
} catch (error) {
console.error("ํ์ผ ์ฒ๋ฆฌ ์ค ์ค๋ฅ:", error);
}
}
processFile("my_large_file.txt");
๋ช ์์ ๋ฆฌ์์ค ๊ด๋ฆฌ๋ฅผ ์ํ ๋ชจ๋ฒ ์ฌ๋ก
JavaScript์์ ๋ช ์์ ๋ฆฌ์์ค ๊ด๋ฆฌ๋ฅผ ํจ๊ณผ์ ์ผ๋ก ํ์ฉํ๋ ค๋ฉด ๋ค์ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ๊ณ ๋ คํ์ญ์์ค:
- ๋ช ์์ ์ ๋ฆฌ๊ฐ ํ์ํ ๋ฆฌ์์ค ์๋ณ: ์ ํ๋ฆฌ์ผ์ด์ ์์ ๋์๋ ์ฑ๋ฅ ๋ฌธ์ ๋ฅผ ์ผ์ผํฌ ๊ฐ๋ฅ์ฑ์ด ์์ด ๋ช ์์ ์ ๋ฆฌ๊ฐ ํ์ํ ๋ฆฌ์์ค๋ฅผ ๊ฒฐ์ ํ์ญ์์ค. ์ฌ๊ธฐ์๋ ํ์ผ ํธ๋ค, ๋คํธ์ํฌ ์ฐ๊ฒฐ, ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ, ํ์ด๋จธ, ์ด๋ฒคํธ ๋ฆฌ์ค๋ ๋ฐ ์ธ๋ถ ํ๋ก์ธ์ค ํธ๋ค์ด ํฌํจ๋ฉ๋๋ค.
- ๋จ์ํ ์๋๋ฆฌ์ค์๋
using
์ ์ธ ์ฌ์ฉ:using
์ ์ธ์ ๋๊ธฐ์ ๋๋ ๋น๋๊ธฐ์ ์ผ๋ก ์ ๋ฆฌํ ์ ์๋ ๋ฆฌ์์ค๋ฅผ ๊ด๋ฆฌํ๋ ๋ฐ ์ ํธ๋๋ ์ ๊ทผ ๋ฐฉ์์ ๋๋ค. ์ด๋ ์๊ธฐ์ ์ ํ ์ ๋ฆฌ๋ฅผ ๋ณด์ฅํ๋ ๊นจ๋ํ๊ณ ์ ์ธ์ ์ธ ๋ฐฉ๋ฒ์ ์ ๊ณตํฉ๋๋ค. - ์ธ๋ถ ๋ฆฌ์์ค์๋
WeakRef
์FinalizationRegistry
์ฌ์ฉ: ์ธ๋ถ ์์คํ ์ด๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ๊ด๋ฆฌํ๋ ๋ฆฌ์์ค๋ฅผ ๋ค๋ฃฐ ๋๋WeakRef
์FinalizationRegistry
๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ์ฒด ์๋ฉธ์ ์ถ์ ํ๊ณ ๊ฐ์ฒด๊ฐ ๊ฐ๋น์ง ์ปฌ๋ ์ ๋ ๋ ์ ๋ฆฌ ์์ ์ ์ํํ์ญ์์ค. - ๊ฐ๋ฅํ๋ฉด ๋น๋๊ธฐ ์ ๋ฆฌ ์ ํธ: ์ ๋ฆฌ ์์
์ I/O๋ ๋ค๋ฅธ ์ ์ฌ์ ์ผ๋ก ๋ธ๋กํน๋ ์ ์๋ ์์
์ด ํฌํจ๋ ๊ฒฝ์ฐ, ๋ฉ์ธ ์ค๋ ๋๋ฅผ ๋ธ๋กํนํ์ง ์๋๋ก ๋น๋๊ธฐ ์ ๋ฆฌ(
Symbol.asyncDispose
)๋ฅผ ์ฌ์ฉํ์ญ์์ค. - ์์ธ๋ฅผ ์ ์คํ๊ฒ ์ฒ๋ฆฌ: ์ ๋ฆฌ ์ฝ๋๊ฐ ์์ธ์ ๋ํด ๋ณต์๋ ฅ์ด ์๋๋ก ๋ณด์ฅํ์ญ์์ค.
try...finally
๋ธ๋ก์ ์ฌ์ฉํ์ฌ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋๋ผ๋ ์ ๋ฆฌ ์ฝ๋๊ฐ ํญ์ ์คํ๋๋๋ก ํ์ญ์์ค. - ์ ๋ฆฌ ๋ก์ง ํ ์คํธ: ๋ฆฌ์์ค๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ํด์ ๋๊ณ ๋ฆฌ์์ค ๋์๊ฐ ๋ฐ์ํ์ง ์๋์ง ํ์ธํ๊ธฐ ์ํด ์ ๋ฆฌ ๋ก์ง์ ์ฒ ์ ํ ํ ์คํธํ์ญ์์ค. ํ๋กํ์ผ๋ง ๋๊ตฌ๋ฅผ ์ฌ์ฉํ์ฌ ๋ฆฌ์์ค ์ฌ์ฉ๋์ ๋ชจ๋ํฐ๋งํ๊ณ ์ ์ฌ์ ์ธ ๋ฌธ์ ๋ฅผ ์๋ณํ์ญ์์ค.
- ํด๋ฆฌํ๊ณผ ํธ๋์คํ์ผ๋ง ๊ณ ๋ ค: `using` ์ ์ธ์ ๋น๊ต์ ์๋ก์ด ๊ธฐ๋ฅ์ ๋๋ค. ์ด์ ํ๊ฒฝ์ ์ง์ํด์ผ ํ๋ ๊ฒฝ์ฐ, ํธํ์ฑ์ ์ ๊ณตํ๊ธฐ ์ํด Babel์ด๋ TypeScript์ ๊ฐ์ ํธ๋์คํ์ผ๋ฌ์ ์ ์ ํ ํด๋ฆฌํ์ ์ฌ์ฉํ๋ ๊ฒ์ ๊ณ ๋ คํ์ญ์์ค.
๋ช ์์ ๋ฆฌ์์ค ๊ด๋ฆฌ์ ์ด์
JavaScript ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ช ์์ ๋ฆฌ์์ค ๊ด๋ฆฌ๋ฅผ ๊ตฌํํ๋ฉด ๋ค์๊ณผ ๊ฐ์ ๋ช ๊ฐ์ง ์ค์ํ ์ด์ ์ด ์์ต๋๋ค:
- ํฅ์๋ ์ ๋ขฐ์ฑ: ์๊ธฐ์ ์ ํ ๋ฆฌ์์ค ์ ๋ฆฌ๋ฅผ ๋ณด์ฅํจ์ผ๋ก์จ ๋ช ์์ ๋ฆฌ์์ค ๊ด๋ฆฌ๋ ๋ฆฌ์์ค ๋์ ๋ฐ ์ ํ๋ฆฌ์ผ์ด์ ์ถฉ๋ ์ํ์ ์ค์ ๋๋ค.
- ํฅ์๋ ์ฑ๋ฅ: ๋ฆฌ์์ค๋ฅผ ์ ์ํ๊ฒ ํด์ ํ๋ฉด ์์คํ ๋ฆฌ์์ค๊ฐ ํ๋ณด๋๊ณ ์ ํ๋ฆฌ์ผ์ด์ ์ฑ๋ฅ์ด ํฅ์๋ฉ๋๋ค. ํนํ ๋ค์์ ๋ฆฌ์์ค๋ฅผ ๋ค๋ฃฐ ๋ ๊ทธ๋ ์ต๋๋ค.
- ์ฆ๊ฐ๋ ์์ธก ๊ฐ๋ฅ์ฑ: ๋ช ์์ ๋ฆฌ์์ค ๊ด๋ฆฌ๋ ๋ฆฌ์์ค์ ์๋ช ์ฃผ๊ธฐ์ ๋ํ ๋ ํฐ ์ ์ด๊ถ์ ์ ๊ณตํ์ฌ ์ ํ๋ฆฌ์ผ์ด์ ๋์์ ๋ ์์ธก ๊ฐ๋ฅํ๊ณ ๋๋ฒ๊น ํ๊ธฐ ์ฝ๊ฒ ๋ง๋ญ๋๋ค.
- ๋จ์ํ๋ ๋๋ฒ๊น : ๋ฆฌ์์ค ๋์๋ ์ง๋จํ๊ณ ๋๋ฒ๊น ํ๊ธฐ ์ด๋ ค์ธ ์ ์์ต๋๋ค. ๋ช ์์ ๋ฆฌ์์ค ๊ด๋ฆฌ๋ ๋ฆฌ์์ค ๊ด๋ จ ๋ฌธ์ ๋ฅผ ๋ ์ฝ๊ฒ ์๋ณํ๊ณ ์์ ํ ์ ์๊ฒ ํด์ค๋๋ค.
- ๋ ๋์ ์ฝ๋ ์ ์ง๋ณด์์ฑ: ๋ช ์์ ๋ฆฌ์์ค ๊ด๋ฆฌ๋ ๋ ๊นจ๋ํ๊ณ ์กฐ์ง์ ์ธ ์ฝ๋๋ฅผ ์ด์งํ์ฌ ์ฝ๋๋ฅผ ์ดํดํ๊ณ ์ ์ง๋ณด์ํ๊ธฐ ์ฝ๊ฒ ๋ง๋ญ๋๋ค.
๊ฒฐ๋ก
๋ช
์์ ๋ฆฌ์์ค ๊ด๋ฆฌ๋ ๊ฒฌ๊ณ ํ๊ณ ์ฑ๋ฅ ์ข์ JavaScript ์ ํ๋ฆฌ์ผ์ด์
์ ๊ตฌ์ถํ๋ ๋ฐ ํ์์ ์ธ ์ธก๋ฉด์
๋๋ค. ๋ช
์์ ์ ๋ฆฌ์ ํ์์ฑ์ ์ดํดํ๊ณ using
์ ์ธ, WeakRef
, FinalizationRegistry
์ ๊ฐ์ ์ต์ ๊ธฐ๋ฅ์ ํ์ฉํจ์ผ๋ก์จ ๊ฐ๋ฐ์๋ ์๊ธฐ์ ์ ํ ๋ฆฌ์์ค ํด์ ๋ฅผ ๋ณด์ฅํ๊ณ ๋ฆฌ์์ค ๋์๋ฅผ ๋ฐฉ์งํ๋ฉฐ ์ ํ๋ฆฌ์ผ์ด์
์ ์ ๋ฐ์ ์ธ ์์ ์ฑ๊ณผ ์ฑ๋ฅ์ ํฅ์์ํฌ ์ ์์ต๋๋ค. ์ด๋ฌํ ๊ธฐ์ ์ ์ฑํํ๋ฉด ๋ค์ํ ๊ตญ์ ์ ๋งฅ๋ฝ์์ ํ๋ ์น ๊ฐ๋ฐ์ ์๊ตฌ๋ฅผ ์ถฉ์กฑ์ํค๋ ๋ฐ ์ค์ํ, ๋ ์ ๋ขฐํ ์ ์๊ณ ์ ์ง๋ณด์ ๊ฐ๋ฅํ๋ฉฐ ํ์ฅ ๊ฐ๋ฅํ JavaScript ์ฝ๋๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.