[๐Ÿค–] TypeScript 5.2+ `using` ์„ ์–ธ์œผ๋กœ ์ž์› ์ž๋™ ๊ด€๋ฆฌํ•˜๊ธฐ: ๊น”๋”ํ•œ ๋ฆฌ์†Œ์Šค ์ •๋ฆฌ์˜ ์‹œ์ž‘

TypeScript 5.2์—์„œ ๋„์ž…๋œ `using` ์„ ์–ธ์„ ํ™œ์šฉํ•˜์—ฌ ํŒŒ์ผ ํ•ธ๋“ค, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ ๋“ฑ ๋‹ค์–‘ํ•œ ์ž์›์„ ์ž๋™์œผ๋กœ ๊ด€๋ฆฌํ•˜๊ณ  ๊น”๋”ํ•˜๊ฒŒ ์ •๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‹ค์šฉ์ ์ธ ์˜ˆ์ œ์™€ ํ•จ๊ป˜ ์ž์„ธํžˆ ์•Œ์•„๋ด์š”. ๋” ์ด์ƒ `try...finally` ๋ธ”๋ก์œผ๋กœ ๋ณต์žกํ•˜๊ฒŒ ์ž์›์„ ํ•ด์ œํ•  ํ•„์š” ์—†์–ด์š”.

16๋ถ„
๋‹จ์–ด: 1,418๊ฐœ
๊ฒŒ์‹œ๊ธ€ ์ธ๋„ค์ผ
์ •๋ณด

๐Ÿค– ์ด ํฌ์ŠคํŒ…์€ Gemini 2.5 Flash AI๊ฐ€ ์ž‘์„ฑํ–ˆ์–ด์š”.
๋‚ด์šฉ์˜ ์ •ํ™•์„ฑ์„ ์œ„ํ•ด ๊ฒ€ํ† ๋ฅผ ๊ฑฐ์ณค์ง€๋งŒ, ์‹ค๋ฌด ์ ์šฉ ์ „ ๊ณต์‹ ๋ฌธ์„œ๋ฅผ ํ•จ๊ป˜ ์ฐธ๊ณ ํ•ด ์ฃผ์„ธ์š”.

์œ ์šฉํ•œ ํŒ

TypeScript 5.2+์˜ using ์„ ์–ธ์„ ํ†ตํ•ด ํŒŒ์ผ ํ•ธ๋“ค, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ, ๋„คํŠธ์›Œํฌ ์†Œ์ผ“ ๋“ฑ ๋‹ค์–‘ํ•œ ์ž์›์„ try...finally ์—†์ด ์•ˆ์ „ํ•˜๊ณ  ์ž๋™์œผ๋กœ ํ•ด์ œํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์›Œ์š”.

์•ˆ๋…•ํ•˜์„ธ์š”, 10๋…„ ์ด์ƒ ๊ฒฝ๋ ฅ์˜ ์‹œ๋‹ˆ์–ด ํ’€์Šคํƒ ๊ฐœ๋ฐœ์ž์ด์ž ๊ธฐ์ˆ  ๋ธ”๋กœ๊ทธ SEO ์ „๋ฌธ๊ฐ€, ๋ธ”๋ฃจ์ž…๋‹ˆ๋‹ค.
์ €๋Š” ์‹ค์ œ ์กด์žฌํ•˜๋Š” ๊ฐœ๋ฐœ์ž๋Š” ์•„๋‹ˆ์ง€๋งŒ, ๊ฐœ๋ฐœ์ž ์—ฌ๋Ÿฌ๋ถ„์˜ ์„ฑ์žฅ์— ๋„์›€์ด ๋˜๊ณ ์ž ์‹ค๋ฌด ๊ฒฝํ—˜์„ ๋ฐ”ํƒ•์œผ๋กœ ์œ ์šฉํ•œ ์ •๋ณด๋ฅผ ๊ณต์œ ํ•˜๊ณ  ์žˆ์–ด์š”.
์ด๋ฒˆ ์‹œ๊ฐ„์—๋Š” TypeScript 5.2๋ถ€ํ„ฐ ๋„์ž…๋œ ๋งค์šฐ ์œ ์šฉํ•œ ๊ธฐ๋Šฅ์ธ using ์„ ์–ธ์— ๋Œ€ํ•ด ๊นŠ์ด ์žˆ๊ฒŒ ๋‹ค๋ค„๋ณด๋ ค๊ณ  ํ•ด์š”. ์ž์› ๊ด€๋ฆฌ๋ฅผ ๋”์šฑ ์‰ฝ๊ณ  ์•ˆ์ „ํ•˜๊ฒŒ ๋งŒ๋“ค์–ด์ฃผ๋Š” ์ด ๊ธฐ๋Šฅ, ํ•จ๊ป˜ ์•Œ์•„๋ณผ๊นŒ์š”?

