나만의 라이브러리를 만들어보고 싶은 생각, 한 번쯤은 해보셨죠? 개발자로서 다양한 문제를 해결하기 위해 라이브러리를 만들어보는 건 흥미로운 일입니다. 특히, 범용적인 라이브러리를 만들고자 할 때는 더욱 신중한 고려가 필요하죠. 오늘은 프론트엔드 개발에서 자주 언급되는 “Framework Agnostic”이라는 개념을 중심으로 이야기를 해보려고 합니다.
Framework Agnostic이란?
Framework Agnostic, 혹시 들어보셨나요? 이 용어는 소프트웨어가 특정 환경에 종속되지 않고 독립적으로 설계됨을 의미합니다. 즉, 특정 프레임워크에 묶이지 않고 다양한 환경에서 사용될 수 있는 라이브러리를 만드는 것이죠.
예를 들어, JavaScript 라이브러리에서 Framework Agnostic 접근 방식이라고 하면, 특정 프레임워크에 종속되지 않는 코드를 작성하는 것이라고 할 수 있습니다. 이렇게 하면 React, Vue 등 여러 프레임워크와 호환될 수 있기 때문이죠.
Tanstack Query
대표적인 라이브러리가 Tanstack Query입니다. 예전에는 React Query로 불렸지만, 이제는 다양한 프레임워크에서도 사용할 수 있는 Framework Agnostic한 라이브러리로 발전했습니다. 어떻게 가능했을까요?
Tanstack Query의 소스 코드를 보면, core 패키지와 각 프레임워크에 맞춘 어댑터 패키지로 구성되어 있습니다. 핵심 로직은 query-core에 담겨있고, React, Vue, Svelte 등 프레임워크에 특화된 부분은 각각의 패키지에 담겨있죠.
계산기, 직접 만들어볼까요?
이제 React에 강하게 결합된 계산기 라이브러리를 다양한 프레임워크에서 사용할 수 있도록 재설계해보겠습니다.
1. 코어 인터페이스 만들기
먼저, 코어 기능을 프레임워크와 독립적으로 정의합니다. 다음은 계산기의 연산 로직을 포함한 코어 클래스의 예입니다:
class Calculator extends EventTarget {
private _result: number = 0;
get result() {
return this._result;
}
add(a: number, b: number) {
this._result = a + b;
this.dispatchEvent(new Event('update'));
}
subtract(a: number, b: number) {
this._result = a - b;
this.dispatchEvent(new Event('update'));
}
multiply(a: number, b: number) {
this._result = a * b;
this.dispatchEvent(new Event('update'));
}
divide(a: number, b: number) {
this._result = a / b;
this.dispatchEvent(new Event('update'));
}
}
2. React 어댑터 만들기
이제 코어를 React에 연동해봅시다. React 상태와 라이프사이클을 연동하는 Hook을 만듭니다.
import { useEffect, useState } from 'react';
function useCalculator() {
const [result, setResult] = useState(0);
const calculator = new Calculator();
useEffect(() => {
const handleUpdate = () => setResult(calculator.result);
calculator.addEventListener('update', handleUpdate);
return () => {
calculator.removeEventListener('update', handleUpdate);
};
}, [calculator]);
return {
result,
add: (a, b) => calculator.add(a, b),
subtract: (a, b) => calculator.subtract(a, b),
multiply: (a, b) => calculator.multiply(a, b),
divide: (a, b) => calculator.divide(a, b),
};
}
어떤가요? 이렇게 생각보다는 쉽게 라이브러리를 만들 수 있답니다.
Framework Agnostic 설계의 장점과 단점
장점
- 재사용성 증가:@b] 다양한 프레임워크에서 사용할 수 있어요.
- 유지보수 용이:@b] 코어와 어댑터를 분리해 각자의 수정이 쉬워요.
단점
- 개발 및 유지보수 비용 증가: 각 프레임워크별 어댑터를 개발하고 유지해야 해요.
- 복잡성 증가: 코어와 어댑터 간의 인터페이스를 관리해야 해요.
결론
Framework Agnostic한 라이브러리를 만드는 것은 단순히 특정 환경에 종속되지 않는 코드를 작성하는 것 이상입니다. 핵심 로직과 프레임워크에 특화된 로직을 분리해, 유지보수와 확장성을 고려해야 하죠. Tanstack Query와 같은 사례를 통해 이 개념을 이해하고, 직접 적용해보는 것은 분명히 가치 있는 일이 아닐까요?
여러분도 범용적인 라이브러리를 만들어보고 싶지 않으신가요? 오늘 알려드린 내용을 활용해보는 것은 어떨까요?