320x100
320x100

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

 

300x250
728x90