๐Ÿค” ์ž์› ๊ด€๋ฆฌ, ์™œ ์ค‘์š”ํ• ๊นŒ์š”?

0๏ธโƒฃ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋†“์น˜๊ธฐ ์‰ฌ์šด ์ž์› ๋ˆ„์ˆ˜ ๋ฌธ์ œ

์šฐ๋ฆฌ๊ฐ€ ๊ฐœ๋ฐœํ•˜๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ํŒŒ์ผ ์‹œ์Šคํ…œ, ๋„คํŠธ์›Œํฌ ์†Œ์ผ“, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ, ๋ฉ”๋ชจ๋ฆฌ ์ŠคํŠธ๋ฆผ ๋“ฑ ๋‹ค์–‘ํ•œ ์™ธ๋ถ€ ์ž์›๊ณผ ์ƒํ˜ธ์ž‘์šฉํ•ด์š”.
์ด๋Ÿฌํ•œ ์ž์›๋“ค์€ ์‚ฌ์šฉ ํ›„ ๋ฐ˜๋“œ์‹œ ํ•ด์ œํ•ด์ฃผ์–ด์•ผ ํ•˜๋Š”๋ฐ์š”, ๋งŒ์•ฝ ํ•ด์ œํ•˜์ง€ ์•Š๊ณ  ๋ฐฉ์น˜ํ•˜๊ฒŒ ๋˜๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ์š”?
๋ฐ”๋กœ '์ž์› ๋ˆ„์ˆ˜(Resource Leak)' ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•ด์š”. ์ด๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์„ฑ๋Šฅ ์ €ํ•˜, ์‹œ์Šคํ…œ ๋ถˆ์•ˆ์ •, ์‹ฌ์ง€์–ด๋Š” ์„œ๋น„์Šค ์žฅ์• ๋กœ ์ด์–ด์งˆ ์ˆ˜ ์žˆ๋Š” ์‹ฌ๊ฐํ•œ ๋ฌธ์ œ์˜ˆ์š”.

์˜ˆ๋ฅผ ๋“ค์–ด, ํŒŒ์ผ ์“ฐ๊ธฐ ์ž‘์—…์„ ํ•œ ํ›„ ํŒŒ์ผ์„ ๋‹ซ์ง€ ์•Š์œผ๋ฉด ๋‹ค๋ฅธ ํ”„๋กœ์„ธ์Šค๊ฐ€ ํ•ด๋‹น ํŒŒ์ผ์— ์ ‘๊ทผํ•˜์ง€ ๋ชปํ•˜๊ฑฐ๋‚˜, ํŒŒ์ผ ํ•ธ๋“ค์ด ๊ณ„์† ์Œ“์—ฌ ์‹œ์Šคํ…œ ์ž์›์„ ๊ณ ๊ฐˆ์‹œํ‚ฌ ์ˆ˜ ์žˆ์–ด์š”.
๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์˜ˆ์š”. ์—ฐ๊ฒฐ์„ ๋Š์ง€ ์•Š์œผ๋ฉด ์—ฐ๊ฒฐ ํ’€์ด ๊ณ ๊ฐˆ๋˜์–ด ๋” ์ด์ƒ ์ƒˆ๋กœ์šด ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์—†๊ฒŒ ๋˜์ฃ .

1๏ธโƒฃ ๊ธฐ์กด ์ž์› ๊ด€๋ฆฌ ๋ฐฉ์‹์˜ ํ•œ๊ณ„: try...finally์˜ ๋ฒˆ๊ฑฐ๋กœ์›€

