JavaScript

[TypeScript] 새로운 JS의 키워드 using!

Dev.JH 2023. 9. 24. 17:43

집에 돌아오는 길 버스에서 NomadCoders 니꼬쌤이 유튜브를 새로 올리신걸 보며 왔다! 유튜브의 제목은 '새로운 JS키워드가 뜬다!' 였고, 프론트엔드 개발자가 되고 싶은 나로서는 영상을 누르지 않을 수가 없었다.

intro: var, let, const 그리고 using!

우리는 이제 기존의 변수선언 키워드 var, let, const 외에도 using 을 볼수 있다고 한다!!

현재 기준(2023.09) 타입스크립트 5.2 버전에서 사용해 볼 수 있으며, 이제 using은 어떨 때, 어떻게 쓰는지 한번 알아보도록하자!

1. 🤷‍♂️using이 왜 필요한데?

기존의 var, let, const와 동일하거나 비슷한 역할이면 아마 이 키워드를 만든 의미가 없을 것이다. 그렇다면 왜 필요한걸까?

using은 자바스크립트 프로그램에서 리소스를 관리하는데 이점을 가진다. 그렇다면 여기서 리소스를 잘 관리한다는게 어떠한 이점이 있는지를 다시 한번 살펴보아야 하겠다. 

리소스 관리를 잘 하면  애플리케이션의 성능 최적화 및 접근성 향상을 이끌어 낼 수 있으며, 이는 사용자 만족도를 향상시키는 요인이 된다. 반대로 리소스 관리가 잘 되지 않는다면 프로그램이 필요한 것보다 더 많은 메모리를 사용하게 되어 실행 속도가 느려지거나 충돌이 발생할 수 있다. 

 

2. 🌍using이 없는 세상

async function getUsers(){
	const db = awiat getDb();		// 데이터베이스에 대한 연결
    	const users = awiat db.query(`SELECT id FROM users;`);		// 쿼리 실행
    	return users;	// 쿼리 실행 결과 반환
}

해당 코드를 보면 어떠한 생각이 드는지 물어보고 싶다! 아마 문제 없을 거라고 생각 할 수 있다. 나도 그냥 보고 넘어갔었으니까! 그냥 읽는 것보다 한 번 뭐가 문제인지 고민을 해보고 넘어가는 것도 좋은 학습 방법이라고 생각이 든다. 고민해보는 시간을 가져보자!

 

.

.

.

 

고민을 해봤다고 믿고 답을 공개하면! 

해당 코드는 데이터베이스에 대한 연결이 닫히지 않는 큰 문제가 있다. 이러한 코드가 하나, 둘, 셋... 계속해서 쌓여 나갈 수록 연결을 제거하지 않고 새 연결을 계속 생성해버리니 데이터베이스에 과부하가 걸리게 되는 요인이 될 수 있다는 것이다!

그래서 생각한 코드는 다음과 같다!!

 

async function getUsers(){
	const db = await getDb();		// 데이터베이스에 대한 연결
    	const users = awiat db.query(`SELECT id FROM users;`);		// 쿼리 실행
        await db.close();	// 연결 제거!
    	return users;	// 쿼리 실행 결과 반환
}


async function getDb() {
	const connection = await mysql.connect(...);
    	return connection;	// 데이터베이스에 대한 액세스 권한을 반환하는 함수
}

현재 await db.close 를 작성함으로써 데이터베이스에 대한 연결을 닫아 주고 이전에 발생했던 문제를 사전에 막아주었다! 

그렇다면 여기서 끝일까? 만약에 3번째 줄, 쿼리 실행 코드가 어떠한 이유로 오류가 발생하여 쿼리가 실행 될 수 없다고 가정해보자. 그렇다면 그 다음에 오는 await db.close는 실행되지 않고 연결이 유지 된 상태가 될 것이다!

음... 그렇다면 이번에는 다음과 같이 예외처리를 해줌으로써 문제를 해결 할 수 있겠다.

 

async function getUsers(){
	const db = awiat getDb();
	try {
	const uesrs = await db.query(`SELECT id FROM users;`);
	return users;
	} catch{
	console.log("error running query")
	} finally{
	await db.close();
	}
}

