저번 시간에는 어떻게 sdk를 세팅하는지에 대해서 알아보았습니다. 오늘은 이어서 sdk에 내부적으로 코드를 어떻게 관리할 것인지 알아보도록 하겠습니다.
SDK를 개발할 때는 다양한 요소를 신경 써서 작업해야 합니다. 이를 효과적으로 해결하기 위해 클래스(Class) 기반 구조를 적용하여 SDK를 설계하였으며, 그 이유를 하나씩 설명해 보겠습니다.
코드의 가독성은 모든 개발자가 신경 써야 할 요소지만, 이번 SDK는 장기적인 프로젝트로 운영될 가능성이 큰 프로젝트였습니다. 따라서, 시간이 지나도 나 자신 혹은 새로운 개발자가 코드를 쉽게 이해하고 유지보수할 수 있도록 구조화하는 것이 중요하다고 생각했습니다.
이러한 이유로, 많은 개발자들이 익숙한 클래스(Class) 기반 구조를 선택하였습니다.
클래스를 사용하면 각 기능을 캡슐화(Encapsulation) 하여 모듈화(Modularization) 할 수 있고, 역할별로 코드를 분리할 수 있습니다.
이로 인해 특정 기능을 수정하거나 유지보수할 때, 관련된 코드만 집중적으로 다룰 수 있어 개발 생산성이 향상됩니다.
SDK는 여러 개발자가 다양한 환경에서 사용하기 때문에, 내부 상태(State)와 메서드(Method)를 신중하게 관리해야 합니다. 모든 기능을 무분별하게 공개할 경우, 예상치 못한 오남용이 발생할 수 있으며, 유지보수 비용이 증가하는 원인이 될 수 있습니다.
따라서, 필요한 기능만 외부에 공개하고, 내부 로직은 보호하는 구조가 중요합니다.
클래스에서 제공하는 private, protected, public 접근 제어자를 활용하면,
필요한 기능만 외부에 노출하고, 내부적으로 관리해야 하는 데이터나 메서드는 감출 수 있습니다.
예를 들어, API 요청을 관리하는 SDK의 경우 axios 인스턴스를 protected로 선언하면
하위 클래스에서 이를 재사용하면서도, 외부에서는 직접 접근하지 못하도록 할 수 있습니다.
SDK의 기능은 시간이 지남에 따라 계속 추가될 가능성이 높습니다.
따라서, 처음부터 확장성을 고려한 설계가 필수적이며, 객체 지향 프로그래밍(OOP)의 상속(Inheritance) 기능을 활용하면 이를 효과적으로 구현할 수 있습니다.
예를 들어, 기본 API 클래스(BaseAPI) 를 만들어 공통 로직을 정의하고,
이를 상속받아(UserAPI, ProductAPI 등) 특정 기능을 확장하는 방식이 가능합니다.
class BaseAPI {
private static instance: BaseAPI
protected axios: AxiosInstance
protected constructor(clientKey: string, debug: boolean) {
this.axios = axios.create({
baseURL: BASE_URL,
})
this.axios.interceptors.request.use(
//axios를 요청할 때마다 실행할 로직
)
}
//BaseAPI 상속
class UserAPI extends BaseAPI {}
class TestAPI extends BaseAPI {}
가독성을 높였습니다.보안성을 강화하였습니다.확장성에 유연하게 대응하였습니다.소프트웨어 디자인 패턴에서 싱글턴 패턴(Singleton pattern)을 따르는 클래스는, 생성자가 여러 차례 호출되더라도 실제로 생성되는 객체는 하나이고 최초 생성 이후에 호출된 생성자는 최초의 생성자가 생성한 객체를 리턴한다. 이와 같은 디자인 유형을 싱글턴 패턴이라고 한다. 주로 공통된 객체를 여러개 생성해서 사용하는 DBCP(DataBase Connection Pool)와 같은 상황에서 많이 사용된다.
- 출처: 위키피디아
간단히 설명하면 싱글톤 패턴은 객체의 인스턴스를 한개만 생성되게 하는 패턴입니다.
SDK를 설계할 때 가장 중요한 요소 중 하나는 사용자가 SDK 내부의 클래스에 직접 접근하는 것을 막는 것입니다. 사용자가 직접 SDK 내부 인스턴스를 생성하고 접근할 수 있다면, 다음과 같은 문제가 발생할 수 있습니다.
이를 방지하기 위해, SDK 내부에서 단일 인스턴스를 관리하고 사용자가 init() 메서드를 호출하여 필요한 API를 초기화하도록 설계하였습니다.
class SdkClass{
public init() {
BaseAPI.initialize()
}
}
const sdkInstance = new SdkClass()
export default sdkInstance
그런데 사용자가 sdk를 사용하게 위해 여러 곳에서 init 메서드를 사용하게 된다면 BaseAPI의 인터셉트 요청이 불필요하게 중복되어 발생하게 됩니다. 이를 해결하기 위해서 싱글톤 패턴을 적용하였습니다!
싱글톤 패턴을 적용하면, SDK의 인스턴스가 한 번만 생성되고 이후에는 동일한 인스턴스를 재사용할 수 있습니다.
이를 통해 중복 초기화 방지 및 리소스 낭비 최소화가 가능합니다.
class BaseAPIClass{
static instanse;
initialize() {
if (SigletonClass.instance) {
return SigletonClass.instance;
}
SigletonClass.instance = this;
}
}