Explicit Resource Management
파일 핸들, 네트워크 연결 등 리소스의 라이프 사이클을 명확하게 제어하는 새로운 방법
이 방법은 코드 안정성과 유지 보수성을 크게 올려주며 리소스 누수 방지에 효과적임
기존 try...finally 패턴을 단순화하고 대규모 복합 리소스 환경에서 신뢰성 높은 자원 처리가 가능해짐
- 구성 요소
using 및 await using 선언 (스코프 종료 시 자동으로 리소스 해제)
[Symbol.dispose](), [Symbol.async dispose]() 심볼 (해제 동작 구현을 위한 메서드)
글로벌 객체 DisposableStack, AsyncDisposableStack (여러 리소스를 그룹화해 효율적으로 관리)
SupperessedError (리소스 정리 중 발생한 에러와 기존 에러를 모두 포함하는 신규 에러 타입)
DisposableStack과 AsyncDisposableStack
여러 리스소를 효율적이고 안전하게 그룹화
각 스택에 리소스를 추가하고 스택 자체를 해제할 때 내부 모든 리소스를 역순으로 해제함
의존 관계가 있는 복잡한 리소스 집합을 다룰 때 위험을 줄이고 코드를 단순화함
- 주요 메서드
use(value) : 스택 맨 위에 디스포저블 리소스를 추가함
adopt(value, onDispose) : 비디스포저블 리소스에 해제 콜백을 묶어 추가함
defer(onDispose) : 리소스 해제 없이 해제 동작만 추가함
move() : 현재 스택의 모든 리소스를 새 스택으로 이동시켜 소유권 이전
dispose(), asyncDispose() : 스택 내 리소스 전체를 해제함
파일 읽기 예시
- AS-IS
import * as fs from 'fs';
function readFile(filePath: string): string {
const fileHandle = fs.openSync(filePath, 'r'); // 파일 열기
try {
const buffer = Buffer.alloc(1024);
const bytesRead = fs.readSync(fileHandle, buffer, 0, buffer.length, 0);
return buffer.toString('utf8', 0, bytesRead);
} finally {
fs.closeSync(fileHandle); // 파일 닫기
}
}
const filePath = './example.txt';
try {
const content = readFile(filePath);
console.log('File Content:', content);
} catch (error) {
console.error('Error:', error.message);
}
- TO-BE
class FileReader implements Disposable {
private fileHandle: number | null = null;
constructor(private filePath: string) {}
async open() {
const fs = await import('fs/promises');
this.fileHandle = await fs.open(this.filePath, 'r');
}
async read(): Promise<string> {
if (this.fileHandle === null) {
throw new Error('File is not open.');
}
const buffer = Buffer.alloc(1024);
const { bytesRead } = await this.fileHandle.read(buffer, 0, buffer.length, 0);
return buffer.toString('utf8', 0, bytesRead);
}
[Symbol.dispose]() {
console.log(`Disposing file handle for: ${this.filePath}`);
if (this.fileHandle) {
this.fileHandle.close();
this.fileHandle = null;
}
}
}
async function readFile(filePath: string) {
using const reader = new FileReader(filePath); // 자원 관리 시작
await reader.open();
const content = await reader.read();
console.log('File Content:', content);
}
readFile('./example.txt');
데이터베이스 연결 예시
- AS-IS
import { createConnection, Connection } from 'mysql2/promise';
async function fetchData() {
let connection: Connection | null = null;
try {
connection = await createConnection({
host: 'localhost',
user: 'root',
database: 'test',
});
const [rows] = await connection.query('SELECT * FROM users');
console.log(rows);
} catch (error) {
console.error('Database error:', error.message);
} finally {
if (connection) {
await connection.end(); // 연결 닫기
}
}
}
fetchData();
- TO-BE
class DatabaseConnection implements AsyncDisposable {
private connected = false;
async connect() {
console.log('Connecting to the database...');
this.connected = true;
}
async query(sql: string): Promise<any[]> {
if (!this.connected) {
throw new Error('Database is not connected.');
}
console.log(`Executing query: ${sql}`);
return [{ id: 1, name: 'John Doe' }];
}
async [Symbol.asyncDispose]() {
console.log('Closing database connection...');
this.connected = false;
}
}
async function fetchData() {
await using const db = new DatabaseConnection(); // 비동기 자원 관리 시작
await db.connect();
const results = await db.query('SELECT * FROM Users');
console.log('Query Results:', results);
}
fetchData();
Referrence
JavaScript의 새로운 슈퍼파워: 명시적 리소스 관리 | GeekNews
Explicit Resource Management 제안은 파일 핸들, 네트워크 연결 등 리소스의 라이프사이클을 명확하게 제어하는 새로운 방법Chromium 134와 V8 v13.8부터 해당 기능을 이용할 수 있음언어에 추가 되는 부분들
news.hada.io
Documentation - TypeScript 5.2
TypeScript 5.2 Release Notes
www.typescriptlang.org
'Programming > JavaScript' 카테고리의 다른 글
Astra - 가볍고 빠른 javascript to exe 컴파일러 (1) | 2025.06.21 |
---|---|
자바스크립트 최신 메서드 (2) | 2025.06.21 |
자바스크립트 클로저에 대해 알아보자 (2) | 2025.06.21 |
자바 스크립트 자료형 총 정리 (1) | 2025.02.16 |
Bun v1.1 출시 (1) | 2024.04.27 |