위의 코드에서는 쿼리의 실행 여부에 상관 없이 항상 await db.close가 실행되므로 앞서 말했던 문제를 해결해 줄 수 있는  좋은 코드라고 볼 수 있다.

 

그러나 위 문제 해결 방법의 단점으로는 데이터베이스를 사용하는 코드의 모든 곳에서 항상 데이터베이스를 명시적으로 닫아줘야 한다는 것이다. 여기서 사람들은 생각을 하게 된다... 데이터베이스가 더 이상 사용되지 않을 때, 데이터베이스 연결을 자동으로 종료하는 방법이 있으면 참 좋을 것 같다고! 그렇게 탄생하게 된 것이 바로 using이다!

3. 📕using을 사용하는 방법

function getResource() {
	return {
            data: "hello world",
                [Symbol.dispose]: () => {
                    console.log('bye world')
                }
	}
}

function main() {
	using myResource = getResource();
    	console.log(myResource.data);
}

main();	// hello word
// bye world

 

위 함수는 객체를 반환하게 된다. 객체 안을 한번 들여다 보도록하자.  'bye world'를 출력하는 정체불명의 함수도 포함이 되어있다. 

우리의 JavaScript는 main 함수를 호출을 했을 때 변수 생성 키워드는 using이고, 'Symbol.dispose' 속성을 가진 객체를 반환하는 것으로 '지금 리소스를 다루는구나' 하고 눈치를 채게 된다. 그리고  main 함수가 완료된 뒤, 자동으로 myResource 변수가 범위를 벗어나면 Symbol.dispose 함수에서 코드를 실행하여 'bye world'를 출력하게 된다. 

자 그럼 어떻게 using을 사용해야하는지 대충 감을 봤으니 실제로 한번 적용해 보자.

 

async function getDb(){
    const connection = await mysql.connect(...);
    return {
    	connection,
        [Symbol.asyncDispose]: async () => {
        	await connection.close();
        },
    }
}

이제 위에서 한번 봤던 getDb함수를 위와 같이 변경한다. 이제 getDb 함수는 기존의 connection을 반환하는 것에서 객체를 반환하는 것으로 바뀌게 되었다! 반환한게 될 객체에는 데이터베이스에 대한 연결이 있으며, 데이터 베이스에 대한 연결을 닫는 'Symbol.asyncDispose' 함수가 존재하게 된다. 이 경우에는 dispose 코드가 async await를 사용해야 하기 때문에 Symbol.Dispose가 아닌 것을 염두에 두자. 자 그럼 이제 getUsers함수를 다음과 같이 바꿀 수 있다.

 

async function getUsers(){
	await using db = await getDb();
	try {
	const uesrs = await db.connection.query(`SELECT id FROM users;`);
	return users;
	} catch{
	console.log("error running query")
	}
}

전과 달라진 점으로는 using 키워드를 통해 db 변수를 생성하고 있으며, Symbol.asyncDispose를 사용하고 있으므로 using 앞에 await을 작성한다. 나도 이렇게 await을 사용해본 것이 처음이라 이상하게 느껴지고 당황스러웠지만 사실은 자연스러운 코드였다. 첫 번째 using 앞의 awaitdispose 코드를 기다리는 것이고, 두 번째는 데이터베이스에 연결될 코드를 기다리는 것이다. 

이제 JavaScript는 getUsers함수가 종료 되는 순간 데이터베이스에 대한 연결을 닫는 'Symbol.asyncDispose' 함수를 자동으로 호출한다. 이제 데이터베이스에 대해 access하고 싶을 때마다 using 키워드를 사용하여 변수를 만들면, 변수 사용이 끝났을 때, 항상 올바르게 폐기되고 연결이 닫히게 될 것이다! using 키워드는 데이터베이스 연결 뿐만 아니라 닫아야하는 파일, 데이터 스트림, 웹 소켓 연결등에서 유리하니 한번 쯤은 사용해보는 것을 권장한다!!

 

 

⭐출처 

https://youtu.be/-NmwyJ5S-IY?si=GEFWlHx0s5MLCqK3