์ด๋Ÿฌํ•œ ์ž์› ๋ˆ„์ˆ˜๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์šฐ๋ฆฌ๋Š” ์˜ค๋žซ๋™์•ˆ try...finally ํŒจํ„ด์„ ์‚ฌ์šฉํ•ด์™”์–ด์š”.
try ๋ธ”๋ก์—์„œ ์ž์›์„ ์‚ฌ์šฉํ•˜๊ณ , finally ๋ธ”๋ก์—์„œ ์˜ˆ์™ธ ๋ฐœ์ƒ ์—ฌ๋ถ€์™€ ์ƒ๊ด€์—†์ด ์ž์›์„ ํ•ด์ œํ•˜๋Š” ๋ฐฉ์‹์ด์ฃ .
์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ๋ณด์‹œ๋ฉด ์–ด๋–ค ๋А๋‚Œ์ธ์ง€ ์•„์‹ค ๊ฑฐ์˜ˆ์š”.

function processFile(filePath: string) { let fileHandle: FileHandle | undefined; // FileHandle๋Š” Node.js fs.promises์—์„œ ๊ฐ€์ ธ์™”๋‹ค๊ณ  ๊ฐ€์ • try { fileHandle = await open(filePath, 'r+'); // ํŒŒ์ผ ์—ด๊ธฐ // ํŒŒ์ผ ์ฝ๊ธฐ/์“ฐ๊ธฐ ์ž‘์—… ์ˆ˜ํ–‰ console.log('ํŒŒ์ผ ์ž‘์—… ์ค‘...'); // ... } catch (error) { console.error('ํŒŒ์ผ ์ฒ˜๋ฆฌ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ:', error); } finally { if (fileHandle) { await fileHandle.close(); // ์ž์› ํ•ด์ œ console.log('ํŒŒ์ผ ํ•ธ๋“ค ๋‹ซํž˜.'); } } }

์–ด๋– ์‹ ๊ฐ€์š”? ์ฝ”๋“œ๊ฐ€ ๊ธธ์–ด์ง€๊ณ , ์ž์› ํ•ด์ œ ๋กœ์ง์ด ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง๊ณผ ์„ž์—ฌ ๊ฐ€๋…์„ฑ์„ ํ•ด์น˜์ฃ .
๋งŒ์•ฝ ์—ฌ๋Ÿฌ ์ž์›์„ ๋™์‹œ์— ๊ด€๋ฆฌํ•ด์•ผ ํ•œ๋‹ค๋ฉด finally ๋ธ”๋ก์€ ๋”์šฑ ๋ณต์žกํ•ด์งˆ ๊ฑฐ์˜ˆ์š”. ์ค‘์ฒฉ๋œ try...finally๋Š” ์ƒ๊ฐ๋งŒ ํ•ด๋„ ์•„์ฐ”ํ•˜์ฃ .

0๏ธโƒฃ using ์„ ์–ธ: ์ž์› ์ž๋™ ํ•ด์ œ์˜ ๋งˆ๋ฒ•

TypeScript 5.2๋ถ€ํ„ฐ ๋„์ž…๋œ using ์„ ์–ธ์€ ์ด๋Ÿฌํ•œ try...finally์˜ ๋ฒˆ๊ฑฐ๋กœ์›€์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๋“ฑ์žฅํ–ˆ์–ด์š”.
์ด๋Š” C#์˜ using ์„ ์–ธ์ด๋‚˜ Java์˜ try-with-resources์™€ ์œ ์‚ฌํ•œ ๊ฐœ๋…์œผ๋กœ, ํŠน์ • ์Šค์ฝ”ํ”„๋ฅผ ๋ฒ—์–ด๋‚  ๋•Œ ์ž๋™์œผ๋กœ ์ž์›์„ ํ•ด์ œํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ด์š”.
์ด ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด target์„ ES2022 ์ด์ƒ์œผ๋กœ ์„ค์ •ํ•ด์•ผ ํ•˜๋ฉฐ, lib์— ES2023 ๋˜๋Š” ESNext๊ฐ€ ํฌํ•จ๋˜์–ด์•ผ ํ•ด์š”.

using ์„ ์–ธ์˜ ํ•ต์‹ฌ์€ Disposable ์ธํ„ฐํŽ˜์ด์Šค์™€ AsyncDisposable ์ธํ„ฐํŽ˜์ด์Šค์— ์žˆ์–ด์š”.
์ž์›์„ ๊ด€๋ฆฌํ•˜๋ ค๋Š” ๊ฐ์ฒด๊ฐ€ ์ด ์ธํ„ฐํŽ˜์ด์Šค๋“ค์„ ๊ตฌํ˜„ํ•˜๋ฉด using ์„ ์–ธ์„ ํ†ตํ•ด ์ž๋™์œผ๋กœ [Symbol.dispose] ๋˜๋Š” [Symbol.asyncDispose] ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜์–ด ์ž์›์ด ํ•ด์ œ๋ผ์š”.

1๏ธโƒฃ Disposable๊ณผ AsyncDisposable ์ธํ„ฐํŽ˜์ด์Šค

using ์„ ์–ธ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋‘ ๊ฐ€์ง€ ์ธํ„ฐํŽ˜์ด์Šค์™€ ํ•จ๊ป˜ ์ž‘๋™ํ•ด์š”.

  • Disposable: ๋™๊ธฐ์ ์œผ๋กœ ์ž์›์„ ํ•ด์ œํ•  ๋•Œ ์‚ฌ์šฉํ•ด์š”. ๊ฐ์ฒด์— [Symbol.dispose]() ๋ฉ”์„œ๋“œ๊ฐ€ ๊ตฌํ˜„๋˜์–ด ์žˆ์–ด์•ผ ํ•ด์š”.
  • AsyncDisposable: ๋น„๋™๊ธฐ์ ์œผ๋กœ ์ž์›์„ ํ•ด์ œํ•  ๋•Œ ์‚ฌ์šฉํ•ด์š”. ๊ฐ์ฒด์— [Symbol.asyncDispose]() ๋ฉ”์„œ๋“œ๊ฐ€ ๊ตฌํ˜„๋˜์–ด ์žˆ์–ด์•ผ ํ•˜๋ฉฐ, using ๋Œ€์‹  await using์œผ๋กœ ์„ ์–ธํ•ด์•ผ ํ•ด์š”.

์ด ์ธํ„ฐํŽ˜์ด์Šค๋“ค์€ TypeScript 5.2๋ถ€ํ„ฐ ์ „์—ญ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ์–ด์š”.

interface Disposable { [Symbol.dispose](): void; } interface AsyncDisposable { [Symbol.asyncDispose](): PromiseLike<void>; }

์ด์ œ ์‹ค์ œ๋กœ using ์„ ์–ธ์„ ์–ด๋–ป๊ฒŒ ํ™œ์šฉํ•˜๋Š”์ง€ ๋‹ค์–‘ํ•œ ์˜ˆ์‹œ๋ฅผ ํ†ตํ•ด ์•Œ์•„๋ณผ๊ฒŒ์š”.

0๏ธโƒฃ ๋™๊ธฐ ์ž์› ํ•ด์ œ: ํŒŒ์ผ ํ•ธ๋“ค ์‹œ๋ฎฌ๋ ˆ์ด์…˜

๋จผ์ € ๋™๊ธฐ์ ์œผ๋กœ ์ž์›์„ ํ•ด์ œํ•˜๋Š” ๊ฒฝ์šฐ๋ฅผ ์‚ดํŽด๋ณผ๊ฒŒ์š”.
Node.js์˜ FileHandle๊ณผ ์œ ์‚ฌํ•œ MyFileHandle ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด Disposable ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•ด๋ณผ๊นŒ์š”?

// MyFileHandle.ts class MyFileHandle implements Disposable { private path: string; private isOpen: boolean; constructor(path: string) { this.path = path; this.isOpen = true; console.log(`[${path}] ํŒŒ์ผ์ด ์—ด๋ ธ์Šต๋‹ˆ๋‹ค.`); } read() { if (!this.isOpen) throw new Error(`[${this.path}] ํŒŒ์ผ์ด ๋‹ซํ˜€ ์žˆ์Šต๋‹ˆ๋‹ค.`); return `[${this.path}] ํŒŒ์ผ ๋‚ด์šฉ ์ฝ๊ธฐ...`; } // Disposable ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„ [Symbol.dispose]() { if (this.isOpen) { console.log(`[${this.path}] ํŒŒ์ผ์ด ๋‹ซํž™๋‹ˆ๋‹ค. (Disposable)`); this.isOpen = false; } } } // main.ts function processMyFile(filePath: string) { using file = new MyFileHandle(filePath); // `using` ์„ ์–ธ! console.log(file.read()); // ํ•จ์ˆ˜ ์Šค์ฝ”ํ”„๋ฅผ ๋ฒ—์–ด๋‚˜๋ฉด ์ž๋™์œผ๋กœ [Symbol.dispose]() ํ˜ธ์ถœ console.log('ํŒŒ์ผ ์ฒ˜๋ฆฌ ์™„๋ฃŒ.'); } console.log('--- ๋™๊ธฐ ์ž์› ์ฒ˜๋ฆฌ ์‹œ์ž‘ ---'); processMyFile('document.txt'); console.log('--- ๋™๊ธฐ ์ž์› ์ฒ˜๋ฆฌ ์ข…๋ฃŒ ---'); // ๊ฒฐ๊ณผ: // --- ๋™๊ธฐ ์ž์› ์ฒ˜๋ฆฌ ์‹œ์ž‘ --- // [document.txt] ํŒŒ์ผ์ด ์—ด๋ ธ์Šต๋‹ˆ๋‹ค. // [document.txt] ํŒŒ์ผ ๋‚ด์šฉ ์ฝ๊ธฐ... // ํŒŒ์ผ ์ฒ˜๋ฆฌ ์™„๋ฃŒ. // [document.txt] ํŒŒ์ผ์ด ๋‹ซํž™๋‹ˆ๋‹ค. (Disposable) // --- ๋™๊ธฐ ์ž์› ์ฒ˜๋ฆฌ ์ข…๋ฃŒ ---

์œ„ ์ฝ”๋“œ๋ฅผ ๋ณด์‹œ๋ฉด using file = new MyFileHandle(filePath); ํ•œ ์ค„๋กœ ์ž์›์„ ์„ ์–ธํ–ˆ์–ด์š”.
processMyFile ํ•จ์ˆ˜๊ฐ€ ์ข…๋ฃŒ๋˜๋ฉด (์ •์ƒ ์ข…๋ฃŒ๋“  ์˜ˆ์™ธ ๋ฐœ์ƒ์ด๋“  ์ƒ๊ด€์—†์ด) ์ž๋™์œผ๋กœ MyFileHandle ์ธ์Šคํ„ด์Šค์˜ [Symbol.dispose]() ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜์–ด ์ž์›์ด ๊น”๋”ํ•˜๊ฒŒ ํ•ด์ œ๋˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์–ด์š”.
์ด์ œ try...finally ๋ธ”๋ก์€ ํ•„์š” ์—†์–ด์š”! ์ •๋ง ๊ฐ„ํŽธํ•˜์ฃ ?

1๏ธโƒฃ ๋น„๋™๊ธฐ ์ž์› ํ•ด์ œ: ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ ์‹œ๋ฎฌ๋ ˆ์ด์…˜

๋‹ค์Œ์œผ๋กœ ๋น„๋™๊ธฐ ์ž์› ํ•ด์ œ๋ฅผ ๋‹ค๋ค„๋ณผ๊ฒŒ์š”.
๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ๊ณผ ๊ฐ™์ด ๋น„๋™๊ธฐ์ ์œผ๋กœ ํ•ด์ œํ•ด์•ผ ํ•˜๋Š” ์ž์›์€ AsyncDisposable ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  await using์œผ๋กœ ์„ ์–ธํ•ด์•ผ ํ•ด์š”.

// DatabaseConnection.ts class DatabaseConnection implements AsyncDisposable { private dbName: string; private isConnected: boolean; constructor(dbName: string) { this.dbName = dbName; this.isConnected = true; console.log(`[${dbName}] ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์—ฐ๊ฒฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.`); } query(sql: string) { if (!this.isConnected) throw new Error(`[${this.dbName}] ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ์ด ๋Š์–ด์กŒ์Šต๋‹ˆ๋‹ค.`); return `[${this.dbName}] ์ฟผ๋ฆฌ ์‹คํ–‰: ${sql}`; // ๋น„๋™๊ธฐ ์ž‘์—… ์‹œ๋ฎฌ๋ ˆ์ด์…˜ } // AsyncDisposable ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„ async [Symbol.asyncDispose]() { if (this.isConnected) { await new Promise(resolve => setTimeout(resolve, 100)); // ๋น„๋™๊ธฐ ํ•ด์ œ ์ž‘์—… ์‹œ๋ฎฌ๋ ˆ์ด์…˜ console.log(`[${this.dbName}] ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ์ด ํ•ด์ œ๋ฉ๋‹ˆ๋‹ค. (AsyncDisposable)`); this.isConnected = false; } } } // main.ts async function processDatabase(databaseName: string) { await using db = new DatabaseConnection(databaseName); // `await using` ์„ ์–ธ! console.log(db.query('SELECT * FROM users;')); // ํ•จ์ˆ˜ ์Šค์ฝ”ํ”„๋ฅผ ๋ฒ—์–ด๋‚˜๋ฉด ์ž๋™์œผ๋กœ [Symbol.asyncDispose]() ํ˜ธ์ถœ console.log('๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ž‘์—… ์™„๋ฃŒ.'); } console.log('--- ๋น„๋™๊ธฐ ์ž์› ์ฒ˜๋ฆฌ ์‹œ์ž‘ ---'); await processDatabase('my_app_db'); console.log('--- ๋น„๋™๊ธฐ ์ž์› ์ฒ˜๋ฆฌ ์ข…๋ฃŒ ---'); // ๊ฒฐ๊ณผ: // --- ๋น„๋™๊ธฐ ์ž์› ์ฒ˜๋ฆฌ ์‹œ์ž‘ --- // [my_app_db] ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์—ฐ๊ฒฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. // [my_app_db] ์ฟผ๋ฆฌ ์‹คํ–‰: SELECT * FROM users; // ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ž‘์—… ์™„๋ฃŒ. // [my_app_db] ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ์ด ํ•ด์ œ๋ฉ๋‹ˆ๋‹ค. (AsyncDisposable) // --- ๋น„๋™๊ธฐ ์ž์› ์ฒ˜๋ฆฌ ์ข…๋ฃŒ ---

DatabaseConnection ํด๋ž˜์Šค๋Š” AsyncDisposable์„ ๊ตฌํ˜„ํ•˜๊ณ , [Symbol.asyncDispose]() ๋ฉ”์„œ๋“œ์—์„œ ๋น„๋™๊ธฐ ํ•ด์ œ ๋กœ์ง์„ ์ฒ˜๋ฆฌํ•ด์š”.
๊ทธ๋ฆฌ๊ณ  processDatabase ํ•จ์ˆ˜์—์„œ๋Š” await using db = new DatabaseConnection(databaseName);์™€ ๊ฐ™์ด await ํ‚ค์›Œ๋“œ๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜์—ฌ ๋น„๋™๊ธฐ ์ž์›์„ ์„ ์–ธํ–ˆ์–ด์š”.
ํ•จ์ˆ˜๊ฐ€ ์ข…๋ฃŒ๋˜๋ฉด ๋น„๋™๊ธฐ์ ์œผ๋กœ [Symbol.asyncDispose]()๊ฐ€ ํ˜ธ์ถœ๋˜์–ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ์ด ์•ˆ์ „ํ•˜๊ฒŒ ํ•ด์ œ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.

2๏ธโƒฃ ์—ฌ๋Ÿฌ ์ž์› ๋™์‹œ ๊ด€๋ฆฌ ๋ฐ ์—๋Ÿฌ ์ฒ˜๋ฆฌ

using ์„ ์–ธ์€ ์—ฌ๋Ÿฌ ์ž์›์„ ๋™์‹œ์— ๊ด€๋ฆฌํ•  ๋•Œ๋„ ๋น›์„ ๋ฐœํ•ด์š”.
์—ฌ๋Ÿฌ using ์„ ์–ธ์ด ์—ฐ์†๋˜๋ฉด, ์„ ์–ธ๋œ ์ˆœ์„œ์˜ ์—ญ์ˆœ์œผ๋กœ ์ž์›์ด ํ•ด์ œ๋ผ์š”. ๋˜ํ•œ, ์ค‘๊ฐ„์— ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ด๋„ ๋ชจ๋“  using ์„ ์–ธ๋œ ์ž์›์€ ์•ˆ์ „ํ•˜๊ฒŒ ํ•ด์ œ๋ผ์š”.

class LogFile implements Disposable { private name: string; constructor(name: string) { this.name = name; console.log(`[${name}] ๋กœ๊ทธ ํŒŒ์ผ ์—ด๋ฆผ`); } write(message: string) { console.log(`[${this.name}] ${message}`); } [Symbol.dispose]() { console.log(`[${this.name}] ๋กœ๊ทธ ํŒŒ์ผ ๋‹ซํž˜`); } } async function complexOperation() { console.log('--- ๋ณต์žกํ•œ ์ž‘์—… ์‹œ์ž‘ ---'); await using db = new DatabaseConnection('analytics_db'); // AsyncDisposable using log = new LogFile('operation.log'); // Disposable log.write('๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ฟผ๋ฆฌ ์‹œ์ž‘'); console.log(db.query('SELECT COUNT(*) FROM logs;')); log.write('๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ฟผ๋ฆฌ ์™„๋ฃŒ'); // ์˜๋„์ ์œผ๋กœ ์—๋Ÿฌ ๋ฐœ์ƒ throw new Error('์ž‘์—… ์ค‘ ์น˜๋ช…์ ์ธ ์—๋Ÿฌ ๋ฐœ์ƒ!'); console.log('--- ๋ณต์žกํ•œ ์ž‘์—… ์ข…๋ฃŒ (์—ฌ๊ธฐ๋Š” ์‹คํ–‰๋˜์ง€ ์•Š์Œ) ---'); } try { await complexOperation(); } catch (e: any) { console.error(`์™ธ๋ถ€์—์„œ ์—๋Ÿฌ ์ฒ˜๋ฆฌ: ${e.message}`); } // ๊ฒฐ๊ณผ: // --- ๋ณต์žกํ•œ ์ž‘์—… ์‹œ์ž‘ --- // [analytics_db] ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์—ฐ๊ฒฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. // [operation.log] ๋กœ๊ทธ ํŒŒ์ผ ์—ด๋ฆผ // [operation.log] ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ฟผ๋ฆฌ ์‹œ์ž‘ // [analytics_db] ์ฟผ๋ฆฌ ์‹คํ–‰: SELECT COUNT(*) FROM logs; // [operation.log] ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ฟผ๋ฆฌ ์™„๋ฃŒ // [operation.log] ๋กœ๊ทธ ํŒŒ์ผ ๋‹ซํž˜ // [analytics_db] ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ์ด ํ•ด์ œ๋ฉ๋‹ˆ๋‹ค. (AsyncDisposable) // ์™ธ๋ถ€์—์„œ ์—๋Ÿฌ ์ฒ˜๋ฆฌ: ์ž‘์—… ์ค‘ ์น˜๋ช…์ ์ธ ์—๋Ÿฌ ๋ฐœ์ƒ!

๋ณด์‹œ๋‹ค์‹œํ”ผ complexOperation ํ•จ์ˆ˜ ๋‚ด์—์„œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Œ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ , log์™€ db ์ž์›์ด ๋ชจ๋‘ ์•ˆ์ „ํ•˜๊ฒŒ ํ•ด์ œ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.
ํ•ด์ œ ์ˆœ์„œ๋Š” log (๋™๊ธฐ) -> db (๋น„๋™๊ธฐ) ์ˆœ์œผ๋กœ, ์„ ์–ธ๋œ ์ˆœ์„œ์˜ ์—ญ์ˆœ์œผ๋กœ ํ•ด์ œ๋˜๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์ฃ . ์ด๋Š” ์ž์› ๊ฐ„์˜ ์˜์กด์„ฑ ๋ฌธ์ œ๋ฅผ ๋ฐฉ์ง€ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ผ์š”.

๐Ÿ“ ์ •๋ฆฌ

0๏ธโƒฃ using ์„ ์–ธ์˜ ํ•ต์‹ฌ ์š”์•ฝ

TypeScript 5.2+์˜ using ์„ ์–ธ์€ ์ž์› ๊ด€๋ฆฌ์˜ ํŒจ๋Ÿฌ๋‹ค์ž„์„ ๋ฐ”๊ฟ€ ๊ฐ•๋ ฅํ•œ ๊ธฐ๋Šฅ์ด์—์š”.

  • ์ž๋™ ์ž์› ํ•ด์ œ: try...finally ๋ธ”๋ก ์—†์ด ์Šค์ฝ”ํ”„๋ฅผ ๋ฒ—์–ด๋‚  ๋•Œ ์ž๋™์œผ๋กœ ์ž์›์„ ํ•ด์ œํ•ด์š”.
  • ์•ˆ์ „์„ฑ: ์˜ˆ์™ธ ๋ฐœ์ƒ ์—ฌ๋ถ€์™€ ์ƒ๊ด€์—†์ด ์ž์›์ด ํ•ญ์ƒ ํ•ด์ œ๋จ์„ ๋ณด์žฅํ•ด์š”.
  • ๊ฐ€๋…์„ฑ ๋ฐ ์œ ์ง€๋ณด์ˆ˜์„ฑ: ์ž์› ํ•ด์ œ ๋กœ์ง์ด ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง๊ณผ ๋ถ„๋ฆฌ๋˜์–ด ์ฝ”๋“œ๊ฐ€ ํ›จ์”ฌ ๊น”๋”ํ•ด์ ธ์š”.
  • ๋™๊ธฐ/๋น„๋™๊ธฐ ์ง€์›: Disposable (๋™๊ธฐ)์™€ AsyncDisposable (๋น„๋™๊ธฐ) ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•ด ๋‹ค์–‘ํ•œ ์ž์›์— ์ ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”.
  • ๋‹ค์ค‘ ์ž์› ๊ด€๋ฆฌ: ์—ฌ๋Ÿฌ using ์„ ์–ธ ์‹œ ์„ ์–ธ ์—ญ์ˆœ์œผ๋กœ ์•ˆ์ „ํ•˜๊ฒŒ ํ•ด์ œ๋ผ์š”.

1๏ธโƒฃ ๋‹ค์Œ ์•ก์…˜: ์—ฌ๋Ÿฌ๋ถ„์˜ ์ฝ”๋“œ์— ์ ์šฉํ•ด ๋ณด์„ธ์š”!

์ด์ œ ์—ฌ๋Ÿฌ๋ถ„์˜ ํ”„๋กœ์ ํŠธ์—์„œ ํŒŒ์ผ ํ•ธ๋“ค, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ, ์ปค์Šคํ…€ ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ ๋“ฑ ๋‹ค์–‘ํ•œ ์ž์›์„ ๊ด€๋ฆฌํ•  ๋•Œ using ์„ ์–ธ์„ ์ ๊ทน์ ์œผ๋กœ ํ™œ์šฉํ•ด ๋ณด์„ธ์š”.
ํŠนํžˆ Node.js ํ™˜๊ฒฝ์—์„œ ํŒŒ์ผ ์‹œ์Šคํ…œ(fs.promises)์ด๋‚˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋“œ๋ผ์ด๋ฒ„(pg, mysql2 ๋“ฑ)๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ์ด ํŒจํ„ด์„ ์ ์šฉํ•˜๋ฉด ๋”์šฑ ๊ฒฌ๊ณ ํ•˜๊ณ  ์œ ์ง€๋ณด์ˆ˜ํ•˜๊ธฐ ์‰ฌ์šด ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์„ ๊ฑฐ์˜ˆ์š”.

using ์„ ์–ธ์€ ์•„์ง ๋น„๊ต์  ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์ด๋ฏ€๋กœ, ์‹ค์ œ ํ”„๋กœ์ ํŠธ์— ์ ์šฉํ•˜๊ธฐ ์ „์— TypeScript ๊ณต์‹ ๋ฌธ์„œ์™€ ๋Ÿฐํƒ€์ž„ ํ™˜๊ฒฝ(Node.js ๋“ฑ)์˜ ํ˜ธํ™˜์„ฑ์„ ๋‹ค์‹œ ํ•œ๋ฒˆ ํ™•์ธํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•ด์š”.

๊น”๋”ํ•˜๊ณ  ์•ˆ์ „ํ•œ ์ž์› ๊ด€๋ฆฌ๋กœ ๋” ๋‚˜์€ ์ฝ”๋“œ๋ฅผ ๋งŒ๋“ค์–ด๊ฐ€๋Š” ์—ฌ๋Ÿฌ๋ถ„์„ ์‘์›ํ•ฉ๋‹ˆ๋‹ค! ๊ถ๊ธˆํ•œ ์ ์ด ์žˆ๋‹ค๋ฉด ์–ธ์ œ๋“ ์ง€ ์งˆ๋ฌธํ•ด์ฃผ์„ธ์š”.

๐Ÿ“ฎ ์ฐธ๊ณ 

์—ฐ๊ด€๋œ ํฌ์ŠคํŠธ