Admin 원소스 관리

박상하·2025년 3월 5일

1년차

목록 보기
4/26

Admin을 하나의 파일에서 관리 📁

우리 서비스는 총 3개(1개는 출시 예정)가 있다. 모두 이커머스 서비스로 Admin 페이지의 구조가 동일하다. 디테일한 부분은 각각 다른 점이 있지만 파일을 나누어 관리하는 것보다 하나의 파일에서 관리하는 것이 좋지 않겠냐고 CTO님께서 제안을 하셨다. 그래서 Admin을 하나의 파일로 합치는 업무를 배정받았다.

환경 변수 사용

결국 각 Admin의 구조가 같더라도 데이터는 다르다.
어떤 플랫폼인지에 따라 BASE_URL, PARIMARY_COLOR 등 분기되야 하는 데이터들이 존재했다.

이는 환경 변수로 분기 할 수 있다.

cross-env

해당 라이브러리는 package.json에 환경 변수를 넣어주고 process.env로 접근할 수 있게 해주는 라이브러리이다.

//package.json
"A_service-start:dev" : "cross-env REACT_APP_ENVIROMENT=A_DEV yarn start"
"B_service-start:dev" : "cross-env REACT_APP_ENVIROMENT=A_DEV yarn start"
//api.ts
const ENVIROMENT = process.env.REACT_APP_ENVIROMENT

이런식으로 접근이 가능하다.

이를 사용하면 package.json에서 start/build등을 할 때 환경변수 값을 분리하여 주입해줄 수 있다.

그렇다면 이제 ENVIROMENT라는 변수값을 사용하여 데이터를 분기해보자

개발/운영에 따른 분기

const IS_DEV = ENVIROMENT.includes('dev')

플랫폼에 따른 분기

const PLATFORM= ENVIROMENT.split('_')[0]

BASE_URL의 경우에는

const baseUrlConfig ={
 A:'https://www.AA'
 B:'https://www.BB'
 C:'https://www.CC'
}

사용 시점에서

baseUIrlConfig[PLATFORM]

다음과 같이 사용하고자 하였다.

객체 접근 방식의 단점

위 처럼 객체로 접근하는 방식으로 구현을 하고 팀원분들께 의견을 여쭤봤다.

단점은 크게 2가지가 있었다.

  1. PLATFORM 값에 대한 검증은 할 수 없다.
  2. 매번 PLATFORM을 사용하는 곳마다 import 해야한다.

특히, 현재 PLATFORM 데이터는 환경변수에서 split 메서드를 사용해서 가져온다.

이는 package.json에서 환경변수를 주입할 때 강제적으로 데이터의 형태가 정해져야한다는 점을 의미한다.

(ㅁ_ㅁ 이런식)

그런데 만약 이런 규칙을 나만 알고 있다면 다른 개발자가 이 코드에 접근할 때 어려움을 느낄 수 있다.

적어도 오류를 남겨서 개발자가 이런 규칙이 있다는 걸 인지하고 수정할 수 있어야한다.

그래서 다음과 같은 방법을 제안해주셨다.

PLATFORM 값을 검증할 수 있고 PLATFORM을 매번 import 하지 않는 "싱글톤 클래스 방식" 으로 구현 하기

싱글톤 ?

싱글톤 패턴은 특정 클래스의 인스턴스를 1개만 생성되는 것을 보장하는 디자인 패턴이다.

즉, 생성자를 통해서 여러 번 호출이 되더라도 인스턴스를 새로 생성하지 않고 최초 호출 시에 담아두었던 인스턴스를 재활용 하는 패턴이다.

지금의 상황에 알맞다. 최초 1회 (서비스에 들어왔을 때) 환경 변수에 따른 기본 값들을 정의해줄 수 있는 방법이다.

또한 class 기반이기에 PLATFORM에 대한 검증이 가능하다.

구현 코드

class ConfigByPlatform {
    private static instance: ConfigByPlatform;
    private platform: string;

    private constructor() {
        // PLATFORM 키워드에 대한 검증
        if (!['cuma', 'market', 'food'].includes(PLATFORM)) {
            throw new Error(`Unknown environment: ${PLATFORM}`);
        }
        this.platform = PLATFORM;
    }

    static getInstance(): ConfigByPlatform {
        if (!ConfigByPlatform.instance) {
            ConfigByPlatform.instance = new ConfigByPlatform();
        }
        return ConfigByPlatform.instance;
    }

    // 정의된 객체와 PLATFORM 키워드 대입 검증
    private getConfigValue(config, configName) {
        if (config[this.platform]) {
            return config[this.platform];
        }
        throw new Error(`잘못된 key 값입니다: ${configName}`);
    }

    get cumaAIButtonString() {
        return this.getConfigValue(cumaAIButtonConfig, 'cumaAIButtonConfig');
    }

    get paymentMethodTypeCard() {
        return this.getConfigValue(paymentMethodTypeCardConfig, 'paymentMethodTypeCardConfig');
    }

    get paymentMethodTypeBankTransfer() {
        return this.getConfigValue(paymentMethodTypeBankTransferConfig, 'paymentMethodTypeBankTransferConfig');
    }

    get distributor() {
        return this.getConfigValue(distributorConfig, 'distributorConfig');
    }

    get favicon() {
        return this.getConfigValue(faviconConfig, 'faviconConfig');
    }

    get title() {
        return this.getConfigValue(titleConfig, 'titleConfig');
    }

    get bottomMenuListButtons() {
        return this.getConfigValue(bottomMenuListButtonsNameConfig, 'bottomMenuListButtonsNameConfig');
    }

    get propertyJson() {
        return this.getConfigValue(propertyJsonConfig, 'propertyJsonConfig');
    }

    get initialPropertyJson() {
        return this.getConfigValue(initialPropertyJsonConfig, '(initialPropertyJsonConfig');
    }

    get defaultPropertyJson() {
        return this.getConfigValue(defaultPropertyJsonDefaultConfig, 'defaultPropertyJsonDefaultConfig');
    }
}

export const configByPlatform = ConfigByPlatform.getInstance();



이렇게 구현하면 다음과 같이 사용 가능하다.

```js
      return configByPlatform.paymentMethodTypeBankTransfer;

마무리

이를 사용하여 각 상황에 알맞는 값을 넣어 줄 수 있었다.

그런데 이를 수정할 수록 방법의 장단점이 있다는 것을 알게 되었다.
객체 맵핑은 사실 선언시 시점이나 사용시점에서는 간단하게 사용이 가능했다. 나의 주관으로는 가독성은 더 나았던 거 같다.

그런데 싱글톤을 사용해서 타당성 검증과 에러를 던질 수 있게 되었지만 코드의 양은 많아졌고 선언 시점에서는 가독성이 아쉬운 점이 있다.

어떤 코드를 사용할지는 내가 선택해야하지만 그 의도와 장/단점을 익혀두는게 중요하다 느꼈다. 🏌️‍♂️

0개의 댓글